diff options
author | murphy <murphy@rubychan.de> | 2008-01-21 03:22:59 +0000 |
---|---|---|
committer | murphy <murphy@rubychan.de> | 2008-01-21 03:22:59 +0000 |
commit | 538fd572f0beaccd9f25c13fcf47af5ad2c3a3f4 (patch) | |
tree | 178f1ff495b975d33207afe516e9b03ca5bdc88c | |
parent | 2ec1b9399186f32d36d549eb1f915f9ab4e61647 (diff) | |
download | coderay-538fd572f0beaccd9f25c13fcf47af5ad2c3a3f4.tar.gz |
Added ruby.rails test to repository.
-rw-r--r-- | test/scanners/ruby/rails.expected.raydebug | 74259 | ||||
-rw-r--r-- | test/scanners/ruby/rails.in.rb | 74259 |
2 files changed, 148518 insertions, 0 deletions
diff --git a/test/scanners/ruby/rails.expected.raydebug b/test/scanners/ruby/rails.expected.raydebug new file mode 100644 index 0000000..484f200 --- /dev/null +++ b/test/scanners/ruby/rails.expected.raydebug @@ -0,0 +1,74259 @@ +ident(require) string<delimiter(')content(rbconfig)delimiter(')> +ident(require) string<delimiter(')content(find)delimiter(')> +ident(require) string<delimiter(')content(ftools)delimiter(')> + +ident(include) constant(Config) + +comment(# this was adapted from rdoc's install.rb by way of Log4r) + +global_variable($sitedir) operator(=) constant(CONFIG)operator([)string<delimiter(")content(sitelibdir)delimiter(")>operator(]) +reserved(unless) global_variable($sitedir) + ident(version) operator(=) constant(CONFIG)operator([)string<delimiter(")content(MAJOR)delimiter(")>operator(]) operator(+) string<delimiter(")content(.)delimiter(")> operator(+) constant(CONFIG)operator([)string<delimiter(")content(MINOR)delimiter(")>operator(]) + global_variable($libdir) operator(=) constant(File)operator(.)ident(join)operator(()constant(CONFIG)operator([)string<delimiter(")content(libdir)delimiter(")>operator(])operator(,) string<delimiter(")content(ruby)delimiter(")>operator(,) ident(version)operator(\)) + global_variable($sitedir) operator(=) global_variable($:)operator(.)ident(find) operator({)operator(|)ident(x)operator(|) ident(x) operator(=)operator(~) regexp<delimiter(/)content(site_ruby)delimiter(/)> operator(}) + reserved(if) operator(!)global_variable($sitedir) + global_variable($sitedir) operator(=) constant(File)operator(.)ident(join)operator(()global_variable($libdir)operator(,) string<delimiter(")content(site_ruby)delimiter(")>operator(\)) + reserved(elsif) global_variable($sitedir) operator(!)operator(~) constant(Regexp)operator(.)ident(quote)operator(()ident(version)operator(\)) + global_variable($sitedir) operator(=) constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) ident(version)operator(\)) + reserved(end) +reserved(end) + +comment(# the acual gruntwork) +constant(Dir)operator(.)ident(chdir)operator(()string<delimiter(")content(lib)delimiter(")>operator(\)) + +constant(Find)operator(.)ident(find)operator(()string<delimiter(")content(action_mailer)delimiter(")>operator(,) string<delimiter(")content(action_mailer.rb)delimiter(")>operator(\)) operator({) operator(|)ident(f)operator(|) + reserved(if) ident(f)operator([)integer(-3)operator(..)integer(-1)operator(]) operator(==) string<delimiter(")content(.rb)delimiter(")> + constant(File)operator(::)ident(install)operator(()ident(f)operator(,) constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) operator(*)ident(f)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator(\))operator(,) integer(0644)operator(,) pre_constant(true)operator(\)) + reserved(else) + constant(File)operator(::)ident(makedirs)operator(()constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) operator(*)ident(f)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator(\))operator(\)) + reserved(end) +operator(}) +reserved(module) class(ActionMailer) + reserved(module) class(AdvAttrAccessor) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + reserved(def) method(adv_attr_accessor)operator(()operator(*)ident(names)operator(\)) + ident(names)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(ivar) operator(=) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + + ident(define_method)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(=)delimiter(")>operator(\)) reserved(do) operator(|)ident(value)operator(|) + ident(instance_variable_set)operator(()ident(ivar)operator(,) ident(value)operator(\)) + reserved(end) + + ident(define_method)operator(()ident(name)operator(\)) reserved(do) operator(|*)ident(parameters)operator(|) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(expected 0 or 1 parameters)delimiter(")> reserved(unless) ident(parameters)operator(.)ident(length) operator(<=) integer(1) + reserved(if) ident(parameters)operator(.)ident(empty?) + reserved(if) ident(instance_variables)operator(.)ident(include?)operator(()ident(ivar)operator(\)) + ident(instance_variable_get)operator(()ident(ivar)operator(\)) + reserved(end) + reserved(else) + ident(instance_variable_set)operator(()ident(ivar)operator(,) ident(parameters)operator(.)ident(first)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_mailer/adv_attr_accessor)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/part)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/part_container)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/utils)delimiter(')> +ident(require) string<delimiter(')content(tmail/net)delimiter(')> + +reserved(module) class(ActionMailer) comment(#:nodoc:) + comment(# ActionMailer allows you to send email from your application using a mailer model and views.) + comment(#) + comment(# = Mailer Models) + comment(# To use ActionMailer, you need to create a mailer model.) + comment(# ) + comment(# $ script/generate mailer Notifier) + comment(#) + comment(# The generated model inherits from ActionMailer::Base. Emails are defined by creating methods within the model which are then ) + comment(# used to set variables to be used in the mail template, to change options on the mail, or ) + comment(# to add attachments.) + comment(#) + comment(# Examples:) + comment(#) + comment(# class Notifier < ActionMailer::Base) + comment(# def signup_notification(recipient\)) + comment(# recipients recipient.email_address_with_name) + comment(# from "system@example.com") + comment(# subject "New account information") + comment(# body "account" => recipient) + comment(# end) + comment(# end) + comment(#) + comment(# Mailer methods have the following configuration methods available.) + comment(#) + comment(# * <tt>recipients</tt> - Takes one or more email addresses. These addresses are where your email will be delivered to. Sets the <tt>To:</tt> header.) + comment(# * <tt>subject</tt> - The subject of your email. Sets the <tt>Subject:</tt> header.) + comment(# * <tt>from</tt> - Who the email you are sending is from. Sets the <tt>From:</tt> header.) + comment(# * <tt>cc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header.) + comment(# * <tt>bcc</tt> - Takes one or more email address. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc</tt> header.) + comment(# * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent.) + comment(# * <tt>content_type</tt> - Specify the content type of the message. Defaults to <tt>text/plain</tt>.) + comment(# * <tt>headers</tt> - Specify additional headers to be set for the message, e.g. <tt>headers 'X-Mail-Count' => 107370</tt>.) + comment(#) + comment(# The <tt>body</tt> method has special behavior. It takes a hash which generates an instance variable) + comment(# named after each key in the hash containing the value that that key points to.) + comment(#) + comment(# So, for example, <tt>body "account" => recipient</tt> would result) + comment(# in an instance variable <tt>@account</tt> with the value of <tt>recipient</tt> being accessible in the ) + comment(# view.) + comment(#) + comment(# = Mailer Views) + comment(# Like ActionController, each mailer class has a corresponding view directory) + comment(# in which each method of the class looks for a template with its name.) + comment(# To define a template to be used with a mailing, create an <tt>.rhtml</tt> file with the same name as the method) + comment(# in your mailer model. For example, in the mailer defined above, the template at ) + comment(# <tt>app/views/notifier/signup_notification.rhtml</tt> would be used to generate the email.) + comment(#) + comment(# Variables defined in the model are accessible as instance variables in the view.) + comment(#) + comment(# Emails by default are sent in plain text, so a sample view for our model example might look like this:) + comment(#) + comment(# Hi <%= @account.name %>,) + comment(# Thanks for joining our service! Please check back often.) + comment(#) + comment(# = Sending Mail) + comment(# Once a mailer action and template are defined, you can deliver your message or create it and save it ) + comment(# for delivery later:) + comment(#) + comment(# Notifier.deliver_signup_notification(david\) # sends the email) + comment(# mail = Notifier.create_signup_notification(david\) # => a tmail object) + comment(# Notifier.deliver(mail\)) + comment(# ) + comment(# You never instantiate your mailer class. Rather, your delivery instance) + comment(# methods are automatically wrapped in class methods that start with the word) + comment(# <tt>deliver_</tt> followed by the name of the mailer method that you would) + comment(# like to deliver. The <tt>signup_notification</tt> method defined above is) + comment(# delivered by invoking <tt>Notifier.deliver_signup_notification</tt>.) + comment(#) + comment(# = HTML Email) + comment(# To send mail as HTML, make sure your view (the <tt>.rhtml</tt> file\) generates HTML and) + comment(# set the content type to html.) + comment(#) + comment(# class MyMailer < ActionMailer::Base) + comment(# def signup_notification(recipient\)) + comment(# recipients recipient.email_address_with_name) + comment(# subject "New account information") + comment(# body "account" => recipient) + comment(# from "system@example.com") + comment(# content_type "text/html" # Here's where the magic happens) + comment(# end) + comment(# end ) + comment(#) + comment(# = Multipart Email) + comment(# You can explicitly specify multipart messages:) + comment(#) + comment(# class ApplicationMailer < ActionMailer::Base) + comment(# def signup_notification(recipient\)) + comment(# recipients recipient.email_address_with_name) + comment(# subject "New account information") + comment(# from "system@example.com") + comment(#) + comment(# part :content_type => "text/html",) + comment(# :body => render_message("signup-as-html", :account => recipient\)) + comment(#) + comment(# part "text/plain" do |p|) + comment(# p.body = render_message("signup-as-plain", :account => recipient\)) + comment(# p.transfer_encoding = "base64") + comment(# end) + comment(# end) + comment(# end) + comment(# ) + comment(# Multipart messages can also be used implicitly because ActionMailer will automatically) + comment(# detect and use multipart templates, where each template is named after the name of the action, followed) + comment(# by the content type. Each such detected template will be added as separate part to the message.) + comment(# ) + comment(# For example, if the following templates existed:) + comment(# * signup_notification.text.plain.rhtml) + comment(# * signup_notification.text.html.rhtml) + comment(# * signup_notification.text.xml.rxml) + comment(# * signup_notification.text.x-yaml.rhtml) + comment(# ) + comment(# Each would be rendered and added as a separate part to the message,) + comment(# with the corresponding content type. The same body hash is passed to) + comment(# each template.) + comment(#) + comment(# = Attachments) + comment(# Attachments can be added by using the +attachment+ method.) + comment(#) + comment(# Example:) + comment(#) + comment(# class ApplicationMailer < ActionMailer::Base) + comment(# # attachments) + comment(# def signup_notification(recipient\)) + comment(# recipients recipient.email_address_with_name) + comment(# subject "New account information") + comment(# from "system@example.com") + comment(#) + comment(# attachment :content_type => "image/jpeg",) + comment(# :body => File.read("an-image.jpg"\)) + comment(#) + comment(# attachment "application/pdf" do |a|) + comment(# a.body = generate_your_pdf_here(\)) + comment(# end) + comment(# end) + comment(# end ) + comment(#) + comment(# = Configuration options) + comment(#) + comment(# These options are specified on the class level, like <tt>ActionMailer::Base.template_root = "/my/templates"</tt>) + comment(#) + comment(# * <tt>template_root</tt> - template root determines the base from which template references will be made.) + comment(#) + comment(# * <tt>logger</tt> - the logger is used for generating information on the mailing run if available.) + comment(# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.) + comment(#) + comment(# * <tt>server_settings</tt> - Allows detailed configuration of the server:) + comment(# * <tt>:address</tt> Allows you to use a remote mail server. Just change it from its default "localhost" setting.) + comment(# * <tt>:port</tt> On the off chance that your mail server doesn't run on port 25, you can change it.) + comment(# * <tt>:domain</tt> If you need to specify a HELO domain, you can do it here.) + comment(# * <tt>:user_name</tt> If your mail server requires authentication, set the username in this setting.) + comment(# * <tt>:password</tt> If your mail server requires authentication, set the password in this setting.) + comment(# * <tt>:authentication</tt> If your mail server requires authentication, you need to specify the authentication type here. ) + comment(# This is a symbol and one of :plain, :login, :cram_md5) + comment(#) + comment(# * <tt>raise_delivery_errors</tt> - whether or not errors should be raised if the email fails to be delivered.) + comment(#) + comment(# * <tt>delivery_method</tt> - Defines a delivery method. Possible values are :smtp (default\), :sendmail, and :test.) + comment(# Sendmail is assumed to be present at "/usr/sbin/sendmail".) + comment(#) + comment(# * <tt>perform_deliveries</tt> - Determines whether deliver_* methods are actually carried out. By default they are,) + comment(# but this can be turned off to help functional testing.) + comment(#) + comment(# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful) + comment(# for unit and functional testing.) + comment(#) + comment(# * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also ) + comment(# pick a different charset from inside a method with <tt>@charset</tt>.) + comment(# * <tt>default_content_type</tt> - The default content type used for the main part of the message. Defaults to "text/plain". You) + comment(# can also pick a different content type from inside a method with <tt>@content_type</tt>. ) + comment(# * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to nil. You) + comment(# can also pick a different value from inside a method with <tt>@mime_version</tt>. When multipart messages are in) + comment(# use, <tt>@mime_version</tt> will be set to "1.0" if it is not set inside a method.) + comment(# * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates) + comment(# which specify the content type in their filenames\) this variable controls how the parts are ordered. Defaults to) + comment(# ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client) + comment(# and appear last in the mime encoded message. You can also pick a different order from inside a method with) + comment(# <tt>@implicit_parts_order</tt>.) + reserved(class) class(Base) + ident(include) constant(AdvAttrAccessor)operator(,) constant(PartContainer) + + comment(# Action Mailer subclasses should be reloaded by the dispatcher in Rails) + comment(# when Dependencies.mechanism = :load.) + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + ident(private_class_method) symbol(:new) comment(#:nodoc:) + + ident(class_inheritable_accessor) symbol(:template_root) + ident(cattr_accessor) symbol(:logger) + + class_variable(@@server_settings) operator(=) operator({) + symbol(:address) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:port) operator(=)operator(>) integer(25)operator(,) + symbol(:domain) operator(=)operator(>) string<delimiter(')content(localhost.localdomain)delimiter(')>operator(,) + symbol(:user_name) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:password) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:authentication) operator(=)operator(>) pre_constant(nil) + operator(}) + ident(cattr_accessor) symbol(:server_settings) + + class_variable(@@raise_delivery_errors) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:raise_delivery_errors) + + class_variable(@@delivery_method) operator(=) symbol(:smtp) + ident(cattr_accessor) symbol(:delivery_method) + + class_variable(@@perform_deliveries) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:perform_deliveries) + + class_variable(@@deliveries) operator(=) operator([)operator(]) + ident(cattr_accessor) symbol(:deliveries) + + class_variable(@@default_charset) operator(=) string<delimiter(")content(utf-8)delimiter(")> + ident(cattr_accessor) symbol(:default_charset) + + class_variable(@@default_content_type) operator(=) string<delimiter(")content(text/plain)delimiter(")> + ident(cattr_accessor) symbol(:default_content_type) + + class_variable(@@default_mime_version) operator(=) pre_constant(nil) + ident(cattr_accessor) symbol(:default_mime_version) + + class_variable(@@default_implicit_parts_order) operator(=) operator([) string<delimiter(")content(text/html)delimiter(")>operator(,) string<delimiter(")content(text/enriched)delimiter(")>operator(,) string<delimiter(")content(text/plain)delimiter(")> operator(]) + ident(cattr_accessor) symbol(:default_implicit_parts_order) + + comment(# Specify the BCC addresses for the message) + ident(adv_attr_accessor) symbol(:bcc) + + comment(# Define the body of the message. This is either a Hash (in which case it) + comment(# specifies the variables to pass to the template when it is rendered\),) + comment(# or a string, in which case it specifies the actual text of the message.) + ident(adv_attr_accessor) symbol(:body) + + comment(# Specify the CC addresses for the message.) + ident(adv_attr_accessor) symbol(:cc) + + comment(# Specify the charset to use for the message. This defaults to the) + comment(# +default_charset+ specified for ActionMailer::Base.) + ident(adv_attr_accessor) symbol(:charset) + + comment(# Specify the content type for the message. This defaults to <tt>text/plain</tt>) + comment(# in most cases, but can be automatically set in some situations.) + ident(adv_attr_accessor) symbol(:content_type) + + comment(# Specify the from address for the message.) + ident(adv_attr_accessor) symbol(:from) + + comment(# Specify additional headers to be added to the message.) + ident(adv_attr_accessor) symbol(:headers) + + comment(# Specify the order in which parts should be sorted, based on content-type.) + comment(# This defaults to the value for the +default_implicit_parts_order+.) + ident(adv_attr_accessor) symbol(:implicit_parts_order) + + comment(# Override the mailer name, which defaults to an inflected version of the) + comment(# mailer's class name. If you want to use a template in a non-standard) + comment(# location, you can use this to specify that location.) + ident(adv_attr_accessor) symbol(:mailer_name) + + comment(# Defaults to "1.0", but may be explicitly given if needed.) + ident(adv_attr_accessor) symbol(:mime_version) + + comment(# The recipient addresses for the message, either as a string (for a single) + comment(# address\) or an array (for multiple addresses\).) + ident(adv_attr_accessor) symbol(:recipients) + + comment(# The date on which the message was sent. If not set (the default\), the) + comment(# header will be set by the delivery agent.) + ident(adv_attr_accessor) symbol(:sent_on) + + comment(# Specify the subject of the message.) + ident(adv_attr_accessor) symbol(:subject) + + comment(# Specify the template name to use for current message. This is the "base") + comment(# template name, without the extension or directory, and may be used to) + comment(# have multiple mailer methods share the same template.) + ident(adv_attr_accessor) symbol(:template) + + comment(# The mail object instance referenced by this mailer.) + ident(attr_reader) symbol(:mail) + + reserved(class) operator(<<) class(self) + reserved(def) method(method_missing)operator(()ident(method_symbol)operator(,) operator(*)ident(parameters)operator(\))comment(#:nodoc:) + reserved(case) ident(method_symbol)operator(.)ident(id2name) + reserved(when) regexp<delimiter(/)content(^create_([_a-z])char(\\w)content(*\))delimiter(/)> reserved(then) ident(new)operator(()global_variable($1)operator(,) operator(*)ident(parameters)operator(\))operator(.)ident(mail) + reserved(when) regexp<delimiter(/)content(^deliver_([_a-z])char(\\w)content(*\))delimiter(/)> reserved(then) ident(new)operator(()global_variable($1)operator(,) operator(*)ident(parameters)operator(\))operator(.)ident(deliver!) + reserved(when) string<delimiter(")content(new)delimiter(")> reserved(then) pre_constant(nil) + reserved(else) reserved(super) + reserved(end) + reserved(end) + + comment(# Receives a raw email, parses it into an email object, decodes it,) + comment(# instantiates a new mailer, and passes the email object to the mailer) + comment(# object's #receive method. If you want your mailer to be able to) + comment(# process incoming messages, you'll need to implement a #receive) + comment(# method that accepts the email object as a parameter:) + comment(#) + comment(# class MyMailer < ActionMailer::Base) + comment(# def receive(mail\)) + comment(# ...) + comment(# end) + comment(# end) + reserved(def) method(receive)operator(()ident(raw_email)operator(\)) + ident(logger)operator(.)ident(info) string<delimiter(")content(Received mail:)char(\\n)content( )inline<inline_delimiter(#{)ident(raw_email)inline_delimiter(})>delimiter(")> reserved(unless) ident(logger)operator(.)ident(nil?) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(raw_email)operator(\)) + ident(mail)operator(.)ident(base64_decode) + ident(new)operator(.)ident(receive)operator(()ident(mail)operator(\)) + reserved(end) + + comment(# Deliver the given mail object directly. This can be used to deliver) + comment(# a preconstructed mail object, like:) + comment(#) + comment(# email = MyMailer.create_some_mail(parameters\)) + comment(# email.set_some_obscure_header "frobnicate") + comment(# MyMailer.deliver(email\)) + reserved(def) method(deliver)operator(()ident(mail)operator(\)) + ident(new)operator(.)ident(deliver!)operator(()ident(mail)operator(\)) + reserved(end) + reserved(end) + + comment(# Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer) + comment(# will be initialized according to the named method. If not, the mailer will) + comment(# remain uninitialized (useful when you only need to invoke the "receive") + comment(# method, for instance\).) + reserved(def) method(initialize)operator(()ident(method_name)operator(=)pre_constant(nil)operator(,) operator(*)ident(parameters)operator(\)) comment(#:nodoc:) + ident(create!)operator(()ident(method_name)operator(,) operator(*)ident(parameters)operator(\)) reserved(if) ident(method_name) + reserved(end) + + comment(# Initialize the mailer via the given +method_name+. The body will be) + comment(# rendered and a new TMail::Mail object created.) + reserved(def) method(create!)operator(()ident(method_name)operator(,) operator(*)ident(parameters)operator(\)) comment(#:nodoc:) + ident(initialize_defaults)operator(()ident(method_name)operator(\)) + ident(send)operator(()ident(method_name)operator(,) operator(*)ident(parameters)operator(\)) + + comment(# If an explicit, textual body has not been set, we check assumptions.) + reserved(unless) constant(String) operator(===) instance_variable(@body) + comment(# First, we look to see if there are any likely templates that match,) + comment(# which include the content-type in their file name (i.e.,) + comment(# "the_template_file.text.html.rhtml", etc.\). Only do this if parts) + comment(# have not already been specified manually.) + reserved(if) instance_variable(@parts)operator(.)ident(empty?) + ident(templates) operator(=) constant(Dir)operator(.)ident(glob)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(template_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)instance_variable(@template)inline_delimiter(})>content(.*)delimiter(")>operator(\)) + ident(templates)operator(.)ident(each) reserved(do) operator(|)ident(path)operator(|) + comment(# TODO: don't hardcode rhtml|rxml) + ident(basename) operator(=) constant(File)operator(.)ident(basename)operator(()ident(path)operator(\)) + reserved(next) reserved(unless) ident(md) operator(=) regexp<delimiter(/)content(^([^)char(\\.)content(]+\))char(\\.)content(([^)char(\\.)content(]+)char(\\.)content([^)char(\\+)content(]+\))char(\\.)content((rhtml|rxml\)$)delimiter(/)>operator(.)ident(match)operator(()ident(basename)operator(\)) + ident(template_name) operator(=) ident(basename) + ident(content_type) operator(=) ident(md)operator(.)ident(captures)operator([)integer(1)operator(])operator(.)ident(gsub)operator(()string<delimiter(')content(.)delimiter(')>operator(,) string<delimiter(')content(/)delimiter(')>operator(\)) + instance_variable(@parts) operator(<<) constant(Part)operator(.)ident(new)operator(()symbol(:content_type) operator(=)operator(>) ident(content_type)operator(,) + symbol(:disposition) operator(=)operator(>) string<delimiter(")content(inline)delimiter(")>operator(,) symbol(:charset) operator(=)operator(>) ident(charset)operator(,) + symbol(:body) operator(=)operator(>) ident(render_message)operator(()ident(template_name)operator(,) instance_variable(@body)operator(\))operator(\)) + reserved(end) + reserved(unless) instance_variable(@parts)operator(.)ident(empty?) + instance_variable(@content_type) operator(=) string<delimiter(")content(multipart/alternative)delimiter(")> + instance_variable(@parts) operator(=) ident(sort_parts)operator(()instance_variable(@parts)operator(,) instance_variable(@implicit_parts_order)operator(\)) + reserved(end) + reserved(end) + + comment(# Then, if there were such templates, we check to see if we ought to) + comment(# also render a "normal" template (without the content type\). If a) + comment(# normal template exists (or if there were no implicit parts\) we render) + comment(# it.) + ident(template_exists) operator(=) instance_variable(@parts)operator(.)ident(empty?) + ident(template_exists) operator(||=) constant(Dir)operator(.)ident(glob)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(template_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)instance_variable(@template)inline_delimiter(})>content(.*)delimiter(")>operator(\))operator(.)ident(any?) operator({) operator(|)ident(i)operator(|) constant(File)operator(.)ident(basename)operator(()ident(i)operator(\))operator(.)ident(split)operator(()string<delimiter(")content(.)delimiter(")>operator(\))operator(.)ident(length) operator(==) integer(2) operator(}) + instance_variable(@body) operator(=) ident(render_message)operator(()instance_variable(@template)operator(,) instance_variable(@body)operator(\)) reserved(if) ident(template_exists) + + comment(# Finally, if there are other message parts and a textual body exists,) + comment(# we shift it onto the front of the parts and set the body to nil (so) + comment(# that create_mail doesn't try to render it in addition to the parts\).) + reserved(if) operator(!)instance_variable(@parts)operator(.)ident(empty?) operator(&&) constant(String) operator(===) instance_variable(@body) + instance_variable(@parts)operator(.)ident(unshift) constant(Part)operator(.)ident(new)operator(()symbol(:charset) operator(=)operator(>) ident(charset)operator(,) symbol(:body) operator(=)operator(>) instance_variable(@body)operator(\)) + instance_variable(@body) operator(=) pre_constant(nil) + reserved(end) + reserved(end) + + comment(# If this is a multipart e-mail add the mime_version if it is not) + comment(# already set.) + instance_variable(@mime_version) operator(||=) string<delimiter(")content(1.0)delimiter(")> reserved(if) operator(!)instance_variable(@parts)operator(.)ident(empty?) + + comment(# build the mail object itself) + instance_variable(@mail) operator(=) ident(create_mail) + reserved(end) + + comment(# Delivers a TMail::Mail object. By default, it delivers the cached mail) + comment(# object (from the #create! method\). If no cached mail object exists, and) + comment(# no alternate has been given as the parameter, this will fail.) + reserved(def) method(deliver!)operator(()ident(mail) operator(=) instance_variable(@mail)operator(\)) + ident(raise) string<delimiter(")content(no mail object available for delivery!)delimiter(")> reserved(unless) ident(mail) + ident(logger)operator(.)ident(info) string<delimiter(")content(Sent mail:)char(\\n)content( )inline<inline_delimiter(#{)ident(mail)operator(.)ident(encoded)inline_delimiter(})>delimiter(")> reserved(unless) ident(logger)operator(.)ident(nil?) + + reserved(begin) + ident(send)operator(()string<delimiter(")content(perform_delivery_)inline<inline_delimiter(#{)ident(delivery_method)inline_delimiter(})>delimiter(")>operator(,) ident(mail)operator(\)) reserved(if) ident(perform_deliveries) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + ident(raise) ident(e) reserved(if) ident(raise_delivery_errors) + reserved(end) + + reserved(return) ident(mail) + reserved(end) + + ident(private) + comment(# Set up the default values for the various instance variables of this) + comment(# mailer. Subclasses may override this method to provide different) + comment(# defaults.) + reserved(def) method(initialize_defaults)operator(()ident(method_name)operator(\)) + instance_variable(@charset) operator(||=) class_variable(@@default_charset)operator(.)ident(dup) + instance_variable(@content_type) operator(||=) class_variable(@@default_content_type)operator(.)ident(dup) + instance_variable(@implicit_parts_order) operator(||=) class_variable(@@default_implicit_parts_order)operator(.)ident(dup) + instance_variable(@template) operator(||=) ident(method_name) + instance_variable(@mailer_name) operator(||=) constant(Inflector)operator(.)ident(underscore)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(name)operator(\)) + instance_variable(@parts) operator(||=) operator([)operator(]) + instance_variable(@headers) operator(||=) operator({)operator(}) + instance_variable(@body) operator(||=) operator({)operator(}) + instance_variable(@mime_version) operator(=) class_variable(@@default_mime_version)operator(.)ident(dup) reserved(if) class_variable(@@default_mime_version) + reserved(end) + + reserved(def) method(render_message)operator(()ident(method_name)operator(,) ident(body)operator(\)) + ident(render) symbol(:file) operator(=)operator(>) ident(method_name)operator(,) symbol(:body) operator(=)operator(>) ident(body) + reserved(end) + + reserved(def) method(render)operator(()ident(opts)operator(\)) + ident(body) operator(=) ident(opts)operator(.)ident(delete)operator(()symbol(:body)operator(\)) + ident(initialize_template_class)operator(()ident(body)operator(\))operator(.)ident(render)operator(()ident(opts)operator(\)) + reserved(end) + + reserved(def) method(template_path) + string<delimiter(")inline<inline_delimiter(#{)ident(template_root)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(mailer_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(initialize_template_class)operator(()ident(assigns)operator(\)) + constant(ActionView)operator(::)constant(Base)operator(.)ident(new)operator(()ident(template_path)operator(,) ident(assigns)operator(,) pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(sort_parts)operator(()ident(parts)operator(,) ident(order) operator(=) operator([)operator(])operator(\)) + ident(order) operator(=) ident(order)operator(.)ident(collect) operator({) operator(|)ident(s)operator(|) ident(s)operator(.)ident(downcase) operator(}) + + ident(parts) operator(=) ident(parts)operator(.)ident(sort) reserved(do) operator(|)ident(a)operator(,) ident(b)operator(|) + ident(a_ct) operator(=) ident(a)operator(.)ident(content_type)operator(.)ident(downcase) + ident(b_ct) operator(=) ident(b)operator(.)ident(content_type)operator(.)ident(downcase) + + ident(a_in) operator(=) ident(order)operator(.)ident(include?) ident(a_ct) + ident(b_in) operator(=) ident(order)operator(.)ident(include?) ident(b_ct) + + ident(s) operator(=) reserved(case) + reserved(when) ident(a_in) operator(&&) ident(b_in) + ident(order)operator(.)ident(index)operator(()ident(a_ct)operator(\)) operator(<=>) ident(order)operator(.)ident(index)operator(()ident(b_ct)operator(\)) + reserved(when) ident(a_in) + integer(-1) + reserved(when) ident(b_in) + integer(1) + reserved(else) + ident(a_ct) operator(<=>) ident(b_ct) + reserved(end) + + comment(# reverse the ordering because parts that come last are displayed) + comment(# first in mail clients) + operator(()ident(s) operator(*) integer(-1)operator(\)) + reserved(end) + + ident(parts) + reserved(end) + + reserved(def) method(create_mail) + ident(m) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + + ident(m)operator(.)ident(subject)operator(,) operator(=) ident(quote_any_if_necessary)operator(()ident(charset)operator(,) ident(subject)operator(\)) + ident(m)operator(.)ident(to)operator(,) ident(m)operator(.)ident(from) operator(=) ident(quote_any_address_if_necessary)operator(()ident(charset)operator(,) ident(recipients)operator(,) ident(from)operator(\)) + ident(m)operator(.)ident(bcc) operator(=) ident(quote_address_if_necessary)operator(()ident(bcc)operator(,) ident(charset)operator(\)) reserved(unless) ident(bcc)operator(.)ident(nil?) + ident(m)operator(.)ident(cc) operator(=) ident(quote_address_if_necessary)operator(()ident(cc)operator(,) ident(charset)operator(\)) reserved(unless) ident(cc)operator(.)ident(nil?) + + ident(m)operator(.)ident(mime_version) operator(=) ident(mime_version) reserved(unless) ident(mime_version)operator(.)ident(nil?) + ident(m)operator(.)ident(date) operator(=) ident(sent_on)operator(.)ident(to_time) reserved(rescue) ident(sent_on) reserved(if) ident(sent_on) + ident(headers)operator(.)ident(each) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(m)operator([)ident(k)operator(]) operator(=) ident(v) operator(}) + + ident(real_content_type)operator(,) ident(ctype_attrs) operator(=) ident(parse_content_type) + + reserved(if) instance_variable(@parts)operator(.)ident(empty?) + ident(m)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) ident(ctype_attrs)operator(\)) + ident(m)operator(.)ident(body) operator(=) constant(Utils)operator(.)ident(normalize_new_lines)operator(()ident(body)operator(\)) + reserved(else) + reserved(if) constant(String) operator(===) ident(body) + ident(part) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + ident(part)operator(.)ident(body) operator(=) constant(Utils)operator(.)ident(normalize_new_lines)operator(()ident(body)operator(\)) + ident(part)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) ident(ctype_attrs)operator(\)) + ident(part)operator(.)ident(set_content_disposition) string<delimiter(")content(inline)delimiter(")> + ident(m)operator(.)ident(parts) operator(<<) ident(part) + reserved(end) + + instance_variable(@parts)operator(.)ident(each) reserved(do) operator(|)ident(p)operator(|) + ident(part) operator(=) operator(()constant(TMail)operator(::)constant(Mail) operator(===) ident(p) operator(?) ident(p) operator(:) ident(p)operator(.)ident(to_mail)operator(()pre_constant(self)operator(\))operator(\)) + ident(m)operator(.)ident(parts) operator(<<) ident(part) + reserved(end) + + reserved(if) ident(real_content_type) operator(=)operator(~) regexp<delimiter(/)content(multipart)delimiter(/)> + ident(ctype_attrs)operator(.)ident(delete) string<delimiter(")content(charset)delimiter(")> + ident(m)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) ident(ctype_attrs)operator(\)) + reserved(end) + reserved(end) + + instance_variable(@mail) operator(=) ident(m) + reserved(end) + + reserved(def) method(perform_delivery_smtp)operator(()ident(mail)operator(\)) + ident(destinations) operator(=) ident(mail)operator(.)ident(destinations) + ident(mail)operator(.)ident(ready_to_send) + + constant(Net)operator(::)constant(SMTP)operator(.)ident(start)operator(()ident(server_settings)operator([)symbol(:address)operator(])operator(,) ident(server_settings)operator([)symbol(:port)operator(])operator(,) ident(server_settings)operator([)symbol(:domain)operator(])operator(,) + ident(server_settings)operator([)symbol(:user_name)operator(])operator(,) ident(server_settings)operator([)symbol(:password)operator(])operator(,) ident(server_settings)operator([)symbol(:authentication)operator(])operator(\)) reserved(do) operator(|)ident(smtp)operator(|) + ident(smtp)operator(.)ident(sendmail)operator(()ident(mail)operator(.)ident(encoded)operator(,) ident(mail)operator(.)ident(from)operator(,) ident(destinations)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(perform_delivery_sendmail)operator(()ident(mail)operator(\)) + constant(IO)operator(.)ident(popen)operator(()string<delimiter(")content(/usr/sbin/sendmail -i -t)delimiter(")>operator(,)string<delimiter(")content(w+)delimiter(")>operator(\)) reserved(do) operator(|)ident(sm)operator(|) + ident(sm)operator(.)ident(print)operator(()ident(mail)operator(.)ident(encoded)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\r)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(\)) + ident(sm)operator(.)ident(flush) + reserved(end) + reserved(end) + + reserved(def) method(perform_delivery_test)operator(()ident(mail)operator(\)) + ident(deliveries) operator(<<) ident(mail) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionMailer) + reserved(module) class(Helpers) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + + comment(# Initialize the base module to aggregate its helpers.) + ident(base)operator(.)ident(class_inheritable_accessor) symbol(:master_helper_module) + ident(base)operator(.)ident(master_helper_module) operator(=) constant(Module)operator(.)ident(new) + + comment(# Extend base with class methods to declare helpers.) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + + ident(base)operator(.)ident(class_eval) reserved(do) + comment(# Wrap inherited to create a new master helper module for subclasses.) + reserved(class) operator(<<) class(self) + ident(alias_method) symbol(:inherited_without_helper)operator(,) symbol(:inherited) + ident(alias_method) symbol(:inherited)operator(,) symbol(:inherited_with_helper) + reserved(end) + + comment(# Wrap initialize_template_class to extend new template class) + comment(# instances with the master helper module.) + ident(alias_method) symbol(:initialize_template_class_without_helper)operator(,) symbol(:initialize_template_class) + ident(alias_method) symbol(:initialize_template_class)operator(,) symbol(:initialize_template_class_with_helper) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Makes all the (instance\) methods in the helper module available to templates rendered through this controller.) + comment(# See ActionView::Helpers (link:classes/ActionView/Helpers.html\) for more about making your own helper modules ) + comment(# available to the templates.) + reserved(def) method(add_template_helper)operator(()ident(helper_module)operator(\)) comment(#:nodoc:) + ident(master_helper_module)operator(.)ident(module_eval) string<delimiter(")content(include )inline<inline_delimiter(#{)ident(helper_module)inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Declare a helper:) + comment(# helper :foo) + comment(# requires 'foo_helper' and includes FooHelper in the template class.) + comment(# helper FooHelper) + comment(# includes FooHelper in the template class.) + comment(# helper { def foo(\) "#{bar} is the very best" end }) + comment(# evaluates the block in the template class, adding method #foo.) + comment(# helper(:three, BlindHelper\) { def mice(\) 'mice' end }) + comment(# does all three.) + reserved(def) method(helper)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(args)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(arg)operator(|) + reserved(case) ident(arg) + reserved(when) constant(Module) + ident(add_template_helper)operator(()ident(arg)operator(\)) + reserved(when) constant(String)operator(,) constant(Symbol) + ident(file_name) operator(=) ident(arg)operator(.)ident(to_s)operator(.)ident(underscore) operator(+) string<delimiter(')content(_helper)delimiter(')> + ident(class_name) operator(=) ident(file_name)operator(.)ident(camelize) + + reserved(begin) + ident(require_dependency)operator(()ident(file_name)operator(\)) + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(load_error) + ident(requiree) operator(=) regexp<delimiter(/)content( -- (.*?\)()char(\\.)content(rb\)?$)delimiter(/)>operator(.)ident(match)operator(()ident(load_error)operator(\))operator(.)ident(to_a)operator([)integer(1)operator(]) + ident(msg) operator(=) operator(()ident(requiree) operator(==) ident(file_name)operator(\)) operator(?) string<delimiter(")content(Missing helper file helpers/)inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>content(.rb)delimiter(")> operator(:) string<delimiter(")content(Can't load file: )inline<inline_delimiter(#{)ident(requiree)inline_delimiter(})>delimiter(")> + ident(raise) constant(LoadError)operator(.)ident(new)operator(()ident(msg)operator(\))operator(.)ident(copy_blame!)operator(()ident(load_error)operator(\)) + reserved(end) + + ident(add_template_helper)operator(()ident(class_name)operator(.)ident(constantize)operator(\)) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(helper expects String, Symbol, or Module argument)delimiter(')> + reserved(end) + reserved(end) + + comment(# Evaluate block in template class if given.) + ident(master_helper_module)operator(.)ident(module_eval)operator(()operator(&)ident(block)operator(\)) reserved(if) ident(block_given?) + reserved(end) + + comment(# Declare a controller method as a helper. For example,) + comment(# helper_method :link_to) + comment(# def link_to(name, options\) ... end) + comment(# makes the link_to controller method available in the view.) + reserved(def) method(helper_method)operator(()operator(*)ident(methods)operator(\)) + ident(methods)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(master_helper_module)operator(.)ident(module_eval) string<delimiter(<<-end_eval)>string<content( + def )inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content((*args, &block\) + controller.send(%()inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(\), *args, &block\) + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + + comment(# Declare a controller attribute as a helper. For example,) + comment(# helper_attr :name) + comment(# attr_accessor :name) + comment(# makes the name and name= controller methods available in the view.) + comment(# The is a convenience wrapper for helper_method.) + reserved(def) method(helper_attr)operator(()operator(*)ident(attrs)operator(\)) + ident(attrs)operator(.)ident(flatten)operator(.)ident(each) operator({) operator(|)ident(attr)operator(|) ident(helper_method)operator(()ident(attr)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(attr)inline_delimiter(})>content(=)delimiter(")>operator(\)) operator(}) + reserved(end) + + ident(private) + reserved(def) method(inherited_with_helper)operator(()ident(child)operator(\)) + ident(inherited_without_helper)operator(()ident(child)operator(\)) + reserved(begin) + ident(child)operator(.)ident(master_helper_module) operator(=) constant(Module)operator(.)ident(new) + ident(child)operator(.)ident(master_helper_module)operator(.)ident(send) symbol(:include)operator(,) ident(master_helper_module) + ident(child)operator(.)ident(helper) ident(child)operator(.)ident(name)operator(.)ident(underscore) + reserved(rescue) constant(MissingSourceFile) operator(=)operator(>) ident(e) + ident(raise) reserved(unless) ident(e)operator(.)ident(is_missing?)operator(()string<delimiter(")content(helpers/)inline<inline_delimiter(#{)ident(child)operator(.)ident(name)operator(.)ident(underscore)inline_delimiter(})>content(_helper)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + comment(# Extend the template class instance with our controller's helper module.) + reserved(def) method(initialize_template_class_with_helper)operator(()ident(assigns)operator(\)) + ident(returning)operator(()ident(template) operator(=) ident(initialize_template_class_without_helper)operator(()ident(assigns)operator(\))operator(\)) reserved(do) + ident(template)operator(.)ident(extend) pre_constant(self)operator(.)ident(class)operator(.)ident(master_helper_module) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) string<delimiter(')content(text/format)delimiter(')> + +reserved(module) class(MailHelper) + comment(# Uses Text::Format to take the text and format it, indented two spaces for) + comment(# each line, and wrapped at 72 columns.) + reserved(def) method(block_format)operator(()ident(text)operator(\)) + ident(formatted) operator(=) ident(text)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\n)char(\\r)char(\\n)delimiter(/)>operator(\))operator(.)ident(collect) operator({) operator(|)ident(paragraph)operator(|) + constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(() + symbol(:columns) operator(=)operator(>) integer(72)operator(,) symbol(:first_indent) operator(=)operator(>) integer(2)operator(,) symbol(:body_indent) operator(=)operator(>) integer(2)operator(,) symbol(:text) operator(=)operator(>) ident(paragraph) + operator(\))operator(.)ident(format) + operator(})operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + + comment(# Make list points stand on their own line) + ident(formatted)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content([ ]*([*]+\) ([^*]*\))delimiter(/)>operator(\)) operator({) operator(|)ident(s)operator(|) string<delimiter(")content( )inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content( )inline<inline_delimiter(#{)global_variable($2)operator(.)ident(strip)inline_delimiter(})>char(\\n)delimiter(")> operator(}) + ident(formatted)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content([ ]*([#]+\) ([^#]*\))delimiter(/)>operator(\)) operator({) operator(|)ident(s)operator(|) string<delimiter(")content( )inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content( )inline<inline_delimiter(#{)global_variable($2)operator(.)ident(strip)inline_delimiter(})>char(\\n)delimiter(")> operator(}) + + ident(formatted) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_mailer/adv_attr_accessor)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/part_container)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/utils)delimiter(')> + +reserved(module) class(ActionMailer) + comment(# Represents a subpart of an email message. It shares many similar) + comment(# attributes of ActionMailer::Base. Although you can create parts manually) + comment(# and add them to the #parts list of the mailer, it is easier) + comment(# to use the helper methods in ActionMailer::PartContainer.) + reserved(class) class(Part) + ident(include) constant(ActionMailer)operator(::)constant(AdvAttrAccessor) + ident(include) constant(ActionMailer)operator(::)constant(PartContainer) + + comment(# Represents the body of the part, as a string. This should not be a) + comment(# Hash (like ActionMailer::Base\), but if you want a template to be rendered) + comment(# into the body of a subpart you can do it with the mailer's #render method) + comment(# and assign the result here.) + ident(adv_attr_accessor) symbol(:body) + + comment(# Specify the charset for this subpart. By default, it will be the charset) + comment(# of the containing part or mailer.) + ident(adv_attr_accessor) symbol(:charset) + + comment(# The content disposition of this part, typically either "inline" or) + comment(# "attachment".) + ident(adv_attr_accessor) symbol(:content_disposition) + + comment(# The content type of the part.) + ident(adv_attr_accessor) symbol(:content_type) + + comment(# The filename to use for this subpart (usually for attachments\).) + ident(adv_attr_accessor) symbol(:filename) + + comment(# Accessor for specifying additional headers to include with this part.) + ident(adv_attr_accessor) symbol(:headers) + + comment(# The transfer encoding to use for this subpart, like "base64" or) + comment(# "quoted-printable".) + ident(adv_attr_accessor) symbol(:transfer_encoding) + + comment(# Create a new part from the given +params+ hash. The valid params keys) + comment(# correspond to the accessors.) + reserved(def) method(initialize)operator(()ident(params)operator(\)) + instance_variable(@content_type) operator(=) ident(params)operator([)symbol(:content_type)operator(]) + instance_variable(@content_disposition) operator(=) ident(params)operator([)symbol(:disposition)operator(]) operator(||) string<delimiter(")content(inline)delimiter(")> + instance_variable(@charset) operator(=) ident(params)operator([)symbol(:charset)operator(]) + instance_variable(@body) operator(=) ident(params)operator([)symbol(:body)operator(]) + instance_variable(@filename) operator(=) ident(params)operator([)symbol(:filename)operator(]) + instance_variable(@transfer_encoding) operator(=) ident(params)operator([)symbol(:transfer_encoding)operator(]) operator(||) string<delimiter(")content(quoted-printable)delimiter(")> + instance_variable(@headers) operator(=) ident(params)operator([)symbol(:headers)operator(]) operator(||) operator({)operator(}) + instance_variable(@parts) operator(=) operator([)operator(]) + reserved(end) + + comment(# Convert the part to a mail object which can be included in the parts) + comment(# list of another mail object.) + reserved(def) method(to_mail)operator(()ident(defaults)operator(\)) + ident(part) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + + ident(real_content_type)operator(,) ident(ctype_attrs) operator(=) ident(parse_content_type)operator(()ident(defaults)operator(\)) + + reserved(if) instance_variable(@parts)operator(.)ident(empty?) + ident(part)operator(.)ident(content_transfer_encoding) operator(=) ident(transfer_encoding) operator(||) string<delimiter(")content(quoted-printable)delimiter(")> + reserved(case) operator(()ident(transfer_encoding) operator(||) string<delimiter(")delimiter(")>operator(\))operator(.)ident(downcase) + reserved(when) string<delimiter(")content(base64)delimiter(")> reserved(then) + ident(part)operator(.)ident(body) operator(=) constant(TMail)operator(::)constant(Base64)operator(.)ident(folding_encode)operator(()ident(body)operator(\)) + reserved(when) string<delimiter(")content(quoted-printable)delimiter(")> + ident(part)operator(.)ident(body) operator(=) operator([)constant(Utils)operator(.)ident(normalize_new_lines)operator(()ident(body)operator(\))operator(])operator(.)ident(pack)operator(()string<delimiter(")content(M*)delimiter(")>operator(\)) + reserved(else) + ident(part)operator(.)ident(body) operator(=) ident(body) + reserved(end) + + comment(# Always set the content_type after setting the body and or parts!) + comment(# Also don't set filename and name when there is none (like in) + comment(# non-attachment parts\)) + reserved(if) ident(content_disposition) operator(==) string<delimiter(")content(attachment)delimiter(")> + ident(ctype_attrs)operator(.)ident(delete) string<delimiter(")content(charset)delimiter(")> + ident(part)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) + ident(squish)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(filename)operator(\))operator(.)ident(merge)operator(()ident(ctype_attrs)operator(\))operator(\)) + ident(part)operator(.)ident(set_content_disposition)operator(()ident(content_disposition)operator(,) + ident(squish)operator(()string<delimiter(")content(filename)delimiter(")> operator(=)operator(>) ident(filename)operator(\))operator(.)ident(merge)operator(()ident(ctype_attrs)operator(\))operator(\)) + reserved(else) + ident(part)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) ident(ctype_attrs)operator(\)) + ident(part)operator(.)ident(set_content_disposition)operator(()ident(content_disposition)operator(\)) + reserved(end) + reserved(else) + reserved(if) constant(String) operator(===) ident(body) + ident(part) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + ident(part)operator(.)ident(body) operator(=) ident(body) + ident(part)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) ident(ctype_attrs)operator(\)) + ident(part)operator(.)ident(set_content_disposition) string<delimiter(")content(inline)delimiter(")> + ident(m)operator(.)ident(parts) operator(<<) ident(part) + reserved(end) + + instance_variable(@parts)operator(.)ident(each) reserved(do) operator(|)ident(p)operator(|) + ident(prt) operator(=) operator(()constant(TMail)operator(::)constant(Mail) operator(===) ident(p) operator(?) ident(p) operator(:) ident(p)operator(.)ident(to_mail)operator(()ident(defaults)operator(\))operator(\)) + ident(part)operator(.)ident(parts) operator(<<) ident(prt) + reserved(end) + + ident(part)operator(.)ident(set_content_type)operator(()ident(real_content_type)operator(,) pre_constant(nil)operator(,) ident(ctype_attrs)operator(\)) reserved(if) ident(real_content_type) operator(=)operator(~) regexp<delimiter(/)content(multipart)delimiter(/)> + reserved(end) + + ident(headers)operator(.)ident(each) operator({) operator(|)ident(k)operator(,)ident(v)operator(|) ident(part)operator([)ident(k)operator(]) operator(=) ident(v) operator(}) + + ident(part) + reserved(end) + + ident(private) + + reserved(def) method(squish)operator(()ident(values)operator(=)operator({)operator(})operator(\)) + ident(values)operator(.)ident(delete_if) operator({) operator(|)ident(k)operator(,)ident(v)operator(|) ident(v)operator(.)ident(nil?) operator(}) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionMailer) + comment(# Accessors and helpers that ActionMailer::Base and ActionMailer::Part have) + comment(# in common. Using these helpers you can easily add subparts or attachments) + comment(# to your message:) + comment(#) + comment(# def my_mail_message(...\)) + comment(# ...) + comment(# part "text/plain" do |p|) + comment(# p.body "hello, world") + comment(# p.transfer_encoding "base64") + comment(# end) + comment(#) + comment(# attachment "image/jpg" do |a|) + comment(# a.body = File.read("hello.jpg"\)) + comment(# a.filename = "hello.jpg") + comment(# end) + comment(# end) + reserved(module) class(PartContainer) + comment(# The list of subparts of this container) + ident(attr_reader) symbol(:parts) + + comment(# Add a part to a multipart message, with the given content-type. The) + comment(# part itself is yielded to the block so that other properties (charset,) + comment(# body, headers, etc.\) can be set on it.) + reserved(def) method(part)operator(()ident(params)operator(\)) + ident(params) operator(=) operator({)symbol(:content_type) operator(=)operator(>) ident(params)operator(}) reserved(if) constant(String) operator(===) ident(params) + ident(part) operator(=) constant(Part)operator(.)ident(new)operator(()ident(params)operator(\)) + reserved(yield) ident(part) reserved(if) ident(block_given?) + instance_variable(@parts) operator(<<) ident(part) + reserved(end) + + comment(# Add an attachment to a multipart message. This is simply a part with the) + comment(# content-disposition set to "attachment".) + reserved(def) method(attachment)operator(()ident(params)operator(,) operator(&)ident(block)operator(\)) + ident(params) operator(=) operator({) symbol(:content_type) operator(=)operator(>) ident(params) operator(}) reserved(if) constant(String) operator(===) ident(params) + ident(params) operator(=) operator({) symbol(:disposition) operator(=)operator(>) string<delimiter(")content(attachment)delimiter(")>operator(,) + symbol(:transfer_encoding) operator(=)operator(>) string<delimiter(")content(base64)delimiter(")> operator(})operator(.)ident(merge)operator(()ident(params)operator(\)) + ident(part)operator(()ident(params)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + ident(private) + + reserved(def) method(parse_content_type)operator(()ident(defaults)operator(=)pre_constant(nil)operator(\)) + reserved(return) operator([)ident(defaults) operator(&&) ident(defaults)operator(.)ident(content_type)operator(,) operator({)operator(})operator(]) reserved(if) ident(content_type)operator(.)ident(blank?) + ident(ctype)operator(,) operator(*)ident(attrs) operator(=) ident(content_type)operator(.)ident(split)operator(()regexp<delimiter(/)content(;)char(\\s)content(*)delimiter(/)>operator(\)) + ident(attrs) operator(=) ident(attrs)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(h)operator(,)ident(s)operator(|) ident(k)operator(,)ident(v) operator(=) ident(s)operator(.)ident(split)operator(()regexp<delimiter(/)content(=)delimiter(/)>operator(,) integer(2)operator(\))operator(;) ident(h)operator([)ident(k)operator(]) operator(=) ident(v)operator(;) ident(h) operator(}) + operator([)ident(ctype)operator(,) operator({)string<delimiter(")content(charset)delimiter(")> operator(=)operator(>) ident(charset) operator(||) ident(defaults) operator(&&) ident(defaults)operator(.)ident(charset)operator(})operator(.)ident(merge)operator(()ident(attrs)operator(\))operator(]) + reserved(end) + + reserved(end) +reserved(end) +reserved(module) class(ActionMailer) + reserved(module) class(Quoting) comment(#:nodoc:) + comment(# Convert the given text into quoted printable format, with an instruction) + comment(# that the text be eventually interpreted in the given charset.) + reserved(def) method(quoted_printable)operator(()ident(text)operator(,) ident(charset)operator(\)) + ident(text) operator(=) ident(text)operator(.)ident(gsub)operator(() regexp<delimiter(/)content([^a-z ])delimiter(/)modifier(i)> operator(\)) operator({) ident(quoted_printable_encode)operator(()global_variable($&)operator(\)) operator(})operator(.) + ident(gsub)operator(() regexp<delimiter(/)content( )delimiter(/)>operator(,) string<delimiter(")content(_)delimiter(")> operator(\)) + string<delimiter(")content(=?)inline<inline_delimiter(#{)ident(charset)inline_delimiter(})>content(?Q?)inline<inline_delimiter(#{)ident(text)inline_delimiter(})>content(?=)delimiter(")> + reserved(end) + + comment(# Convert the given character to quoted printable format, taking into) + comment(# account multi-byte characters (if executing with $KCODE="u", for instance\)) + reserved(def) method(quoted_printable_encode)operator(()ident(character)operator(\)) + ident(result) operator(=) string<delimiter(")delimiter(")> + ident(character)operator(.)ident(each_byte) operator({) operator(|)ident(b)operator(|) ident(result) operator(<<) string<delimiter(")content(=%02x)delimiter(")> operator(%) ident(b) operator(}) + ident(result) + reserved(end) + + comment(# A quick-and-dirty regexp for determining whether a string contains any) + comment(# characters that need escaping.) + reserved(if) operator(!)reserved(defined?)operator(()constant(CHARS_NEEDING_QUOTING)operator(\)) + constant(CHARS_NEEDING_QUOTING) operator(=) regexp<delimiter(/)content([)char(\\000)content(-)char(\\011)char(\\013)char(\\014)char(\\016)content(-)char(\\037)char(\\177)content(-)char(\\377)content(])delimiter(/)> + reserved(end) + + comment(# Quote the given text if it contains any "illegal" characters) + reserved(def) method(quote_if_necessary)operator(()ident(text)operator(,) ident(charset)operator(\)) + operator(()ident(text) operator(=)operator(~) constant(CHARS_NEEDING_QUOTING)operator(\)) operator(?) + ident(quoted_printable)operator(()ident(text)operator(,) ident(charset)operator(\)) operator(:) + ident(text) + reserved(end) + + comment(# Quote any of the given strings if they contain any "illegal" characters) + reserved(def) method(quote_any_if_necessary)operator(()ident(charset)operator(,) operator(*)ident(args)operator(\)) + ident(args)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) ident(quote_if_necessary)operator(()ident(v)operator(,) ident(charset)operator(\)) operator(}) + reserved(end) + + comment(# Quote the given address if it needs to be. The address may be a) + comment(# regular email address, or it can be a phrase followed by an address in) + comment(# brackets. The phrase is the only part that will be quoted, and only if) + comment(# it needs to be. This allows extended characters to be used in the) + comment(# "to", "from", "cc", and "bcc" headers.) + reserved(def) method(quote_address_if_necessary)operator(()ident(address)operator(,) ident(charset)operator(\)) + reserved(if) constant(Array) operator(===) ident(address) + ident(address)operator(.)ident(map) operator({) operator(|)ident(a)operator(|) ident(quote_address_if_necessary)operator(()ident(a)operator(,) ident(charset)operator(\)) operator(}) + reserved(elsif) ident(address) operator(=)operator(~) regexp<delimiter(/)content(^()char(\\S)content(.*\))char(\\s)content(+(<.*>\)$)delimiter(/)> + ident(address) operator(=) global_variable($2) + ident(phrase) operator(=) ident(quote_if_necessary)operator(()global_variable($1)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(^['"](.*\)['"]$)delimiter(/)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\))operator(,) ident(charset)operator(\)) + string<delimiter(")char(\\")inline<inline_delimiter(#{)ident(phrase)inline_delimiter(})>char(\\")content( )inline<inline_delimiter(#{)ident(address)inline_delimiter(})>delimiter(")> + reserved(else) + ident(address) + reserved(end) + reserved(end) + + comment(# Quote any of the given addresses, if they need to be.) + reserved(def) method(quote_any_address_if_necessary)operator(()ident(charset)operator(,) operator(*)ident(args)operator(\)) + ident(args)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) ident(quote_address_if_necessary)operator(()ident(v)operator(,) ident(charset)operator(\)) operator(}) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionMailer) + reserved(module) class(Utils) comment(#:nodoc:) + reserved(def) method(normalize_new_lines)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\r)char(\\n)content(?)delimiter(/)>operator(,) string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + ident(module_function) symbol(:normalize_new_lines) + reserved(end) +reserved(end) +comment(#--) +comment(# Text::Format for Ruby) +comment(# Version 0.63) +comment(#) +comment(# Copyright (c\) 2002 - 2003 Austin Ziegler) +comment(#) +comment(# $Id: format.rb,v 1.1.1.1 2004/10/14 11:59:57 webster132 Exp $) +comment(#) +comment(# ==========================================================================) +comment(# Revision History ::) +comment(# YYYY.MM.DD Change ID Developer) +comment(# Description) +comment(# --------------------------------------------------------------------------) +comment(# 2002.10.18 Austin Ziegler) +comment(# Fixed a minor problem with tabs not being counted. Changed) +comment(# abbreviations from Hash to Array to better suit Ruby's) +comment(# capabilities. Fixed problems with the way that Array arguments) +comment(# are handled in calls to the major object types, excepting in) +comment(# Text::Format#expand and Text::Format#unexpand (these will) +comment(# probably need to be fixed\).) +comment(# 2002.10.30 Austin Ziegler) +comment(# Fixed the ordering of the <=> for binary tests. Fixed) +comment(# Text::Format#expand and Text::Format#unexpand to handle array) +comment(# arguments better.) +comment(# 2003.01.24 Austin Ziegler) +comment(# Fixed a problem with Text::Format::RIGHT_FILL handling where a) +comment(# single word is larger than #columns. Removed Comparable) +comment(# capabilities (<=> doesn't make sense; == does\). Added Symbol) +comment(# equivalents for the Hash initialization. Hash initialization has) +comment(# been modified so that values are set as follows (Symbols are) +comment(# highest priority; strings are middle; defaults are lowest\):) +comment(# @columns = arg[:columns] || arg['columns'] || @columns) +comment(# Added #hard_margins, #split_rules, #hyphenator, and #split_words.) +comment(# 2003.02.07 Austin Ziegler) +comment(# Fixed the installer for proper case-sensitive handling.) +comment(# 2003.03.28 Austin Ziegler) +comment(# Added the ability for a hyphenator to receive the formatter) +comment(# object. Fixed a bug for strings matching /\\A\\s*\\Z/ failing) +comment(# entirely. Fixed a test case failing under 1.6.8. ) +comment(# 2003.04.04 Austin Ziegler) +comment(# Handle the case of hyphenators returning nil for first/rest.) +comment(# 2003.09.17 Austin Ziegler) +comment(# Fixed a problem where #paragraphs(" "\) was raising) +comment(# NoMethodError.) +comment(#) +comment(# ==========================================================================) +comment(#++) + +reserved(module) class(Text) comment(#:nodoc:) + comment(# Text::Format for Ruby is copyright 2002 - 2005 by Austin Ziegler. It) + comment(# is available under Ruby's licence, the Perl Artistic licence, or the) + comment(# GNU GPL version 2 (or at your option, any later version\). As a) + comment(# special exception, for use with official Rails (provided by the) + comment(# rubyonrails.org development team\) and any project created with) + comment(# official Rails, the following alternative MIT-style licence may be) + comment(# used:) + comment(#) + comment(# == Text::Format Licence for Rails and Rails Applications) + comment(# Permission is hereby granted, free of charge, to any person) + comment(# obtaining a copy of this software and associated documentation files) + comment(# (the "Software"\), to deal in the Software without restriction,) + comment(# including without limitation the rights to use, copy, modify, merge,) + comment(# publish, distribute, sublicense, and/or sell copies of the Software,) + comment(# and to permit persons to whom the Software is furnished to do so,) + comment(# subject to the following conditions:) + comment(#) + comment(# * The names of its contributors may not be used to endorse or) + comment(# promote products derived from this software without specific prior) + comment(# written permission.) + comment(#) + comment(# The above copyright notice and this permission notice shall be) + comment(# included in all copies or substantial portions of the Software.) + comment(#) + comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) + comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) + comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) + comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS) + comment(# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN) + comment(# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN) + comment(# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE) + comment(# SOFTWARE. ) + reserved(class) class(Format) + constant(VERSION) operator(=) string<delimiter(')content(0.63)delimiter(')> + + comment(# Local abbreviations. More can be added with Text::Format.abbreviations) + constant(ABBREV) operator(=) operator([) string<delimiter(')content(Mr)delimiter(')>operator(,) string<delimiter(')content(Mrs)delimiter(')>operator(,) string<delimiter(')content(Ms)delimiter(')>operator(,) string<delimiter(')content(Jr)delimiter(')>operator(,) string<delimiter(')content(Sr)delimiter(')> operator(]) + + comment(# Formatting values) + constant(LEFT_ALIGN) operator(=) integer(0) + constant(RIGHT_ALIGN) operator(=) integer(1) + constant(RIGHT_FILL) operator(=) integer(2) + constant(JUSTIFY) operator(=) integer(3) + + comment(# Word split modes (only applies when #hard_margins is true\).) + constant(SPLIT_FIXED) operator(=) integer(1) + constant(SPLIT_CONTINUATION) operator(=) integer(2) + constant(SPLIT_HYPHENATION) operator(=) integer(4) + constant(SPLIT_CONTINUATION_FIXED) operator(=) constant(SPLIT_CONTINUATION) operator(|) constant(SPLIT_FIXED) + constant(SPLIT_HYPHENATION_FIXED) operator(=) constant(SPLIT_HYPHENATION) operator(|) constant(SPLIT_FIXED) + constant(SPLIT_HYPHENATION_CONTINUATION) operator(=) constant(SPLIT_HYPHENATION) operator(|) constant(SPLIT_CONTINUATION) + constant(SPLIT_ALL) operator(=) constant(SPLIT_HYPHENATION) operator(|) constant(SPLIT_CONTINUATION) operator(|) constant(SPLIT_FIXED) + + comment(# Words forcibly split by Text::Format will be stored as split words.) + comment(# This class represents a word forcibly split.) + reserved(class) class(SplitWord) + comment(# The word that was split.) + ident(attr_reader) symbol(:word) + comment(# The first part of the word that was split.) + ident(attr_reader) symbol(:first) + comment(# The remainder of the word that was split.) + ident(attr_reader) symbol(:rest) + + reserved(def) method(initialize)operator(()ident(word)operator(,) ident(first)operator(,) ident(rest)operator(\)) comment(#:nodoc:) + instance_variable(@word) operator(=) ident(word) + instance_variable(@first) operator(=) ident(first) + instance_variable(@rest) operator(=) ident(rest) + reserved(end) + reserved(end) + + ident(private) + constant(LEQ_RE) operator(=) regexp<delimiter(/)content([.?!]['"]?$)delimiter(/)> + + reserved(def) method(brk_re)operator(()ident(i)operator(\)) comment(#:nodoc:) + regexp<delimiter(%r/)content(((?:)char(\\S)content(+)char(\\s)content(+\){)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>content(}\)(.+\))delimiter(/)> + reserved(end) + + reserved(def) method(posint)operator(()ident(p)operator(\)) comment(#:nodoc:) + ident(p)operator(.)ident(to_i)operator(.)ident(abs) + reserved(end) + + ident(public) + comment(# Compares two Text::Format objects. All settings of the objects are) + comment(# compared *except* #hyphenator. Generated results (e.g., #split_words\)) + comment(# are not compared, either.) + reserved(def) method(==)operator(()ident(o)operator(\)) + operator(()instance_variable(@text) operator(==) ident(o)operator(.)ident(text)operator(\)) operator(&&) + operator(()instance_variable(@columns) operator(==) ident(o)operator(.)ident(columns)operator(\)) operator(&&) + operator(()instance_variable(@left_margin) operator(==) ident(o)operator(.)ident(left_margin)operator(\)) operator(&&) + operator(()instance_variable(@right_margin) operator(==) ident(o)operator(.)ident(right_margin)operator(\)) operator(&&) + operator(()instance_variable(@hard_margins) operator(==) ident(o)operator(.)ident(hard_margins)operator(\)) operator(&&) + operator(()instance_variable(@split_rules) operator(==) ident(o)operator(.)ident(split_rules)operator(\)) operator(&&) + operator(()instance_variable(@first_indent) operator(==) ident(o)operator(.)ident(first_indent)operator(\)) operator(&&) + operator(()instance_variable(@body_indent) operator(==) ident(o)operator(.)ident(body_indent)operator(\)) operator(&&) + operator(()instance_variable(@tag_text) operator(==) ident(o)operator(.)ident(tag_text)operator(\)) operator(&&) + operator(()instance_variable(@tabstop) operator(==) ident(o)operator(.)ident(tabstop)operator(\)) operator(&&) + operator(()instance_variable(@format_style) operator(==) ident(o)operator(.)ident(format_style)operator(\)) operator(&&) + operator(()instance_variable(@extra_space) operator(==) ident(o)operator(.)ident(extra_space)operator(\)) operator(&&) + operator(()instance_variable(@tag_paragraph) operator(==) ident(o)operator(.)ident(tag_paragraph)operator(\)) operator(&&) + operator(()instance_variable(@nobreak) operator(==) ident(o)operator(.)ident(nobreak)operator(\)) operator(&&) + operator(()instance_variable(@abbreviations) operator(==) ident(o)operator(.)ident(abbreviations)operator(\)) operator(&&) + operator(()instance_variable(@nobreak_regex) operator(==) ident(o)operator(.)ident(nobreak_regex)operator(\)) + reserved(end) + + comment(# The text to be manipulated. Note that value is optional, but if the) + comment(# formatting functions are called without values, this text is what will) + comment(# be formatted.) + comment(#) + comment(# *Default*:: <tt>[]</tt>) + comment(# <b>Used in</b>:: All methods) + ident(attr_accessor) symbol(:text) + + comment(# The total width of the format area. The margins, indentation, and text) + comment(# are formatted into this space.) + comment(#) + comment(# COLUMNS) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin indent text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>72</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>,) + comment(# <tt>#center</tt>) + ident(attr_reader) symbol(:columns) + + comment(# The total width of the format area. The margins, indentation, and text) + comment(# are formatted into this space. The value provided is silently) + comment(# converted to a positive integer.) + comment(#) + comment(# COLUMNS) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin indent text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>72</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>,) + comment(# <tt>#center</tt>) + reserved(def) method(columns=)operator(()ident(c)operator(\)) + instance_variable(@columns) operator(=) ident(posint)operator(()ident(c)operator(\)) + reserved(end) + + comment(# The number of spaces used for the left margin.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# LEFT MARGIN indent text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>0</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>,) + comment(# <tt>#center</tt>) + ident(attr_reader) symbol(:left_margin) + + comment(# The number of spaces used for the left margin. The value provided is) + comment(# silently converted to a positive integer value.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# LEFT MARGIN indent text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>0</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>,) + comment(# <tt>#center</tt>) + reserved(def) method(left_margin=)operator(()ident(left)operator(\)) + instance_variable(@left_margin) operator(=) ident(posint)operator(()ident(left)operator(\)) + reserved(end) + + comment(# The number of spaces used for the right margin.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin indent text is formatted into here RIGHT MARGIN) + comment(#) + comment(# *Default*:: <tt>0</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>,) + comment(# <tt>#center</tt>) + ident(attr_reader) symbol(:right_margin) + + comment(# The number of spaces used for the right margin. The value provided is) + comment(# silently converted to a positive integer value.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin indent text is formatted into here RIGHT MARGIN) + comment(#) + comment(# *Default*:: <tt>0</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>,) + comment(# <tt>#center</tt>) + reserved(def) method(right_margin=)operator(()ident(r)operator(\)) + instance_variable(@right_margin) operator(=) ident(posint)operator(()ident(r)operator(\)) + reserved(end) + + comment(# The number of spaces to indent the first line of a paragraph.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin INDENT text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>4</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_reader) symbol(:first_indent) + + comment(# The number of spaces to indent the first line of a paragraph. The) + comment(# value provided is silently converted to a positive integer value.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin INDENT text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>4</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(first_indent=)operator(()ident(f)operator(\)) + instance_variable(@first_indent) operator(=) ident(posint)operator(()ident(f)operator(\)) + reserved(end) + + comment(# The number of spaces to indent all lines after the first line of a) + comment(# paragraph.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin INDENT text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>0</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_reader) symbol(:body_indent) + + comment(# The number of spaces to indent all lines after the first line of) + comment(# a paragraph. The value provided is silently converted to a) + comment(# positive integer value.) + comment(#) + comment(# columns) + comment(# <-------------------------------------------------------------->) + comment(# <-----------><------><---------------------------><------------>) + comment(# left margin INDENT text is formatted into here right margin) + comment(#) + comment(# *Default*:: <tt>0</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(body_indent=)operator(()ident(b)operator(\)) + instance_variable(@body_indent) operator(=) ident(posint)operator(()ident(b)operator(\)) + reserved(end) + + comment(# Normally, words larger than the format area will be placed on a line) + comment(# by themselves. Setting this to +true+ will force words larger than the) + comment(# format area to be split into one or more "words" each at most the size) + comment(# of the format area. The first line and the original word will be) + comment(# placed into <tt>#split_words</tt>. Note that this will cause the) + comment(# output to look *similar* to a #format_style of JUSTIFY. (Lines will be) + comment(# filled as much as possible.\)) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:hard_margins) + + comment(# An array of words split during formatting if #hard_margins is set to) + comment(# +true+.) + comment(# #split_words << Text::Format::SplitWord.new(word, first, rest\)) + ident(attr_reader) symbol(:split_words) + + comment(# The object responsible for hyphenating. It must respond to) + comment(# #hyphenate_to(word, size\) or #hyphenate_to(word, size, formatter\) and) + comment(# return an array of the word split into two parts; if there is a) + comment(# hyphenation mark to be applied, responsibility belongs to the) + comment(# hyphenator object. The size is the MAXIMUM size permitted, including) + comment(# any hyphenation marks. If the #hyphenate_to method has an arity of 3,) + comment(# the formatter will be provided to the method. This allows the) + comment(# hyphenator to make decisions about the hyphenation based on the) + comment(# formatting rules.) + comment(#) + comment(# *Default*:: +nil+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_reader) symbol(:hyphenator) + + comment(# The object responsible for hyphenating. It must respond to) + comment(# #hyphenate_to(word, size\) and return an array of the word hyphenated) + comment(# into two parts. The size is the MAXIMUM size permitted, including any) + comment(# hyphenation marks.) + comment(#) + comment(# *Default*:: +nil+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(hyphenator=)operator(()ident(h)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(h)operator(.)ident(inspect)inline_delimiter(})>content( is not a valid hyphenator.)delimiter(")> reserved(unless) ident(h)operator(.)ident(respond_to?)operator(()symbol(:hyphenate_to)operator(\)) + ident(arity) operator(=) ident(h)operator(.)ident(method)operator(()symbol(:hyphenate_to)operator(\))operator(.)ident(arity) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(h)operator(.)ident(inspect)inline_delimiter(})>content( must have exactly two or three arguments.)delimiter(")> reserved(unless) operator([)integer(2)operator(,) integer(3)operator(])operator(.)ident(include?)operator(()ident(arity)operator(\)) + instance_variable(@hyphenator) operator(=) ident(h) + instance_variable(@hyphenator_arity) operator(=) ident(arity) + reserved(end) + + comment(# Specifies the split mode; used only when #hard_margins is set to) + comment(# +true+. Allowable values are:) + comment(# [+SPLIT_FIXED+] The word will be split at the number of) + comment(# characters needed, with no marking at all.) + comment(# repre) + comment(# senta) + comment(# ion) + comment(# [+SPLIT_CONTINUATION+] The word will be split at the number of) + comment(# characters needed, with a C-style continuation) + comment(# character. If a word is the only item on a) + comment(# line and it cannot be split into an) + comment(# appropriate size, SPLIT_FIXED will be used.) + comment(# repr\\) + comment(# esen\\) + comment(# tati\\) + comment(# on) + comment(# [+SPLIT_HYPHENATION+] The word will be split according to the) + comment(# hyphenator specified in #hyphenator. If there) + comment(# is no #hyphenator specified, works like) + comment(# SPLIT_CONTINUATION. The example is using) + comment(# TeX::Hyphen. If a word is the only item on a) + comment(# line and it cannot be split into an) + comment(# appropriate size, SPLIT_CONTINUATION mode will) + comment(# be used.) + comment(# rep-) + comment(# re-) + comment(# sen-) + comment(# ta-) + comment(# tion) + comment(#) + comment(# *Default*:: <tt>Text::Format::SPLIT_FIXED</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_reader) symbol(:split_rules) + + comment(# Specifies the split mode; used only when #hard_margins is set to) + comment(# +true+. Allowable values are:) + comment(# [+SPLIT_FIXED+] The word will be split at the number of) + comment(# characters needed, with no marking at all.) + comment(# repre) + comment(# senta) + comment(# ion) + comment(# [+SPLIT_CONTINUATION+] The word will be split at the number of) + comment(# characters needed, with a C-style continuation) + comment(# character.) + comment(# repr\\) + comment(# esen\\) + comment(# tati\\) + comment(# on) + comment(# [+SPLIT_HYPHENATION+] The word will be split according to the) + comment(# hyphenator specified in #hyphenator. If there) + comment(# is no #hyphenator specified, works like) + comment(# SPLIT_CONTINUATION. The example is using) + comment(# TeX::Hyphen as the #hyphenator.) + comment(# rep-) + comment(# re-) + comment(# sen-) + comment(# ta-) + comment(# tion) + comment(#) + comment(# These values can be bitwise ORed together (e.g., <tt>SPLIT_FIXED |) + comment(# SPLIT_CONTINUATION</tt>\) to provide fallback split methods. In the) + comment(# example given, an attempt will be made to split the word using the) + comment(# rules of SPLIT_CONTINUATION; if there is not enough room, the word) + comment(# will be split with the rules of SPLIT_FIXED. These combinations are) + comment(# also available as the following values:) + comment(# * +SPLIT_CONTINUATION_FIXED+) + comment(# * +SPLIT_HYPHENATION_FIXED+) + comment(# * +SPLIT_HYPHENATION_CONTINUATION+) + comment(# * +SPLIT_ALL+) + comment(#) + comment(# *Default*:: <tt>Text::Format::SPLIT_FIXED</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(split_rules=)operator(()ident(s)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Invalid value provided for split_rules.)delimiter(")> reserved(if) operator(()operator(()ident(s) operator(<) constant(SPLIT_FIXED)operator(\)) operator(||) operator(()ident(s) operator(>) constant(SPLIT_ALL)operator(\))operator(\)) + instance_variable(@split_rules) operator(=) ident(s) + reserved(end) + + comment(# Indicates whether sentence terminators should be followed by a single) + comment(# space (+false+\), or two spaces (+true+\).) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:extra_space) + + comment(# Defines the current abbreviations as an array. This is only used if) + comment(# extra_space is turned on.) + comment(#) + comment(# If one is abbreviating "President" as "Pres." (abbreviations =) + comment(# ["Pres"]\), then the results of formatting will be as illustrated in) + comment(# the table below:) + comment(#) + comment(# extra_space | include? | !include?) + comment(# true | Pres. Lincoln | Pres. Lincoln) + comment(# false | Pres. Lincoln | Pres. Lincoln) + comment(#) + comment(# *Default*:: <tt>{}</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:abbreviations) + + comment(# Indicates whether the formatting of paragraphs should be done with) + comment(# tagged paragraphs. Useful only with <tt>#tag_text</tt>.) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:tag_paragraph) + + comment(# The array of text to be placed before each paragraph when) + comment(# <tt>#tag_paragraph</tt> is +true+. When <tt>#format(\)</tt> is called,) + comment(# only the first element of the array is used. When <tt>#paragraphs</tt>) + comment(# is called, then each entry in the array will be used once, with) + comment(# corresponding paragraphs. If the tag elements are exhausted before the) + comment(# text is exhausted, then the remaining paragraphs will not be tagged.) + comment(# Regardless of indentation settings, a blank line will be inserted) + comment(# between all paragraphs when <tt>#tag_paragraph</tt> is +true+.) + comment(#) + comment(# *Default*:: <tt>[]</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:tag_text) + + comment(# Indicates whether or not the non-breaking space feature should be) + comment(# used.) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:nobreak) + + comment(# A hash which holds the regular expressions on which spaces should not) + comment(# be broken. The hash is set up such that the key is the first word and) + comment(# the value is the second word.) + comment(#) + comment(# For example, if +nobreak_regex+ contains the following hash:) + comment(#) + comment(# { '^Mrs?\\.$' => '\\S+$', '^\\S+$' => '^(?:S|J\)r\\.$'}) + comment(#) + comment(# Then "Mr. Jones", "Mrs. Jones", and "Jones Jr." would not be broken.) + comment(# If this simple matching algorithm indicates that there should not be a) + comment(# break at the current end of line, then a backtrack is done until there) + comment(# are two words on which line breaking is permitted. If two such words) + comment(# are not found, then the end of the line will be broken *regardless*.) + comment(# If there is a single word on the current line, then no backtrack is) + comment(# done and the word is stuck on the end.) + comment(#) + comment(# *Default*:: <tt>{}</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_accessor) symbol(:nobreak_regex) + + comment(# Indicates the number of spaces that a single tab represents.) + comment(#) + comment(# *Default*:: <tt>8</tt>) + comment(# <b>Used in</b>:: <tt>#expand</tt>, <tt>#unexpand</tt>,) + comment(# <tt>#paragraphs</tt>) + ident(attr_reader) symbol(:tabstop) + + comment(# Indicates the number of spaces that a single tab represents.) + comment(#) + comment(# *Default*:: <tt>8</tt>) + comment(# <b>Used in</b>:: <tt>#expand</tt>, <tt>#unexpand</tt>,) + comment(# <tt>#paragraphs</tt>) + reserved(def) method(tabstop=)operator(()ident(t)operator(\)) + instance_variable(@tabstop) operator(=) ident(posint)operator(()ident(t)operator(\)) + reserved(end) + + comment(# Specifies the format style. Allowable values are:) + comment(# [+LEFT_ALIGN+] Left justified, ragged right.) + comment(# |A paragraph that is|) + comment(# |left aligned.|) + comment(# [+RIGHT_ALIGN+] Right justified, ragged left.) + comment(# |A paragraph that is|) + comment(# | right aligned.|) + comment(# [+RIGHT_FILL+] Left justified, right ragged, filled to width by) + comment(# spaces. (Essentially the same as +LEFT_ALIGN+ except) + comment(# that lines are padded on the right.\)) + comment(# |A paragraph that is|) + comment(# |left aligned. |) + comment(# [+JUSTIFY+] Fully justified, words filled to width by spaces,) + comment(# except the last line.) + comment(# |A paragraph that|) + comment(# |is justified.|) + comment(#) + comment(# *Default*:: <tt>Text::Format::LEFT_ALIGN</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + ident(attr_reader) symbol(:format_style) + + comment(# Specifies the format style. Allowable values are:) + comment(# [+LEFT_ALIGN+] Left justified, ragged right.) + comment(# |A paragraph that is|) + comment(# |left aligned.|) + comment(# [+RIGHT_ALIGN+] Right justified, ragged left.) + comment(# |A paragraph that is|) + comment(# | right aligned.|) + comment(# [+RIGHT_FILL+] Left justified, right ragged, filled to width by) + comment(# spaces. (Essentially the same as +LEFT_ALIGN+ except) + comment(# that lines are padded on the right.\)) + comment(# |A paragraph that is|) + comment(# |left aligned. |) + comment(# [+JUSTIFY+] Fully justified, words filled to width by spaces.) + comment(# |A paragraph that|) + comment(# |is justified.|) + comment(#) + comment(# *Default*:: <tt>Text::Format::LEFT_ALIGN</tt>) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(format_style=)operator(()ident(fs)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Invalid value provided for format_style.)delimiter(")> reserved(if) operator(()operator(()ident(fs) operator(<) constant(LEFT_ALIGN)operator(\)) operator(||) operator(()ident(fs) operator(>) constant(JUSTIFY)operator(\))operator(\)) + instance_variable(@format_style) operator(=) ident(fs) + reserved(end) + + comment(# Indicates that the format style is left alignment.) + comment(#) + comment(# *Default*:: +true+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(left_align?) + reserved(return) instance_variable(@format_style) operator(==) constant(LEFT_ALIGN) + reserved(end) + + comment(# Indicates that the format style is right alignment.) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(right_align?) + reserved(return) instance_variable(@format_style) operator(==) constant(RIGHT_ALIGN) + reserved(end) + + comment(# Indicates that the format style is right fill.) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(right_fill?) + reserved(return) instance_variable(@format_style) operator(==) constant(RIGHT_FILL) + reserved(end) + + comment(# Indicates that the format style is full justification.) + comment(#) + comment(# *Default*:: +false+) + comment(# <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>) + reserved(def) method(justify?) + reserved(return) instance_variable(@format_style) operator(==) constant(JUSTIFY) + reserved(end) + + comment(# The default implementation of #hyphenate_to implements) + comment(# SPLIT_CONTINUATION.) + reserved(def) method(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(\)) + operator([)ident(word)operator([)integer(0) operator(..) operator(()ident(size) operator(-) integer(2)operator(\))operator(]) operator(+) string<delimiter(")char(\\\\)delimiter(")>operator(,) ident(word)operator([)operator(()ident(size) operator(-) integer(1)operator(\)) operator(..) integer(-1)operator(])operator(]) + reserved(end) + + ident(private) + reserved(def) method(__do_split_word)operator(()ident(word)operator(,) ident(size)operator(\)) comment(#:nodoc:) + operator([)ident(word)operator([)integer(0) operator(..) operator(()ident(size) operator(-) integer(1)operator(\))operator(])operator(,) ident(word)operator([)ident(size) operator(..) integer(-1)operator(])operator(]) + reserved(end) + + reserved(def) method(__format)operator(()ident(to_wrap)operator(\)) comment(#:nodoc:) + ident(words) operator(=) ident(to_wrap)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\s)content(+)delimiter(/)>operator(\))operator(.)ident(compact) + ident(words)operator(.)ident(shift) reserved(if) ident(words)operator([)integer(0)operator(])operator(.)ident(nil?) reserved(or) ident(words)operator([)integer(0)operator(])operator(.)ident(empty?) + ident(to_wrap) operator(=) operator([)operator(]) + + ident(abbrev) operator(=) pre_constant(false) + ident(width) operator(=) instance_variable(@columns) operator(-) instance_variable(@first_indent) operator(-) instance_variable(@left_margin) operator(-) instance_variable(@right_margin) + ident(indent_str) operator(=) string<delimiter(')content( )delimiter(')> operator(*) instance_variable(@first_indent) + ident(first_line) operator(=) pre_constant(true) + ident(line) operator(=) ident(words)operator(.)ident(shift) + ident(abbrev) operator(=) ident(__is_abbrev)operator(()ident(line)operator(\)) reserved(unless) ident(line)operator(.)ident(nil?) operator(||) ident(line)operator(.)ident(empty?) + + reserved(while) ident(w) operator(=) ident(words)operator(.)ident(shift) + reserved(if) operator(()ident(w)operator(.)ident(size) operator(+) ident(line)operator(.)ident(size) operator(<) operator(()ident(width) operator(-) integer(1)operator(\))operator(\)) operator(||) + operator(()operator(()ident(line) operator(!)operator(~) constant(LEQ_RE) operator(||) ident(abbrev)operator(\)) operator(&&) operator(()ident(w)operator(.)ident(size) operator(+) ident(line)operator(.)ident(size) operator(<) ident(width)operator(\))operator(\)) + ident(line) operator(<<) string<delimiter(")content( )delimiter(")> reserved(if) operator(()ident(line) operator(=)operator(~) constant(LEQ_RE)operator(\)) operator(&&) operator(()reserved(not) ident(abbrev)operator(\)) + ident(line) operator(<<) string<delimiter(")content( )inline<inline_delimiter(#{)ident(w)inline_delimiter(})>delimiter(")> + reserved(else) + ident(line)operator(,) ident(w) operator(=) ident(__do_break)operator(()ident(line)operator(,) ident(w)operator(\)) reserved(if) instance_variable(@nobreak) + ident(line)operator(,) ident(w) operator(=) ident(__do_hyphenate)operator(()ident(line)operator(,) ident(w)operator(,) ident(width)operator(\)) reserved(if) instance_variable(@hard_margins) + reserved(if) ident(w)operator(.)ident(index)operator(()regexp<delimiter(/)char(\\s)content(+)delimiter(/)>operator(\)) + ident(w)operator(,) operator(*)ident(w2) operator(=) ident(w)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\s)content(+)delimiter(/)>operator(\)) + ident(words)operator(.)ident(unshift)operator(()ident(w2)operator(\)) + ident(words)operator(.)ident(flatten!) + reserved(end) + ident(to_wrap) operator(<<) ident(__make_line)operator(()ident(line)operator(,) ident(indent_str)operator(,) ident(width)operator(,) ident(w)operator(.)ident(nil?)operator(\)) reserved(unless) ident(line)operator(.)ident(nil?) + reserved(if) ident(first_line) + ident(first_line) operator(=) pre_constant(false) + ident(width) operator(=) instance_variable(@columns) operator(-) instance_variable(@body_indent) operator(-) instance_variable(@left_margin) operator(-) instance_variable(@right_margin) + ident(indent_str) operator(=) string<delimiter(')content( )delimiter(')> operator(*) instance_variable(@body_indent) + reserved(end) + ident(line) operator(=) ident(w) + reserved(end) + + ident(abbrev) operator(=) ident(__is_abbrev)operator(()ident(w)operator(\)) reserved(unless) ident(w)operator(.)ident(nil?) + reserved(end) + + ident(loop) reserved(do) + reserved(break) reserved(if) ident(line)operator(.)ident(nil?) reserved(or) ident(line)operator(.)ident(empty?) + ident(line)operator(,) ident(w) operator(=) ident(__do_hyphenate)operator(()ident(line)operator(,) ident(w)operator(,) ident(width)operator(\)) reserved(if) instance_variable(@hard_margins) + ident(to_wrap) operator(<<) ident(__make_line)operator(()ident(line)operator(,) ident(indent_str)operator(,) ident(width)operator(,) ident(w)operator(.)ident(nil?)operator(\)) + ident(line) operator(=) ident(w) + reserved(end) + + reserved(if) operator(()instance_variable(@tag_paragraph) operator(&&) operator(()ident(to_wrap)operator(.)ident(size) operator(>) integer(0)operator(\))operator(\)) reserved(then) + ident(clr) operator(=) regexp<delimiter(%r{)content(`()char(\\w)content(+\)')delimiter(})>operator(.)ident(match)operator(()operator([)ident(caller)operator(()integer(1)operator(\))operator(])operator(.)ident(flatten)operator([)integer(0)operator(])operator(\))operator([)integer(1)operator(]) + ident(clr) operator(=) string<delimiter(")delimiter(")> reserved(if) ident(clr)operator(.)ident(nil?) + + reserved(if) operator(()operator(()reserved(not) instance_variable(@tag_text)operator([)integer(0)operator(])operator(.)ident(nil?)operator(\)) operator(&&) operator(()instance_variable(@tag_cur)operator(.)ident(size) operator(<) integer(1)operator(\)) operator(&&) + operator(()ident(clr) operator(!=) string<delimiter(")content(__paragraphs)delimiter(")>operator(\))operator(\)) reserved(then) + instance_variable(@tag_cur) operator(=) instance_variable(@tag_text)operator([)integer(0)operator(]) + reserved(end) + + ident(fchar) operator(=) regexp<delimiter(/)content(()char(\\S)content(\))delimiter(/)>operator(.)ident(match)operator(()ident(to_wrap)operator([)integer(0)operator(])operator(\))operator([)integer(1)operator(]) + ident(white) operator(=) ident(to_wrap)operator([)integer(0)operator(])operator(.)ident(index)operator(()ident(fchar)operator(\)) + reserved(if) operator(()operator(()ident(white) operator(-) instance_variable(@left_margin) operator(-) integer(1)operator(\)) operator(>) instance_variable(@tag_cur)operator(.)ident(size)operator(\)) reserved(then) + ident(white) operator(=) instance_variable(@tag_cur)operator(.)ident(size) operator(+) instance_variable(@left_margin) + ident(to_wrap)operator([)integer(0)operator(])operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(^ {)inline<inline_delimiter(#{)ident(white)inline_delimiter(})>content(})delimiter(/)>operator(,) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content( )delimiter(')> operator(*) instance_variable(@left_margin)inline_delimiter(})>inline<inline_delimiter(#{)instance_variable(@tag_cur)inline_delimiter(})>delimiter(")>operator(\)) + reserved(else) + ident(to_wrap)operator(.)ident(unshift)operator(()string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content( )delimiter(')> operator(*) instance_variable(@left_margin)inline_delimiter(})>inline<inline_delimiter(#{)instance_variable(@tag_cur)inline_delimiter(})>char(\\n)delimiter(")>operator(\)) + reserved(end) + reserved(end) + ident(to_wrap)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + comment(# format lines in text into paragraphs with each element of @wrap a) + comment(# paragraph; uses Text::Format.format for the formatting) + reserved(def) method(__paragraphs)operator(()ident(to_wrap)operator(\)) comment(#:nodoc:) + reserved(if) operator(()operator(()instance_variable(@first_indent) operator(==) instance_variable(@body_indent)operator(\)) operator(||) instance_variable(@tag_paragraph)operator(\)) reserved(then) + ident(p_end) operator(=) string<delimiter(")char(\\n)delimiter(")> + reserved(else) + ident(p_end) operator(=) string<delimiter(')delimiter(')> + reserved(end) + + ident(cnt) operator(=) integer(0) + ident(ret) operator(=) operator([)operator(]) + ident(to_wrap)operator(.)ident(each) reserved(do) operator(|)ident(tw)operator(|) + instance_variable(@tag_cur) operator(=) instance_variable(@tag_text)operator([)ident(cnt)operator(]) reserved(if) instance_variable(@tag_paragraph) + instance_variable(@tag_cur) operator(=) string<delimiter(')delimiter(')> reserved(if) instance_variable(@tag_cur)operator(.)ident(nil?) + ident(line) operator(=) ident(__format)operator(()ident(tw)operator(\)) + ident(ret) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(line)inline_delimiter(})>inline<inline_delimiter(#{)ident(p_end)inline_delimiter(})>delimiter(")> reserved(if) operator(()reserved(not) ident(line)operator(.)ident(nil?)operator(\)) operator(&&) operator(()ident(line)operator(.)ident(size) operator(>) integer(0)operator(\)) + ident(cnt) operator(+=) integer(1) + reserved(end) + + ident(ret)operator([)integer(-1)operator(])operator(.)ident(chomp!) reserved(unless) ident(ret)operator(.)ident(empty?) + ident(ret)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + comment(# center text using spaces on left side to pad it out empty lines) + comment(# are preserved) + reserved(def) method(__center)operator(()ident(to_center)operator(\)) comment(#:nodoc:) + ident(tabs) operator(=) integer(0) + ident(width) operator(=) instance_variable(@columns) operator(-) instance_variable(@left_margin) operator(-) instance_variable(@right_margin) + ident(centered) operator(=) operator([)operator(]) + ident(to_center)operator(.)ident(each) reserved(do) operator(|)ident(tc)operator(|) + ident(s) operator(=) ident(tc)operator(.)ident(strip) + ident(tabs) operator(=) ident(s)operator(.)ident(count)operator(()string<delimiter(")char(\\t)delimiter(")>operator(\)) + ident(tabs) operator(=) integer(0) reserved(if) ident(tabs)operator(.)ident(nil?) + ident(ct) operator(=) operator(()operator(()ident(width) operator(-) ident(s)operator(.)ident(size) operator(-) operator(()ident(tabs) operator(*) instance_variable(@tabstop)operator(\)) operator(+) ident(tabs)operator(\)) operator(/) integer(2)operator(\)) + ident(ct) operator(=) operator(()ident(width) operator(-) instance_variable(@left_margin) operator(-) instance_variable(@right_margin)operator(\)) operator(-) ident(ct) + ident(centered) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(s)operator(.)ident(rjust)operator(()ident(ct)operator(\))inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + ident(centered)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + comment(# expand tabs to spaces should be similar to Text::Tabs::expand) + reserved(def) method(__expand)operator(()ident(to_expand)operator(\)) comment(#:nodoc:) + ident(expanded) operator(=) operator([)operator(]) + ident(to_expand)operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator(.)ident(each) operator({) operator(|)ident(te)operator(|) ident(expanded) operator(<<) ident(te)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\t)delimiter(/)>operator(,) string<delimiter(')content( )delimiter(')> operator(*) instance_variable(@tabstop)operator(\)) operator(}) + ident(expanded)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(__unexpand)operator(()ident(to_unexpand)operator(\)) comment(#:nodoc:) + ident(unexpanded) operator(=) operator([)operator(]) + ident(to_unexpand)operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator(.)ident(each) operator({) operator(|)ident(tu)operator(|) ident(unexpanded) operator(<<) ident(tu)operator(.)ident(gsub)operator(()regexp<delimiter(/)content( {)inline<inline_delimiter(#{)instance_variable(@tabstop)inline_delimiter(})>content(})delimiter(/)>operator(,) string<delimiter(")char(\\t)delimiter(")>operator(\)) operator(}) + ident(unexpanded)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(__is_abbrev)operator(()ident(word)operator(\)) comment(#:nodoc:) + comment(# remove period if there is one.) + ident(w) operator(=) ident(word)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\.)content($)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) reserved(unless) ident(word)operator(.)ident(nil?) + reserved(return) pre_constant(true) reserved(if) operator(()operator(!)instance_variable(@extra_space) operator(||) constant(ABBREV)operator(.)ident(include?)operator(()ident(w)operator(\)) operator(||) instance_variable(@abbreviations)operator(.)ident(include?)operator(()ident(w)operator(\))operator(\)) + pre_constant(false) + reserved(end) + + reserved(def) method(__make_line)operator(()ident(line)operator(,) ident(indent)operator(,) ident(width)operator(,) ident(last) operator(=) pre_constant(false)operator(\)) comment(#:nodoc:) + ident(lmargin) operator(=) string<delimiter(")content( )delimiter(")> operator(*) instance_variable(@left_margin) + ident(fill) operator(=) string<delimiter(")content( )delimiter(")> operator(*) operator(()ident(width) operator(-) ident(line)operator(.)ident(size)operator(\)) reserved(if) ident(right_fill?) operator(&&) operator(()ident(line)operator(.)ident(size) operator(<=) ident(width)operator(\)) + + reserved(if) operator(()ident(justify?) operator(&&) operator(()operator(()reserved(not) ident(line)operator(.)ident(nil?)operator(\)) operator(&&) operator(()reserved(not) ident(line)operator(.)ident(empty?)operator(\))operator(\)) operator(&&) ident(line) operator(=)operator(~) regexp<delimiter(/)char(\\S)content(+)char(\\s)content(+)char(\\S)content(+)delimiter(/)> operator(&&) operator(!)ident(last)operator(\)) + ident(spaces) operator(=) ident(width) operator(-) ident(line)operator(.)ident(size) + ident(words) operator(=) ident(line)operator(.)ident(split)operator(()regexp<delimiter(/)content(()char(\\s)content(+\))delimiter(/)>operator(\)) + ident(ws) operator(=) ident(spaces) operator(/) operator(()ident(words)operator(.)ident(size) operator(/) integer(2)operator(\)) + ident(spaces) operator(=) ident(spaces) operator(%) operator(()ident(words)operator(.)ident(size) operator(/) integer(2)operator(\)) reserved(if) ident(ws) operator(>) integer(0) + ident(words)operator(.)ident(reverse)operator(.)ident(each) reserved(do) operator(|)ident(rw)operator(|) + reserved(next) reserved(if) operator(()ident(rw) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\S)delimiter(/)>operator(\)) + ident(rw)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^)delimiter(/)>operator(,) string<delimiter(")content( )delimiter(")> operator(*) ident(ws)operator(\)) + reserved(next) reserved(unless) operator(()ident(spaces) operator(>) integer(0)operator(\)) + ident(rw)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^)delimiter(/)>operator(,) string<delimiter(")content( )delimiter(")>operator(\)) + ident(spaces) operator(-=) integer(1) + reserved(end) + ident(line) operator(=) ident(words)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + ident(line) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(lmargin)inline_delimiter(})>inline<inline_delimiter(#{)ident(indent)inline_delimiter(})>inline<inline_delimiter(#{)ident(line)inline_delimiter(})>inline<inline_delimiter(#{)ident(fill)inline_delimiter(})>char(\\n)delimiter(")> reserved(unless) ident(line)operator(.)ident(nil?) + reserved(if) ident(right_align?) operator(&&) operator(()reserved(not) ident(line)operator(.)ident(nil?)operator(\)) + ident(line)operator(.)ident(sub)operator(()regexp<delimiter(/)content(^)delimiter(/)>operator(,) string<delimiter(")content( )delimiter(")> operator(*) operator(()instance_variable(@columns) operator(-) instance_variable(@right_margin) operator(-) operator(()ident(line)operator(.)ident(size) operator(-) integer(1)operator(\))operator(\))operator(\)) + reserved(else) + ident(line) + reserved(end) + reserved(end) + + reserved(def) method(__do_hyphenate)operator(()ident(line)operator(,) ident(next_line)operator(,) ident(width)operator(\)) comment(#:nodoc:) + ident(rline) operator(=) ident(line)operator(.)ident(dup) reserved(rescue) ident(line) + ident(rnext) operator(=) ident(next_line)operator(.)ident(dup) reserved(rescue) ident(next_line) + ident(loop) reserved(do) + reserved(if) ident(rline)operator(.)ident(size) operator(==) ident(width) + reserved(break) + reserved(elsif) ident(rline)operator(.)ident(size) operator(>) ident(width) + ident(words) operator(=) ident(rline)operator(.)ident(strip)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\s)content(+)delimiter(/)>operator(\)) + ident(word) operator(=) ident(words)operator([)integer(-1)operator(])operator(.)ident(dup) + ident(size) operator(=) ident(width) operator(-) ident(rline)operator(.)ident(size) operator(+) ident(word)operator(.)ident(size) + reserved(if) operator(()ident(size) operator(<=) integer(0)operator(\)) + ident(words)operator([)integer(-1)operator(]) operator(=) pre_constant(nil) + ident(rline) operator(=) ident(words)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))operator(.)ident(strip) + ident(rnext) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(word)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(rnext)inline_delimiter(})>delimiter(")>operator(.)ident(strip) + reserved(next) + reserved(end) + + ident(first) operator(=) ident(rest) operator(=) pre_constant(nil) + + reserved(if) operator(()operator(()instance_variable(@split_rules) operator(&) constant(SPLIT_HYPHENATION)operator(\)) operator(!=) integer(0)operator(\)) + reserved(if) instance_variable(@hyphenator_arity) operator(==) integer(2) + ident(first)operator(,) ident(rest) operator(=) instance_variable(@hyphenator)operator(.)ident(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(\)) + reserved(else) + ident(first)operator(,) ident(rest) operator(=) instance_variable(@hyphenator)operator(.)ident(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(,) pre_constant(self)operator(\)) + reserved(end) + reserved(end) + + reserved(if) operator(()operator(()instance_variable(@split_rules) operator(&) constant(SPLIT_CONTINUATION)operator(\)) operator(!=) integer(0)operator(\)) reserved(and) ident(first)operator(.)ident(nil?) + ident(first)operator(,) ident(rest) operator(=) pre_constant(self)operator(.)ident(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(\)) + reserved(end) + + reserved(if) operator(()operator(()instance_variable(@split_rules) operator(&) constant(SPLIT_FIXED)operator(\)) operator(!=) integer(0)operator(\)) reserved(and) ident(first)operator(.)ident(nil?) + ident(first)operator(.)ident(nil?) reserved(or) instance_variable(@split_rules) operator(==) constant(SPLIT_FIXED) + ident(first)operator(,) ident(rest) operator(=) ident(__do_split_word)operator(()ident(word)operator(,) ident(size)operator(\)) + reserved(end) + + reserved(if) ident(first)operator(.)ident(nil?) + ident(words)operator([)integer(-1)operator(]) operator(=) pre_constant(nil) + ident(rest) operator(=) ident(word) + reserved(else) + ident(words)operator([)integer(-1)operator(]) operator(=) ident(first) + instance_variable(@split_words) operator(<<) constant(SplitWord)operator(.)ident(new)operator(()ident(word)operator(,) ident(first)operator(,) ident(rest)operator(\)) + reserved(end) + ident(rline) operator(=) ident(words)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))operator(.)ident(strip) + ident(rnext) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(rest)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(rnext)inline_delimiter(})>delimiter(")>operator(.)ident(strip) + reserved(break) + reserved(else) + reserved(break) reserved(if) ident(rnext)operator(.)ident(nil?) reserved(or) ident(rnext)operator(.)ident(empty?) reserved(or) ident(rline)operator(.)ident(nil?) reserved(or) ident(rline)operator(.)ident(empty?) + ident(words) operator(=) ident(rnext)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\s)content(+)delimiter(/)>operator(\)) + ident(word) operator(=) ident(words)operator(.)ident(shift) + ident(size) operator(=) ident(width) operator(-) ident(rline)operator(.)ident(size) operator(-) integer(1) + + reserved(if) operator(()ident(size) operator(<=) integer(0)operator(\)) + ident(rnext) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(word)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(words)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))inline_delimiter(})>delimiter(")>operator(.)ident(strip) + reserved(break) + reserved(end) + + ident(first) operator(=) ident(rest) operator(=) pre_constant(nil) + + reserved(if) operator(()operator(()instance_variable(@split_rules) operator(&) constant(SPLIT_HYPHENATION)operator(\)) operator(!=) integer(0)operator(\)) + reserved(if) instance_variable(@hyphenator_arity) operator(==) integer(2) + ident(first)operator(,) ident(rest) operator(=) instance_variable(@hyphenator)operator(.)ident(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(\)) + reserved(else) + ident(first)operator(,) ident(rest) operator(=) instance_variable(@hyphenator)operator(.)ident(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(,) pre_constant(self)operator(\)) + reserved(end) + reserved(end) + + ident(first)operator(,) ident(rest) operator(=) pre_constant(self)operator(.)ident(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(\)) reserved(if) operator(()operator(()instance_variable(@split_rules) operator(&) constant(SPLIT_CONTINUATION)operator(\)) operator(!=) integer(0)operator(\)) reserved(and) ident(first)operator(.)ident(nil?) + + ident(first)operator(,) ident(rest) operator(=) ident(__do_split_word)operator(()ident(word)operator(,) ident(size)operator(\)) reserved(if) operator(()operator(()instance_variable(@split_rules) operator(&) constant(SPLIT_FIXED)operator(\)) operator(!=) integer(0)operator(\)) reserved(and) ident(first)operator(.)ident(nil?) + + reserved(if) operator(()ident(rline)operator(.)ident(size) operator(+) operator(()ident(first) operator(?) ident(first)operator(.)ident(size) operator(:) integer(0)operator(\))operator(\)) operator(<) ident(width) + instance_variable(@split_words) operator(<<) constant(SplitWord)operator(.)ident(new)operator(()ident(word)operator(,) ident(first)operator(,) ident(rest)operator(\)) + ident(rline) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(rline)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(first)inline_delimiter(})>delimiter(")>operator(.)ident(strip) + ident(rnext) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(rest)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(words)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))inline_delimiter(})>delimiter(")>operator(.)ident(strip) + reserved(end) + reserved(break) + reserved(end) + reserved(end) + operator([)ident(rline)operator(,) ident(rnext)operator(]) + reserved(end) + + reserved(def) method(__do_break)operator(()ident(line)operator(,) ident(next_line)operator(\)) comment(#:nodoc:) + ident(no_brk) operator(=) pre_constant(false) + ident(words) operator(=) operator([)operator(]) + ident(words) operator(=) ident(line)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\s)content(+)delimiter(/)>operator(\)) reserved(unless) ident(line)operator(.)ident(nil?) + ident(last_word) operator(=) ident(words)operator([)integer(-1)operator(]) + + instance_variable(@nobreak_regex)operator(.)ident(each) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(no_brk) operator(=) operator(()operator(()ident(last_word) operator(=)operator(~) regexp<delimiter(/)inline<inline_delimiter(#{)ident(k)inline_delimiter(})>delimiter(/)>operator(\)) reserved(and) operator(()ident(next_line) operator(=)operator(~) regexp<delimiter(/)inline<inline_delimiter(#{)ident(v)inline_delimiter(})>delimiter(/)>operator(\))operator(\)) operator(}) + + reserved(if) ident(no_brk) operator(&&) ident(words)operator(.)ident(size) operator(>) integer(1) + ident(i) operator(=) ident(words)operator(.)ident(size) + reserved(while) ident(i) operator(>) integer(0) + ident(no_brk) operator(=) pre_constant(false) + instance_variable(@nobreak_regex)operator(.)ident(each) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(no_brk) operator(=) operator(()operator(()ident(words)operator([)ident(i) operator(+) integer(1)operator(]) operator(=)operator(~) regexp<delimiter(/)inline<inline_delimiter(#{)ident(k)inline_delimiter(})>delimiter(/)>operator(\)) operator(&&) operator(()ident(words)operator([)ident(i)operator(]) operator(=)operator(~) regexp<delimiter(/)inline<inline_delimiter(#{)ident(v)inline_delimiter(})>delimiter(/)>operator(\))operator(\)) operator(}) + ident(i) operator(-=) integer(1) + reserved(break) reserved(if) reserved(not) ident(no_brk) + reserved(end) + reserved(if) ident(i) operator(>) integer(0) + ident(l) operator(=) ident(brk_re)operator(()ident(i)operator(\))operator(.)ident(match)operator(()ident(line)operator(\)) + ident(line)operator(.)ident(sub!)operator(()ident(brk_re)operator(()ident(i)operator(\))operator(,) ident(l)operator([)integer(1)operator(])operator(\)) + ident(next_line) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(l)operator([)integer(2)operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(next_line)inline_delimiter(})>delimiter(")> + ident(line)operator(.)ident(sub!)operator(()regexp<delimiter(/)char(\\s)content(+$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + reserved(end) + operator([)ident(line)operator(,) ident(next_line)operator(]) + reserved(end) + + reserved(def) method(__create)operator(()ident(arg) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) comment(#:nodoc:) + comment(# Format::Text.new(text-to-wrap\)) + instance_variable(@text) operator(=) ident(arg) reserved(unless) ident(arg)operator(.)ident(nil?) + comment(# Defaults) + instance_variable(@columns) operator(=) integer(72) + instance_variable(@tabstop) operator(=) integer(8) + instance_variable(@first_indent) operator(=) integer(4) + instance_variable(@body_indent) operator(=) integer(0) + instance_variable(@format_style) operator(=) constant(LEFT_ALIGN) + instance_variable(@left_margin) operator(=) integer(0) + instance_variable(@right_margin) operator(=) integer(0) + instance_variable(@extra_space) operator(=) pre_constant(false) + instance_variable(@text) operator(=) constant(Array)operator(.)ident(new) reserved(if) instance_variable(@text)operator(.)ident(nil?) + instance_variable(@tag_paragraph) operator(=) pre_constant(false) + instance_variable(@tag_text) operator(=) constant(Array)operator(.)ident(new) + instance_variable(@tag_cur) operator(=) string<delimiter(")delimiter(")> + instance_variable(@abbreviations) operator(=) constant(Array)operator(.)ident(new) + instance_variable(@nobreak) operator(=) pre_constant(false) + instance_variable(@nobreak_regex) operator(=) constant(Hash)operator(.)ident(new) + instance_variable(@split_words) operator(=) constant(Array)operator(.)ident(new) + instance_variable(@hard_margins) operator(=) pre_constant(false) + instance_variable(@split_rules) operator(=) constant(SPLIT_FIXED) + instance_variable(@hyphenator) operator(=) pre_constant(self) + instance_variable(@hyphenator_arity) operator(=) pre_constant(self)operator(.)ident(method)operator(()symbol(:hyphenate_to)operator(\))operator(.)ident(arity) + + ident(instance_eval)operator(()operator(&)ident(block)operator(\)) reserved(unless) ident(block)operator(.)ident(nil?) + reserved(end) + + ident(public) + comment(# Formats text into a nice paragraph format. The text is separated) + comment(# into words and then reassembled a word at a time using the settings) + comment(# of this Format object. If a word is larger than the number of) + comment(# columns available for formatting, then that word will appear on the) + comment(# line by itself.) + comment(#) + comment(# If +to_wrap+ is +nil+, then the value of <tt>#text</tt> will be) + comment(# worked on.) + reserved(def) method(format)operator(()ident(to_wrap) operator(=) pre_constant(nil)operator(\)) + ident(to_wrap) operator(=) instance_variable(@text) reserved(if) ident(to_wrap)operator(.)ident(nil?) + reserved(if) ident(to_wrap)operator(.)ident(class) operator(==) constant(Array) + ident(__format)operator(()ident(to_wrap)operator([)integer(0)operator(])operator(\)) + reserved(else) + ident(__format)operator(()ident(to_wrap)operator(\)) + reserved(end) + reserved(end) + + comment(# Considers each element of text (provided or internal\) as a paragraph.) + comment(# If <tt>#first_indent</tt> is the same as <tt>#body_indent</tt>, then) + comment(# paragraphs will be separated by a single empty line in the result;) + comment(# otherwise, the paragraphs will follow immediately after each other.) + comment(# Uses <tt>#format</tt> to do the heavy lifting.) + reserved(def) method(paragraphs)operator(()ident(to_wrap) operator(=) pre_constant(nil)operator(\)) + ident(to_wrap) operator(=) instance_variable(@text) reserved(if) ident(to_wrap)operator(.)ident(nil?) + ident(__paragraphs)operator(()operator([)ident(to_wrap)operator(])operator(.)ident(flatten)operator(\)) + reserved(end) + + comment(# Centers the text, preserving empty lines and tabs.) + reserved(def) method(center)operator(()ident(to_center) operator(=) pre_constant(nil)operator(\)) + ident(to_center) operator(=) instance_variable(@text) reserved(if) ident(to_center)operator(.)ident(nil?) + ident(__center)operator(()operator([)ident(to_center)operator(])operator(.)ident(flatten)operator(\)) + reserved(end) + + comment(# Replaces all tab characters in the text with <tt>#tabstop</tt> spaces.) + reserved(def) method(expand)operator(()ident(to_expand) operator(=) pre_constant(nil)operator(\)) + ident(to_expand) operator(=) instance_variable(@text) reserved(if) ident(to_expand)operator(.)ident(nil?) + reserved(if) ident(to_expand)operator(.)ident(class) operator(==) constant(Array) + ident(to_expand)operator(.)ident(collect) operator({) operator(|)ident(te)operator(|) ident(__expand)operator(()ident(te)operator(\)) operator(}) + reserved(else) + ident(__expand)operator(()ident(to_expand)operator(\)) + reserved(end) + reserved(end) + + comment(# Replaces all occurrences of <tt>#tabstop</tt> consecutive spaces) + comment(# with a tab character.) + reserved(def) method(unexpand)operator(()ident(to_unexpand) operator(=) pre_constant(nil)operator(\)) + ident(to_unexpand) operator(=) instance_variable(@text) reserved(if) ident(to_unexpand)operator(.)ident(nil?) + reserved(if) ident(to_unexpand)operator(.)ident(class) operator(==) constant(Array) + ident(to_unexpand)operator(.)ident(collect) operator({) operator(|)ident(te)operator(|) ident(v) operator(<<) ident(__unexpand)operator(()ident(te)operator(\)) operator(}) + reserved(else) + ident(__unexpand)operator(()ident(to_unexpand)operator(\)) + reserved(end) + reserved(end) + + comment(# This constructor takes advantage of a technique for Ruby object) + comment(# construction introduced by Andy Hunt and Dave Thomas (see reference\),) + comment(# where optional values are set using commands in a block.) + comment(#) + comment(# Text::Format.new {) + comment(# columns = 72) + comment(# left_margin = 0) + comment(# right_margin = 0) + comment(# first_indent = 4) + comment(# body_indent = 0) + comment(# format_style = Text::Format::LEFT_ALIGN) + comment(# extra_space = false) + comment(# abbreviations = {}) + comment(# tag_paragraph = false) + comment(# tag_text = []) + comment(# nobreak = false) + comment(# nobreak_regex = {}) + comment(# tabstop = 8) + comment(# text = nil) + comment(# }) + comment(#) + comment(# As shown above, +arg+ is optional. If +arg+ is specified and is a) + comment(# +String+, then arg is used as the default value of <tt>#text</tt>.) + comment(# Alternately, an existing Text::Format object can be used or a Hash can) + comment(# be used. With all forms, a block can be specified.) + comment(#) + comment(# *Reference*:: "Object Construction and Blocks") + comment(# <http://www.pragmaticprogrammer.com/ruby/articles/insteval.html>) + comment(#) + reserved(def) method(initialize)operator(()ident(arg) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + reserved(case) ident(arg) + reserved(when) constant(Text)operator(::)constant(Format) + ident(__create)operator(()ident(arg)operator(.)ident(text)operator(\)) reserved(do) + instance_variable(@columns) operator(=) ident(arg)operator(.)ident(columns) + instance_variable(@tabstop) operator(=) ident(arg)operator(.)ident(tabstop) + instance_variable(@first_indent) operator(=) ident(arg)operator(.)ident(first_indent) + instance_variable(@body_indent) operator(=) ident(arg)operator(.)ident(body_indent) + instance_variable(@format_style) operator(=) ident(arg)operator(.)ident(format_style) + instance_variable(@left_margin) operator(=) ident(arg)operator(.)ident(left_margin) + instance_variable(@right_margin) operator(=) ident(arg)operator(.)ident(right_margin) + instance_variable(@extra_space) operator(=) ident(arg)operator(.)ident(extra_space) + instance_variable(@tag_paragraph) operator(=) ident(arg)operator(.)ident(tag_paragraph) + instance_variable(@tag_text) operator(=) ident(arg)operator(.)ident(tag_text) + instance_variable(@abbreviations) operator(=) ident(arg)operator(.)ident(abbreviations) + instance_variable(@nobreak) operator(=) ident(arg)operator(.)ident(nobreak) + instance_variable(@nobreak_regex) operator(=) ident(arg)operator(.)ident(nobreak_regex) + instance_variable(@text) operator(=) ident(arg)operator(.)ident(text) + instance_variable(@hard_margins) operator(=) ident(arg)operator(.)ident(hard_margins) + instance_variable(@split_words) operator(=) ident(arg)operator(.)ident(split_words) + instance_variable(@split_rules) operator(=) ident(arg)operator(.)ident(split_rules) + instance_variable(@hyphenator) operator(=) ident(arg)operator(.)ident(hyphenator) + reserved(end) + ident(instance_eval)operator(()operator(&)ident(block)operator(\)) reserved(unless) ident(block)operator(.)ident(nil?) + reserved(when) constant(Hash) + ident(__create) reserved(do) + instance_variable(@columns) operator(=) ident(arg)operator([)symbol(:columns)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(columns)delimiter(')>operator(]) operator(||) instance_variable(@columns) + instance_variable(@tabstop) operator(=) ident(arg)operator([)symbol(:tabstop)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(tabstop)delimiter(')>operator(]) operator(||) instance_variable(@tabstop) + instance_variable(@first_indent) operator(=) ident(arg)operator([)symbol(:first_indent)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(first_indent)delimiter(')>operator(]) operator(||) instance_variable(@first_indent) + instance_variable(@body_indent) operator(=) ident(arg)operator([)symbol(:body_indent)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(body_indent)delimiter(')>operator(]) operator(||) instance_variable(@body_indent) + instance_variable(@format_style) operator(=) ident(arg)operator([)symbol(:format_style)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(format_style)delimiter(')>operator(]) operator(||) instance_variable(@format_style) + instance_variable(@left_margin) operator(=) ident(arg)operator([)symbol(:left_margin)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(left_margin)delimiter(')>operator(]) operator(||) instance_variable(@left_margin) + instance_variable(@right_margin) operator(=) ident(arg)operator([)symbol(:right_margin)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(right_margin)delimiter(')>operator(]) operator(||) instance_variable(@right_margin) + instance_variable(@extra_space) operator(=) ident(arg)operator([)symbol(:extra_space)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(extra_space)delimiter(')>operator(]) operator(||) instance_variable(@extra_space) + instance_variable(@text) operator(=) ident(arg)operator([)symbol(:text)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(text)delimiter(')>operator(]) operator(||) instance_variable(@text) + instance_variable(@tag_paragraph) operator(=) ident(arg)operator([)symbol(:tag_paragraph)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(tag_paragraph)delimiter(')>operator(]) operator(||) instance_variable(@tag_paragraph) + instance_variable(@tag_text) operator(=) ident(arg)operator([)symbol(:tag_text)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(tag_text)delimiter(')>operator(]) operator(||) instance_variable(@tag_text) + instance_variable(@abbreviations) operator(=) ident(arg)operator([)symbol(:abbreviations)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(abbreviations)delimiter(')>operator(]) operator(||) instance_variable(@abbreviations) + instance_variable(@nobreak) operator(=) ident(arg)operator([)symbol(:nobreak)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(nobreak)delimiter(')>operator(]) operator(||) instance_variable(@nobreak) + instance_variable(@nobreak_regex) operator(=) ident(arg)operator([)symbol(:nobreak_regex)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(nobreak_regex)delimiter(')>operator(]) operator(||) instance_variable(@nobreak_regex) + instance_variable(@hard_margins) operator(=) ident(arg)operator([)symbol(:hard_margins)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(hard_margins)delimiter(')>operator(]) operator(||) instance_variable(@hard_margins) + instance_variable(@split_rules) operator(=) ident(arg)operator([)symbol(:split_rules)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(split_rules)delimiter(')>operator(]) operator(||) instance_variable(@split_rules) + instance_variable(@hyphenator) operator(=) ident(arg)operator([)symbol(:hyphenator)operator(]) operator(||) ident(arg)operator([)string<delimiter(')content(hyphenator)delimiter(')>operator(]) operator(||) instance_variable(@hyphenator) + reserved(end) + ident(instance_eval)operator(()operator(&)ident(block)operator(\)) reserved(unless) ident(block)operator(.)ident(nil?) + reserved(when) constant(String) + ident(__create)operator(()ident(arg)operator(,) operator(&)ident(block)operator(\)) + reserved(when) constant(NilClass) + ident(__create)operator(()operator(&)ident(block)operator(\)) + reserved(else) + ident(raise) constant(TypeError) + reserved(end) + reserved(end) + reserved(end) +reserved(end) + +reserved(if) pre_constant(__FILE__) operator(==) global_variable($0) + ident(require) string<delimiter(')content(test/unit)delimiter(')> + + reserved(class) class(TestText__Format) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) comment(#:nodoc:) + ident(attr_accessor) symbol(:format_o) + + constant(GETTYSBURG) operator(=) string<delimiter(<<-'EOS')>string<content( + Four score and seven years ago our fathers brought forth on this + continent a new nation, conceived in liberty and dedicated to the + proposition that all men are created equal. Now we are engaged in + a great civil war, testing whether that nation or any nation so + conceived and so dedicated can long endure. We are met on a great + battlefield of that war. We have come to dedicate a portion of + that field as a final resting-place for those who here gave their + lives that that nation might live. It is altogether fitting and + proper that we should do this. But in a larger sense, we cannot + dedicate, we cannot consecrate, we cannot hallow this ground. + The brave men, living and dead who struggled here have consecrated + it far above our poor power to add or detract. The world will + little note nor long remember what we say here, but it can never + forget what they did here. It is for us the living rather to be + dedicated here to the unfinished work which they who fought here + have thus far so nobly advanced. It is rather for us to be here + dedicated to the great task remaining before us--that from these + honored dead we take increased devotion to that cause for which + they gave the last full measure of devotion--that we here highly + resolve that these dead shall not have died in vain, that this + nation under God shall have a new birth of freedom, and that + government of the people, by the people, for the people shall + not perish from the earth. + + -- Pres. Abraham Lincoln, 19 November 1863)delimiter( + EOS)> + + constant(FIVE_COL) operator(=) string<delimiter(")content(Four )char(\\n)content(score)char(\\n)content(and s)char(\\n)content(even )char(\\n)content(years)char(\\n)content(ago o)char(\\n)content(ur fa)char(\\n)content(thers)char(\\n)content(broug)char(\\n)content(ht fo)char(\\n)content(rth o)char(\\n)content(n thi)char(\\n)content(s con)char(\\n)content(tinen)char(\\n)content(t a n)char(\\n)content(ew na)char(\\n)content(tion,)char(\\n)content(conce)char(\\n)content(ived )char(\\n)content(in li)char(\\n)content(berty)char(\\n)content(and d)char(\\n)content(edica)char(\\n)content(ted t)char(\\n)content(o the)char(\\n)content(propo)char(\\n)content(sitio)char(\\n)content(n tha)char(\\n)content(t all)char(\\n)content(men a)char(\\n)content(re cr)char(\\n)content(eated)char(\\n)content(equal)char(\\n)content(. Now)char(\\n)content(we ar)char(\\n)content(e eng)char(\\n)content(aged )char(\\n)content(in a )char(\\n)content(great)char(\\n)content(civil)char(\\n)content(war, )char(\\n)content(testi)char(\\n)content(ng wh)char(\\n)content(ether)char(\\n)content(that )char(\\n)content(natio)char(\\n)content(n or )char(\\n)content(any n)char(\\n)content(ation)char(\\n)content(so co)char(\\n)content(nceiv)char(\\n)content(ed an)char(\\n)content(d so )char(\\n)content(dedic)char(\\n)content(ated )char(\\n)content(can l)char(\\n)content(ong e)char(\\n)content(ndure)char(\\n)content(. We )char(\\n)content(are m)char(\\n)content(et on)char(\\n)content(a gre)char(\\n)content(at ba)char(\\n)content(ttlef)char(\\n)content(ield )char(\\n)content(of th)char(\\n)content(at wa)char(\\n)content(r. We)char(\\n)content(have )char(\\n)content(come )char(\\n)content(to de)char(\\n)content(dicat)char(\\n)content(e a p)char(\\n)content(ortio)char(\\n)content(n of )char(\\n)content(that )char(\\n)content(field)char(\\n)content(as a )char(\\n)content(final)char(\\n)content(resti)char(\\n)content(ng-pl)char(\\n)content(ace f)char(\\n)content(or th)char(\\n)content(ose w)char(\\n)content(ho he)char(\\n)content(re ga)char(\\n)content(ve th)char(\\n)content(eir l)char(\\n)content(ives )char(\\n)content(that )char(\\n)content(that )char(\\n)content(natio)char(\\n)content(n mig)char(\\n)content(ht li)char(\\n)content(ve. I)char(\\n)content(t is )char(\\n)content(altog)char(\\n)content(ether)char(\\n)content(fitti)char(\\n)content(ng an)char(\\n)content(d pro)char(\\n)content(per t)char(\\n)content(hat w)char(\\n)content(e sho)char(\\n)content(uld d)char(\\n)content(o thi)char(\\n)content(s. Bu)char(\\n)content(t in )char(\\n)content(a lar)char(\\n)content(ger s)char(\\n)content(ense,)char(\\n)content(we ca)char(\\n)content(nnot )char(\\n)content(dedic)char(\\n)content(ate, )char(\\n)content(we ca)char(\\n)content(nnot )char(\\n)content(conse)char(\\n)content(crate)char(\\n)content(, we )char(\\n)content(canno)char(\\n)content(t hal)char(\\n)content(low t)char(\\n)content(his g)char(\\n)content(round)char(\\n)content(. The)char(\\n)content(brave)char(\\n)content(men, )char(\\n)content(livin)char(\\n)content(g and)char(\\n)content(dead )char(\\n)content(who s)char(\\n)content(trugg)char(\\n)content(led h)char(\\n)content(ere h)char(\\n)content(ave c)char(\\n)content(onsec)char(\\n)content(rated)char(\\n)content(it fa)char(\\n)content(r abo)char(\\n)content(ve ou)char(\\n)content(r poo)char(\\n)content(r pow)char(\\n)content(er to)char(\\n)content(add o)char(\\n)content(r det)char(\\n)content(ract.)char(\\n)content(The w)char(\\n)content(orld )char(\\n)content(will )char(\\n)content(littl)char(\\n)content(e not)char(\\n)content(e nor)char(\\n)content(long )char(\\n)content(remem)char(\\n)content(ber w)char(\\n)content(hat w)char(\\n)content(e say)char(\\n)content(here,)char(\\n)content(but i)char(\\n)content(t can)char(\\n)content(never)char(\\n)content(forge)char(\\n)content(t wha)char(\\n)content(t the)char(\\n)content(y did)char(\\n)content(here.)char(\\n)content(It is)char(\\n)content(for u)char(\\n)content(s the)char(\\n)content(livin)char(\\n)content(g rat)char(\\n)content(her t)char(\\n)content(o be )char(\\n)content(dedic)char(\\n)content(ated )char(\\n)content(here )char(\\n)content(to th)char(\\n)content(e unf)char(\\n)content(inish)char(\\n)content(ed wo)char(\\n)content(rk wh)char(\\n)content(ich t)char(\\n)content(hey w)char(\\n)content(ho fo)char(\\n)content(ught )char(\\n)content(here )char(\\n)content(have )char(\\n)content(thus )char(\\n)content(far s)char(\\n)content(o nob)char(\\n)content(ly ad)char(\\n)content(vance)char(\\n)content(d. It)char(\\n)content(is ra)char(\\n)content(ther )char(\\n)content(for u)char(\\n)content(s to )char(\\n)content(be he)char(\\n)content(re de)char(\\n)content(dicat)char(\\n)content(ed to)char(\\n)content(the g)char(\\n)content(reat )char(\\n)content(task )char(\\n)content(remai)char(\\n)content(ning )char(\\n)content(befor)char(\\n)content(e us-)char(\\n)content(-that)char(\\n)content(from )char(\\n)content(these)char(\\n)content(honor)char(\\n)content(ed de)char(\\n)content(ad we)char(\\n)content(take )char(\\n)content(incre)char(\\n)content(ased )char(\\n)content(devot)char(\\n)content(ion t)char(\\n)content(o tha)char(\\n)content(t cau)char(\\n)content(se fo)char(\\n)content(r whi)char(\\n)content(ch th)char(\\n)content(ey ga)char(\\n)content(ve th)char(\\n)content(e las)char(\\n)content(t ful)char(\\n)content(l mea)char(\\n)content(sure )char(\\n)content(of de)char(\\n)content(votio)char(\\n)content(n--th)char(\\n)content(at we)char(\\n)content(here )char(\\n)content(highl)char(\\n)content(y res)char(\\n)content(olve )char(\\n)content(that )char(\\n)content(these)char(\\n)content(dead )char(\\n)content(shall)char(\\n)content(not h)char(\\n)content(ave d)char(\\n)content(ied i)char(\\n)content(n vai)char(\\n)content(n, th)char(\\n)content(at th)char(\\n)content(is na)char(\\n)content(tion )char(\\n)content(under)char(\\n)content(God s)char(\\n)content(hall )char(\\n)content(have )char(\\n)content(a new)char(\\n)content(birth)char(\\n)content(of fr)char(\\n)content(eedom)char(\\n)content(, and)char(\\n)content(that )char(\\n)content(gover)char(\\n)content(nment)char(\\n)content(of th)char(\\n)content(e peo)char(\\n)content(ple, )char(\\n)content(by th)char(\\n)content(e peo)char(\\n)content(ple, )char(\\n)content(for t)char(\\n)content(he pe)char(\\n)content(ople )char(\\n)content(shall)char(\\n)content(not p)char(\\n)content(erish)char(\\n)content(from )char(\\n)content(the e)char(\\n)content(arth.)char(\\n)content(-- Pr)char(\\n)content(es. A)char(\\n)content(braha)char(\\n)content(m Lin)char(\\n)content(coln,)char(\\n)content(19 No)char(\\n)content(vembe)char(\\n)content(r 186)char(\\n)content(3 )char(\\n)delimiter(")> + + constant(FIVE_CNT) operator(=) string<delimiter(")content(Four )char(\\n)content(score)char(\\n)content(and )char(\\n)content(seven)char(\\n)content(years)char(\\n)content(ago )char(\\n)content(our )char(\\n)content(fath)char(\\\\)char(\\n)content(ers )char(\\n)content(brou)char(\\\\)char(\\n)content(ght )char(\\n)content(forth)char(\\n)content(on t)char(\\\\)char(\\n)content(his )char(\\n)content(cont)char(\\\\)char(\\n)content(inent)char(\\n)content(a new)char(\\n)content(nati)char(\\\\)char(\\n)content(on, )char(\\n)content(conc)char(\\\\)char(\\n)content(eived)char(\\n)content(in l)char(\\\\)char(\\n)content(iber)char(\\\\)char(\\n)content(ty a)char(\\\\)char(\\n)content(nd d)char(\\\\)char(\\n)content(edic)char(\\\\)char(\\n)content(ated )char(\\n)content(to t)char(\\\\)char(\\n)content(he p)char(\\\\)char(\\n)content(ropo)char(\\\\)char(\\n)content(siti)char(\\\\)char(\\n)content(on t)char(\\\\)char(\\n)content(hat )char(\\n)content(all )char(\\n)content(men )char(\\n)content(are )char(\\n)content(crea)char(\\\\)char(\\n)content(ted )char(\\n)content(equa)char(\\\\)char(\\n)content(l. N)char(\\\\)char(\\n)content(ow we)char(\\n)content(are )char(\\n)content(enga)char(\\\\)char(\\n)content(ged )char(\\n)content(in a )char(\\n)content(great)char(\\n)content(civil)char(\\n)content(war, )char(\\n)content(test)char(\\\\)char(\\n)content(ing )char(\\n)content(whet)char(\\\\)char(\\n)content(her )char(\\n)content(that )char(\\n)content(nati)char(\\\\)char(\\n)content(on or)char(\\n)content(any )char(\\n)content(nati)char(\\\\)char(\\n)content(on so)char(\\n)content(conc)char(\\\\)char(\\n)content(eived)char(\\n)content(and )char(\\n)content(so d)char(\\\\)char(\\n)content(edic)char(\\\\)char(\\n)content(ated )char(\\n)content(can )char(\\n)content(long )char(\\n)content(endu)char(\\\\)char(\\n)content(re. )char(\\n)content(We a)char(\\\\)char(\\n)content(re m)char(\\\\)char(\\n)content(et on)char(\\n)content(a gr)char(\\\\)char(\\n)content(eat )char(\\n)content(batt)char(\\\\)char(\\n)content(lefi)char(\\\\)char(\\n)content(eld )char(\\n)content(of t)char(\\\\)char(\\n)content(hat )char(\\n)content(war. )char(\\n)content(We h)char(\\\\)char(\\n)content(ave )char(\\n)content(come )char(\\n)content(to d)char(\\\\)char(\\n)content(edic)char(\\\\)char(\\n)content(ate a)char(\\n)content(port)char(\\\\)char(\\n)content(ion )char(\\n)content(of t)char(\\\\)char(\\n)content(hat )char(\\n)content(field)char(\\n)content(as a )char(\\n)content(final)char(\\n)content(rest)char(\\\\)char(\\n)content(ing-)char(\\\\)char(\\n)content(place)char(\\n)content(for )char(\\n)content(those)char(\\n)content(who )char(\\n)content(here )char(\\n)content(gave )char(\\n)content(their)char(\\n)content(lives)char(\\n)content(that )char(\\n)content(that )char(\\n)content(nati)char(\\\\)char(\\n)content(on m)char(\\\\)char(\\n)content(ight )char(\\n)content(live.)char(\\n)content(It is)char(\\n)content(alto)char(\\\\)char(\\n)content(geth)char(\\\\)char(\\n)content(er f)char(\\\\)char(\\n)content(itti)char(\\\\)char(\\n)content(ng a)char(\\\\)char(\\n)content(nd p)char(\\\\)char(\\n)content(roper)char(\\n)content(that )char(\\n)content(we s)char(\\\\)char(\\n)content(hould)char(\\n)content(do t)char(\\\\)char(\\n)content(his. )char(\\n)content(But )char(\\n)content(in a )char(\\n)content(larg)char(\\\\)char(\\n)content(er s)char(\\\\)char(\\n)content(ense,)char(\\n)content(we c)char(\\\\)char(\\n)content(annot)char(\\n)content(dedi)char(\\\\)char(\\n)content(cate,)char(\\n)content(we c)char(\\\\)char(\\n)content(annot)char(\\n)content(cons)char(\\\\)char(\\n)content(ecra)char(\\\\)char(\\n)content(te, )char(\\n)content(we c)char(\\\\)char(\\n)content(annot)char(\\n)content(hall)char(\\\\)char(\\n)content(ow t)char(\\\\)char(\\n)content(his )char(\\n)content(grou)char(\\\\)char(\\n)content(nd. )char(\\n)content(The )char(\\n)content(brave)char(\\n)content(men, )char(\\n)content(livi)char(\\\\)char(\\n)content(ng a)char(\\\\)char(\\n)content(nd d)char(\\\\)char(\\n)content(ead )char(\\n)content(who )char(\\n)content(stru)char(\\\\)char(\\n)content(ggled)char(\\n)content(here )char(\\n)content(have )char(\\n)content(cons)char(\\\\)char(\\n)content(ecra)char(\\\\)char(\\n)content(ted )char(\\n)content(it f)char(\\\\)char(\\n)content(ar a)char(\\\\)char(\\n)content(bove )char(\\n)content(our )char(\\n)content(poor )char(\\n)content(power)char(\\n)content(to a)char(\\\\)char(\\n)content(dd or)char(\\n)content(detr)char(\\\\)char(\\n)content(act. )char(\\n)content(The )char(\\n)content(world)char(\\n)content(will )char(\\n)content(litt)char(\\\\)char(\\n)content(le n)char(\\\\)char(\\n)content(ote )char(\\n)content(nor )char(\\n)content(long )char(\\n)content(reme)char(\\\\)char(\\n)content(mber )char(\\n)content(what )char(\\n)content(we s)char(\\\\)char(\\n)content(ay h)char(\\\\)char(\\n)content(ere, )char(\\n)content(but )char(\\n)content(it c)char(\\\\)char(\\n)content(an n)char(\\\\)char(\\n)content(ever )char(\\n)content(forg)char(\\\\)char(\\n)content(et w)char(\\\\)char(\\n)content(hat )char(\\n)content(they )char(\\n)content(did )char(\\n)content(here.)char(\\n)content(It is)char(\\n)content(for )char(\\n)content(us t)char(\\\\)char(\\n)content(he l)char(\\\\)char(\\n)content(iving)char(\\n)content(rath)char(\\\\)char(\\n)content(er to)char(\\n)content(be d)char(\\\\)char(\\n)content(edic)char(\\\\)char(\\n)content(ated )char(\\n)content(here )char(\\n)content(to t)char(\\\\)char(\\n)content(he u)char(\\\\)char(\\n)content(nfin)char(\\\\)char(\\n)content(ished)char(\\n)content(work )char(\\n)content(which)char(\\n)content(they )char(\\n)content(who )char(\\n)content(foug)char(\\\\)char(\\n)content(ht h)char(\\\\)char(\\n)content(ere )char(\\n)content(have )char(\\n)content(thus )char(\\n)content(far )char(\\n)content(so n)char(\\\\)char(\\n)content(obly )char(\\n)content(adva)char(\\\\)char(\\n)content(nced.)char(\\n)content(It is)char(\\n)content(rath)char(\\\\)char(\\n)content(er f)char(\\\\)char(\\n)content(or us)char(\\n)content(to be)char(\\n)content(here )char(\\n)content(dedi)char(\\\\)char(\\n)content(cated)char(\\n)content(to t)char(\\\\)char(\\n)content(he g)char(\\\\)char(\\n)content(reat )char(\\n)content(task )char(\\n)content(rema)char(\\\\)char(\\n)content(ining)char(\\n)content(befo)char(\\\\)char(\\n)content(re u)char(\\\\)char(\\n)content(s--t)char(\\\\)char(\\n)content(hat )char(\\n)content(from )char(\\n)content(these)char(\\n)content(hono)char(\\\\)char(\\n)content(red )char(\\n)content(dead )char(\\n)content(we t)char(\\\\)char(\\n)content(ake )char(\\n)content(incr)char(\\\\)char(\\n)content(eased)char(\\n)content(devo)char(\\\\)char(\\n)content(tion )char(\\n)content(to t)char(\\\\)char(\\n)content(hat )char(\\n)content(cause)char(\\n)content(for )char(\\n)content(which)char(\\n)content(they )char(\\n)content(gave )char(\\n)content(the )char(\\n)content(last )char(\\n)content(full )char(\\n)content(meas)char(\\\\)char(\\n)content(ure )char(\\n)content(of d)char(\\\\)char(\\n)content(evot)char(\\\\)char(\\n)content(ion-)char(\\\\)char(\\n)content(-that)char(\\n)content(we h)char(\\\\)char(\\n)content(ere )char(\\n)content(high)char(\\\\)char(\\n)content(ly r)char(\\\\)char(\\n)content(esol)char(\\\\)char(\\n)content(ve t)char(\\\\)char(\\n)content(hat )char(\\n)content(these)char(\\n)content(dead )char(\\n)content(shall)char(\\n)content(not )char(\\n)content(have )char(\\n)content(died )char(\\n)content(in v)char(\\\\)char(\\n)content(ain, )char(\\n)content(that )char(\\n)content(this )char(\\n)content(nati)char(\\\\)char(\\n)content(on u)char(\\\\)char(\\n)content(nder )char(\\n)content(God )char(\\n)content(shall)char(\\n)content(have )char(\\n)content(a new)char(\\n)content(birth)char(\\n)content(of f)char(\\\\)char(\\n)content(reed)char(\\\\)char(\\n)content(om, )char(\\n)content(and )char(\\n)content(that )char(\\n)content(gove)char(\\\\)char(\\n)content(rnme)char(\\\\)char(\\n)content(nt of)char(\\n)content(the )char(\\n)content(peop)char(\\\\)char(\\n)content(le, )char(\\n)content(by t)char(\\\\)char(\\n)content(he p)char(\\\\)char(\\n)content(eopl)char(\\\\)char(\\n)content(e, f)char(\\\\)char(\\n)content(or t)char(\\\\)char(\\n)content(he p)char(\\\\)char(\\n)content(eople)char(\\n)content(shall)char(\\n)content(not )char(\\n)content(peri)char(\\\\)char(\\n)content(sh f)char(\\\\)char(\\n)content(rom )char(\\n)content(the )char(\\n)content(eart)char(\\\\)char(\\n)content(h. --)char(\\n)content(Pres.)char(\\n)content(Abra)char(\\\\)char(\\n)content(ham )char(\\n)content(Linc)char(\\\\)char(\\n)content(oln, )char(\\n)content(19 N)char(\\\\)char(\\n)content(ovem)char(\\\\)char(\\n)content(ber )char(\\n)content(1863 )char(\\n)delimiter(")> + + comment(# Tests both abbreviations and abbreviations=) + reserved(def) method(test_abbreviations) + ident(abbr) operator(=) operator([)string<delimiter(")content( Pres. Abraham Lincoln)char(\\n)delimiter(")>operator(,) string<delimiter(")content( Pres. Abraham Lincoln)char(\\n)delimiter(")>operator(]) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()operator([)operator(])operator(,) instance_variable(@format_o)operator(.)ident(abbreviations)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(abbreviations) operator(=) operator([) string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')> operator(]) operator(}) + ident(assert_equal)operator(()operator([) string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')> operator(])operator(,) instance_variable(@format_o)operator(.)ident(abbreviations)operator(\)) + ident(assert_equal)operator(()ident(abbr)operator([)integer(0)operator(])operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(abbr)operator([)integer(0)operator(])operator(\))operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(extra_space) operator(=) pre_constant(true) operator(}) + ident(assert_equal)operator(()ident(abbr)operator([)integer(1)operator(])operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(abbr)operator([)integer(0)operator(])operator(\))operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(abbreviations) operator(=) operator([) string<delimiter(")content(Pres)delimiter(")> operator(]) operator(}) + ident(assert_equal)operator(()operator([) string<delimiter(")content(Pres)delimiter(")> operator(])operator(,) instance_variable(@format_o)operator(.)ident(abbreviations)operator(\)) + ident(assert_equal)operator(()ident(abbr)operator([)integer(0)operator(])operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(abbr)operator([)integer(0)operator(])operator(\))operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(extra_space) operator(=) pre_constant(false) operator(}) + ident(assert_equal)operator(()ident(abbr)operator([)integer(0)operator(])operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(abbr)operator([)integer(0)operator(])operator(\))operator(\)) + reserved(end) + + comment(# Tests both body_indent and body_indent=) + reserved(def) method(test_body_indent) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()integer(0)operator(,) instance_variable(@format_o)operator(.)ident(body_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(body_indent) operator(=) integer(7) operator(}) + ident(assert_equal)operator(()integer(7)operator(,) instance_variable(@format_o)operator(.)ident(body_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(body_indent) operator(=) integer(-3) operator(}) + ident(assert_equal)operator(()integer(3)operator(,) instance_variable(@format_o)operator(.)ident(body_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(body_indent) operator(=) string<delimiter(")content(9)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(9)operator(,) instance_variable(@format_o)operator(.)ident(body_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(body_indent) operator(=) string<delimiter(")content(-2)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(2)operator(,) instance_variable(@format_o)operator(.)ident(body_indent)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ [^ ])delimiter(/)>operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(1)operator(])operator(\)) + reserved(end) + + comment(# Tests both columns and columns=) + reserved(def) method(test_columns) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()integer(72)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(columns) operator(=) integer(7) operator(}) + ident(assert_equal)operator(()integer(7)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(columns) operator(=) integer(-3) operator(}) + ident(assert_equal)operator(()integer(3)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(columns) operator(=) string<delimiter(")content(9)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(9)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(columns) operator(=) string<delimiter(")content(-2)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(2)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(columns) operator(=) integer(40) operator(}) + ident(assert_equal)operator(()integer(40)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(this continent$)delimiter(/)>operator(,) + instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(1)operator(])operator(\)) + reserved(end) + + comment(# Tests both extra_space and extra_space=) + reserved(def) method(test_extra_space) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(extra_space)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(extra_space) operator(=) pre_constant(true) operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(extra_space)operator(\)) + comment(# The behaviour of extra_space is tested in test_abbreviations. There) + comment(# is no need to reproduce it here.) + reserved(end) + + comment(# Tests both first_indent and first_indent=) + reserved(def) method(test_first_indent) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()integer(4)operator(,) instance_variable(@format_o)operator(.)ident(first_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(first_indent) operator(=) integer(7) operator(}) + ident(assert_equal)operator(()integer(7)operator(,) instance_variable(@format_o)operator(.)ident(first_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(first_indent) operator(=) integer(-3) operator(}) + ident(assert_equal)operator(()integer(3)operator(,) instance_variable(@format_o)operator(.)ident(first_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(first_indent) operator(=) string<delimiter(")content(9)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(9)operator(,) instance_variable(@format_o)operator(.)ident(first_indent)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(first_indent) operator(=) string<delimiter(")content(-2)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(2)operator(,) instance_variable(@format_o)operator(.)ident(first_indent)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ [^ ])delimiter(/)>operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(0)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_format_style) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()constant(Text)operator(::)constant(Format)operator(::)constant(LEFT_ALIGN)operator(,) instance_variable(@format_o)operator(.)ident(format_style)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^November 1863$)delimiter(/)>operator(,) + instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(-1)operator(])operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_ALIGN) + operator(}) + ident(assert_equal)operator(()constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_ALIGN)operator(,) instance_variable(@format_o)operator(.)ident(format_style)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ +November 1863$)delimiter(/)>operator(,) + instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(-1)operator(])operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL) + operator(}) + ident(assert_equal)operator(()constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL)operator(,) instance_variable(@format_o)operator(.)ident(format_style)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^November 1863 +$)delimiter(/)>operator(,) + instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(-1)operator(])operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(JUSTIFY) operator(}) + ident(assert_equal)operator(()constant(Text)operator(::)constant(Format)operator(::)constant(JUSTIFY)operator(,) instance_variable(@format_o)operator(.)ident(format_style)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^of freedom, and that government of the people, by the people, for the$)delimiter(/)>operator(,) + instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(-3)operator(])operator(\)) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) instance_variable(@format_o)operator(.)ident(format_style) operator(=) integer(33) operator(}) + reserved(end) + + reserved(def) method(test_tag_paragraph) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(tag_paragraph)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tag_paragraph) operator(=) pre_constant(true) operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(tag_paragraph)operator(\)) + ident(assert_not_equal)operator(()instance_variable(@format_o)operator(.)ident(paragraphs)operator(()operator([)constant(GETTYSBURG)operator(,) constant(GETTYSBURG)operator(])operator(\))operator(,) + constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)constant(GETTYSBURG)operator(,) constant(GETTYSBURG)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_tag_text) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()operator([)operator(])operator(,) instance_variable(@format_o)operator(.)ident(tag_text)operator(\)) + ident(assert_equal)operator(()instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(,) + constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(tag_paragraph) operator(=) pre_constant(true) + instance_variable(@format_o)operator(.)ident(tag_text) operator(=) operator([)string<delimiter(")content(Gettysburg Address)delimiter(")>operator(,) string<delimiter(")content(---)delimiter(")>operator(]) + operator(}) + ident(assert_not_equal)operator(()instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(,) + constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(\)) + ident(assert_not_equal)operator(()instance_variable(@format_o)operator(.)ident(paragraphs)operator(()operator([)constant(GETTYSBURG)operator(,) constant(GETTYSBURG)operator(])operator(\))operator(,) + constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)constant(GETTYSBURG)operator(,) constant(GETTYSBURG)operator(])operator(\))operator(\)) + ident(assert_not_equal)operator(()instance_variable(@format_o)operator(.)ident(paragraphs)operator(()operator([)constant(GETTYSBURG)operator(,) constant(GETTYSBURG)operator(,) + constant(GETTYSBURG)operator(])operator(\))operator(,) + constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)constant(GETTYSBURG)operator(,) constant(GETTYSBURG)operator(,) + constant(GETTYSBURG)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_justify?) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(justify?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_ALIGN) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(justify?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(justify?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(JUSTIFY) + operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(justify?)operator(\)) + comment(# The format testing is done in test_format_style) + reserved(end) + + reserved(def) method(test_left_align?) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(left_align?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_ALIGN) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(left_align?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(left_align?)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(JUSTIFY) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(left_align?)operator(\)) + comment(# The format testing is done in test_format_style) + reserved(end) + + reserved(def) method(test_left_margin) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()integer(0)operator(,) instance_variable(@format_o)operator(.)ident(left_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(left_margin) operator(=) integer(-3) operator(}) + ident(assert_equal)operator(()integer(3)operator(,) instance_variable(@format_o)operator(.)ident(left_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(left_margin) operator(=) string<delimiter(")content(9)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(9)operator(,) instance_variable(@format_o)operator(.)ident(left_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(left_margin) operator(=) string<delimiter(")content(-2)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(2)operator(,) instance_variable(@format_o)operator(.)ident(left_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(left_margin) operator(=) integer(7) operator(}) + ident(assert_equal)operator(()integer(7)operator(,) instance_variable(@format_o)operator(.)ident(left_margin)operator(\)) + ident(assert_nothing_raised) operator({) + ident(ft) operator(=) instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ {11}Four score)delimiter(/)>operator(,) ident(ft)operator([)integer(0)operator(])operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ {7}November)delimiter(/)>operator(,) ident(ft)operator([)integer(-1)operator(])operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_hard_margins) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(hard_margins)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(hard_margins) operator(=) pre_constant(true) + instance_variable(@format_o)operator(.)ident(columns) operator(=) integer(5) + instance_variable(@format_o)operator(.)ident(first_indent) operator(=) integer(0) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL) + operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(hard_margins)operator(\)) + ident(assert_equal)operator(()constant(FIVE_COL)operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(split_rules) operator(|=) constant(Text)operator(::)constant(Format)operator(::)constant(SPLIT_CONTINUATION) + ident(assert_equal)operator(()constant(Text)operator(::)constant(Format)operator(::)constant(SPLIT_CONTINUATION_FIXED)operator(,) + instance_variable(@format_o)operator(.)ident(split_rules)operator(\)) + operator(}) + ident(assert_equal)operator(()constant(FIVE_CNT)operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(\)) + reserved(end) + + comment(# Tests both nobreak and nobreak_regex, since one is only useful) + comment(# with the other.) + reserved(def) method(test_nobreak) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(nobreak)operator(\)) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(nobreak_regex)operator(.)ident(empty?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(nobreak) operator(=) pre_constant(true) + instance_variable(@format_o)operator(.)ident(nobreak_regex) operator(=) operator({) string<delimiter(')content(^this$)delimiter(')> operator(=)operator(>) string<delimiter(')content(^continent$)delimiter(')> operator(}) + instance_variable(@format_o)operator(.)ident(columns) operator(=) integer(77) + operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(nobreak)operator(\)) + ident(assert_equal)operator(()operator({) string<delimiter(')content(^this$)delimiter(')> operator(=)operator(>) string<delimiter(')content(^continent$)delimiter(')> operator(})operator(,) instance_variable(@format_o)operator(.)ident(nobreak_regex)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^this continent)delimiter(/)>operator(,) + instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(1)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_right_align?) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(right_align?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_ALIGN) + operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(right_align?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(right_align?)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(JUSTIFY) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(right_align?)operator(\)) + comment(# The format testing is done in test_format_style) + reserved(end) + + reserved(def) method(test_right_fill?) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(right_fill?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_ALIGN) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(right_fill?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(RIGHT_FILL) + operator(}) + ident(assert)operator(()instance_variable(@format_o)operator(.)ident(right_fill?)operator(\)) + ident(assert_nothing_raised) operator({) + instance_variable(@format_o)operator(.)ident(format_style) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(JUSTIFY) + operator(}) + ident(assert)operator(()operator(!)instance_variable(@format_o)operator(.)ident(right_fill?)operator(\)) + comment(# The format testing is done in test_format_style) + reserved(end) + + reserved(def) method(test_right_margin) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()integer(0)operator(,) instance_variable(@format_o)operator(.)ident(right_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(right_margin) operator(=) integer(-3) operator(}) + ident(assert_equal)operator(()integer(3)operator(,) instance_variable(@format_o)operator(.)ident(right_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(right_margin) operator(=) string<delimiter(")content(9)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(9)operator(,) instance_variable(@format_o)operator(.)ident(right_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(right_margin) operator(=) string<delimiter(")content(-2)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(2)operator(,) instance_variable(@format_o)operator(.)ident(right_margin)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(right_margin) operator(=) integer(7) operator(}) + ident(assert_equal)operator(()integer(7)operator(,) instance_variable(@format_o)operator(.)ident(right_margin)operator(\)) + ident(assert_nothing_raised) operator({) + ident(ft) operator(=) instance_variable(@format_o)operator(.)ident(format)operator(()constant(GETTYSBURG)operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ {4}Four score.*forth on$)delimiter(/)>operator(,) ident(ft)operator([)integer(0)operator(])operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^November)delimiter(/)>operator(,) ident(ft)operator([)integer(-1)operator(])operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_tabstop) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()integer(8)operator(,) instance_variable(@format_o)operator(.)ident(tabstop)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tabstop) operator(=) integer(7) operator(}) + ident(assert_equal)operator(()integer(7)operator(,) instance_variable(@format_o)operator(.)ident(tabstop)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tabstop) operator(=) integer(-3) operator(}) + ident(assert_equal)operator(()integer(3)operator(,) instance_variable(@format_o)operator(.)ident(tabstop)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tabstop) operator(=) string<delimiter(")content(9)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(9)operator(,) instance_variable(@format_o)operator(.)ident(tabstop)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tabstop) operator(=) string<delimiter(")content(-2)delimiter(")> operator(}) + ident(assert_equal)operator(()integer(2)operator(,) instance_variable(@format_o)operator(.)ident(tabstop)operator(\)) + reserved(end) + + reserved(def) method(test_text) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()operator([)operator(])operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(text) operator(=) string<delimiter(")content(Test Text)delimiter(")> operator(}) + ident(assert_equal)operator(()string<delimiter(")content(Test Text)delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(text) operator(=) operator([)string<delimiter(")content(Line 1)delimiter(")>operator(,) string<delimiter(")content(Line 2)delimiter(")>operator(]) operator(}) + ident(assert_equal)operator(()operator([)string<delimiter(")content(Line 1)delimiter(")>operator(,) string<delimiter(")content(Line 2)delimiter(")>operator(])operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + reserved(end) + + reserved(def) method(test_s_new) + comment(# new(NilClass\) { block }) + ident(assert_nothing_raised) reserved(do) + instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator({) + pre_constant(self)operator(.)ident(text) operator(=) string<delimiter(")content(Test 1, 2, 3)delimiter(")> + operator(}) + reserved(end) + ident(assert_equal)operator(()string<delimiter(")content(Test 1, 2, 3)delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + + comment(# new(Hash Symbols\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()symbol(:columns) operator(=)operator(>) integer(72)operator(\)) operator(}) + ident(assert_equal)operator(()integer(72)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + + comment(# new(Hash String\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()string<delimiter(')content(columns)delimiter(')> operator(=)operator(>) integer(72)operator(\)) operator(}) + ident(assert_equal)operator(()integer(72)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + + comment(# new(Hash\) { block }) + ident(assert_nothing_raised) reserved(do) + instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()string<delimiter(')content(columns)delimiter(')> operator(=)operator(>) integer(80)operator(\)) operator({) + pre_constant(self)operator(.)ident(text) operator(=) string<delimiter(")content(Test 4, 5, 6)delimiter(")> + operator(}) + reserved(end) + ident(assert_equal)operator(()string<delimiter(")content(Test 4, 5, 6)delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + ident(assert_equal)operator(()integer(80)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + + comment(# new(Text::Format\)) + ident(assert_nothing_raised) reserved(do) + ident(fo) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()instance_variable(@format_o)operator(\)) + ident(assert)operator(()ident(fo) operator(==) instance_variable(@format_o)operator(\)) + reserved(end) + + comment(# new(Text::Format\) { block }) + ident(assert_nothing_raised) reserved(do) + ident(fo) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()instance_variable(@format_o)operator(\)) operator({) pre_constant(self)operator(.)ident(columns) operator(=) integer(79) operator(}) + ident(assert)operator(()ident(fo) operator(!=) instance_variable(@format_o)operator(\)) + reserved(end) + + comment(# new(String\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()string<delimiter(")content(Test A, B, C)delimiter(")>operator(\)) operator(}) + ident(assert_equal)operator(()string<delimiter(")content(Test A, B, C)delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + + comment(# new(String\) { block }) + ident(assert_nothing_raised) reserved(do) + instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()string<delimiter(")content(Test X, Y, Z)delimiter(")>operator(\)) operator({) pre_constant(self)operator(.)ident(columns) operator(=) integer(-5) operator(}) + reserved(end) + ident(assert_equal)operator(()string<delimiter(")content(Test X, Y, Z)delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(text)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@format_o)operator(.)ident(columns)operator(\)) + reserved(end) + + reserved(def) method(test_center) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_nothing_raised) reserved(do) + ident(ct) operator(=) instance_variable(@format_o)operator(.)ident(center)operator(()constant(GETTYSBURG)operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator(\))operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ Four score and seven years ago our fathers brought forth on this)delimiter(/)>operator(,) ident(ct)operator([)integer(0)operator(])operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(^ not perish from the earth.)delimiter(/)>operator(,) ident(ct)operator([)integer(-3)operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_expand) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()string<delimiter(")content( )delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(expand)operator(()string<delimiter(")char(\\t)content( )delimiter(")>operator(\))operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tabstop) operator(=) integer(4) operator(}) + ident(assert_equal)operator(()string<delimiter(")content( )delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(expand)operator(()string<delimiter(")char(\\t)content( )delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_unexpand) + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new) operator(}) + ident(assert_equal)operator(()string<delimiter(")char(\\t)content( )delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(unexpand)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(tabstop) operator(=) integer(4) operator(}) + ident(assert_equal)operator(()string<delimiter(")char(\\t)content( )delimiter(")>operator(,) instance_variable(@format_o)operator(.)ident(unexpand)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_space_only) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(format)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(format)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(format)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(format)operator(()string<delimiter(")content( )char(\\n)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()string<delimiter(")content( )char(\\n)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)string<delimiter(")char(\\n)delimiter(")>operator(])operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)string<delimiter(")content( )delimiter(")>operator(])operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)string<delimiter(")content( )delimiter(")>operator(])operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")delimiter(")>operator(,) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(.)ident(paragraphs)operator(()operator([)string<delimiter(")content( )char(\\n)delimiter(")>operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_splendiferous) + ident(h) operator(=) pre_constant(nil) + ident(test) operator(=) string<delimiter(")content(This is a splendiferous test)delimiter(")> + ident(assert_nothing_raised) operator({) instance_variable(@format_o) operator(=) constant(Text)operator(::)constant(Format)operator(.)ident(new)operator(()symbol(:columns) operator(=)operator(>) integer(6)operator(,) symbol(:left_margin) operator(=)operator(>) integer(0)operator(,) symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:first_indent) operator(=)operator(>) integer(0)operator(\)) operator(}) + ident(assert_match)operator(()regexp<delimiter(/)content(^splendiferous$)delimiter(/)>operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(test)operator(\))operator(\)) + ident(assert_nothing_raised) operator({) instance_variable(@format_o)operator(.)ident(hard_margins) operator(=) pre_constant(true) operator(}) + ident(assert_match)operator(()regexp<delimiter(/)content(^lendif$)delimiter(/)>operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(test)operator(\))operator(\)) + ident(assert_nothing_raised) operator({) ident(h) operator(=) constant(Object)operator(.)ident(new) operator(}) + ident(assert_nothing_raised) reserved(do) + instance_variable(@format_o)operator(.)ident(split_rules) operator(=) constant(Text)operator(::)constant(Format)operator(::)constant(SPLIT_HYPHENATION) + reserved(class) operator(<<) class(h) comment(#:nodoc:) + reserved(def) method(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(\)) + reserved(return) operator([)string<delimiter(")delimiter(")>operator(,) ident(word)operator(]) reserved(if) ident(size) operator(<) integer(2) + operator([)ident(word)operator([)integer(0) operator(...) ident(size)operator(])operator(,) ident(word)operator([)ident(size) operator(..) integer(-1)operator(])operator(]) + reserved(end) + reserved(end) + instance_variable(@format_o)operator(.)ident(hyphenator) operator(=) ident(h) + reserved(end) + ident(assert_match)operator(()regexp<delimiter(/)content(^iferou$)delimiter(/)>operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(test)operator(\))operator(\)) + ident(assert_nothing_raised) operator({) ident(h) operator(=) constant(Object)operator(.)ident(new) operator(}) + ident(assert_nothing_raised) reserved(do) + reserved(class) operator(<<) class(h) comment(#:nodoc:) + reserved(def) method(hyphenate_to)operator(()ident(word)operator(,) ident(size)operator(,) ident(formatter)operator(\)) + reserved(return) operator([)string<delimiter(")delimiter(")>operator(,) ident(word)operator(]) reserved(if) ident(word)operator(.)ident(size) operator(<) ident(formatter)operator(.)ident(columns) + operator([)ident(word)operator([)integer(0) operator(...) ident(size)operator(])operator(,) ident(word)operator([)ident(size) operator(..) integer(-1)operator(])operator(]) + reserved(end) + reserved(end) + instance_variable(@format_o)operator(.)ident(hyphenator) operator(=) ident(h) + reserved(end) + ident(assert_match)operator(()regexp<delimiter(/)content(^ferous$)delimiter(/)>operator(,) instance_variable(@format_o)operator(.)ident(format)operator(()ident(test)operator(\))operator(\)) + reserved(end) + reserved(end) +reserved(end) +comment(#) +comment(# address.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/encode)delimiter(')> +ident(require) string<delimiter(')content(tmail/parser)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Address) + + ident(include) constant(TextUtils) + + reserved(def) constant(Address)operator(.)ident(parse)operator(() ident(str) operator(\)) + constant(Parser)operator(.)ident(parse) symbol(:ADDRESS)operator(,) ident(str) + reserved(end) + + reserved(def) method(address_group?) + pre_constant(false) + reserved(end) + + reserved(def) method(initialize)operator(() ident(local)operator(,) ident(domain) operator(\)) + reserved(if) ident(domain) + ident(domain)operator(.)ident(each) reserved(do) operator(|)ident(s)operator(|) + ident(raise) constant(SyntaxError)operator(,) string<delimiter(')content(empty word in domain)delimiter(')> reserved(if) ident(s)operator(.)ident(empty?) + reserved(end) + reserved(end) + instance_variable(@local) operator(=) ident(local) + instance_variable(@domain) operator(=) ident(domain) + instance_variable(@name) operator(=) pre_constant(nil) + instance_variable(@routes) operator(=) operator([)operator(]) + reserved(end) + + ident(attr_reader) symbol(:name) + + reserved(def) method(name=)operator(() ident(str) operator(\)) + instance_variable(@name) operator(=) ident(str) + instance_variable(@name) operator(=) pre_constant(nil) reserved(if) ident(str) reserved(and) ident(str)operator(.)ident(empty?) + reserved(end) + + reserved(alias) method(phrase) method(name) + reserved(alias) method(phrase=) method(name=) + + ident(attr_reader) symbol(:routes) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(address)operator(()operator(\))inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(local) + reserved(return) pre_constant(nil) reserved(unless) instance_variable(@local) + reserved(return) string<delimiter(')content("")delimiter(')> reserved(if) instance_variable(@local)operator(.)ident(size) operator(==) integer(1) reserved(and) instance_variable(@local)operator([)integer(0)operator(])operator(.)ident(empty?) + instance_variable(@local)operator(.)ident(map) operator({)operator(|)ident(i)operator(|) ident(quote_atom)operator(()ident(i)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(domain) + reserved(return) pre_constant(nil) reserved(unless) instance_variable(@domain) + ident(join_domain)operator(()instance_variable(@domain)operator(\)) + reserved(end) + + reserved(def) method(spec) + ident(s) operator(=) pre_constant(self)operator(.)ident(local) + ident(d) operator(=) pre_constant(self)operator(.)ident(domain) + reserved(if) ident(s) reserved(and) ident(d) + ident(s) operator(+) string<delimiter(')content(@)delimiter(')> operator(+) ident(d) + reserved(else) + ident(s) + reserved(end) + reserved(end) + + reserved(alias) method(address) method(spec) + + + reserved(def) method(==)operator(() ident(other) operator(\)) + ident(other)operator(.)ident(respond_to?) symbol(:spec) reserved(and) pre_constant(self)operator(.)ident(spec) operator(==) ident(other)operator(.)ident(spec) + reserved(end) + + reserved(alias) method(eql?) method(==) + + reserved(def) method(hash) + instance_variable(@local)operator(.)ident(hash) operator(^) instance_variable(@domain)operator(.)ident(hash) + reserved(end) + + reserved(def) method(dup) + ident(obj) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(new)operator(()instance_variable(@local)operator(.)ident(dup)operator(,) instance_variable(@domain)operator(.)ident(dup)operator(\)) + ident(obj)operator(.)ident(name) operator(=) instance_variable(@name)operator(.)ident(dup) reserved(if) instance_variable(@name) + ident(obj)operator(.)ident(routes)operator(.)ident(replace) instance_variable(@routes) + ident(obj) + reserved(end) + + ident(include) constant(StrategyInterface) + + reserved(def) method(accept)operator(() ident(strategy)operator(,) ident(dummy1) operator(=) pre_constant(nil)operator(,) ident(dummy2) operator(=) pre_constant(nil) operator(\)) + reserved(unless) instance_variable(@local) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(<>)delimiter(')> comment(# empty return-path) + reserved(return) + reserved(end) + + ident(spec_p) operator(=) operator(()reserved(not) instance_variable(@name) reserved(and) instance_variable(@routes)operator(.)ident(empty?)operator(\)) + reserved(if) instance_variable(@name) + ident(strategy)operator(.)ident(phrase) instance_variable(@name) + ident(strategy)operator(.)ident(space) + reserved(end) + ident(tmp) operator(=) ident(spec_p) operator(?) string<delimiter(')delimiter(')> operator(:) string<delimiter(')content(<)delimiter(')> + reserved(unless) instance_variable(@routes)operator(.)ident(empty?) + ident(tmp) operator(<<) instance_variable(@routes)operator(.)ident(map) operator({)operator(|)ident(i)operator(|) string<delimiter(')content(@)delimiter(')> operator(+) ident(i) operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) operator(<<) string<delimiter(')content(:)delimiter(')> + reserved(end) + ident(tmp) operator(<<) pre_constant(self)operator(.)ident(spec) + ident(tmp) operator(<<) string<delimiter(')content(>)delimiter(')> reserved(unless) ident(spec_p) + ident(strategy)operator(.)ident(meta) ident(tmp) + ident(strategy)operator(.)ident(lwsp) string<delimiter(')delimiter(')> + reserved(end) + + reserved(end) + + + reserved(class) class(AddressGroup) + + ident(include) constant(Enumerable) + + reserved(def) method(address_group?) + pre_constant(true) + reserved(end) + + reserved(def) method(initialize)operator(() ident(name)operator(,) ident(addrs) operator(\)) + instance_variable(@name) operator(=) ident(name) + instance_variable(@addresses) operator(=) ident(addrs) + reserved(end) + + ident(attr_reader) symbol(:name) + + reserved(def) method(==)operator(() ident(other) operator(\)) + ident(other)operator(.)ident(respond_to?) symbol(:to_a) reserved(and) instance_variable(@addresses) operator(==) ident(other)operator(.)ident(to_a) + reserved(end) + + reserved(alias) method(eql?) method(==) + + reserved(def) method(hash) + ident(map) operator({)operator(|)ident(i)operator(|) ident(i)operator(.)ident(hash) operator(})operator(.)ident(hash) + reserved(end) + + reserved(def) method([])operator(() ident(idx) operator(\)) + instance_variable(@addresses)operator([)ident(idx)operator(]) + reserved(end) + + reserved(def) method(size) + instance_variable(@addresses)operator(.)ident(size) + reserved(end) + + reserved(def) method(empty?) + instance_variable(@addresses)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(each)operator(() operator(&)ident(block) operator(\)) + instance_variable(@addresses)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(to_a) + instance_variable(@addresses)operator(.)ident(dup) + reserved(end) + + reserved(alias) method(to_ary) method(to_a) + + reserved(def) method(include?)operator(() ident(a) operator(\)) + instance_variable(@addresses)operator(.)ident(include?) ident(a) + reserved(end) + + reserved(def) method(flatten) + ident(set) operator(=) operator([)operator(]) + instance_variable(@addresses)operator(.)ident(each) reserved(do) operator(|)ident(a)operator(|) + reserved(if) ident(a)operator(.)ident(respond_to?) symbol(:flatten) + ident(set)operator(.)ident(concat) ident(a)operator(.)ident(flatten) + reserved(else) + ident(set)operator(.)ident(push) ident(a) + reserved(end) + reserved(end) + ident(set) + reserved(end) + + reserved(def) method(each_address)operator(() operator(&)ident(block) operator(\)) + ident(flatten)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(add)operator(() ident(a) operator(\)) + instance_variable(@addresses)operator(.)ident(push) ident(a) + reserved(end) + + reserved(alias) method(push) method(add) + + reserved(def) method(delete)operator(() ident(a) operator(\)) + instance_variable(@addresses)operator(.)ident(delete) ident(a) + reserved(end) + + ident(include) constant(StrategyInterface) + + reserved(def) method(accept)operator(() ident(strategy)operator(,) ident(dummy1) operator(=) pre_constant(nil)operator(,) ident(dummy2) operator(=) pre_constant(nil) operator(\)) + ident(strategy)operator(.)ident(phrase) instance_variable(@name) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(:)delimiter(')> + ident(strategy)operator(.)ident(space) + ident(first) operator(=) pre_constant(true) + ident(each) reserved(do) operator(|)ident(mbox)operator(|) + reserved(if) ident(first) + ident(first) operator(=) pre_constant(false) + reserved(else) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(,)delimiter(')> + reserved(end) + ident(strategy)operator(.)ident(space) + ident(mbox)operator(.)ident(accept) ident(strategy) + reserved(end) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(;)delimiter(')> + ident(strategy)operator(.)ident(lwsp) string<delimiter(')delimiter(')> + reserved(end) + + reserved(end) + +reserved(end) comment(# module TMail) +ident(require) string<delimiter(')content(stringio)delimiter(')> + +reserved(module) class(TMail) + reserved(class) class(Attachment) operator(<) constant(StringIO) + ident(attr_accessor) symbol(:original_filename)operator(,) symbol(:content_type) + reserved(end) + + reserved(class) class(Mail) + reserved(def) method(has_attachments?) + ident(multipart?) operator(&&) ident(parts)operator(.)ident(any?) operator({) operator(|)ident(part)operator(|) ident(attachment?)operator(()ident(part)operator(\)) operator(}) + reserved(end) + + reserved(def) method(attachment?)operator(()ident(part)operator(\)) + operator(()ident(part)operator([)string<delimiter(')content(content-disposition)delimiter(')>operator(]) operator(&&) ident(part)operator([)string<delimiter(')content(content-disposition)delimiter(')>operator(])operator(.)ident(disposition) operator(==) string<delimiter(")content(attachment)delimiter(")>operator(\)) operator(||) + ident(part)operator(.)ident(header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(main_type) operator(!=) string<delimiter(")content(text)delimiter(")> + reserved(end) + + reserved(def) method(attachments) + reserved(if) ident(multipart?) + ident(parts)operator(.)ident(collect) operator({) operator(|)ident(part)operator(|) + reserved(if) ident(attachment?)operator(()ident(part)operator(\)) + ident(content) operator(=) ident(part)operator(.)ident(body) comment(# unquoted automatically by TMail#body) + ident(file_name) operator(=) operator(()ident(part)operator([)string<delimiter(')content(content-location)delimiter(')>operator(]) operator(&&) + ident(part)operator([)string<delimiter(')content(content-location)delimiter(')>operator(])operator(.)ident(body)operator(\)) operator(||) + ident(part)operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")>operator(\)) operator(||) + ident(part)operator(.)ident(sub_header)operator(()string<delimiter(")content(content-disposition)delimiter(")>operator(,) string<delimiter(")content(filename)delimiter(")>operator(\)) + + reserved(next) reserved(if) ident(file_name)operator(.)ident(blank?) operator(||) ident(content)operator(.)ident(blank?) + + ident(attachment) operator(=) constant(Attachment)operator(.)ident(new)operator(()ident(content)operator(\)) + ident(attachment)operator(.)ident(original_filename) operator(=) ident(file_name)operator(.)ident(strip) + ident(attachment)operator(.)ident(content_type) operator(=) ident(part)operator(.)ident(content_type) + ident(attachment) + reserved(end) + operator(})operator(.)ident(compact) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(#) +comment(# base64.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +reserved(module) class(TMail) + + reserved(module) class(Base64) + + ident(module_function) + + reserved(def) method(rb_folding_encode)operator(() ident(str)operator(,) ident(eol) operator(=) string<delimiter(")char(\\n)delimiter(")>operator(,) ident(limit) operator(=) integer(60) operator(\)) + operator([)ident(str)operator(])operator(.)ident(pack)operator(()string<delimiter(')content(m)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(rb_encode)operator(() ident(str) operator(\)) + operator([)ident(str)operator(])operator(.)ident(pack)operator(()string<delimiter(')content(m)delimiter(')>operator(\))operator(.)ident(tr)operator(() string<delimiter(")char(\\r)char(\\n)delimiter(")>operator(,) string<delimiter(')delimiter(')> operator(\)) + reserved(end) + + reserved(def) method(rb_decode)operator(() ident(str)operator(,) ident(strict) operator(=) pre_constant(false) operator(\)) + ident(str)operator(.)ident(unpack)operator(()string<delimiter(')content(m)delimiter(')>operator(\)) + reserved(end) + + reserved(begin) + ident(require) string<delimiter(')content(tmail/base64.so)delimiter(')> + reserved(alias) method(folding_encode) method(c_folding_encode) + reserved(alias) method(encode) method(c_encode) + reserved(alias) method(decode) method(c_decode) + reserved(class) operator(<<) class(self) + reserved(alias) method(folding_encode) method(c_folding_encode) + reserved(alias) method(encode) method(c_encode) + reserved(alias) method(decode) method(c_decode) + reserved(end) + reserved(rescue) constant(LoadError) + reserved(alias) method(folding_encode) method(rb_folding_encode) + reserved(alias) method(encode) method(rb_encode) + reserved(alias) method(decode) method(rb_decode) + reserved(class) operator(<<) class(self) + reserved(alias) method(folding_encode) method(rb_folding_encode) + reserved(alias) method(encode) method(rb_encode) + reserved(alias) method(decode) method(rb_decode) + reserved(end) + reserved(end) + + reserved(end) + +reserved(end) +comment(#) +comment(# config.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +reserved(module) class(TMail) + + reserved(class) class(Config) + + reserved(def) method(initialize)operator(() ident(strict) operator(\)) + instance_variable(@strict_parse) operator(=) ident(strict) + instance_variable(@strict_base64decode) operator(=) ident(strict) + reserved(end) + + reserved(def) method(strict_parse?) + instance_variable(@strict_parse) + reserved(end) + + ident(attr_writer) symbol(:strict_parse) + + reserved(def) method(strict_base64decode?) + instance_variable(@strict_base64decode) + reserved(end) + + ident(attr_writer) symbol(:strict_base64decode) + + reserved(def) method(new_body_port)operator(() ident(mail) operator(\)) + constant(StringPort)operator(.)ident(new) + reserved(end) + + reserved(alias) method(new_preamble_port) method(new_body_port) + reserved(alias) method(new_part_port) method(new_body_port) + + reserved(end) + + constant(DEFAULT_CONFIG) operator(=) constant(Config)operator(.)ident(new)operator(()pre_constant(false)operator(\)) + constant(DEFAULT_STRICT_CONFIG) operator(=) constant(Config)operator(.)ident(new)operator(()pre_constant(true)operator(\)) + + reserved(def) constant(Config)operator(.)ident(to_config)operator(() ident(arg) operator(\)) + reserved(return) constant(DEFAULT_STRICT_CONFIG) reserved(if) ident(arg) operator(==) pre_constant(true) + reserved(return) constant(DEFAULT_CONFIG) reserved(if) ident(arg) operator(==) pre_constant(false) + ident(arg) reserved(or) constant(DEFAULT_CONFIG) + reserved(end) + +reserved(end) +comment(#) +comment(# encode.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(nkf)delimiter(')> +ident(require) string<delimiter(')content(tmail/base64.rb)delimiter(')> +ident(require) string<delimiter(')content(tmail/stringio)delimiter(')> +ident(require) string<delimiter(')content(tmail/utils)delimiter(')> + + +reserved(module) class(TMail) + + reserved(module) class(StrategyInterface) + + reserved(def) method(create_dest)operator(() ident(obj) operator(\)) + reserved(case) ident(obj) + reserved(when) pre_constant(nil) + constant(StringOutput)operator(.)ident(new) + reserved(when) constant(String) + constant(StringOutput)operator(.)ident(new)operator(()ident(obj)operator(\)) + reserved(when) constant(IO)operator(,) constant(StringOutput) + ident(obj) + reserved(else) + ident(raise) constant(TypeError)operator(,) string<delimiter(')content(cannot handle this type of object for dest)delimiter(')> + reserved(end) + reserved(end) + ident(module_function) symbol(:create_dest) + + reserved(def) method(encoded)operator(() ident(eol) operator(=) string<delimiter(")char(\\r)char(\\n)delimiter(")>operator(,) ident(charset) operator(=) string<delimiter(')content(j)delimiter(')>operator(,) ident(dest) operator(=) pre_constant(nil) operator(\)) + ident(accept_strategy) constant(Encoder)operator(,) ident(eol)operator(,) ident(charset)operator(,) ident(dest) + reserved(end) + + reserved(def) method(decoded)operator(() ident(eol) operator(=) string<delimiter(")char(\\n)delimiter(")>operator(,) ident(charset) operator(=) string<delimiter(')content(e)delimiter(')>operator(,) ident(dest) operator(=) pre_constant(nil) operator(\)) + ident(accept_strategy) constant(Decoder)operator(,) ident(eol)operator(,) ident(charset)operator(,) ident(dest) + reserved(end) + + reserved(alias) method(to_s) method(decoded) + + reserved(def) method(accept_strategy)operator(() ident(klass)operator(,) ident(eol)operator(,) ident(charset)operator(,) ident(dest) operator(=) pre_constant(nil) operator(\)) + ident(dest) operator(||=) string<delimiter(')delimiter(')> + ident(accept) ident(klass)operator(.)ident(new)operator(()ident(create_dest)operator(()ident(dest)operator(\))operator(,) ident(charset)operator(,) ident(eol)operator(\)) + ident(dest) + reserved(end) + + reserved(end) + + + comment(###) + comment(### MIME B encoding decoder) + comment(###) + + reserved(class) class(Decoder) + + ident(include) constant(TextUtils) + + ident(encoded) operator(=) string<delimiter(')content(=)content(\\?)content((?:iso-2022-jp|euc-jp|shift_jis\))content(\\?)content([QB])content(\\?)content([a-z0-9+/=]+)content(\\?)content(=)delimiter(')> + constant(ENCODED_WORDS) operator(=) regexp<delimiter(/)inline<inline_delimiter(#{)ident(encoded)inline_delimiter(})>content((?:)char(\\s)content(+)inline<inline_delimiter(#{)ident(encoded)inline_delimiter(})>content(\)*)delimiter(/)modifier(i)> + + constant(OUTPUT_ENCODING) operator(=) operator({) + string<delimiter(')content(EUC)delimiter(')> operator(=)operator(>) string<delimiter(')content(e)delimiter(')>operator(,) + string<delimiter(')content(SJIS)delimiter(')> operator(=)operator(>) string<delimiter(')content(s)delimiter(')>operator(,) + operator(}) + + reserved(def) pre_constant(self)operator(.)ident(decode)operator(() ident(str)operator(,) ident(encoding) operator(=) pre_constant(nil) operator(\)) + ident(encoding) operator(||=) operator(()constant(OUTPUT_ENCODING)operator([)global_variable($KCODE)operator(]) operator(||) string<delimiter(')content(j)delimiter(')>operator(\)) + ident(opt) operator(=) string<delimiter(')content(-m)delimiter(')> operator(+) ident(encoding) + ident(str)operator(.)ident(gsub)operator(()constant(ENCODED_WORDS)operator(\)) operator({)operator(|)ident(s)operator(|) constant(NKF)operator(.)ident(nkf)operator(()ident(opt)operator(,) ident(s)operator(\)) operator(}) + reserved(end) + + reserved(def) method(initialize)operator(() ident(dest)operator(,) ident(encoding) operator(=) pre_constant(nil)operator(,) ident(eol) operator(=) string<delimiter(")char(\\n)delimiter(")> operator(\)) + instance_variable(@f) operator(=) constant(StrategyInterface)operator(.)ident(create_dest)operator(()ident(dest)operator(\)) + instance_variable(@encoding) operator(=) operator(()regexp<delimiter(/)char(\\A)content([ejs])delimiter(/)> operator(===) ident(encoding)operator(\)) operator(?) ident(encoding)operator([)integer(0)operator(,)integer(1)operator(]) operator(:) pre_constant(nil) + instance_variable(@eol) operator(=) ident(eol) + reserved(end) + + reserved(def) method(decode)operator(() ident(str) operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(decode)operator(()ident(str)operator(,) instance_variable(@encoding)operator(\)) + reserved(end) + ident(private) symbol(:decode) + + reserved(def) method(terminate) + reserved(end) + + reserved(def) method(header_line)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(decode)operator(()ident(str)operator(\)) + reserved(end) + + reserved(def) method(header_name)operator(() ident(nm) operator(\)) + instance_variable(@f) operator(<<) ident(nm) operator(<<) string<delimiter(')content(: )delimiter(')> + reserved(end) + + reserved(def) method(header_body)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(decode)operator(()ident(str)operator(\)) + reserved(end) + + reserved(def) method(space) + instance_variable(@f) operator(<<) string<delimiter(')content( )delimiter(')> + reserved(end) + + reserved(alias) method(spc) method(space) + + reserved(def) method(lwsp)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(str) + reserved(end) + + reserved(def) method(meta)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(str) + reserved(end) + + reserved(def) method(text)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(decode)operator(()ident(str)operator(\)) + reserved(end) + + reserved(def) method(phrase)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(quote_phrase)operator(()ident(decode)operator(()ident(str)operator(\))operator(\)) + reserved(end) + + reserved(def) method(kv_pair)operator(() ident(k)operator(,) ident(v) operator(\)) + instance_variable(@f) operator(<<) ident(k) operator(<<) string<delimiter(')content(=)delimiter(')> operator(<<) ident(v) + reserved(end) + + reserved(def) method(puts)operator(() ident(str) operator(=) pre_constant(nil) operator(\)) + instance_variable(@f) operator(<<) ident(str) reserved(if) ident(str) + instance_variable(@f) operator(<<) instance_variable(@eol) + reserved(end) + + reserved(def) method(write)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(str) + reserved(end) + + reserved(end) + + + comment(###) + comment(### MIME B-encoding encoder) + comment(###) + + comment(#) + comment(# FIXME: This class can handle only (euc-jp/shift_jis -> iso-2022-jp\).) + comment(#) + reserved(class) class(Encoder) + + ident(include) constant(TextUtils) + + constant(BENCODE_DEBUG) operator(=) pre_constant(false) reserved(unless) reserved(defined?)operator(()constant(BENCODE_DEBUG)operator(\)) + + reserved(def) constant(Encoder)operator(.)ident(encode)operator(() ident(str) operator(\)) + ident(e) operator(=) ident(new)operator(()operator(\)) + ident(e)operator(.)ident(header_body) ident(str) + ident(e)operator(.)ident(terminate) + ident(e)operator(.)ident(dest)operator(.)ident(string) + reserved(end) + + constant(SPACER) operator(=) string<delimiter(")char(\\t)delimiter(")> + constant(MAX_LINE_LEN) operator(=) integer(70) + + constant(OPTIONS) operator(=) operator({) + string<delimiter(')content(EUC)delimiter(')> operator(=)operator(>) string<delimiter(')content(-Ej -m0)delimiter(')>operator(,) + string<delimiter(')content(SJIS)delimiter(')> operator(=)operator(>) string<delimiter(')content(-Sj -m0)delimiter(')>operator(,) + string<delimiter(')content(UTF8)delimiter(')> operator(=)operator(>) pre_constant(nil)operator(,) comment(# FIXME) + string<delimiter(')content(NONE)delimiter(')> operator(=)operator(>) pre_constant(nil) + operator(}) + + reserved(def) method(initialize)operator(() ident(dest) operator(=) pre_constant(nil)operator(,) ident(encoding) operator(=) pre_constant(nil)operator(,) ident(eol) operator(=) string<delimiter(")char(\\r)char(\\n)delimiter(")>operator(,) ident(limit) operator(=) pre_constant(nil) operator(\)) + instance_variable(@f) operator(=) constant(StrategyInterface)operator(.)ident(create_dest)operator(()ident(dest)operator(\)) + instance_variable(@opt) operator(=) constant(OPTIONS)operator([)global_variable($KCODE)operator(]) + instance_variable(@eol) operator(=) ident(eol) + ident(reset) + reserved(end) + + reserved(def) method(normalize_encoding)operator(() ident(str) operator(\)) + reserved(if) instance_variable(@opt) + reserved(then) constant(NKF)operator(.)ident(nkf)operator(()instance_variable(@opt)operator(,) ident(str)operator(\)) + reserved(else) ident(str) + reserved(end) + reserved(end) + + reserved(def) method(reset) + instance_variable(@text) operator(=) string<delimiter(')delimiter(')> + instance_variable(@lwsp) operator(=) string<delimiter(')delimiter(')> + instance_variable(@curlen) operator(=) integer(0) + reserved(end) + + reserved(def) method(terminate) + ident(add_lwsp) string<delimiter(')delimiter(')> + ident(reset) + reserved(end) + + reserved(def) method(dest) + instance_variable(@f) + reserved(end) + + reserved(def) method(puts)operator(() ident(str) operator(=) pre_constant(nil) operator(\)) + instance_variable(@f) operator(<<) ident(str) reserved(if) ident(str) + instance_variable(@f) operator(<<) instance_variable(@eol) + reserved(end) + + reserved(def) method(write)operator(() ident(str) operator(\)) + instance_variable(@f) operator(<<) ident(str) + reserved(end) + + comment(#) + comment(# add) + comment(#) + + reserved(def) method(header_line)operator(() ident(line) operator(\)) + ident(scanadd) ident(line) + reserved(end) + + reserved(def) method(header_name)operator(() ident(name) operator(\)) + ident(add_text) ident(name)operator(.)ident(split)operator(()regexp<delimiter(/)content(-)delimiter(/)>operator(\))operator(.)ident(map) operator({)operator(|)ident(i)operator(|) ident(i)operator(.)ident(capitalize) operator(})operator(.)ident(join)operator(()string<delimiter(')content(-)delimiter(')>operator(\)) + ident(add_text) string<delimiter(')content(:)delimiter(')> + ident(add_lwsp) string<delimiter(')content( )delimiter(')> + reserved(end) + + reserved(def) method(header_body)operator(() ident(str) operator(\)) + ident(scanadd) ident(normalize_encoding)operator(()ident(str)operator(\)) + reserved(end) + + reserved(def) method(space) + ident(add_lwsp) string<delimiter(')content( )delimiter(')> + reserved(end) + + reserved(alias) method(spc) method(space) + + reserved(def) method(lwsp)operator(() ident(str) operator(\)) + ident(add_lwsp) ident(str)operator(.)ident(sub)operator(()regexp<delimiter(/)content([)char(\\r)char(\\n)content(]+[^)char(\\r)char(\\n)content(]*)char(\\z)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(meta)operator(() ident(str) operator(\)) + ident(add_text) ident(str) + reserved(end) + + reserved(def) method(text)operator(() ident(str) operator(\)) + ident(scanadd) ident(normalize_encoding)operator(()ident(str)operator(\)) + reserved(end) + + reserved(def) method(phrase)operator(() ident(str) operator(\)) + ident(str) operator(=) ident(normalize_encoding)operator(()ident(str)operator(\)) + reserved(if) constant(CONTROL_CHAR) operator(===) ident(str) + ident(scanadd) ident(str) + reserved(else) + ident(add_text) ident(quote_phrase)operator(()ident(str)operator(\)) + reserved(end) + reserved(end) + + comment(# FIXME: implement line folding) + comment(#) + reserved(def) method(kv_pair)operator(() ident(k)operator(,) ident(v) operator(\)) + reserved(return) reserved(if) ident(v)operator(.)ident(nil?) + ident(v) operator(=) ident(normalize_encoding)operator(()ident(v)operator(\)) + reserved(if) ident(token_safe?)operator(()ident(v)operator(\)) + ident(add_text) ident(k) operator(+) string<delimiter(')content(=)delimiter(')> operator(+) ident(v) + reserved(elsif) reserved(not) constant(CONTROL_CHAR) operator(===) ident(v) + ident(add_text) ident(k) operator(+) string<delimiter(')content(=)delimiter(')> operator(+) ident(quote_token)operator(()ident(v)operator(\)) + reserved(else) + comment(# apply RFC2231 encoding) + ident(kv) operator(=) ident(k) operator(+) string<delimiter(')content(*=)delimiter(')> operator(+) string<delimiter(")content(iso-2022-jp'ja')delimiter(")> operator(+) ident(encode_value)operator(()ident(v)operator(\)) + ident(add_text) ident(kv) + reserved(end) + reserved(end) + + reserved(def) method(encode_value)operator(() ident(str) operator(\)) + ident(str)operator(.)ident(gsub)operator(()constant(TOKEN_UNSAFE)operator(\)) operator({)operator(|)ident(s)operator(|) string<delimiter(')content(%%%02x)delimiter(')> operator(%) ident(s)operator([)integer(0)operator(]) operator(}) + reserved(end) + + ident(private) + + reserved(def) method(scanadd)operator(() ident(str)operator(,) ident(force) operator(=) pre_constant(false) operator(\)) + ident(types) operator(=) string<delimiter(')delimiter(')> + ident(strs) operator(=) operator([)operator(]) + + reserved(until) ident(str)operator(.)ident(empty?) + reserved(if) ident(m) operator(=) regexp<delimiter(/)char(\\A)content([^)char(\\e)char(\\t)char(\\r)char(\\n)content( ]+)delimiter(/)>operator(.)ident(match)operator(()ident(str)operator(\)) + ident(types) operator(<<) operator(()ident(force) operator(?) string<delimiter(')content(j)delimiter(')> operator(:) string<delimiter(')content(a)delimiter(')>operator(\)) + ident(strs)operator(.)ident(push) ident(m)operator([)integer(0)operator(]) + + reserved(elsif) ident(m) operator(=) regexp<delimiter(/)char(\\A)content([)char(\\t)char(\\r)char(\\n)content( ]+)delimiter(/)>operator(.)ident(match)operator(()ident(str)operator(\)) + ident(types) operator(<<) string<delimiter(')content(s)delimiter(')> + ident(strs)operator(.)ident(push) ident(m)operator([)integer(0)operator(]) + + reserved(elsif) ident(m) operator(=) regexp<delimiter(/)char(\\A)char(\\e)content(..)delimiter(/)>operator(.)ident(match)operator(()ident(str)operator(\)) + ident(esc) operator(=) ident(m)operator([)integer(0)operator(]) + ident(str) operator(=) ident(m)operator(.)ident(post_match) + reserved(if) ident(esc) operator(!=) string<delimiter(")char(\\e)content((B)delimiter(")> reserved(and) ident(m) operator(=) regexp<delimiter(/)char(\\A)content([^)char(\\e)content(]+)delimiter(/)>operator(.)ident(match)operator(()ident(str)operator(\)) + ident(types) operator(<<) string<delimiter(')content(j)delimiter(')> + ident(strs)operator(.)ident(push) ident(m)operator([)integer(0)operator(]) + reserved(end) + + reserved(else) + ident(raise) string<delimiter(')content(TMail FATAL: encoder scan fail)delimiter(')> + reserved(end) + operator(()ident(str) operator(=) ident(m)operator(.)ident(post_match)operator(\)) reserved(unless) ident(m)operator(.)ident(nil?) + reserved(end) + + ident(do_encode) ident(types)operator(,) ident(strs) + reserved(end) + + reserved(def) method(do_encode)operator(() ident(types)operator(,) ident(strs) operator(\)) + comment(#) + comment(# result : (A|E\)(S(A|E\)\)*) + comment(# E : W(SW\)*) + comment(# W : (J|A\)+ but must contain J # (J|A\)*J(J|A\)*) + comment(# A : <<A character string not to be encoded>>) + comment(# J : <<A character string to be encoded>>) + comment(# S : <<LWSP>>) + comment(#) + comment(# An encoding unit is `E'.) + comment(# Input (parameter `types'\) is (J|A\)(J|A|S\)*(J|A\)) + comment(#) + reserved(if) constant(BENCODE_DEBUG) + ident(puts) + ident(puts) string<delimiter(')content(-- do_encode ------------)delimiter(')> + ident(puts) ident(types)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\))operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\)) + ident(p) ident(strs) + reserved(end) + + ident(e) operator(=) regexp<delimiter(/)content([ja]*j[ja]*(?:s[ja]*j[ja]*\)*)delimiter(/)> + + reserved(while) ident(m) operator(=) ident(e)operator(.)ident(match)operator(()ident(types)operator(\)) + ident(pre) operator(=) ident(m)operator(.)ident(pre_match) + ident(concat_A_S) ident(pre)operator(,) ident(strs)operator([)integer(0)operator(,) ident(pre)operator(.)ident(size)operator(]) reserved(unless) ident(pre)operator(.)ident(empty?) + ident(concat_E) ident(m)operator([)integer(0)operator(])operator(,) ident(strs)operator([)ident(m)operator(.)ident(begin)operator(()integer(0)operator(\)) operator(...) ident(m)operator(.)ident(end)operator(()integer(0)operator(\))operator(]) + ident(types) operator(=) ident(m)operator(.)ident(post_match) + ident(strs)operator(.)ident(slice!) integer(0)operator(,) ident(m)operator(.)ident(end)operator(()integer(0)operator(\)) + reserved(end) + ident(concat_A_S) ident(types)operator(,) ident(strs) + reserved(end) + + reserved(def) method(concat_A_S)operator(() ident(types)operator(,) ident(strs) operator(\)) + ident(i) operator(=) integer(0) + ident(types)operator(.)ident(each_byte) reserved(do) operator(|)ident(t)operator(|) + reserved(case) ident(t) + reserved(when) integer(?a) reserved(then) ident(add_text) ident(strs)operator([)ident(i)operator(]) + reserved(when) integer(?s) reserved(then) ident(add_lwsp) ident(strs)operator([)ident(i)operator(]) + reserved(else) + ident(raise) string<delimiter(")content(TMail FATAL: unknown flag: )inline<inline_delimiter(#{)ident(t)operator(.)ident(chr)inline_delimiter(})>delimiter(")> + reserved(end) + ident(i) operator(+=) integer(1) + reserved(end) + reserved(end) + + constant(METHOD_ID) operator(=) operator({) + integer(?j) operator(=)operator(>) symbol(:extract_J)operator(,) + integer(?e) operator(=)operator(>) symbol(:extract_E)operator(,) + integer(?a) operator(=)operator(>) symbol(:extract_A)operator(,) + integer(?s) operator(=)operator(>) symbol(:extract_S) + operator(}) + + reserved(def) method(concat_E)operator(() ident(types)operator(,) ident(strs) operator(\)) + reserved(if) constant(BENCODE_DEBUG) + ident(puts) string<delimiter(')content(---- concat_E)delimiter(')> + ident(puts) string<delimiter(")content(types=)inline<inline_delimiter(#{)ident(types)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\))operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))inline_delimiter(})>delimiter(")> + ident(puts) string<delimiter(")content(strs =)inline<inline_delimiter(#{)ident(strs)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(flush)operator(()operator(\)) reserved(unless) instance_variable(@text)operator(.)ident(empty?) + + ident(chunk) operator(=) string<delimiter(')delimiter(')> + ident(strs)operator(.)ident(each_with_index) reserved(do) operator(|)ident(s)operator(,)ident(i)operator(|) + ident(mid) operator(=) constant(METHOD_ID)operator([)ident(types)operator([)ident(i)operator(])operator(]) + reserved(until) ident(s)operator(.)ident(empty?) + reserved(unless) ident(c) operator(=) ident(__send__)operator(()ident(mid)operator(,) ident(chunk)operator(.)ident(size)operator(,) ident(s)operator(\)) + ident(add_with_encode) ident(chunk) reserved(unless) ident(chunk)operator(.)ident(empty?) + ident(flush) + ident(chunk) operator(=) string<delimiter(')delimiter(')> + ident(fold) + ident(c) operator(=) ident(__send__)operator(()ident(mid)operator(,) integer(0)operator(,) ident(s)operator(\)) + ident(raise) string<delimiter(')content(TMail FATAL: extract fail)delimiter(')> reserved(unless) ident(c) + reserved(end) + ident(chunk) operator(<<) ident(c) + reserved(end) + reserved(end) + ident(add_with_encode) ident(chunk) reserved(unless) ident(chunk)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(extract_J)operator(() ident(chunksize)operator(,) ident(str) operator(\)) + ident(size) operator(=) ident(max_bytes)operator(()ident(chunksize)operator(,) ident(str)operator(.)ident(size)operator(\)) operator(-) integer(6) + ident(size) operator(=) operator(()ident(size) operator(%) integer(2) operator(==) integer(0)operator(\)) operator(?) operator(()ident(size)operator(\)) operator(:) operator(()ident(size) operator(-) integer(1)operator(\)) + reserved(return) pre_constant(nil) reserved(if) ident(size) operator(<=) integer(0) + string<delimiter(")char(\\e)content($B)inline<inline_delimiter(#{)ident(str)operator(.)ident(slice!)operator(()integer(0)operator(,) ident(size)operator(\))inline_delimiter(})>char(\\e)content((B)delimiter(")> + reserved(end) + + reserved(def) method(extract_A)operator(() ident(chunksize)operator(,) ident(str) operator(\)) + ident(size) operator(=) ident(max_bytes)operator(()ident(chunksize)operator(,) ident(str)operator(.)ident(size)operator(\)) + reserved(return) pre_constant(nil) reserved(if) ident(size) operator(<=) integer(0) + ident(str)operator(.)ident(slice!)operator(()integer(0)operator(,) ident(size)operator(\)) + reserved(end) + + reserved(alias) method(extract_S) method(extract_A) + + reserved(def) method(max_bytes)operator(() ident(chunksize)operator(,) ident(ssize) operator(\)) + operator(()ident(restsize)operator(()operator(\)) operator(-) string<delimiter(')content(=?iso-2022-jp?B??=)delimiter(')>operator(.)ident(size)operator(\)) operator(/) integer(4) operator(*) integer(3) operator(-) ident(chunksize) + reserved(end) + + comment(#) + comment(# free length buffer) + comment(#) + + reserved(def) method(add_text)operator(() ident(str) operator(\)) + instance_variable(@text) operator(<<) ident(str) + comment(# puts '---- text -------------------------------------') + comment(# puts "+ #{str.inspect}") + comment(# puts "txt >>>#{@text.inspect}<<<") + reserved(end) + + reserved(def) method(add_with_encode)operator(() ident(str) operator(\)) + instance_variable(@text) operator(<<) string<delimiter(")content(=?iso-2022-jp?B?)inline<inline_delimiter(#{)constant(Base64)operator(.)ident(encode)operator(()ident(str)operator(\))inline_delimiter(})>content(?=)delimiter(")> + reserved(end) + + reserved(def) method(add_lwsp)operator(() ident(lwsp) operator(\)) + comment(# puts '---- lwsp -------------------------------------') + comment(# puts "+ #{lwsp.inspect}") + ident(fold) reserved(if) ident(restsize)operator(()operator(\)) operator(<=) integer(0) + ident(flush) + instance_variable(@lwsp) operator(=) ident(lwsp) + reserved(end) + + reserved(def) method(flush) + comment(# puts '---- flush ----') + comment(# puts "spc >>>#{@lwsp.inspect}<<<") + comment(# puts "txt >>>#{@text.inspect}<<<") + instance_variable(@f) operator(<<) instance_variable(@lwsp) operator(<<) instance_variable(@text) + instance_variable(@curlen) operator(+=) operator(()instance_variable(@lwsp)operator(.)ident(size) operator(+) instance_variable(@text)operator(.)ident(size)operator(\)) + instance_variable(@text) operator(=) string<delimiter(')delimiter(')> + instance_variable(@lwsp) operator(=) string<delimiter(')delimiter(')> + reserved(end) + + reserved(def) method(fold) + comment(# puts '---- fold ----') + instance_variable(@f) operator(<<) instance_variable(@eol) + instance_variable(@curlen) operator(=) integer(0) + instance_variable(@lwsp) operator(=) constant(SPACER) + reserved(end) + + reserved(def) method(restsize) + constant(MAX_LINE_LEN) operator(-) operator(()instance_variable(@curlen) operator(+) instance_variable(@lwsp)operator(.)ident(size) operator(+) instance_variable(@text)operator(.)ident(size)operator(\)) + reserved(end) + + reserved(end) + +reserved(end) comment(# module TMail) +comment(#) +comment(# facade.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/utils)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Mail) + + reserved(def) method(header_string)operator(() ident(name)operator(,) ident(default) operator(=) pre_constant(nil) operator(\)) + ident(h) operator(=) instance_variable(@header)operator([)ident(name)operator(.)ident(downcase)operator(]) reserved(or) reserved(return) ident(default) + ident(h)operator(.)ident(to_s) + reserved(end) + + comment(###) + comment(### attributes) + comment(###) + + ident(include) constant(TextUtils) + + reserved(def) method(set_string_array_attr)operator(() ident(key)operator(,) ident(strs) operator(\)) + ident(strs)operator(.)ident(flatten!) + reserved(if) ident(strs)operator(.)ident(empty?) + instance_variable(@header)operator(.)ident(delete) ident(key)operator(.)ident(downcase) + reserved(else) + ident(store) ident(key)operator(,) ident(strs)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\)) + reserved(end) + ident(strs) + reserved(end) + ident(private) symbol(:set_string_array_attr) + + reserved(def) method(set_string_attr)operator(() ident(key)operator(,) ident(str) operator(\)) + reserved(if) ident(str) + ident(store) ident(key)operator(,) ident(str) + reserved(else) + instance_variable(@header)operator(.)ident(delete) ident(key)operator(.)ident(downcase) + reserved(end) + ident(str) + reserved(end) + ident(private) symbol(:set_string_attr) + + reserved(def) method(set_addrfield)operator(() ident(name)operator(,) ident(arg) operator(\)) + reserved(if) ident(arg) + ident(h) operator(=) constant(HeaderField)operator(.)ident(internal_new)operator(()ident(name)operator(,) instance_variable(@config)operator(\)) + ident(h)operator(.)ident(addrs)operator(.)ident(replace) operator([)ident(arg)operator(])operator(.)ident(flatten) + instance_variable(@header)operator([)ident(name)operator(]) operator(=) ident(h) + reserved(else) + instance_variable(@header)operator(.)ident(delete) ident(name) + reserved(end) + ident(arg) + reserved(end) + ident(private) symbol(:set_addrfield) + + reserved(def) method(addrs2specs)operator(() ident(addrs) operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(addrs) + ident(list) operator(=) ident(addrs)operator(.)ident(map) operator({)operator(|)ident(addr)operator(|) + reserved(if) ident(addr)operator(.)ident(address_group?) + reserved(then) ident(addr)operator(.)ident(map) operator({)operator(|)ident(a)operator(|) ident(a)operator(.)ident(spec) operator(}) + reserved(else) ident(addr)operator(.)ident(spec) + reserved(end) + operator(})operator(.)ident(flatten) + reserved(return) pre_constant(nil) reserved(if) ident(list)operator(.)ident(empty?) + ident(list) + reserved(end) + ident(private) symbol(:addrs2specs) + + + comment(#) + comment(# date time) + comment(#) + + reserved(def) method(date)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(date)delimiter(')>operator(]) + ident(h)operator(.)ident(date) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(date=)operator(() ident(time) operator(\)) + reserved(if) ident(time) + ident(store) string<delimiter(')content(Date)delimiter(')>operator(,) ident(time2str)operator(()ident(time)operator(\)) + reserved(else) + instance_variable(@header)operator(.)ident(delete) string<delimiter(')content(date)delimiter(')> + reserved(end) + ident(time) + reserved(end) + + reserved(def) method(strftime)operator(() ident(fmt)operator(,) ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(t) operator(=) ident(date) + ident(t)operator(.)ident(strftime)operator(()ident(fmt)operator(\)) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + + comment(#) + comment(# destination) + comment(#) + + reserved(def) method(to_addrs)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(to)delimiter(')>operator(]) + ident(h)operator(.)ident(addrs) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(cc_addrs)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(cc)delimiter(')>operator(]) + ident(h)operator(.)ident(addrs) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(bcc_addrs)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(bcc)delimiter(')>operator(]) + ident(h)operator(.)ident(addrs) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(to_addrs=)operator(() ident(arg) operator(\)) + ident(set_addrfield) string<delimiter(')content(to)delimiter(')>operator(,) ident(arg) + reserved(end) + + reserved(def) method(cc_addrs=)operator(() ident(arg) operator(\)) + ident(set_addrfield) string<delimiter(')content(cc)delimiter(')>operator(,) ident(arg) + reserved(end) + + reserved(def) method(bcc_addrs=)operator(() ident(arg) operator(\)) + ident(set_addrfield) string<delimiter(')content(bcc)delimiter(')>operator(,) ident(arg) + reserved(end) + + reserved(def) method(to)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(addrs2specs)operator(()ident(to_addrs)operator(()pre_constant(nil)operator(\))operator(\)) operator(||) ident(default) + reserved(end) + + reserved(def) method(cc)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(addrs2specs)operator(()ident(cc_addrs)operator(()pre_constant(nil)operator(\))operator(\)) operator(||) ident(default) + reserved(end) + + reserved(def) method(bcc)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(addrs2specs)operator(()ident(bcc_addrs)operator(()pre_constant(nil)operator(\))operator(\)) operator(||) ident(default) + reserved(end) + + reserved(def) method(to=)operator(() operator(*)ident(strs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(To)delimiter(')>operator(,) ident(strs) + reserved(end) + + reserved(def) method(cc=)operator(() operator(*)ident(strs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(Cc)delimiter(')>operator(,) ident(strs) + reserved(end) + + reserved(def) method(bcc=)operator(() operator(*)ident(strs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(Bcc)delimiter(')>operator(,) ident(strs) + reserved(end) + + + comment(#) + comment(# originator) + comment(#) + + reserved(def) method(from_addrs)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(from)delimiter(')>operator(]) + ident(h)operator(.)ident(addrs) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(from_addrs=)operator(() ident(arg) operator(\)) + ident(set_addrfield) string<delimiter(')content(from)delimiter(')>operator(,) ident(arg) + reserved(end) + + reserved(def) method(from)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(addrs2specs)operator(()ident(from_addrs)operator(()pre_constant(nil)operator(\))operator(\)) operator(||) ident(default) + reserved(end) + + reserved(def) method(from=)operator(() operator(*)ident(strs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(From)delimiter(')>operator(,) ident(strs) + reserved(end) + + reserved(def) method(friendly_from)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(from)delimiter(')>operator(]) + ident(a)operator(,) operator(=) ident(h)operator(.)ident(addrs) + reserved(return) ident(default) reserved(unless) ident(a) + reserved(return) ident(a)operator(.)ident(phrase) reserved(if) ident(a)operator(.)ident(phrase) + reserved(return) ident(h)operator(.)ident(comments)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\)) reserved(unless) ident(h)operator(.)ident(comments)operator(.)ident(empty?) + ident(a)operator(.)ident(spec) + reserved(end) + + + reserved(def) method(reply_to_addrs)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(reply-to)delimiter(')>operator(]) + ident(h)operator(.)ident(addrs) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(reply_to_addrs=)operator(() ident(arg) operator(\)) + ident(set_addrfield) string<delimiter(')content(reply-to)delimiter(')>operator(,) ident(arg) + reserved(end) + + reserved(def) method(reply_to)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(addrs2specs)operator(()ident(reply_to_addrs)operator(()pre_constant(nil)operator(\))operator(\)) operator(||) ident(default) + reserved(end) + + reserved(def) method(reply_to=)operator(() operator(*)ident(strs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(Reply-To)delimiter(')>operator(,) ident(strs) + reserved(end) + + + reserved(def) method(sender_addr)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(f) operator(=) instance_variable(@header)operator([)string<delimiter(')content(sender)delimiter(')>operator(]) reserved(or) reserved(return) ident(default) + ident(f)operator(.)ident(addr) reserved(or) reserved(return) ident(default) + reserved(end) + + reserved(def) method(sender_addr=)operator(() ident(addr) operator(\)) + reserved(if) ident(addr) + ident(h) operator(=) constant(HeaderField)operator(.)ident(internal_new)operator(()string<delimiter(')content(sender)delimiter(')>operator(,) instance_variable(@config)operator(\)) + ident(h)operator(.)ident(addr) operator(=) ident(addr) + instance_variable(@header)operator([)string<delimiter(')content(sender)delimiter(')>operator(]) operator(=) ident(h) + reserved(else) + instance_variable(@header)operator(.)ident(delete) string<delimiter(')content(sender)delimiter(')> + reserved(end) + ident(addr) + reserved(end) + + reserved(def) method(sender)operator(() ident(default) operator(\)) + ident(f) operator(=) instance_variable(@header)operator([)string<delimiter(')content(sender)delimiter(')>operator(]) reserved(or) reserved(return) ident(default) + ident(a) operator(=) ident(f)operator(.)ident(addr) reserved(or) reserved(return) ident(default) + ident(a)operator(.)ident(spec) + reserved(end) + + reserved(def) method(sender=)operator(() ident(str) operator(\)) + ident(set_string_attr) string<delimiter(')content(Sender)delimiter(')>operator(,) ident(str) + reserved(end) + + + comment(#) + comment(# subject) + comment(#) + + reserved(def) method(subject)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(subject)delimiter(')>operator(]) + ident(h)operator(.)ident(body) + reserved(else) + ident(default) + reserved(end) + reserved(end) + reserved(alias) method(quoted_subject) method(subject) + + reserved(def) method(subject=)operator(() ident(str) operator(\)) + ident(set_string_attr) string<delimiter(')content(Subject)delimiter(')>operator(,) ident(str) + reserved(end) + + + comment(#) + comment(# identity & threading) + comment(#) + + reserved(def) method(message_id)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(message-id)delimiter(')>operator(]) + ident(h)operator(.)ident(id) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(message_id=)operator(() ident(str) operator(\)) + ident(set_string_attr) string<delimiter(')content(Message-Id)delimiter(')>operator(,) ident(str) + reserved(end) + + reserved(def) method(in_reply_to)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(in-reply-to)delimiter(')>operator(]) + ident(h)operator(.)ident(ids) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(in_reply_to=)operator(() operator(*)ident(idstrs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(In-Reply-To)delimiter(')>operator(,) ident(idstrs) + reserved(end) + + reserved(def) method(references)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(references)delimiter(')>operator(]) + ident(h)operator(.)ident(refs) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(references=)operator(() operator(*)ident(strs) operator(\)) + ident(set_string_array_attr) string<delimiter(')content(References)delimiter(')>operator(,) ident(strs) + reserved(end) + + + comment(#) + comment(# MIME headers) + comment(#) + + reserved(def) method(mime_version)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(mime-version)delimiter(')>operator(]) + ident(h)operator(.)ident(version) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(mime_version=)operator(() ident(m)operator(,) ident(opt) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(opt) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(mime-version)delimiter(')>operator(]) + ident(h)operator(.)ident(major) operator(=) ident(m) + ident(h)operator(.)ident(minor) operator(=) ident(opt) + reserved(else) + ident(store) string<delimiter(')content(Mime-Version)delimiter(')>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(m)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(opt)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(else) + ident(store) string<delimiter(')content(Mime-Version)delimiter(')>operator(,) ident(m) + reserved(end) + ident(m) + reserved(end) + + + reserved(def) method(content_type)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) + ident(h)operator(.)ident(content_type) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(main_type)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) + ident(h)operator(.)ident(main_type) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(sub_type)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) + ident(h)operator(.)ident(sub_type) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(set_content_type)operator(() ident(str)operator(,) ident(sub) operator(=) pre_constant(nil)operator(,) ident(param) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(sub) + ident(main)operator(,) ident(sub) operator(=) ident(str)operator(,) ident(sub) + reserved(else) + ident(main)operator(,) ident(sub) operator(=) ident(str)operator(.)ident(split)operator(()regexp<delimiter(%r<)content(/)delimiter(>)>operator(,) integer(2)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(sub type missing: )inline<inline_delimiter(#{)ident(str)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> reserved(unless) ident(sub) + reserved(end) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) + ident(h)operator(.)ident(main_type) operator(=) ident(main) + ident(h)operator(.)ident(sub_type) operator(=) ident(sub) + ident(h)operator(.)ident(params)operator(.)ident(clear) + reserved(else) + ident(store) string<delimiter(')content(Content-Type)delimiter(')>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(main)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(sub)inline_delimiter(})>delimiter(")> + reserved(end) + instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(params)operator(.)ident(replace) ident(param) reserved(if) ident(param) + + ident(str) + reserved(end) + + reserved(alias) method(content_type=) method(set_content_type) + + reserved(def) method(type_param)operator(() ident(name)operator(,) ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) + ident(h)operator([)ident(name)operator(]) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(charset)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) + ident(h)operator([)string<delimiter(')content(charset)delimiter(')>operator(]) reserved(or) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(charset=)operator(() ident(str) operator(\)) + reserved(if) ident(str) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([) string<delimiter(')content(content-type)delimiter(')> operator(]) + ident(h)operator([)string<delimiter(')content(charset)delimiter(')>operator(]) operator(=) ident(str) + reserved(else) + ident(store) string<delimiter(')content(Content-Type)delimiter(')>operator(,) string<delimiter(")content(text/plain; charset=)inline<inline_delimiter(#{)ident(str)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + ident(str) + reserved(end) + + + reserved(def) method(transfer_encoding)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-transfer-encoding)delimiter(')>operator(]) + ident(h)operator(.)ident(encoding) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(def) method(transfer_encoding=)operator(() ident(str) operator(\)) + ident(set_string_attr) string<delimiter(')content(Content-Transfer-Encoding)delimiter(')>operator(,) ident(str) + reserved(end) + + reserved(alias) method(encoding) method(transfer_encoding) + reserved(alias) method(encoding=) method(transfer_encoding=) + reserved(alias) method(content_transfer_encoding) method(transfer_encoding) + reserved(alias) method(content_transfer_encoding=) method(transfer_encoding=) + + + reserved(def) method(disposition)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-disposition)delimiter(')>operator(]) + ident(h)operator(.)ident(disposition) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(alias) method(content_disposition) method(disposition) + + reserved(def) method(set_disposition)operator(() ident(str)operator(,) ident(params) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-disposition)delimiter(')>operator(]) + ident(h)operator(.)ident(disposition) operator(=) ident(str) + ident(h)operator(.)ident(params)operator(.)ident(clear) + reserved(else) + ident(store)operator(()string<delimiter(')content(Content-Disposition)delimiter(')>operator(,) ident(str)operator(\)) + ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-disposition)delimiter(')>operator(]) + reserved(end) + ident(h)operator(.)ident(params)operator(.)ident(replace) ident(params) reserved(if) ident(params) + reserved(end) + + reserved(alias) method(disposition=) method(set_disposition) + reserved(alias) method(set_content_disposition) method(set_disposition) + reserved(alias) method(content_disposition=) method(set_disposition) + + reserved(def) method(disposition_param)operator(() ident(name)operator(,) ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-disposition)delimiter(')>operator(]) + ident(h)operator([)ident(name)operator(]) operator(||) ident(default) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + comment(###) + comment(### utils) + comment(###) + + reserved(def) method(create_reply) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()string<delimiter(')delimiter(')>operator(\)) + ident(mail)operator(.)ident(subject) operator(=) string<delimiter(')content(Re: )delimiter(')> operator(+) ident(subject)operator(()string<delimiter(')delimiter(')>operator(\))operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)content((?:)char(\\[)content([^)char(\\])content(]+)char(\\])content(\)?(?:)char(\\s)content(*Re:\)*)char(\\s)content(*)delimiter(/)modifier(i)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(mail)operator(.)ident(to_addrs) operator(=) ident(reply_addresses)operator(()operator([)operator(])operator(\)) + ident(mail)operator(.)ident(in_reply_to) operator(=) operator([)ident(message_id)operator(()pre_constant(nil)operator(\))operator(])operator(.)ident(compact) + ident(mail)operator(.)ident(references) operator(=) ident(references)operator(()operator([)operator(])operator(\)) operator(+) operator([)ident(message_id)operator(()pre_constant(nil)operator(\))operator(])operator(.)ident(compact) + ident(mail)operator(.)ident(mime_version) operator(=) string<delimiter(')content(1.0)delimiter(')> + ident(mail) + reserved(end) + + + reserved(def) method(base64_encode) + ident(store) string<delimiter(')content(Content-Transfer-Encoding)delimiter(')>operator(,) string<delimiter(')content(Base64)delimiter(')> + pre_constant(self)operator(.)ident(body) operator(=) constant(Base64)operator(.)ident(folding_encode)operator(()pre_constant(self)operator(.)ident(body)operator(\)) + reserved(end) + + reserved(def) method(base64_decode) + reserved(if) regexp<delimiter(/)content(base64)delimiter(/)modifier(i)> operator(===) pre_constant(self)operator(.)ident(transfer_encoding)operator(()string<delimiter(')delimiter(')>operator(\)) + ident(store) string<delimiter(')content(Content-Transfer-Encoding)delimiter(')>operator(,) string<delimiter(')content(8bit)delimiter(')> + pre_constant(self)operator(.)ident(body) operator(=) constant(Base64)operator(.)ident(decode)operator(()pre_constant(self)operator(.)ident(body)operator(,) instance_variable(@config)operator(.)ident(strict_base64decode?)operator(\)) + reserved(end) + reserved(end) + + + reserved(def) method(destinations)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(ret) operator(=) operator([)operator(]) + string<delimiter(%w()content( to cc bcc )delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(nm)operator(|) + reserved(if) ident(h) operator(=) instance_variable(@header)operator([)ident(nm)operator(]) + ident(h)operator(.)ident(addrs)operator(.)ident(each) operator({)operator(|)ident(i)operator(|) ident(ret)operator(.)ident(push) ident(i)operator(.)ident(address) operator(}) + reserved(end) + reserved(end) + ident(ret)operator(.)ident(empty?) operator(?) ident(default) operator(:) ident(ret) + reserved(end) + + reserved(def) method(each_destination)operator(() operator(&)ident(block) operator(\)) + ident(destinations)operator(()operator([)operator(])operator(\))operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(if) constant(Address) operator(===) ident(i) + reserved(yield) ident(i) + reserved(else) + ident(i)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(alias) method(each_dest) method(each_destination) + + + reserved(def) method(reply_addresses)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(reply_to_addrs)operator(()pre_constant(nil)operator(\)) reserved(or) ident(from_addrs)operator(()pre_constant(nil)operator(\)) reserved(or) ident(default) + reserved(end) + + reserved(def) method(error_reply_addresses)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(s) operator(=) ident(sender)operator(()pre_constant(nil)operator(\)) + operator([)ident(s)operator(]) + reserved(else) + ident(from_addrs)operator(()ident(default)operator(\)) + reserved(end) + reserved(end) + + + reserved(def) method(multipart?) + ident(main_type)operator(()string<delimiter(')delimiter(')>operator(\))operator(.)ident(downcase) operator(==) string<delimiter(')content(multipart)delimiter(')> + reserved(end) + + reserved(end) comment(# class Mail) + +reserved(end) comment(# module TMail) +comment(#) +comment(# header.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/encode)delimiter(')> +ident(require) string<delimiter(')content(tmail/address)delimiter(')> +ident(require) string<delimiter(')content(tmail/parser)delimiter(')> +ident(require) string<delimiter(')content(tmail/config)delimiter(')> +ident(require) string<delimiter(')content(tmail/utils)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(HeaderField) + + ident(include) constant(TextUtils) + + reserved(class) operator(<<) class(self) + + reserved(alias) method(newobj) method(new) + + reserved(def) method(new)operator(() ident(name)operator(,) ident(body)operator(,) ident(conf) operator(=) constant(DEFAULT_CONFIG) operator(\)) + ident(klass) operator(=) constant(FNAME_TO_CLASS)operator([)ident(name)operator(.)ident(downcase)operator(]) operator(||) constant(UnstructuredHeader) + ident(klass)operator(.)ident(newobj) ident(body)operator(,) ident(conf) + reserved(end) + + reserved(def) method(new_from_port)operator(() ident(port)operator(,) ident(name)operator(,) ident(conf) operator(=) constant(DEFAULT_CONFIG) operator(\)) + ident(re) operator(=) constant(Regep)operator(.)ident(new)operator(()string<delimiter(')content(\\A)content(()delimiter(')> operator(+) constant(Regexp)operator(.)ident(quote)operator(()ident(name)operator(\)) operator(+) string<delimiter(')content(\):)delimiter(')>operator(,) string<delimiter(')content(i)delimiter(')>operator(\)) + ident(str) operator(=) pre_constant(nil) + ident(port)operator(.)ident(ropen) operator({)operator(|)ident(f)operator(|) + ident(f)operator(.)ident(each) reserved(do) operator(|)ident(line)operator(|) + reserved(if) ident(m) operator(=) ident(re)operator(.)ident(match)operator(()ident(line)operator(\)) reserved(then) ident(str) operator(=) ident(m)operator(.)ident(post_match)operator(.)ident(strip) + reserved(elsif) ident(str) reserved(and) regexp<delimiter(/)char(\\A)content([)char(\\t)content( ])delimiter(/)> operator(===) ident(line) reserved(then) ident(str) operator(<<) string<delimiter(')content( )delimiter(')> operator(<<) ident(line)operator(.)ident(strip) + reserved(elsif) regexp<delimiter(/)char(\\A)content(-*)char(\\s)content(*)char(\\z)delimiter(/)> operator(===) ident(line) reserved(then) reserved(break) + reserved(elsif) ident(str) reserved(then) reserved(break) + reserved(end) + reserved(end) + operator(}) + ident(new)operator(()ident(name)operator(,) ident(str)operator(,) constant(Config)operator(.)ident(to_config)operator(()ident(conf)operator(\))operator(\)) + reserved(end) + + reserved(def) method(internal_new)operator(() ident(name)operator(,) ident(conf) operator(\)) + constant(FNAME_TO_CLASS)operator([)ident(name)operator(])operator(.)ident(newobj)operator(()string<delimiter(')delimiter(')>operator(,) ident(conf)operator(,) pre_constant(true)operator(\)) + reserved(end) + + reserved(end) comment(# class << self) + + reserved(def) method(initialize)operator(() ident(body)operator(,) ident(conf)operator(,) ident(intern) operator(=) pre_constant(false) operator(\)) + instance_variable(@body) operator(=) ident(body) + instance_variable(@config) operator(=) ident(conf) + + instance_variable(@illegal) operator(=) pre_constant(false) + instance_variable(@parsed) operator(=) pre_constant(false) + reserved(if) ident(intern) + instance_variable(@parsed) operator(=) pre_constant(true) + ident(parse_init) + reserved(end) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)instance_variable(@body)operator(.)ident(inspect)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(illegal?) + instance_variable(@illegal) + reserved(end) + + reserved(def) method(empty?) + ident(ensure_parsed) + reserved(return) pre_constant(true) reserved(if) instance_variable(@illegal) + ident(isempty?) + reserved(end) + + ident(private) + + reserved(def) method(ensure_parsed) + reserved(return) reserved(if) instance_variable(@parsed) + instance_variable(@parsed) operator(=) pre_constant(true) + ident(parse) + reserved(end) + + comment(# defabstract parse) + comment(# end) + + reserved(def) method(clear_parse_status) + instance_variable(@parsed) operator(=) pre_constant(false) + instance_variable(@illegal) operator(=) pre_constant(false) + reserved(end) + + ident(public) + + reserved(def) method(body) + ident(ensure_parsed) + ident(v) operator(=) constant(Decoder)operator(.)ident(new)operator(()ident(s) operator(=) string<delimiter(')delimiter(')>operator(\)) + ident(do_accept) ident(v) + ident(v)operator(.)ident(terminate) + ident(s) + reserved(end) + + reserved(def) method(body=)operator(() ident(str) operator(\)) + instance_variable(@body) operator(=) ident(str) + ident(clear_parse_status) + reserved(end) + + ident(include) constant(StrategyInterface) + + reserved(def) method(accept)operator(() ident(strategy)operator(,) ident(dummy1) operator(=) pre_constant(nil)operator(,) ident(dummy2) operator(=) pre_constant(nil) operator(\)) + ident(ensure_parsed) + ident(do_accept) ident(strategy) + ident(strategy)operator(.)ident(terminate) + reserved(end) + + comment(# abstract do_accept) + + reserved(end) + + + reserved(class) class(UnstructuredHeader) operator(<) constant(HeaderField) + + reserved(def) method(body) + ident(ensure_parsed) + instance_variable(@body) + reserved(end) + + reserved(def) method(body=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@body) operator(=) ident(arg) + reserved(end) + + ident(private) + + reserved(def) method(parse_init) + reserved(end) + + reserved(def) method(parse) + instance_variable(@body) operator(=) constant(Decoder)operator(.)ident(decode)operator(()instance_variable(@body)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\n)content(|)char(\\r)char(\\n)content(|)char(\\r)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) instance_variable(@body) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(strategy)operator(.)ident(text) instance_variable(@body) + reserved(end) + + reserved(end) + + + reserved(class) class(StructuredHeader) operator(<) constant(HeaderField) + + reserved(def) method(comments) + ident(ensure_parsed) + instance_variable(@comments) + reserved(end) + + ident(private) + + reserved(def) method(parse) + ident(save) operator(=) pre_constant(nil) + + reserved(begin) + ident(parse_init) + ident(do_parse) + reserved(rescue) constant(SyntaxError) + reserved(if) reserved(not) ident(save) reserved(and) ident(mime_encoded?) instance_variable(@body) + ident(save) operator(=) instance_variable(@body) + instance_variable(@body) operator(=) constant(Decoder)operator(.)ident(decode)operator(()ident(save)operator(\)) + reserved(retry) + reserved(elsif) ident(save) + instance_variable(@body) operator(=) ident(save) + reserved(end) + + instance_variable(@illegal) operator(=) pre_constant(true) + ident(raise) reserved(if) instance_variable(@config)operator(.)ident(strict_parse?) + reserved(end) + reserved(end) + + reserved(def) method(parse_init) + instance_variable(@comments) operator(=) operator([)operator(]) + ident(init) + reserved(end) + + reserved(def) method(do_parse) + ident(obj) operator(=) constant(Parser)operator(.)ident(parse)operator(()pre_constant(self)operator(.)ident(class)operator(::)constant(PARSE_TYPE)operator(,) instance_variable(@body)operator(,) instance_variable(@comments)operator(\)) + ident(set) ident(obj) reserved(if) ident(obj) + reserved(end) + + reserved(end) + + + reserved(class) class(DateTimeHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:DATETIME) + + reserved(def) method(date) + ident(ensure_parsed) + instance_variable(@date) + reserved(end) + + reserved(def) method(date=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@date) operator(=) ident(arg) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@date) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(t) operator(\)) + instance_variable(@date) operator(=) ident(t) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) instance_variable(@date) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(strategy)operator(.)ident(meta) ident(time2str)operator(()instance_variable(@date)operator(\)) + reserved(end) + + reserved(end) + + + reserved(class) class(AddressHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:MADDRESS) + + reserved(def) method(addrs) + ident(ensure_parsed) + instance_variable(@addrs) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@addrs) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(set)operator(() ident(a) operator(\)) + instance_variable(@addrs) operator(=) ident(a) + reserved(end) + + reserved(def) method(isempty?) + instance_variable(@addrs)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(first) operator(=) pre_constant(true) + instance_variable(@addrs)operator(.)ident(each) reserved(do) operator(|)ident(a)operator(|) + reserved(if) ident(first) + ident(first) operator(=) pre_constant(false) + reserved(else) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(,)delimiter(')> + ident(strategy)operator(.)ident(space) + reserved(end) + ident(a)operator(.)ident(accept) ident(strategy) + reserved(end) + + instance_variable(@comments)operator(.)ident(each) reserved(do) operator(|)ident(c)operator(|) + ident(strategy)operator(.)ident(space) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(()delimiter(')> + ident(strategy)operator(.)ident(text) ident(c) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(\))delimiter(')> + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(ReturnPathHeader) operator(<) constant(AddressHeader) + + constant(PARSE_TYPE) operator(=) symbol(:RETPATH) + + reserved(def) method(addr) + ident(addrs)operator(()operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(spec) + ident(a) operator(=) ident(addr)operator(()operator(\)) reserved(or) reserved(return) pre_constant(nil) + ident(a)operator(.)ident(spec) + reserved(end) + + reserved(def) method(routes) + ident(a) operator(=) ident(addr)operator(()operator(\)) reserved(or) reserved(return) pre_constant(nil) + ident(a)operator(.)ident(routes) + reserved(end) + + ident(private) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(a) operator(=) ident(addr)operator(()operator(\)) + + ident(strategy)operator(.)ident(meta) string<delimiter(')content(<)delimiter(')> + reserved(unless) ident(a)operator(.)ident(routes)operator(.)ident(empty?) + ident(strategy)operator(.)ident(meta) ident(a)operator(.)ident(routes)operator(.)ident(map) operator({)operator(|)ident(i)operator(|) string<delimiter(')content(@)delimiter(')> operator(+) ident(i) operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(:)delimiter(')> + reserved(end) + ident(spec) operator(=) ident(a)operator(.)ident(spec) + ident(strategy)operator(.)ident(meta) ident(spec) reserved(if) ident(spec) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(>)delimiter(')> + reserved(end) + + reserved(end) + + + reserved(class) class(SingleAddressHeader) operator(<) constant(AddressHeader) + + reserved(def) method(addr) + ident(addrs)operator(()operator(\))operator([)integer(0)operator(]) + reserved(end) + + ident(private) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(a) operator(=) ident(addr)operator(()operator(\)) + ident(a)operator(.)ident(accept) ident(strategy) + instance_variable(@comments)operator(.)ident(each) reserved(do) operator(|)ident(c)operator(|) + ident(strategy)operator(.)ident(space) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(()delimiter(')> + ident(strategy)operator(.)ident(text) ident(c) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(\))delimiter(')> + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(MessageIdHeader) operator(<) constant(StructuredHeader) + + reserved(def) method(id) + ident(ensure_parsed) + instance_variable(@id) + reserved(end) + + reserved(def) method(id=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@id) operator(=) ident(arg) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@id) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) instance_variable(@id) + reserved(end) + + reserved(def) method(do_parse) + instance_variable(@id) operator(=) instance_variable(@body)operator(.)ident(slice)operator(()constant(MESSAGE_ID)operator(\)) reserved(or) + ident(raise) constant(SyntaxError)operator(,) string<delimiter(")content(wrong Message-ID format: )inline<inline_delimiter(#{)instance_variable(@body)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(strategy)operator(.)ident(meta) instance_variable(@id) + reserved(end) + + reserved(end) + + + reserved(class) class(ReferencesHeader) operator(<) constant(StructuredHeader) + + reserved(def) method(refs) + ident(ensure_parsed) + instance_variable(@refs) + reserved(end) + + reserved(def) method(each_id) + pre_constant(self)operator(.)ident(refs)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(yield) ident(i) reserved(if) constant(MESSAGE_ID) operator(===) ident(i) + reserved(end) + reserved(end) + + reserved(def) method(ids) + ident(ensure_parsed) + instance_variable(@ids) + reserved(end) + + reserved(def) method(each_phrase) + pre_constant(self)operator(.)ident(refs)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(yield) ident(i) reserved(unless) constant(MESSAGE_ID) operator(===) ident(i) + reserved(end) + reserved(end) + + reserved(def) method(phrases) + ident(ret) operator(=) operator([)operator(]) + ident(each_phrase) operator({)operator(|)ident(i)operator(|) ident(ret)operator(.)ident(push) ident(i) operator(}) + ident(ret) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@refs) operator(=) operator([)operator(]) + instance_variable(@ids) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(isempty?) + instance_variable(@ids)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(do_parse) + ident(str) operator(=) instance_variable(@body) + reserved(while) ident(m) operator(=) constant(MESSAGE_ID)operator(.)ident(match)operator(()ident(str)operator(\)) + ident(pre) operator(=) ident(m)operator(.)ident(pre_match)operator(.)ident(strip) + instance_variable(@refs)operator(.)ident(push) ident(pre) reserved(unless) ident(pre)operator(.)ident(empty?) + instance_variable(@refs)operator(.)ident(push) ident(s) operator(=) ident(m)operator([)integer(0)operator(]) + instance_variable(@ids)operator(.)ident(push) ident(s) + ident(str) operator(=) ident(m)operator(.)ident(post_match) + reserved(end) + ident(str) operator(=) ident(str)operator(.)ident(strip) + instance_variable(@refs)operator(.)ident(push) ident(str) reserved(unless) ident(str)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(first) operator(=) pre_constant(true) + instance_variable(@ids)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(if) ident(first) + ident(first) operator(=) pre_constant(false) + reserved(else) + ident(strategy)operator(.)ident(space) + reserved(end) + ident(strategy)operator(.)ident(meta) ident(i) + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(ReceivedHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:RECEIVED) + + reserved(def) method(from) + ident(ensure_parsed) + instance_variable(@from) + reserved(end) + + reserved(def) method(from=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@from) operator(=) ident(arg) + reserved(end) + + reserved(def) method(by) + ident(ensure_parsed) + instance_variable(@by) + reserved(end) + + reserved(def) method(by=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@by) operator(=) ident(arg) + reserved(end) + + reserved(def) method(via) + ident(ensure_parsed) + instance_variable(@via) + reserved(end) + + reserved(def) method(via=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@via) operator(=) ident(arg) + reserved(end) + + reserved(def) method(with) + ident(ensure_parsed) + instance_variable(@with) + reserved(end) + + reserved(def) method(id) + ident(ensure_parsed) + instance_variable(@id) + reserved(end) + + reserved(def) method(id=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@id) operator(=) ident(arg) + reserved(end) + + reserved(def) method(_for) + ident(ensure_parsed) + instance_variable(@_for) + reserved(end) + + reserved(def) method(_for=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@_for) operator(=) ident(arg) + reserved(end) + + reserved(def) method(date) + ident(ensure_parsed) + instance_variable(@date) + reserved(end) + + reserved(def) method(date=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@date) operator(=) ident(arg) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@from) operator(=) instance_variable(@by) operator(=) instance_variable(@via) operator(=) instance_variable(@with) operator(=) instance_variable(@id) operator(=) instance_variable(@_for) operator(=) pre_constant(nil) + instance_variable(@with) operator(=) operator([)operator(]) + instance_variable(@date) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(args) operator(\)) + instance_variable(@from)operator(,) instance_variable(@by)operator(,) instance_variable(@via)operator(,) instance_variable(@with)operator(,) instance_variable(@id)operator(,) instance_variable(@_for)operator(,) instance_variable(@date) operator(=) operator(*)ident(args) + reserved(end) + + reserved(def) method(isempty?) + instance_variable(@with)operator(.)ident(empty?) reserved(and) reserved(not) operator(()instance_variable(@from) reserved(or) instance_variable(@by) reserved(or) instance_variable(@via) reserved(or) instance_variable(@id) reserved(or) instance_variable(@_for) reserved(or) instance_variable(@date)operator(\)) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(list) operator(=) operator([)operator(]) + ident(list)operator(.)ident(push) string<delimiter(')content(from )delimiter(')> operator(+) instance_variable(@from) reserved(if) instance_variable(@from) + ident(list)operator(.)ident(push) string<delimiter(')content(by )delimiter(')> operator(+) instance_variable(@by) reserved(if) instance_variable(@by) + ident(list)operator(.)ident(push) string<delimiter(')content(via )delimiter(')> operator(+) instance_variable(@via) reserved(if) instance_variable(@via) + instance_variable(@with)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + ident(list)operator(.)ident(push) string<delimiter(')content(with )delimiter(')> operator(+) ident(i) + reserved(end) + ident(list)operator(.)ident(push) string<delimiter(')content(id )delimiter(')> operator(+) instance_variable(@id) reserved(if) instance_variable(@id) + ident(list)operator(.)ident(push) string<delimiter(')content(for <)delimiter(')> operator(+) instance_variable(@_for) operator(+) string<delimiter(')content(>)delimiter(')> reserved(if) instance_variable(@_for) + + ident(first) operator(=) pre_constant(true) + ident(list)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + ident(strategy)operator(.)ident(space) reserved(unless) ident(first) + ident(strategy)operator(.)ident(meta) ident(i) + ident(first) operator(=) pre_constant(false) + reserved(end) + reserved(if) instance_variable(@date) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(;)delimiter(')> + ident(strategy)operator(.)ident(space) + ident(strategy)operator(.)ident(meta) ident(time2str)operator(()instance_variable(@date)operator(\)) + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(KeywordsHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:KEYWORDS) + + reserved(def) method(keys) + ident(ensure_parsed) + instance_variable(@keys) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@keys) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(set)operator(() ident(a) operator(\)) + instance_variable(@keys) operator(=) ident(a) + reserved(end) + + reserved(def) method(isempty?) + instance_variable(@keys)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(first) operator(=) pre_constant(true) + instance_variable(@keys)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(if) ident(first) + ident(first) operator(=) pre_constant(false) + reserved(else) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(,)delimiter(')> + reserved(end) + ident(strategy)operator(.)ident(meta) ident(i) + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(EncryptedHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:ENCRYPTED) + + reserved(def) method(encrypter) + ident(ensure_parsed) + instance_variable(@encrypter) + reserved(end) + + reserved(def) method(encrypter=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@encrypter) operator(=) ident(arg) + reserved(end) + + reserved(def) method(keyword) + ident(ensure_parsed) + instance_variable(@keyword) + reserved(end) + + reserved(def) method(keyword=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@keyword) operator(=) ident(arg) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@encrypter) operator(=) pre_constant(nil) + instance_variable(@keyword) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(args) operator(\)) + instance_variable(@encrypter)operator(,) instance_variable(@keyword) operator(=) ident(args) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) operator(()instance_variable(@encrypter) reserved(or) instance_variable(@keyword)operator(\)) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + reserved(if) instance_variable(@key) + ident(strategy)operator(.)ident(meta) instance_variable(@encrypter) operator(+) string<delimiter(')content(,)delimiter(')> + ident(strategy)operator(.)ident(space) + ident(strategy)operator(.)ident(meta) instance_variable(@keyword) + reserved(else) + ident(strategy)operator(.)ident(meta) instance_variable(@encrypter) + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(MimeVersionHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:MIMEVERSION) + + reserved(def) method(major) + ident(ensure_parsed) + instance_variable(@major) + reserved(end) + + reserved(def) method(major=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@major) operator(=) ident(arg) + reserved(end) + + reserved(def) method(minor) + ident(ensure_parsed) + instance_variable(@minor) + reserved(end) + + reserved(def) method(minor=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@minor) operator(=) ident(arg) + reserved(end) + + reserved(def) method(version) + ident(sprintf)operator(()string<delimiter(')content(%d.%d)delimiter(')>operator(,) ident(major)operator(,) ident(minor)operator(\)) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@major) operator(=) pre_constant(nil) + instance_variable(@minor) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(args) operator(\)) + instance_variable(@major)operator(,) instance_variable(@minor) operator(=) operator(*)ident(args) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) operator(()instance_variable(@major) reserved(or) instance_variable(@minor)operator(\)) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(strategy)operator(.)ident(meta) ident(sprintf)operator(()string<delimiter(')content(%d.%d)delimiter(')>operator(,) instance_variable(@major)operator(,) instance_variable(@minor)operator(\)) + reserved(end) + + reserved(end) + + + reserved(class) class(ContentTypeHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:CTYPE) + + reserved(def) method(main_type) + ident(ensure_parsed) + instance_variable(@main) + reserved(end) + + reserved(def) method(main_type=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@main) operator(=) ident(arg)operator(.)ident(downcase) + reserved(end) + + reserved(def) method(sub_type) + ident(ensure_parsed) + instance_variable(@sub) + reserved(end) + + reserved(def) method(sub_type=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@sub) operator(=) ident(arg)operator(.)ident(downcase) + reserved(end) + + reserved(def) method(content_type) + ident(ensure_parsed) + instance_variable(@sub) operator(?) ident(sprintf)operator(()string<delimiter(')content(%s/%s)delimiter(')>operator(,) instance_variable(@main)operator(,) instance_variable(@sub)operator(\)) operator(:) instance_variable(@main) + reserved(end) + + reserved(def) method(params) + ident(ensure_parsed) + instance_variable(@params) + reserved(end) + + reserved(def) method([])operator(() ident(key) operator(\)) + ident(ensure_parsed) + instance_variable(@params) reserved(and) instance_variable(@params)operator([)ident(key)operator(]) + reserved(end) + + reserved(def) method([]=)operator(() ident(key)operator(,) ident(val) operator(\)) + ident(ensure_parsed) + operator(()instance_variable(@params) operator(||=) operator({)operator(})operator(\))operator([)ident(key)operator(]) operator(=) ident(val) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@main) operator(=) instance_variable(@sub) operator(=) instance_variable(@params) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(args) operator(\)) + instance_variable(@main)operator(,) instance_variable(@sub)operator(,) instance_variable(@params) operator(=) operator(*)ident(args) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) operator(()instance_variable(@main) reserved(or) instance_variable(@sub)operator(\)) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + reserved(if) instance_variable(@sub) + ident(strategy)operator(.)ident(meta) ident(sprintf)operator(()string<delimiter(')content(%s/%s)delimiter(')>operator(,) instance_variable(@main)operator(,) instance_variable(@sub)operator(\)) + reserved(else) + ident(strategy)operator(.)ident(meta) instance_variable(@main) + reserved(end) + instance_variable(@params)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,)ident(v)operator(|) + reserved(if) ident(v) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(;)delimiter(')> + ident(strategy)operator(.)ident(space) + ident(strategy)operator(.)ident(kv_pair) ident(k)operator(,) ident(v) + reserved(end) + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(ContentTransferEncodingHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:CENCODING) + + reserved(def) method(encoding) + ident(ensure_parsed) + instance_variable(@encoding) + reserved(end) + + reserved(def) method(encoding=)operator(() ident(arg) operator(\)) + ident(ensure_parsed) + instance_variable(@encoding) operator(=) ident(arg) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@encoding) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(s) operator(\)) + instance_variable(@encoding) operator(=) ident(s) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) instance_variable(@encoding) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(strategy)operator(.)ident(meta) instance_variable(@encoding)operator(.)ident(capitalize) + reserved(end) + + reserved(end) + + + reserved(class) class(ContentDispositionHeader) operator(<) constant(StructuredHeader) + + constant(PARSE_TYPE) operator(=) symbol(:CDISPOSITION) + + reserved(def) method(disposition) + ident(ensure_parsed) + instance_variable(@disposition) + reserved(end) + + reserved(def) method(disposition=)operator(() ident(str) operator(\)) + ident(ensure_parsed) + instance_variable(@disposition) operator(=) ident(str)operator(.)ident(downcase) + reserved(end) + + reserved(def) method(params) + ident(ensure_parsed) + instance_variable(@params) + reserved(end) + + reserved(def) method([])operator(() ident(key) operator(\)) + ident(ensure_parsed) + instance_variable(@params) reserved(and) instance_variable(@params)operator([)ident(key)operator(]) + reserved(end) + + reserved(def) method([]=)operator(() ident(key)operator(,) ident(val) operator(\)) + ident(ensure_parsed) + operator(()instance_variable(@params) operator(||=) operator({)operator(})operator(\))operator([)ident(key)operator(]) operator(=) ident(val) + reserved(end) + + ident(private) + + reserved(def) method(init) + instance_variable(@disposition) operator(=) instance_variable(@params) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(set)operator(() ident(args) operator(\)) + instance_variable(@disposition)operator(,) instance_variable(@params) operator(=) operator(*)ident(args) + reserved(end) + + reserved(def) method(isempty?) + reserved(not) instance_variable(@disposition) reserved(and) operator(()reserved(not) instance_variable(@params) reserved(or) instance_variable(@params)operator(.)ident(empty?)operator(\)) + reserved(end) + + reserved(def) method(do_accept)operator(() ident(strategy) operator(\)) + ident(strategy)operator(.)ident(meta) instance_variable(@disposition) + instance_variable(@params)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,)ident(v)operator(|) + ident(strategy)operator(.)ident(meta) string<delimiter(')content(;)delimiter(')> + ident(strategy)operator(.)ident(space) + ident(strategy)operator(.)ident(kv_pair) ident(k)operator(,) ident(v) + reserved(end) + reserved(end) + + reserved(end) + + + reserved(class) class(HeaderField) comment(# redefine) + + constant(FNAME_TO_CLASS) operator(=) operator({) + string<delimiter(')content(date)delimiter(')> operator(=)operator(>) constant(DateTimeHeader)operator(,) + string<delimiter(')content(resent-date)delimiter(')> operator(=)operator(>) constant(DateTimeHeader)operator(,) + string<delimiter(')content(to)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(cc)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(bcc)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(from)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(reply-to)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(resent-to)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(resent-cc)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(resent-bcc)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(resent-from)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(resent-reply-to)delimiter(')> operator(=)operator(>) constant(AddressHeader)operator(,) + string<delimiter(')content(sender)delimiter(')> operator(=)operator(>) constant(SingleAddressHeader)operator(,) + string<delimiter(')content(resent-sender)delimiter(')> operator(=)operator(>) constant(SingleAddressHeader)operator(,) + string<delimiter(')content(return-path)delimiter(')> operator(=)operator(>) constant(ReturnPathHeader)operator(,) + string<delimiter(')content(message-id)delimiter(')> operator(=)operator(>) constant(MessageIdHeader)operator(,) + string<delimiter(')content(resent-message-id)delimiter(')> operator(=)operator(>) constant(MessageIdHeader)operator(,) + string<delimiter(')content(in-reply-to)delimiter(')> operator(=)operator(>) constant(ReferencesHeader)operator(,) + string<delimiter(')content(received)delimiter(')> operator(=)operator(>) constant(ReceivedHeader)operator(,) + string<delimiter(')content(references)delimiter(')> operator(=)operator(>) constant(ReferencesHeader)operator(,) + string<delimiter(')content(keywords)delimiter(')> operator(=)operator(>) constant(KeywordsHeader)operator(,) + string<delimiter(')content(encrypted)delimiter(')> operator(=)operator(>) constant(EncryptedHeader)operator(,) + string<delimiter(')content(mime-version)delimiter(')> operator(=)operator(>) constant(MimeVersionHeader)operator(,) + string<delimiter(')content(content-type)delimiter(')> operator(=)operator(>) constant(ContentTypeHeader)operator(,) + string<delimiter(')content(content-transfer-encoding)delimiter(')> operator(=)operator(>) constant(ContentTransferEncodingHeader)operator(,) + string<delimiter(')content(content-disposition)delimiter(')> operator(=)operator(>) constant(ContentDispositionHeader)operator(,) + string<delimiter(')content(content-id)delimiter(')> operator(=)operator(>) constant(MessageIdHeader)operator(,) + string<delimiter(')content(subject)delimiter(')> operator(=)operator(>) constant(UnstructuredHeader)operator(,) + string<delimiter(')content(comments)delimiter(')> operator(=)operator(>) constant(UnstructuredHeader)operator(,) + string<delimiter(')content(content-description)delimiter(')> operator(=)operator(>) constant(UnstructuredHeader) + operator(}) + + reserved(end) + +reserved(end) comment(# module TMail) +comment(#) +comment(# info.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +reserved(module) class(TMail) + + constant(Version) operator(=) string<delimiter(')content(0.10.7)delimiter(')> + constant(Copyright) operator(=) string<delimiter(')content(Copyright (c\) 1998-2002 Minero Aoki)delimiter(')> + +reserved(end) +ident(require) string<delimiter(')content(tmail/mailbox)delimiter(')> +comment(#) +comment(# mail.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/facade)delimiter(')> +ident(require) string<delimiter(')content(tmail/encode)delimiter(')> +ident(require) string<delimiter(')content(tmail/header)delimiter(')> +ident(require) string<delimiter(')content(tmail/port)delimiter(')> +ident(require) string<delimiter(')content(tmail/config)delimiter(')> +ident(require) string<delimiter(')content(tmail/utils)delimiter(')> +ident(require) string<delimiter(')content(tmail/attachments)delimiter(')> +ident(require) string<delimiter(')content(tmail/quoting)delimiter(')> +ident(require) string<delimiter(')content(socket)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Mail) + + reserved(class) operator(<<) class(self) + reserved(def) method(load)operator(() ident(fname) operator(\)) + ident(new)operator(()constant(FilePort)operator(.)ident(new)operator(()ident(fname)operator(\))operator(\)) + reserved(end) + + reserved(alias) method(load_from) method(load) + reserved(alias) method(loadfrom) method(load) + + reserved(def) method(parse)operator(() ident(str) operator(\)) + ident(new)operator(()constant(StringPort)operator(.)ident(new)operator(()ident(str)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(initialize)operator(() ident(port) operator(=) pre_constant(nil)operator(,) ident(conf) operator(=) constant(DEFAULT_CONFIG) operator(\)) + instance_variable(@port) operator(=) ident(port) operator(||) constant(StringPort)operator(.)ident(new) + instance_variable(@config) operator(=) constant(Config)operator(.)ident(to_config)operator(()ident(conf)operator(\)) + + instance_variable(@header) operator(=) operator({)operator(}) + instance_variable(@body_port) operator(=) pre_constant(nil) + instance_variable(@body_parsed) operator(=) pre_constant(false) + instance_variable(@epilogue) operator(=) string<delimiter(')delimiter(')> + instance_variable(@parts) operator(=) operator([)operator(]) + + instance_variable(@port)operator(.)ident(ropen) operator({)operator(|)ident(f)operator(|) + ident(parse_header) ident(f) + ident(parse_body) ident(f) reserved(unless) instance_variable(@port)operator(.)ident(reproducible?) + operator(}) + reserved(end) + + ident(attr_reader) symbol(:port) + + reserved(def) method(inspect) + string<delimiter(")char(\\#)content(<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( port=)inline<inline_delimiter(#{)instance_variable(@port)operator(.)ident(inspect)inline_delimiter(})>content( bodyport=)inline<inline_delimiter(#{)instance_variable(@body_port)operator(.)ident(inspect)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + comment(#) + comment(# to_s interfaces) + comment(#) + + ident(public) + + ident(include) constant(StrategyInterface) + + reserved(def) method(write_back)operator(() ident(eol) operator(=) string<delimiter(")char(\\n)delimiter(")>operator(,) ident(charset) operator(=) string<delimiter(')content(e)delimiter(')> operator(\)) + ident(parse_body) + instance_variable(@port)operator(.)ident(wopen) operator({)operator(|)ident(stream)operator(|) ident(encoded) ident(eol)operator(,) ident(charset)operator(,) ident(stream) operator(}) + reserved(end) + + reserved(def) method(accept)operator(() ident(strategy) operator(\)) + ident(with_multipart_encoding)operator(()ident(strategy)operator(\)) operator({) + ident(ordered_each) reserved(do) operator(|)ident(name)operator(,) ident(field)operator(|) + reserved(next) reserved(if) ident(field)operator(.)ident(empty?) + ident(strategy)operator(.)ident(header_name) ident(canonical)operator(()ident(name)operator(\)) + ident(field)operator(.)ident(accept) ident(strategy) + ident(strategy)operator(.)ident(puts) + reserved(end) + ident(strategy)operator(.)ident(puts) + ident(body_port)operator(()operator(\))operator(.)ident(ropen) operator({)operator(|)ident(r)operator(|) + ident(strategy)operator(.)ident(write) ident(r)operator(.)ident(read) + operator(}) + operator(}) + reserved(end) + + ident(private) + + reserved(def) method(canonical)operator(() ident(name) operator(\)) + ident(name)operator(.)ident(split)operator(()regexp<delimiter(/)content(-)delimiter(/)>operator(\))operator(.)ident(map) operator({)operator(|)ident(s)operator(|) ident(s)operator(.)ident(capitalize) operator(})operator(.)ident(join)operator(()string<delimiter(')content(-)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(with_multipart_encoding)operator(() ident(strategy) operator(\)) + reserved(if) ident(parts)operator(()operator(\))operator(.)ident(empty?) comment(# DO NOT USE @parts) + reserved(yield) + + reserved(else) + ident(bound) operator(=) operator(::)constant(TMail)operator(.)ident(new_boundary) + reserved(if) instance_variable(@header)operator(.)ident(key?) string<delimiter(')content(content-type)delimiter(')> + instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(params)operator([)string<delimiter(')content(boundary)delimiter(')>operator(]) operator(=) ident(bound) + reserved(else) + ident(store) string<delimiter(')content(Content-Type)delimiter(')>operator(,) string<delimiter(%<)content(multipart/mixed; boundary=")inline<inline_delimiter(#{)ident(bound)inline_delimiter(})>content(")delimiter(>)> + reserved(end) + + reserved(yield) + + ident(parts)operator(()operator(\))operator(.)ident(each) reserved(do) operator(|)ident(tm)operator(|) + ident(strategy)operator(.)ident(puts) + ident(strategy)operator(.)ident(puts) string<delimiter(')content(--)delimiter(')> operator(+) ident(bound) + ident(tm)operator(.)ident(accept) ident(strategy) + reserved(end) + ident(strategy)operator(.)ident(puts) + ident(strategy)operator(.)ident(puts) string<delimiter(')content(--)delimiter(')> operator(+) ident(bound) operator(+) string<delimiter(')content(--)delimiter(')> + ident(strategy)operator(.)ident(write) ident(epilogue)operator(()operator(\)) + reserved(end) + reserved(end) + + comment(###) + comment(### header) + comment(###) + + ident(public) + + constant(ALLOW_MULTIPLE) operator(=) operator({) + string<delimiter(')content(received)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-date)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-from)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-sender)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-to)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-cc)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-bcc)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(resent-message-id)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(comments)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(keywords)delimiter(')> operator(=)operator(>) pre_constant(true) + operator(}) + constant(USE_ARRAY) operator(=) constant(ALLOW_MULTIPLE) + + reserved(def) method(header) + instance_variable(@header)operator(.)ident(dup) + reserved(end) + + reserved(def) method([])operator(() ident(key) operator(\)) + instance_variable(@header)operator([)ident(key)operator(.)ident(downcase)operator(]) + reserved(end) + + reserved(def) method(sub_header)operator(()ident(key)operator(,) ident(param)operator(\)) + operator(()ident(hdr) operator(=) pre_constant(self)operator([)ident(key)operator(])operator(\)) operator(?) ident(hdr)operator([)ident(param)operator(]) operator(:) pre_constant(nil) + reserved(end) + + reserved(alias) method(fetch) method([]) + + reserved(def) method([]=)operator(() ident(key)operator(,) ident(val) operator(\)) + ident(dkey) operator(=) ident(key)operator(.)ident(downcase) + + reserved(if) ident(val)operator(.)ident(nil?) + instance_variable(@header)operator(.)ident(delete) ident(dkey) + reserved(return) pre_constant(nil) + reserved(end) + + reserved(case) ident(val) + reserved(when) constant(String) + ident(header) operator(=) ident(new_hf)operator(()ident(key)operator(,) ident(val)operator(\)) + reserved(when) constant(HeaderField) + operator(;) + reserved(when) constant(Array) + constant(ALLOW_MULTIPLE)operator(.)ident(include?) ident(dkey) reserved(or) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(: Header must not be multiple)delimiter(")> + instance_variable(@header)operator([)ident(dkey)operator(]) operator(=) ident(val) + reserved(return) ident(val) + reserved(else) + ident(header) operator(=) ident(new_hf)operator(()ident(key)operator(,) ident(val)operator(.)ident(to_s)operator(\)) + reserved(end) + reserved(if) constant(ALLOW_MULTIPLE)operator(.)ident(include?) ident(dkey) + operator(()instance_variable(@header)operator([)ident(dkey)operator(]) operator(||=) operator([)operator(])operator(\))operator(.)ident(push) ident(header) + reserved(else) + instance_variable(@header)operator([)ident(dkey)operator(]) operator(=) ident(header) + reserved(end) + + ident(val) + reserved(end) + + reserved(alias) method(store) method([]=) + + reserved(def) method(each_header) + instance_variable(@header)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(val)operator(|) + operator([)ident(val)operator(])operator(.)ident(flatten)operator(.)ident(each) operator({)operator(|)ident(v)operator(|) reserved(yield) ident(key)operator(,) ident(v) operator(}) + reserved(end) + reserved(end) + + reserved(alias) method(each_pair) method(each_header) + + reserved(def) method(each_header_name)operator(() operator(&)ident(block) operator(\)) + instance_variable(@header)operator(.)ident(each_key)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(alias) method(each_key) method(each_header_name) + + reserved(def) method(each_field)operator(() operator(&)ident(block) operator(\)) + instance_variable(@header)operator(.)ident(values)operator(.)ident(flatten)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(alias) method(each_value) method(each_field) + + constant(FIELD_ORDER) operator(=) string<delimiter(%w()content( + return-path received + resent-date resent-from resent-sender resent-to + resent-cc resent-bcc resent-message-id + date from sender reply-to to cc bcc + message-id in-reply-to references + subject comments keywords + mime-version content-type content-transfer-encoding + content-disposition content-description + )delimiter(\))> + + reserved(def) method(ordered_each) + ident(list) operator(=) instance_variable(@header)operator(.)ident(keys) + constant(FIELD_ORDER)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + reserved(if) ident(list)operator(.)ident(delete)operator(()ident(name)operator(\)) + operator([)instance_variable(@header)operator([)ident(name)operator(])operator(])operator(.)ident(flatten)operator(.)ident(each) operator({)operator(|)ident(v)operator(|) reserved(yield) ident(name)operator(,) ident(v) operator(}) + reserved(end) + reserved(end) + ident(list)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + operator([)instance_variable(@header)operator([)ident(name)operator(])operator(])operator(.)ident(flatten)operator(.)ident(each) operator({)operator(|)ident(v)operator(|) reserved(yield) ident(name)operator(,) ident(v) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(clear) + instance_variable(@header)operator(.)ident(clear) + reserved(end) + + reserved(def) method(delete)operator(() ident(key) operator(\)) + instance_variable(@header)operator(.)ident(delete) ident(key)operator(.)ident(downcase) + reserved(end) + + reserved(def) method(delete_if) + instance_variable(@header)operator(.)ident(delete_if) reserved(do) operator(|)ident(key)operator(,)ident(val)operator(|) + reserved(if) constant(Array) operator(===) ident(val) + ident(val)operator(.)ident(delete_if) operator({)operator(|)ident(v)operator(|) reserved(yield) ident(key)operator(,) ident(v) operator(}) + ident(val)operator(.)ident(empty?) + reserved(else) + reserved(yield) ident(key)operator(,) ident(val) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(keys) + instance_variable(@header)operator(.)ident(keys) + reserved(end) + + reserved(def) method(key?)operator(() ident(key) operator(\)) + instance_variable(@header)operator(.)ident(key?) ident(key)operator(.)ident(downcase) + reserved(end) + + reserved(def) method(values_at)operator(() operator(*)ident(args) operator(\)) + ident(args)operator(.)ident(map) operator({)operator(|)ident(k)operator(|) instance_variable(@header)operator([)ident(k)operator(.)ident(downcase)operator(]) operator(})operator(.)ident(flatten) + reserved(end) + + reserved(alias) method(indexes) method(values_at) + reserved(alias) method(indices) method(values_at) + + ident(private) + + reserved(def) method(parse_header)operator(() ident(f) operator(\)) + ident(name) operator(=) ident(field) operator(=) pre_constant(nil) + ident(unixfrom) operator(=) pre_constant(nil) + + reserved(while) ident(line) operator(=) ident(f)operator(.)ident(gets) + reserved(case) ident(line) + reserved(when) regexp<delimiter(/)char(\\A)content([ )char(\\t)content(])delimiter(/)> comment(# continue from prev line) + ident(raise) constant(SyntaxError)operator(,) string<delimiter(')content(mail is began by space)delimiter(')> reserved(unless) ident(field) + ident(field) operator(<<) string<delimiter(')content( )delimiter(')> operator(<<) ident(line)operator(.)ident(strip) + + reserved(when) regexp<delimiter(/)char(\\A)content(([^)char(\\:)content( )char(\\t)content(]+\):)char(\\s)content(*)delimiter(/)> comment(# new header line) + ident(add_hf) ident(name)operator(,) ident(field) reserved(if) ident(field) + ident(name) operator(=) global_variable($1) + ident(field) operator(=) global_variable($') comment(#.strip) + + reserved(when) regexp<delimiter(/)char(\\A)char(\\-)content(*)char(\\s)content(*)char(\\z)delimiter(/)> comment(# end of header) + ident(add_hf) ident(name)operator(,) ident(field) reserved(if) ident(field) + ident(name) operator(=) ident(field) operator(=) pre_constant(nil) + reserved(break) + + reserved(when) regexp<delimiter(/)char(\\A)content(From ()char(\\S)content(+\))delimiter(/)> + ident(unixfrom) operator(=) global_variable($1) + + reserved(when) regexp<delimiter(/)content(^charset=.*)delimiter(/)> + + reserved(else) + ident(raise) constant(SyntaxError)operator(,) string<delimiter(")content(wrong mail header: ')inline<inline_delimiter(#{)ident(line)operator(.)ident(inspect)inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + ident(add_hf) ident(name)operator(,) ident(field) reserved(if) ident(name) + + reserved(if) ident(unixfrom) + ident(add_hf) string<delimiter(')content(Return-Path)delimiter(')>operator(,) string<delimiter(")content(<)inline<inline_delimiter(#{)ident(unixfrom)inline_delimiter(})>content(>)delimiter(")> reserved(unless) instance_variable(@header)operator([)string<delimiter(')content(return-path)delimiter(')>operator(]) + reserved(end) + reserved(end) + + reserved(def) method(add_hf)operator(() ident(name)operator(,) ident(field) operator(\)) + ident(key) operator(=) ident(name)operator(.)ident(downcase) + ident(field) operator(=) ident(new_hf)operator(()ident(name)operator(,) ident(field)operator(\)) + + reserved(if) constant(ALLOW_MULTIPLE)operator(.)ident(include?) ident(key) + operator(()instance_variable(@header)operator([)ident(key)operator(]) operator(||=) operator([)operator(])operator(\))operator(.)ident(push) ident(field) + reserved(else) + instance_variable(@header)operator([)ident(key)operator(]) operator(=) ident(field) + reserved(end) + reserved(end) + + reserved(def) method(new_hf)operator(() ident(name)operator(,) ident(field) operator(\)) + constant(HeaderField)operator(.)ident(new)operator(()ident(name)operator(,) ident(field)operator(,) instance_variable(@config)operator(\)) + reserved(end) + + comment(###) + comment(### body) + comment(###) + + ident(public) + + reserved(def) method(body_port) + ident(parse_body) + instance_variable(@body_port) + reserved(end) + + reserved(def) method(each)operator(() operator(&)ident(block) operator(\)) + ident(body_port)operator(()operator(\))operator(.)ident(ropen) operator({)operator(|)ident(f)operator(|) ident(f)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) operator(}) + reserved(end) + + reserved(def) method(quoted_body) + ident(parse_body) + instance_variable(@body_port)operator(.)ident(ropen) operator({)operator(|)ident(f)operator(|) + reserved(return) ident(f)operator(.)ident(read) + operator(}) + reserved(end) + + reserved(def) method(body=)operator(() ident(str) operator(\)) + ident(parse_body) + instance_variable(@body_port)operator(.)ident(wopen) operator({)operator(|)ident(f)operator(|) ident(f)operator(.)ident(write) ident(str) operator(}) + ident(str) + reserved(end) + + reserved(alias) method(preamble) method(body) + reserved(alias) method(preamble=) method(body=) + + reserved(def) method(epilogue) + ident(parse_body) + instance_variable(@epilogue)operator(.)ident(dup) + reserved(end) + + reserved(def) method(epilogue=)operator(() ident(str) operator(\)) + ident(parse_body) + instance_variable(@epilogue) operator(=) ident(str) + ident(str) + reserved(end) + + reserved(def) method(parts) + ident(parse_body) + instance_variable(@parts) + reserved(end) + + reserved(def) method(each_part)operator(() operator(&)ident(block) operator(\)) + ident(parts)operator(()operator(\))operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + ident(private) + + reserved(def) method(parse_body)operator(() ident(f) operator(=) pre_constant(nil) operator(\)) + reserved(return) reserved(if) instance_variable(@body_parsed) + reserved(if) ident(f) + ident(parse_body_0) ident(f) + reserved(else) + instance_variable(@port)operator(.)ident(ropen) operator({)operator(|)ident(f)operator(|) + ident(skip_header) ident(f) + ident(parse_body_0) ident(f) + operator(}) + reserved(end) + instance_variable(@body_parsed) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(skip_header)operator(() ident(f) operator(\)) + reserved(while) ident(line) operator(=) ident(f)operator(.)ident(gets) + reserved(return) reserved(if) regexp<delimiter(/)char(\\A)content([)char(\\r)char(\\n)content(]*)char(\\z)delimiter(/)> operator(===) ident(line) + reserved(end) + reserved(end) + + reserved(def) method(parse_body_0)operator(() ident(f) operator(\)) + reserved(if) ident(multipart?) + ident(read_multipart) ident(f) + reserved(else) + instance_variable(@body_port) operator(=) instance_variable(@config)operator(.)ident(new_body_port)operator(()pre_constant(self)operator(\)) + instance_variable(@body_port)operator(.)ident(wopen) operator({)operator(|)ident(w)operator(|) + ident(w)operator(.)ident(write) ident(f)operator(.)ident(read) + operator(}) + reserved(end) + reserved(end) + + reserved(def) method(read_multipart)operator(() ident(src) operator(\)) + ident(bound) operator(=) instance_variable(@header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(params)operator([)string<delimiter(')content(boundary)delimiter(')>operator(]) + ident(is_sep) operator(=) regexp<delimiter(/)char(\\A)content(--)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote) ident(bound)inline_delimiter(})>content((?:--\)?[ )char(\\t)content(]*(?:)char(\\n)content(|)char(\\r)char(\\n)content(|)char(\\r)content(\))delimiter(/)> + ident(lastbound) operator(=) string<delimiter(")content(--)inline<inline_delimiter(#{)ident(bound)inline_delimiter(})>content(--)delimiter(")> + + ident(ports) operator(=) operator([) instance_variable(@config)operator(.)ident(new_preamble_port)operator(()pre_constant(self)operator(\)) operator(]) + reserved(begin) + ident(f) operator(=) ident(ports)operator(.)ident(last)operator(.)ident(wopen) + reserved(while) ident(line) operator(=) ident(src)operator(.)ident(gets) + reserved(if) ident(is_sep) operator(===) ident(line) + ident(f)operator(.)ident(close) + reserved(break) reserved(if) ident(line)operator(.)ident(strip) operator(==) ident(lastbound) + ident(ports)operator(.)ident(push) instance_variable(@config)operator(.)ident(new_part_port)operator(()pre_constant(self)operator(\)) + ident(f) operator(=) ident(ports)operator(.)ident(last)operator(.)ident(wopen) + reserved(else) + ident(f) operator(<<) ident(line) + reserved(end) + reserved(end) + instance_variable(@epilogue) operator(=) operator(()ident(src)operator(.)ident(read) operator(||) string<delimiter(')delimiter(')>operator(\)) + reserved(ensure) + ident(f)operator(.)ident(close) reserved(if) ident(f) reserved(and) reserved(not) ident(f)operator(.)ident(closed?) + reserved(end) + + instance_variable(@body_port) operator(=) ident(ports)operator(.)ident(shift) + instance_variable(@parts) operator(=) ident(ports)operator(.)ident(map) operator({)operator(|)ident(p)operator(|) pre_constant(self)operator(.)ident(class)operator(.)ident(new)operator(()ident(p)operator(,) instance_variable(@config)operator(\)) operator(}) + reserved(end) + + reserved(end) comment(# class Mail) + +reserved(end) comment(# module TMail) +comment(#) +comment(# mailbox.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/port)delimiter(')> +ident(require) string<delimiter(')content(socket)delimiter(')> +ident(require) string<delimiter(')content(mutex_m)delimiter(')> + + +reserved(unless) operator([)operator(])operator(.)ident(respond_to?)operator(()symbol(:sort_by)operator(\)) +reserved(module) class(Enumerable)comment(#:nodoc:) + reserved(def) method(sort_by) + ident(map) operator({)operator(|)ident(i)operator(|) operator([)reserved(yield)operator(()ident(i)operator(\))operator(,) ident(i)operator(]) operator(})operator(.)ident(sort) operator({)operator(|)ident(a)operator(,)ident(b)operator(|) ident(a)operator(.)ident(first) operator(<=>) ident(b)operator(.)ident(first) operator(})operator(.)ident(map) operator({)operator(|)ident(i)operator(|) ident(i)operator([)integer(1)operator(]) operator(}) + reserved(end) +reserved(end) +reserved(end) + + +reserved(module) class(TMail) + + reserved(class) class(MhMailbox) + + constant(PORT_CLASS) operator(=) constant(MhPort) + + reserved(def) method(initialize)operator(() ident(dir) operator(\)) + ident(edir) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(dir)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(not directory: )inline<inline_delimiter(#{)ident(dir)inline_delimiter(})>delimiter(")>\ + reserved(unless) constant(FileTest)operator(.)ident(directory?) ident(edir) + instance_variable(@dirname) operator(=) ident(edir) + instance_variable(@last_file) operator(=) pre_constant(nil) + instance_variable(@last_atime) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(directory) + instance_variable(@dirname) + reserved(end) + + reserved(alias) method(dirname) method(directory) + + ident(attr_accessor) symbol(:last_atime) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(close) + reserved(end) + + reserved(def) method(new_port) + constant(PORT_CLASS)operator(.)ident(new)operator(()ident(next_file_name)operator(()operator(\))operator(\)) + reserved(end) + + reserved(def) method(each_port) + ident(mail_files)operator(()operator(\))operator(.)ident(each) reserved(do) operator(|)ident(path)operator(|) + reserved(yield) constant(PORT_CLASS)operator(.)ident(new)operator(()ident(path)operator(\)) + reserved(end) + instance_variable(@last_atime) operator(=) constant(Time)operator(.)ident(now) + reserved(end) + + reserved(alias) method(each) method(each_port) + + reserved(def) method(reverse_each_port) + ident(mail_files)operator(()operator(\))operator(.)ident(reverse_each) reserved(do) operator(|)ident(path)operator(|) + reserved(yield) constant(PORT_CLASS)operator(.)ident(new)operator(()ident(path)operator(\)) + reserved(end) + instance_variable(@last_atime) operator(=) constant(Time)operator(.)ident(now) + reserved(end) + + reserved(alias) method(reverse_each) method(reverse_each_port) + + comment(# old #each_mail returns Port) + comment(#def each_mail) + comment(# each_port do |port|) + comment(# yield Mail.new(port\)) + comment(# end) + comment(#end) + + reserved(def) method(each_new_port)operator(() ident(mtime) operator(=) pre_constant(nil)operator(,) operator(&)ident(block) operator(\)) + ident(mtime) operator(||=) instance_variable(@last_atime) + reserved(return) ident(each_port)operator(()operator(&)ident(block)operator(\)) reserved(unless) ident(mtime) + reserved(return) reserved(unless) constant(File)operator(.)ident(mtime)operator(()instance_variable(@dirname)operator(\)) operator(>)operator(=) ident(mtime) + + ident(mail_files)operator(()operator(\))operator(.)ident(each) reserved(do) operator(|)ident(path)operator(|) + reserved(yield) constant(PORT_CLASS)operator(.)ident(new)operator(()ident(path)operator(\)) reserved(if) constant(File)operator(.)ident(mtime)operator(()ident(path)operator(\)) operator(>) ident(mtime) + reserved(end) + instance_variable(@last_atime) operator(=) constant(Time)operator(.)ident(now) + reserved(end) + + ident(private) + + reserved(def) method(mail_files) + constant(Dir)operator(.)ident(entries)operator(()instance_variable(@dirname)operator(\))\ + operator(.)ident(select) operator({)operator(|)ident(s)operator(|) regexp<delimiter(/)char(\\A)char(\\d)content(+)char(\\z)delimiter(/)> operator(===) ident(s) operator(})\ + operator(.)ident(map) operator({)operator(|)ident(s)operator(|) ident(s)operator(.)ident(to_i) operator(})\ + operator(.)ident(sort)\ + operator(.)ident(map) operator({)operator(|)ident(i)operator(|) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")> operator(})\ + operator(.)ident(select) operator({)operator(|)ident(path)operator(|) constant(FileTest)operator(.)ident(file?) ident(path) operator(}) + reserved(end) + + reserved(def) method(next_file_name) + reserved(unless) ident(n) operator(=) instance_variable(@last_file) + ident(n) operator(=) integer(0) + constant(Dir)operator(.)ident(entries)operator(()instance_variable(@dirname)operator(\))\ + operator(.)ident(select) operator({)operator(|)ident(s)operator(|) regexp<delimiter(/)char(\\A)char(\\d)content(+)char(\\z)delimiter(/)> operator(===) ident(s) operator(})\ + operator(.)ident(map) operator({)operator(|)ident(s)operator(|) ident(s)operator(.)ident(to_i) operator(})operator(.)ident(sort)\ + operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(next) reserved(unless) constant(FileTest)operator(.)ident(file?) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")> + ident(n) operator(=) ident(i) + reserved(end) + reserved(end) + reserved(begin) + ident(n) operator(+=) integer(1) + reserved(end) reserved(while) constant(FileTest)operator(.)ident(exist?) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>delimiter(")> + instance_variable(@last_file) operator(=) ident(n) + + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(end) comment(# MhMailbox) + + constant(MhLoader) operator(=) constant(MhMailbox) + + + reserved(class) class(UNIXMbox) + + reserved(def) constant(UNIXMbox)operator(.)ident(lock)operator(() ident(fname) operator(\)) + reserved(begin) + ident(f) operator(=) constant(File)operator(.)ident(open)operator(()ident(fname)operator(\)) + ident(f)operator(.)ident(flock) constant(File)operator(::)constant(LOCK_EX) + reserved(yield) ident(f) + reserved(ensure) + ident(f)operator(.)ident(flock) constant(File)operator(::)constant(LOCK_UN) + ident(f)operator(.)ident(close) reserved(if) ident(f) reserved(and) reserved(not) ident(f)operator(.)ident(closed?) + reserved(end) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(alias) method(newobj) method(new) + reserved(end) + + reserved(def) constant(UNIXMbox)operator(.)ident(new)operator(() ident(fname)operator(,) ident(tmpdir) operator(=) pre_constant(nil)operator(,) ident(readonly) operator(=) pre_constant(false) operator(\)) + ident(tmpdir) operator(=) constant(ENV)operator([)string<delimiter(')content(TEMP)delimiter(')>operator(]) operator(||) constant(ENV)operator([)string<delimiter(')content(TMP)delimiter(')>operator(]) operator(||) string<delimiter(')content(/tmp)delimiter(')> + ident(newobj)operator(()ident(fname)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(tmpdir)inline_delimiter(})>content(/ruby_tmail_)inline<inline_delimiter(#{)global_variable($$)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(rand)operator(()operator(\))inline_delimiter(})>delimiter(")>operator(,) ident(readonly)operator(,) pre_constant(false)operator(\)) + reserved(end) + + reserved(def) constant(UNIXMbox)operator(.)ident(static_new)operator(() ident(fname)operator(,) ident(dir)operator(,) ident(readonly) operator(=) pre_constant(false) operator(\)) + ident(newobj)operator(()ident(fname)operator(,) ident(dir)operator(,) ident(readonly)operator(,) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(initialize)operator(() ident(fname)operator(,) ident(mhdir)operator(,) ident(readonly)operator(,) ident(static) operator(\)) + instance_variable(@filename) operator(=) ident(fname) + instance_variable(@readonly) operator(=) ident(readonly) + instance_variable(@closed) operator(=) pre_constant(false) + + constant(Dir)operator(.)ident(mkdir) ident(mhdir) + instance_variable(@real) operator(=) constant(MhMailbox)operator(.)ident(new)operator(()ident(mhdir)operator(\)) + instance_variable(@finalizer) operator(=) constant(UNIXMbox)operator(.)ident(mkfinal)operator(()instance_variable(@real)operator(,) instance_variable(@filename)operator(,) operator(!)instance_variable(@readonly)operator(,) operator(!)ident(static)operator(\)) + constant(ObjectSpace)operator(.)ident(define_finalizer) pre_constant(self)operator(,) instance_variable(@finalizer) + reserved(end) + + reserved(def) constant(UNIXMbox)operator(.)ident(mkfinal)operator(() ident(mh)operator(,) ident(mboxfile)operator(,) ident(writeback_p)operator(,) ident(cleanup_p) operator(\)) + ident(lambda) operator({) + reserved(if) ident(writeback_p) + ident(lock)operator(()ident(mboxfile)operator(\)) operator({)operator(|)ident(f)operator(|) + ident(mh)operator(.)ident(each_port) reserved(do) operator(|)ident(port)operator(|) + ident(f)operator(.)ident(puts) ident(create_from_line)operator(()ident(port)operator(\)) + ident(port)operator(.)ident(ropen) operator({)operator(|)ident(r)operator(|) + ident(f)operator(.)ident(puts) ident(r)operator(.)ident(read) + operator(}) + reserved(end) + operator(}) + reserved(end) + reserved(if) ident(cleanup_p) + constant(Dir)operator(.)ident(foreach)operator(()ident(mh)operator(.)ident(dirname)operator(\)) reserved(do) operator(|)ident(fname)operator(|) + reserved(next) reserved(if) regexp<delimiter(/)char(\\A)char(\\.)char(\\.)content(?)char(\\z)delimiter(/)> operator(===) ident(fname) + constant(File)operator(.)ident(unlink) string<delimiter(")inline<inline_delimiter(#{)ident(mh)operator(.)ident(dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>delimiter(")> + reserved(end) + constant(Dir)operator(.)ident(rmdir) ident(mh)operator(.)ident(dirname) + reserved(end) + operator(}) + reserved(end) + + comment(# make _From line) + reserved(def) constant(UNIXMbox)operator(.)ident(create_from_line)operator(() ident(port) operator(\)) + ident(sprintf) string<delimiter(')content(From %s %s)delimiter(')>operator(,) + ident(fromaddr)operator(()operator(\))operator(,) constant(TextUtils)operator(.)ident(time2str)operator(()constant(File)operator(.)ident(mtime)operator(()ident(port)operator(.)ident(filename)operator(\))operator(\)) + reserved(end) + + reserved(def) constant(UNIXMbox)operator(.)ident(fromaddr) + ident(h) operator(=) constant(HeaderField)operator(.)ident(new_from_port)operator(()ident(port)operator(,) string<delimiter(')content(Return-Path)delimiter(')>operator(\)) operator(||) + constant(HeaderField)operator(.)ident(new_from_port)operator(()ident(port)operator(,) string<delimiter(')content(From)delimiter(')>operator(\)) reserved(or) reserved(return) string<delimiter(')content(nobody)delimiter(')> + ident(a) operator(=) ident(h)operator(.)ident(addrs)operator([)integer(0)operator(]) reserved(or) reserved(return) string<delimiter(')content(nobody)delimiter(')> + ident(a)operator(.)ident(spec) + reserved(end) + ident(private_class_method) symbol(:fromaddr) + + reserved(def) method(close) + reserved(return) reserved(if) instance_variable(@closed) + + constant(ObjectSpace)operator(.)ident(undefine_finalizer) pre_constant(self) + instance_variable(@finalizer)operator(.)ident(call) + instance_variable(@finalizer) operator(=) pre_constant(nil) + instance_variable(@real) operator(=) pre_constant(nil) + instance_variable(@closed) operator(=) pre_constant(true) + instance_variable(@updated) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(each_port)operator(() operator(&)ident(block) operator(\)) + ident(close_check) + ident(update) + instance_variable(@real)operator(.)ident(each_port)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(alias) method(each) method(each_port) + + reserved(def) method(reverse_each_port)operator(() operator(&)ident(block) operator(\)) + ident(close_check) + ident(update) + instance_variable(@real)operator(.)ident(reverse_each_port)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(alias) method(reverse_each) method(reverse_each_port) + + comment(# old #each_mail returns Port) + comment(#def each_mail( &block \)) + comment(# each_port do |port|) + comment(# yield Mail.new(port\)) + comment(# end) + comment(#end) + + reserved(def) method(each_new_port)operator(() ident(mtime) operator(=) pre_constant(nil) operator(\)) + ident(close_check) + ident(update) + instance_variable(@real)operator(.)ident(each_new_port)operator(()ident(mtime)operator(\)) operator({)operator(|)ident(p)operator(|) reserved(yield) ident(p) operator(}) + reserved(end) + + reserved(def) method(new_port) + ident(close_check) + instance_variable(@real)operator(.)ident(new_port) + reserved(end) + + ident(private) + + reserved(def) method(close_check) + instance_variable(@closed) reserved(and) ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(accessing already closed mbox)delimiter(')> + reserved(end) + + reserved(def) method(update) + reserved(return) reserved(if) constant(FileTest)operator(.)ident(zero?)operator(()instance_variable(@filename)operator(\)) + reserved(return) reserved(if) instance_variable(@updated) reserved(and) constant(File)operator(.)ident(mtime)operator(()instance_variable(@filename)operator(\)) operator(<) instance_variable(@updated) + ident(w) operator(=) pre_constant(nil) + ident(port) operator(=) pre_constant(nil) + ident(time) operator(=) pre_constant(nil) + constant(UNIXMbox)operator(.)ident(lock)operator(()instance_variable(@filename)operator(\)) operator({)operator(|)ident(f)operator(|) + reserved(begin) + ident(f)operator(.)ident(each) reserved(do) operator(|)ident(line)operator(|) + reserved(if) regexp<delimiter(/)char(\\A)content(From )delimiter(/)> operator(===) ident(line) + ident(w)operator(.)ident(close) reserved(if) ident(w) + constant(File)operator(.)ident(utime) ident(time)operator(,) ident(time)operator(,) ident(port)operator(.)ident(filename) reserved(if) ident(time) + + ident(port) operator(=) instance_variable(@real)operator(.)ident(new_port) + ident(w) operator(=) ident(port)operator(.)ident(wopen) + ident(time) operator(=) ident(fromline2time)operator(()ident(line)operator(\)) + reserved(else) + ident(w)operator(.)ident(print) ident(line) reserved(if) ident(w) + reserved(end) + reserved(end) + reserved(ensure) + reserved(if) ident(w) reserved(and) reserved(not) ident(w)operator(.)ident(closed?) + ident(w)operator(.)ident(close) + constant(File)operator(.)ident(utime) ident(time)operator(,) ident(time)operator(,) ident(port)operator(.)ident(filename) reserved(if) ident(time) + reserved(end) + reserved(end) + ident(f)operator(.)ident(truncate)operator(()integer(0)operator(\)) reserved(unless) instance_variable(@readonly) + instance_variable(@updated) operator(=) constant(Time)operator(.)ident(now) + operator(}) + reserved(end) + + reserved(def) method(fromline2time)operator(() ident(line) operator(\)) + ident(m) operator(=) regexp<delimiter(/)char(\\A)content(From )char(\\S)content(+ )char(\\w)content(+ ()char(\\w)content(+\) ()char(\\d)content(+\) ()char(\\d)content(+\):()char(\\d)content(+\):()char(\\d)content(+\) ()char(\\d)content(+\))delimiter(/)>operator(.)ident(match)operator(()ident(line)operator(\)) \ + reserved(or) reserved(return) pre_constant(nil) + constant(Time)operator(.)ident(local)operator(()ident(m)operator([)integer(6)operator(])operator(.)ident(to_i)operator(,) ident(m)operator([)integer(1)operator(])operator(,) ident(m)operator([)integer(2)operator(])operator(.)ident(to_i)operator(,) ident(m)operator([)integer(3)operator(])operator(.)ident(to_i)operator(,) ident(m)operator([)integer(4)operator(])operator(.)ident(to_i)operator(,) ident(m)operator([)integer(5)operator(])operator(.)ident(to_i)operator(\)) + reserved(end) + + reserved(end) comment(# UNIXMbox) + + constant(MboxLoader) operator(=) constant(UNIXMbox) + + + reserved(class) class(Maildir) + + ident(extend) constant(Mutex_m) + + constant(PORT_CLASS) operator(=) constant(MaildirPort) + + instance_variable(@seq) operator(=) integer(0) + reserved(def) constant(Maildir)operator(.)ident(unique_number) + ident(synchronize) operator({) + instance_variable(@seq) operator(+=) integer(1) + reserved(return) instance_variable(@seq) + operator(}) + reserved(end) + + reserved(def) method(initialize)operator(() ident(dir) operator(=) pre_constant(nil) operator(\)) + instance_variable(@dirname) operator(=) ident(dir) operator(||) constant(ENV)operator([)string<delimiter(')content(MAILDIR)delimiter(')>operator(]) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(not directory: )inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>delimiter(")>\ + reserved(unless) constant(FileTest)operator(.)ident(directory?) instance_variable(@dirname) + instance_variable(@new) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/new)delimiter(")> + instance_variable(@tmp) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/tmp)delimiter(")> + instance_variable(@cur) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(/cur)delimiter(")> + reserved(end) + + reserved(def) method(directory) + instance_variable(@dirname) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)instance_variable(@dirname)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(close) + reserved(end) + + reserved(def) method(each_port) + ident(mail_files)operator(()instance_variable(@cur)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(path)operator(|) + reserved(yield) constant(PORT_CLASS)operator(.)ident(new)operator(()ident(path)operator(\)) + reserved(end) + reserved(end) + + reserved(alias) method(each) method(each_port) + + reserved(def) method(reverse_each_port) + ident(mail_files)operator(()instance_variable(@cur)operator(\))operator(.)ident(reverse_each) reserved(do) operator(|)ident(path)operator(|) + reserved(yield) constant(PORT_CLASS)operator(.)ident(new)operator(()ident(path)operator(\)) + reserved(end) + reserved(end) + + reserved(alias) method(reverse_each) method(reverse_each_port) + + reserved(def) method(new_port) + ident(fname) operator(=) pre_constant(nil) + ident(tmpfname) operator(=) pre_constant(nil) + ident(newfname) operator(=) pre_constant(nil) + + reserved(begin) + ident(fname) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(Time)operator(.)ident(now)operator(.)ident(to_i)inline_delimiter(})>content(.)inline<inline_delimiter(#{)global_variable($$)inline_delimiter(})>content(_)inline<inline_delimiter(#{)constant(Maildir)operator(.)ident(unique_number)inline_delimiter(})>content(.)inline<inline_delimiter(#{)constant(Socket)operator(.)ident(gethostname)inline_delimiter(})>delimiter(")> + + ident(tmpfname) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@tmp)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>delimiter(")> + ident(newfname) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@new)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>delimiter(")> + reserved(end) reserved(while) constant(FileTest)operator(.)ident(exist?) ident(tmpfname) + + reserved(if) ident(block_given?) + constant(File)operator(.)ident(open)operator(()ident(tmpfname)operator(,) string<delimiter(')content(w)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) reserved(yield) ident(f) operator(}) + constant(File)operator(.)ident(rename) ident(tmpfname)operator(,) ident(newfname) + constant(PORT_CLASS)operator(.)ident(new)operator(()ident(newfname)operator(\)) + reserved(else) + constant(File)operator(.)ident(open)operator(()ident(tmpfname)operator(,) string<delimiter(')content(w)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) ident(f)operator(.)ident(write) string<delimiter(")char(\\n)char(\\n)delimiter(")> operator(}) + constant(PORT_CLASS)operator(.)ident(new)operator(()ident(tmpfname)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(each_new_port) + ident(mail_files)operator(()instance_variable(@new)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(path)operator(|) + ident(dest) operator(=) instance_variable(@cur) operator(+) string<delimiter(')content(/)delimiter(')> operator(+) constant(File)operator(.)ident(basename)operator(()ident(path)operator(\)) + constant(File)operator(.)ident(rename) ident(path)operator(,) ident(dest) + reserved(yield) constant(PORT_CLASS)operator(.)ident(new)operator(()ident(dest)operator(\)) + reserved(end) + + ident(check_tmp) + reserved(end) + + constant(TOO_OLD) operator(=) integer(60) operator(*) integer(60) operator(*) integer(36) comment(# 36 hour) + + reserved(def) method(check_tmp) + ident(old) operator(=) constant(Time)operator(.)ident(now)operator(.)ident(to_i) operator(-) constant(TOO_OLD) + + ident(each_filename)operator(()instance_variable(@tmp)operator(\)) reserved(do) operator(|)ident(full)operator(,) ident(fname)operator(|) + reserved(if) constant(FileTest)operator(.)ident(file?) ident(full) reserved(and) + constant(File)operator(.)ident(stat)operator(()ident(full)operator(\))operator(.)ident(mtime)operator(.)ident(to_i) operator(<) ident(old) + constant(File)operator(.)ident(unlink) ident(full) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + + reserved(def) method(mail_files)operator(() ident(dir) operator(\)) + constant(Dir)operator(.)ident(entries)operator(()ident(dir)operator(\))\ + operator(.)ident(select) operator({)operator(|)ident(s)operator(|) ident(s)operator([)integer(0)operator(]) operator(!=) integer(?.) operator(})\ + operator(.)ident(sort_by) operator({)operator(|)ident(s)operator(|) ident(s)operator(.)ident(slice)operator(()regexp<delimiter(/)char(\\A)char(\\d)content(+)delimiter(/)>operator(\))operator(.)ident(to_i) operator(})\ + operator(.)ident(map) operator({)operator(|)ident(s)operator(|) string<delimiter(")inline<inline_delimiter(#{)ident(dir)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(s)inline_delimiter(})>delimiter(")> operator(})\ + operator(.)ident(select) operator({)operator(|)ident(path)operator(|) constant(FileTest)operator(.)ident(file?) ident(path) operator(}) + reserved(end) + + reserved(def) method(each_filename)operator(() ident(dir) operator(\)) + constant(Dir)operator(.)ident(foreach)operator(()ident(dir)operator(\)) reserved(do) operator(|)ident(fname)operator(|) + ident(path) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(dir)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>delimiter(")> + reserved(if) ident(fname)operator([)integer(0)operator(]) operator(!=) integer(?.) reserved(and) constant(FileTest)operator(.)ident(file?) ident(path) + reserved(yield) ident(path)operator(,) ident(fname) + reserved(end) + reserved(end) + reserved(end) + + reserved(end) comment(# Maildir) + + constant(MaildirLoader) operator(=) constant(Maildir) + +reserved(end) comment(# module TMail) +ident(require) string<delimiter(')content(tmail/mailbox)delimiter(')> +comment(#) +comment(# net.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(nkf)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Mail) + + reserved(def) method(send_to)operator(() ident(smtp) operator(\)) + ident(do_send_to)operator(()ident(smtp)operator(\)) reserved(do) + ident(ready_to_send) + reserved(end) + reserved(end) + + reserved(def) method(send_text_to)operator(() ident(smtp) operator(\)) + ident(do_send_to)operator(()ident(smtp)operator(\)) reserved(do) + ident(ready_to_send) + ident(mime_encode) + reserved(end) + reserved(end) + + reserved(def) method(do_send_to)operator(() ident(smtp) operator(\)) + ident(from) operator(=) ident(from_address) reserved(or) ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(no from address)delimiter(')> + operator(()ident(dests) operator(=) ident(destinations)operator(\))operator(.)ident(empty?) reserved(and) ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(no receipient)delimiter(')> + reserved(yield) + ident(send_to_0) ident(smtp)operator(,) ident(from)operator(,) ident(dests) + reserved(end) + ident(private) symbol(:do_send_to) + + reserved(def) method(send_to_0)operator(() ident(smtp)operator(,) ident(from)operator(,) ident(to) operator(\)) + ident(smtp)operator(.)ident(ready)operator(()ident(from)operator(,) ident(to)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(encoded) string<delimiter(")char(\\r)char(\\n)delimiter(")>operator(,) string<delimiter(')content(j)delimiter(')>operator(,) ident(f)operator(,) string<delimiter(')delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(ready_to_send) + ident(delete_no_send_fields) + ident(add_message_id) + ident(add_date) + reserved(end) + + constant(NOSEND_FIELDS) operator(=) string<delimiter(%w()content( + received + bcc + )delimiter(\))> + + reserved(def) method(delete_no_send_fields) + constant(NOSEND_FIELDS)operator(.)ident(each) reserved(do) operator(|)ident(nm)operator(|) + ident(delete) ident(nm) + reserved(end) + ident(delete_if) operator({)operator(|)ident(n)operator(,)ident(v)operator(|) ident(v)operator(.)ident(empty?) operator(}) + reserved(end) + + reserved(def) method(add_message_id)operator(() ident(fqdn) operator(=) pre_constant(nil) operator(\)) + pre_constant(self)operator(.)ident(message_id) operator(=) operator(::)constant(TMail)operator(::)ident(new_message_id)operator(()ident(fqdn)operator(\)) + reserved(end) + + reserved(def) method(add_date) + pre_constant(self)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(now) + reserved(end) + + reserved(def) method(mime_encode) + reserved(if) ident(parts)operator(.)ident(empty?) + ident(mime_encode_singlepart) + reserved(else) + ident(mime_encode_multipart) pre_constant(true) + reserved(end) + reserved(end) + + reserved(def) method(mime_encode_singlepart) + pre_constant(self)operator(.)ident(mime_version) operator(=) string<delimiter(')content(1.0)delimiter(')> + ident(b) operator(=) ident(body) + reserved(if) constant(NKF)operator(.)ident(guess)operator(()ident(b)operator(\)) operator(!=) constant(NKF)operator(::)constant(BINARY) + ident(mime_encode_text) ident(b) + reserved(else) + ident(mime_encode_binary) ident(b) + reserved(end) + reserved(end) + + reserved(def) method(mime_encode_text)operator(() ident(body) operator(\)) + pre_constant(self)operator(.)ident(body) operator(=) constant(NKF)operator(.)ident(nkf)operator(()string<delimiter(')content(-j -m0)delimiter(')>operator(,) ident(body)operator(\)) + pre_constant(self)operator(.)ident(set_content_type) string<delimiter(')content(text)delimiter(')>operator(,) string<delimiter(')content(plain)delimiter(')>operator(,) operator({)string<delimiter(')content(charset)delimiter(')> operator(=)operator(>) string<delimiter(')content(iso-2022-jp)delimiter(')>operator(}) + pre_constant(self)operator(.)ident(encoding) operator(=) string<delimiter(')content(7bit)delimiter(')> + reserved(end) + + reserved(def) method(mime_encode_binary)operator(() ident(body) operator(\)) + pre_constant(self)operator(.)ident(body) operator(=) operator([)ident(body)operator(])operator(.)ident(pack)operator(()string<delimiter(')content(m)delimiter(')>operator(\)) + pre_constant(self)operator(.)ident(set_content_type) string<delimiter(')content(application)delimiter(')>operator(,) string<delimiter(')content(octet-stream)delimiter(')> + pre_constant(self)operator(.)ident(encoding) operator(=) string<delimiter(')content(Base64)delimiter(')> + reserved(end) + + reserved(def) method(mime_encode_multipart)operator(() ident(top) operator(=) pre_constant(true) operator(\)) + pre_constant(self)operator(.)ident(mime_version) operator(=) string<delimiter(')content(1.0)delimiter(')> reserved(if) ident(top) + pre_constant(self)operator(.)ident(set_content_type) string<delimiter(')content(multipart)delimiter(')>operator(,) string<delimiter(')content(mixed)delimiter(')> + ident(e) operator(=) ident(encoding)operator(()pre_constant(nil)operator(\)) + reserved(if) ident(e) reserved(and) reserved(not) regexp<delimiter(/)char(\\A)content((?:7bit|8bit|binary\))char(\\z)delimiter(/)modifier(i)> operator(===) ident(e) + ident(raise) constant(ArgumentError)operator(,) + string<delimiter(')content(using C.T.Encoding with multipart mail is not permitted)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(create_empty_mail) + pre_constant(self)operator(.)ident(class)operator(.)ident(new)operator(()constant(StringPort)operator(.)ident(new)operator(()string<delimiter(')delimiter(')>operator(\))operator(,) instance_variable(@config)operator(\)) + reserved(end) + + reserved(def) method(create_reply) + ident(setup_reply) ident(create_empty_mail)operator(()operator(\)) + reserved(end) + + reserved(def) method(setup_reply)operator(() ident(m) operator(\)) + reserved(if) ident(tmp) operator(=) ident(reply_addresses)operator(()pre_constant(nil)operator(\)) + ident(m)operator(.)ident(to_addrs) operator(=) ident(tmp) + reserved(end) + + ident(mid) operator(=) ident(message_id)operator(()pre_constant(nil)operator(\)) + ident(tmp) operator(=) ident(references)operator(()pre_constant(nil)operator(\)) operator(||) operator([)operator(]) + ident(tmp)operator(.)ident(push) ident(mid) reserved(if) ident(mid) + ident(m)operator(.)ident(in_reply_to) operator(=) operator([)ident(mid)operator(]) reserved(if) ident(mid) + ident(m)operator(.)ident(references) operator(=) ident(tmp) reserved(unless) ident(tmp)operator(.)ident(empty?) + ident(m)operator(.)ident(subject) operator(=) string<delimiter(')content(Re: )delimiter(')> operator(+) ident(subject)operator(()string<delimiter(')delimiter(')>operator(\))operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)content((?:)char(\\s)content(*re:\)+)delimiter(/)modifier(i)>operator(,) string<delimiter(')delimiter(')>operator(\)) + + ident(m) + reserved(end) + + reserved(def) method(create_forward) + ident(setup_forward) ident(create_empty_mail)operator(()operator(\)) + reserved(end) + + reserved(def) method(setup_forward)operator(() ident(mail) operator(\)) + ident(m) operator(=) constant(Mail)operator(.)ident(new)operator(()constant(StringPort)operator(.)ident(new)operator(()string<delimiter(')delimiter(')>operator(\))operator(\)) + ident(m)operator(.)ident(body) operator(=) ident(decoded) + ident(m)operator(.)ident(set_content_type) string<delimiter(')content(message)delimiter(')>operator(,) string<delimiter(')content(rfc822)delimiter(')> + ident(m)operator(.)ident(encoding) operator(=) ident(encoding)operator(()string<delimiter(')content(7bit)delimiter(')>operator(\)) + ident(mail)operator(.)ident(parts)operator(.)ident(push) ident(m) + reserved(end) + + reserved(end) + + + reserved(class) class(DeleteFields) + + constant(NOSEND_FIELDS) operator(=) string<delimiter(%w()content( + received + bcc + )delimiter(\))> + + reserved(def) method(initialize)operator(() ident(nosend) operator(=) pre_constant(nil)operator(,) ident(delempty) operator(=) pre_constant(true) operator(\)) + instance_variable(@no_send_fields) operator(=) ident(nosend) operator(||) constant(NOSEND_FIELDS)operator(.)ident(dup) + instance_variable(@delete_empty_fields) operator(=) ident(delempty) + reserved(end) + + ident(attr) symbol(:no_send_fields) + ident(attr) symbol(:delete_empty_fields)operator(,) pre_constant(true) + + reserved(def) method(exec)operator(() ident(mail) operator(\)) + instance_variable(@no_send_fields)operator(.)ident(each) reserved(do) operator(|)ident(nm)operator(|) + ident(delete) ident(nm) + reserved(end) + ident(delete_if) operator({)operator(|)ident(n)operator(,)ident(v)operator(|) ident(v)operator(.)ident(empty?) operator(}) reserved(if) instance_variable(@delete_empty_fields) + reserved(end) + + reserved(end) + + + reserved(class) class(AddMessageId) + + reserved(def) method(initialize)operator(() ident(fqdn) operator(=) pre_constant(nil) operator(\)) + instance_variable(@fqdn) operator(=) ident(fqdn) + reserved(end) + + ident(attr) symbol(:fqdn)operator(,) pre_constant(true) + + reserved(def) method(exec)operator(() ident(mail) operator(\)) + ident(mail)operator(.)ident(message_id) operator(=) operator(::)constant(TMail)operator(::)ident(new_msgid)operator(()instance_variable(@fqdn)operator(\)) + reserved(end) + + reserved(end) + + + reserved(class) class(AddDate) + + reserved(def) method(exec)operator(() ident(mail) operator(\)) + ident(mail)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(now) + reserved(end) + + reserved(end) + + + reserved(class) class(MimeEncodeAuto) + + reserved(def) method(initialize)operator(() ident(s) operator(=) pre_constant(nil)operator(,) ident(m) operator(=) pre_constant(nil) operator(\)) + instance_variable(@singlepart_composer) operator(=) ident(s) operator(||) constant(MimeEncodeSingle)operator(.)ident(new) + instance_variable(@multipart_composer) operator(=) ident(m) operator(||) constant(MimeEncodeMulti)operator(.)ident(new) + reserved(end) + + ident(attr) symbol(:singlepart_composer) + ident(attr) symbol(:multipart_composer) + + reserved(def) method(exec)operator(() ident(mail) operator(\)) + reserved(if) ident(mail)operator(.)ident(_builtin_multipart?) + reserved(then) instance_variable(@multipart_composer) + reserved(else) instance_variable(@singlepart_composer) reserved(end)operator(.)ident(exec) ident(mail) + reserved(end) + + reserved(end) + + + reserved(class) class(MimeEncodeSingle) + + reserved(def) method(exec)operator(() ident(mail) operator(\)) + ident(mail)operator(.)ident(mime_version) operator(=) string<delimiter(')content(1.0)delimiter(')> + ident(b) operator(=) ident(mail)operator(.)ident(body) + reserved(if) constant(NKF)operator(.)ident(guess)operator(()ident(b)operator(\)) operator(!=) constant(NKF)operator(::)constant(BINARY) + ident(on_text) ident(b) + reserved(else) + ident(on_binary) ident(b) + reserved(end) + reserved(end) + + reserved(def) method(on_text)operator(() ident(body) operator(\)) + ident(mail)operator(.)ident(body) operator(=) constant(NKF)operator(.)ident(nkf)operator(()string<delimiter(')content(-j -m0)delimiter(')>operator(,) ident(body)operator(\)) + ident(mail)operator(.)ident(set_content_type) string<delimiter(')content(text)delimiter(')>operator(,) string<delimiter(')content(plain)delimiter(')>operator(,) operator({)string<delimiter(')content(charset)delimiter(')> operator(=)operator(>) string<delimiter(')content(iso-2022-jp)delimiter(')>operator(}) + ident(mail)operator(.)ident(encoding) operator(=) string<delimiter(')content(7bit)delimiter(')> + reserved(end) + + reserved(def) method(on_binary)operator(() ident(body) operator(\)) + ident(mail)operator(.)ident(body) operator(=) operator([)ident(body)operator(])operator(.)ident(pack)operator(()string<delimiter(')content(m)delimiter(')>operator(\)) + ident(mail)operator(.)ident(set_content_type) string<delimiter(')content(application)delimiter(')>operator(,) string<delimiter(')content(octet-stream)delimiter(')> + ident(mail)operator(.)ident(encoding) operator(=) string<delimiter(')content(Base64)delimiter(')> + reserved(end) + + reserved(end) + + + reserved(class) class(MimeEncodeMulti) + + reserved(def) method(exec)operator(() ident(mail)operator(,) ident(top) operator(=) pre_constant(true) operator(\)) + ident(mail)operator(.)ident(mime_version) operator(=) string<delimiter(')content(1.0)delimiter(')> reserved(if) ident(top) + ident(mail)operator(.)ident(set_content_type) string<delimiter(')content(multipart)delimiter(')>operator(,) string<delimiter(')content(mixed)delimiter(')> + ident(e) operator(=) ident(encoding)operator(()pre_constant(nil)operator(\)) + reserved(if) ident(e) reserved(and) reserved(not) regexp<delimiter(/)char(\\A)content((?:7bit|8bit|binary\))char(\\z)delimiter(/)modifier(i)> operator(===) ident(e) + ident(raise) constant(ArgumentError)operator(,) + string<delimiter(')content(using C.T.Encoding with multipart mail is not permitted)delimiter(')> + reserved(end) + ident(mail)operator(.)ident(parts)operator(.)ident(each) reserved(do) operator(|)ident(m)operator(|) + ident(exec) ident(m)operator(,) pre_constant(false) reserved(if) ident(m)operator(.)ident(_builtin_multipart?) + reserved(end) + reserved(end) + + reserved(end) + +reserved(end) comment(# module TMail) +comment(#) +comment(# obsolete.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +reserved(module) class(TMail) + + comment(# mail.rb) + reserved(class) class(Mail) + reserved(alias) method(include?) method(key?) + reserved(alias) method(has_key?) method(key?) + + reserved(def) method(values) + ident(ret) operator(=) operator([)operator(]) + ident(each_field) operator({)operator(|)ident(v)operator(|) ident(ret)operator(.)ident(push) ident(v) operator(}) + ident(ret) + reserved(end) + + reserved(def) method(value?)operator(() ident(val) operator(\)) + constant(HeaderField) operator(===) ident(val) reserved(or) reserved(return) pre_constant(false) + + operator([) instance_variable(@header)operator([)ident(val)operator(.)ident(name)operator(.)ident(downcase)operator(]) operator(])operator(.)ident(flatten)operator(.)ident(include?) ident(val) + reserved(end) + + reserved(alias) method(has_value?) method(value?) + reserved(end) + + + comment(# facade.rb) + reserved(class) class(Mail) + reserved(def) method(from_addr)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + ident(addr)operator(,) operator(=) ident(from_addrs)operator(()pre_constant(nil)operator(\)) + ident(addr) operator(||) ident(default) + reserved(end) + + reserved(def) method(from_address)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(a) operator(=) ident(from_addr)operator(()pre_constant(nil)operator(\)) + ident(a)operator(.)ident(spec) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(alias) method(from_address=) method(from_addrs=) + + reserved(def) method(from_phrase)operator(() ident(default) operator(=) pre_constant(nil) operator(\)) + reserved(if) ident(a) operator(=) ident(from_addr)operator(()pre_constant(nil)operator(\)) + ident(a)operator(.)ident(phrase) + reserved(else) + ident(default) + reserved(end) + reserved(end) + + reserved(alias) method(msgid) method(message_id) + reserved(alias) method(msgid=) method(message_id=) + + reserved(alias) method(each_dest) method(each_destination) + reserved(end) + + + comment(# address.rb) + reserved(class) class(Address) + reserved(alias) method(route) method(routes) + reserved(alias) method(addr) method(spec) + + reserved(def) method(spec=)operator(() ident(str) operator(\)) + instance_variable(@local)operator(,) instance_variable(@domain) operator(=) ident(str)operator(.)ident(split)operator(()regexp<delimiter(/)content(@)delimiter(/)>operator(,)integer(2)operator(\))operator(.)ident(map) operator({)operator(|)ident(s)operator(|) ident(s)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\.)delimiter(/)>operator(\)) operator(}) + reserved(end) + + reserved(alias) method(addr=) method(spec=) + reserved(alias) method(address=) method(spec=) + reserved(end) + + + comment(# mbox.rb) + reserved(class) class(MhMailbox) + reserved(alias) method(new_mail) method(new_port) + reserved(alias) method(each_mail) method(each_port) + reserved(alias) method(each_newmail) method(each_new_port) + reserved(end) + reserved(class) class(UNIXMbox) + reserved(alias) method(new_mail) method(new_port) + reserved(alias) method(each_mail) method(each_port) + reserved(alias) method(each_newmail) method(each_new_port) + reserved(end) + reserved(class) class(Maildir) + reserved(alias) method(new_mail) method(new_port) + reserved(alias) method(each_mail) method(each_port) + reserved(alias) method(each_newmail) method(each_new_port) + reserved(end) + + + comment(# utils.rb) + ident(extend) constant(TextUtils) + + reserved(class) operator(<<) class(self) + reserved(alias) method(msgid?) method(message_id?) + reserved(alias) method(boundary) method(new_boundary) + reserved(alias) method(msgid) method(new_message_id) + reserved(alias) method(new_msgid) method(new_message_id) + reserved(end) + + reserved(def) constant(Mail)operator(.)ident(boundary) + operator(::)constant(TMail)operator(.)ident(new_boundary) + reserved(end) + + reserved(def) constant(Mail)operator(.)ident(msgid) + operator(::)constant(TMail)operator(.)ident(new_message_id) + reserved(end) + +reserved(end) comment(# module TMail) +comment(#) +comment(# DO NOT MODIFY!!!!) +comment(# This file is automatically generated by racc 1.4.3) +comment(# from racc grammer file "parser.y".) +comment(#) +comment(#) +comment(# parser.rb: generated by racc (runtime embedded\)) +comment(#) + +comment(###### racc/parser.rb) + +reserved(unless) global_variable($")operator(.)ident(index) string<delimiter(')content(racc/parser.rb)delimiter(')> +global_variable($")operator(.)ident(push) string<delimiter(')content(racc/parser.rb)delimiter(')> + +pre_constant(self)operator(.)ident(class)operator(.)ident(module_eval) string<delimiter(<<'..end /home/aamine/lib/ruby/racc/parser.rb modeval..idb76f2e220d')>operator(,) string<delimiter(')content(/home/aamine/lib/ruby/racc/parser.rb)delimiter(')>operator(,) integer(1)string<content( +# +# parser.rb +# +# Copyright (c\) 1999-2003 Minero Aoki <aamine@loveruby.net> +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# +# As a special exception, when this code is copied by Racc +# into a Racc output file, you may use that output file +# without restriction. +# +# $Id: parser.rb,v 1.1.1.1 2004/10/14 11:59:58 webster132 Exp $ +# + +unless defined? NotImplementedError + NotImplementedError = NotImplementError +end + + +module Racc + class ParseError < StandardError; end +end +unless defined?(::ParseError\) + ParseError = Racc::ParseError +end + + +module Racc + + unless defined? Racc_No_Extentions + Racc_No_Extentions = false + end + + class Parser + + Racc_Runtime_Version = '1.4.3' + Racc_Runtime_Revision = '$Revision: 1.1.1.1 $'.split(/)content(\\s)content(+/\)[1] + + Racc_Runtime_Core_Version_R = '1.4.3' + Racc_Runtime_Core_Revision_R = '$Revision: 1.1.1.1 $'.split(/)content(\\s)content(+/\)[1] + begin + require 'racc/cparse' + # Racc_Runtime_Core_Version_C = (defined in extention\) + Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split(/)content(\\s)content(+/\)[2] + unless new.respond_to?(:_racc_do_parse_c, true\) + raise LoadError, 'old cparse.so' + end + if Racc_No_Extentions + raise LoadError, 'selecting ruby version of racc runtime core' + end + + Racc_Main_Parsing_Routine = :_racc_do_parse_c + Racc_YY_Parse_Method = :_racc_yyparse_c + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C + Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C + Racc_Runtime_Type = 'c' + rescue LoadError + Racc_Main_Parsing_Routine = :_racc_do_parse_rb + Racc_YY_Parse_Method = :_racc_yyparse_rb + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R + Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R + Racc_Runtime_Type = 'ruby' + end + + def self.racc_runtime_type + Racc_Runtime_Type + end + + private + + def _racc_setup + @yydebug = false unless self.class::Racc_debug_parser + @yydebug = false unless defined? @yydebug + if @yydebug + @racc_debug_out = $stderr unless defined? @racc_debug_out + @racc_debug_out ||= $stderr + end + arg = self.class::Racc_arg + arg[13] = true if arg.size < 14 + arg + end + + def _racc_init_sysvars + @racc_state = [0] + @racc_tstack = [] + @racc_vstack = [] + + @racc_t = nil + @racc_val = nil + + @racc_read_next = true + + @racc_user_yyerror = false + @racc_error_status = 0 + end + + + ### + ### do_parse + ### + + def do_parse + __send__ Racc_Main_Parsing_Routine, _racc_setup(\), false + end + + def next_token + raise NotImplementedError, "#{self.class})content(\\#)content(next_token is not defined" + end + + def _racc_do_parse_rb( arg, in_debug \) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + + _racc_init_sysvars + tok = act = i = nil + nerr = 0 + + catch(:racc_end_parse\) { + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token(\) + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1\) # error token + end + racc_read_token(@racc_t, tok, @racc_val\) if @yydebug + @racc_read_next = false + end + end + i += @racc_t + if i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + ; + else + act = action_default[@racc_state[-1]] + end + else + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg\) + end + end + } + end + + + ### + ### yyparse + ### + + def yyparse( recv, mid \) + __send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(\), true + end + + def _racc_yyparse_rb( recv, mid, arg, c_debug \) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + + _racc_init_sysvars + tok = nil + act = nil + i = nil + nerr = 0 + + + catch(:racc_end_parse\) { + until i = action_pointer[@racc_state[-1]] + while act = _racc_evalact(action_default[@racc_state[-1]], arg\) + end + end + + recv.__send__(mid\) do |tok, val| +# $stderr.puts "rd: tok=#{tok}, val=#{val}" + unless tok + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1\) # error token + end + @racc_val = val + @racc_read_next = false + + i += @racc_t + if i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + ; +# $stderr.puts "01: act=#{act}" + else + act = action_default[@racc_state[-1]] +# $stderr.puts "02: act=#{act}" +# $stderr.puts "curstate=#{@racc_state[-1]}" + end + + while act = _racc_evalact(act, arg\) + end + + while not (i = action_pointer[@racc_state[-1]]\) or + not @racc_read_next or + @racc_t == 0 # $ + if i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + ; +# $stderr.puts "03: act=#{act}" + else +# $stderr.puts "04: act=#{act}" + act = action_default[@racc_state[-1]] + end + + while act = _racc_evalact(act, arg\) + end + end + end + } + end + + + ### + ### common + ### + + def _racc_evalact( act, arg \) +# $stderr.puts "ea: act=#{act}" + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg +nerr = 0 # tmp + + if act > 0 and act < shift_n + # + # shift + # + + if @racc_error_status > 0 + @racc_error_status -= 1 unless @racc_t == 1 # error token + end + + @racc_vstack.push @racc_val + @racc_state.push act + @racc_read_next = true + + if @yydebug + @racc_tstack.push @racc_t + racc_shift @racc_t, @racc_tstack, @racc_vstack + end + + elsif act < 0 and act > -reduce_n + # + # reduce + # + + code = catch(:racc_jump\) { + @racc_state.push _racc_do_reduce(arg, act\) + false + } + if code + case code + when 1 # yyerror + @racc_user_yyerror = true # user_yyerror + return -reduce_n + when 2 # yyaccept + return shift_n + else + raise RuntimeError, '[Racc Bug] unknown jump code' + end + end + + elsif act == shift_n + # + # accept + # + + racc_accept if @yydebug + throw :racc_end_parse, @racc_vstack[0] + + elsif act == -reduce_n + # + # error + # + + case @racc_error_status + when 0 + unless arg[21] # user_yyerror + nerr += 1 + on_error @racc_t, @racc_val, @racc_vstack + end + when 3 + if @racc_t == 0 # is $ + throw :racc_end_parse, nil + end + @racc_read_next = true + end + @racc_user_yyerror = false + @racc_error_status = 3 + + while true + if i = action_pointer[@racc_state[-1]] + i += 1 # error token + if i >= 0 and + (act = action_table[i]\) and + action_check[i] == @racc_state[-1] + break + end + end + + throw :racc_end_parse, nil if @racc_state.size < 2 + @racc_state.pop + @racc_vstack.pop + if @yydebug + @racc_tstack.pop + racc_e_pop @racc_state, @racc_tstack, @racc_vstack + end + end + + return act + + else + raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}" + end + + racc_next_state(@racc_state[-1], @racc_state\) if @yydebug + + nil + end + + def _racc_do_reduce( arg, act \) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + state = @racc_state + vstack = @racc_vstack + tstack = @racc_tstack + + i = act * -3 + len = reduce_table[i] + reduce_to = reduce_table[i+1] + method_id = reduce_table[i+2] + void_array = [] + + tmp_t = tstack[-len, len] if @yydebug + tmp_v = vstack[-len, len] + tstack[-len, len] = void_array if @yydebug + vstack[-len, len] = void_array + state[-len, len] = void_array + + # tstack must be updated AFTER method call + if use_result + vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]\) + else + vstack.push __send__(method_id, tmp_v, vstack\) + end + tstack.push reduce_to + + racc_reduce(tmp_t, reduce_to, tstack, vstack\) if @yydebug + + k1 = reduce_to - nt_base + if i = goto_pointer[k1] + i += state[-1] + if i >= 0 and (curstate = goto_table[i]\) and goto_check[i] == k1 + return curstate + end + end + goto_default[k1] + end + + def on_error( t, val, vstack \) + raise ParseError, sprintf(")content(\\n)content(parse error on value %s (%s\)", + val.inspect, token_to_str(t\) || '?'\) + end + + def yyerror + throw :racc_jump, 1 + end + + def yyaccept + throw :racc_jump, 2 + end + + def yyerrok + @racc_error_status = 0 + end + + + # for debugging output + + def racc_read_token( t, tok, val \) + @racc_debug_out.print 'read ' + @racc_debug_out.print tok.inspect, '(', racc_token2str(t\), '\) ' + @racc_debug_out.puts val.inspect + @racc_debug_out.puts + end + + def racc_shift( tok, tstack, vstack \) + @racc_debug_out.puts "shift #{racc_token2str tok}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_reduce( toks, sim, tstack, vstack \) + out = @racc_debug_out + out.print 'reduce ' + if toks.empty? + out.print ' <none>' + else + toks.each {|t| out.print ' ', racc_token2str(t\) } + end + out.puts " --> #{racc_token2str(sim\)}" + + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_accept + @racc_debug_out.puts 'accept' + @racc_debug_out.puts + end + + def racc_e_pop( state, tstack, vstack \) + @racc_debug_out.puts 'error recovering mode: pop token' + racc_print_states state + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_next_state( curstate, state \) + @racc_debug_out.puts "goto #{curstate}" + racc_print_states state + @racc_debug_out.puts + end + + def racc_print_stacks( t, v \) + out = @racc_debug_out + out.print ' [' + t.each_index do |i| + out.print ' (', racc_token2str(t[i]\), ' ', v[i].inspect, '\)' + end + out.puts ' ]' + end + + def racc_print_states( s \) + out = @racc_debug_out + out.print ' [' + s.each {|st| out.print ' ', st } + out.puts ' ]' + end + + def racc_token2str( tok \) + self.class::Racc_token_to_s_table[tok] or + raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string" + end + + def token_to_str( t \) + self.class::Racc_token_to_s_table[t] + end + + end + +end)delimiter( +..end /home/aamine/lib/ruby/racc/parser.rb modeval..idb76f2e220d)> +reserved(end) comment(# end of racc/parser.rb) + + +comment(#) +comment(# parser.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/scanner)delimiter(')> +ident(require) string<delimiter(')content(tmail/utils)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Parser) operator(<) constant(Racc)operator(::)constant(Parser) + +ident(module_eval) string<delimiter(<<'..end parser.y modeval..id43721faf1c')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(331)string<content( + + include TextUtils + + def self.parse( ident, str, cmt = nil \) + new.parse(ident, str, cmt\) + end + + MAILP_DEBUG = false + + def initialize + self.debug = MAILP_DEBUG + end + + def debug=( flag \) + @yydebug = flag && Racc_debug_parser + @scanner_debug = flag + end + + def debug + @yydebug + end + + def parse( ident, str, comments = nil \) + @scanner = Scanner.new(str, ident, comments\) + @scanner.debug = @scanner_debug + @first = [ident, ident] + result = yyparse(self, :parse_in\) + comments.map! {|c| to_kcode(c\) } if comments + result + end + + private + + def parse_in( &block \) + yield @first + @scanner.scan(&block\) + end + + def on_error( t, val, vstack \) + raise SyntaxError, "parse error on token #{racc_token2str t}" + end +)delimiter( +..end parser.y modeval..id43721faf1c)> + +comment(##### racc 1.4.3 generates ###) + +ident(racc_reduce_table) operator(=) operator([) + integer(0)operator(,) integer(0)operator(,) symbol(:racc_error)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_1)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_2)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_3)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_4)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_5)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_6)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_7)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_8)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_9)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_10)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_11)operator(,) + integer(2)operator(,) integer(35)operator(,) symbol(:_reduce_12)operator(,) + integer(6)operator(,) integer(36)operator(,) symbol(:_reduce_13)operator(,) + integer(0)operator(,) integer(48)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(48)operator(,) symbol(:_reduce_none)operator(,) + integer(3)operator(,) integer(49)operator(,) symbol(:_reduce_16)operator(,) + integer(5)operator(,) integer(49)operator(,) symbol(:_reduce_17)operator(,) + integer(1)operator(,) integer(50)operator(,) symbol(:_reduce_18)operator(,) + integer(7)operator(,) integer(37)operator(,) symbol(:_reduce_19)operator(,) + integer(0)operator(,) integer(51)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(51)operator(,) symbol(:_reduce_21)operator(,) + integer(0)operator(,) integer(52)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(52)operator(,) symbol(:_reduce_23)operator(,) + integer(1)operator(,) integer(58)operator(,) symbol(:_reduce_24)operator(,) + integer(3)operator(,) integer(58)operator(,) symbol(:_reduce_25)operator(,) + integer(2)operator(,) integer(58)operator(,) symbol(:_reduce_26)operator(,) + integer(0)operator(,) integer(53)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(53)operator(,) symbol(:_reduce_28)operator(,) + integer(0)operator(,) integer(54)operator(,) symbol(:_reduce_29)operator(,) + integer(3)operator(,) integer(54)operator(,) symbol(:_reduce_30)operator(,) + integer(0)operator(,) integer(55)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(55)operator(,) symbol(:_reduce_32)operator(,) + integer(2)operator(,) integer(55)operator(,) symbol(:_reduce_33)operator(,) + integer(0)operator(,) integer(56)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(56)operator(,) symbol(:_reduce_35)operator(,) + integer(1)operator(,) integer(61)operator(,) symbol(:_reduce_36)operator(,) + integer(1)operator(,) integer(61)operator(,) symbol(:_reduce_37)operator(,) + integer(0)operator(,) integer(57)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(57)operator(,) symbol(:_reduce_39)operator(,) + integer(1)operator(,) integer(38)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(38)operator(,) symbol(:_reduce_none)operator(,) + integer(3)operator(,) integer(38)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(46)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(46)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(46)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(39)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(39)operator(,) symbol(:_reduce_47)operator(,) + integer(1)operator(,) integer(64)operator(,) symbol(:_reduce_48)operator(,) + integer(3)operator(,) integer(64)operator(,) symbol(:_reduce_49)operator(,) + integer(1)operator(,) integer(68)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(68)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(69)operator(,) symbol(:_reduce_52)operator(,) + integer(3)operator(,) integer(69)operator(,) symbol(:_reduce_53)operator(,) + integer(1)operator(,) integer(47)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(47)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(47)operator(,) symbol(:_reduce_56)operator(,) + integer(2)operator(,) integer(67)operator(,) symbol(:_reduce_none)operator(,) + integer(3)operator(,) integer(65)operator(,) symbol(:_reduce_58)operator(,) + integer(2)operator(,) integer(65)operator(,) symbol(:_reduce_59)operator(,) + integer(1)operator(,) integer(70)operator(,) symbol(:_reduce_60)operator(,) + integer(2)operator(,) integer(70)operator(,) symbol(:_reduce_61)operator(,) + integer(4)operator(,) integer(62)operator(,) symbol(:_reduce_62)operator(,) + integer(3)operator(,) integer(62)operator(,) symbol(:_reduce_63)operator(,) + integer(2)operator(,) integer(72)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(73)operator(,) symbol(:_reduce_65)operator(,) + integer(4)operator(,) integer(73)operator(,) symbol(:_reduce_66)operator(,) + integer(3)operator(,) integer(63)operator(,) symbol(:_reduce_67)operator(,) + integer(1)operator(,) integer(63)operator(,) symbol(:_reduce_68)operator(,) + integer(1)operator(,) integer(74)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(74)operator(,) symbol(:_reduce_70)operator(,) + integer(1)operator(,) integer(71)operator(,) symbol(:_reduce_71)operator(,) + integer(3)operator(,) integer(71)operator(,) symbol(:_reduce_72)operator(,) + integer(1)operator(,) integer(59)operator(,) symbol(:_reduce_73)operator(,) + integer(3)operator(,) integer(59)operator(,) symbol(:_reduce_74)operator(,) + integer(1)operator(,) integer(76)operator(,) symbol(:_reduce_75)operator(,) + integer(2)operator(,) integer(76)operator(,) symbol(:_reduce_76)operator(,) + integer(1)operator(,) integer(75)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(75)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(75)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(77)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(77)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(77)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(66)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(66)operator(,) symbol(:_reduce_none)operator(,) + integer(3)operator(,) integer(60)operator(,) symbol(:_reduce_85)operator(,) + integer(1)operator(,) integer(40)operator(,) symbol(:_reduce_86)operator(,) + integer(3)operator(,) integer(40)operator(,) symbol(:_reduce_87)operator(,) + integer(1)operator(,) integer(79)operator(,) symbol(:_reduce_none)operator(,) + integer(2)operator(,) integer(79)operator(,) symbol(:_reduce_89)operator(,) + integer(1)operator(,) integer(41)operator(,) symbol(:_reduce_90)operator(,) + integer(2)operator(,) integer(41)operator(,) symbol(:_reduce_91)operator(,) + integer(3)operator(,) integer(42)operator(,) symbol(:_reduce_92)operator(,) + integer(5)operator(,) integer(43)operator(,) symbol(:_reduce_93)operator(,) + integer(3)operator(,) integer(43)operator(,) symbol(:_reduce_94)operator(,) + integer(0)operator(,) integer(80)operator(,) symbol(:_reduce_95)operator(,) + integer(5)operator(,) integer(80)operator(,) symbol(:_reduce_96)operator(,) + integer(1)operator(,) integer(82)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(82)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(44)operator(,) symbol(:_reduce_99)operator(,) + integer(3)operator(,) integer(45)operator(,) symbol(:_reduce_100)operator(,) + integer(0)operator(,) integer(81)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(81)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none)operator(,) + integer(1)operator(,) integer(78)operator(,) symbol(:_reduce_none) operator(]) + +ident(racc_reduce_n) operator(=) integer(110) + +ident(racc_shift_n) operator(=) integer(168) + +ident(racc_action_table) operator(=) operator([) + integer(-70)operator(,) integer(-69)operator(,) integer(23)operator(,) integer(25)operator(,) integer(146)operator(,) integer(147)operator(,) integer(29)operator(,) integer(31)operator(,) integer(105)operator(,) integer(106)operator(,) + integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(136)operator(,) integer(27)operator(,) integer(-70)operator(,) integer(-69)operator(,) integer(32)operator(,) integer(101)operator(,) + integer(-70)operator(,) integer(-69)operator(,) integer(154)operator(,) integer(100)operator(,) integer(113)operator(,) integer(115)operator(,) integer(-70)operator(,) integer(-69)operator(,) integer(-70)operator(,) integer(109)operator(,) + integer(75)operator(,) integer(23)operator(,) integer(25)operator(,) integer(101)operator(,) integer(155)operator(,) integer(29)operator(,) integer(31)operator(,) integer(142)operator(,) integer(143)operator(,) integer(16)operator(,) + integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(107)operator(,) integer(27)operator(,) integer(23)operator(,) integer(25)operator(,) integer(32)operator(,) integer(98)operator(,) integer(29)operator(,) + integer(31)operator(,) integer(96)operator(,) integer(94)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(78)operator(,) integer(27)operator(,) integer(23)operator(,) + integer(25)operator(,) integer(32)operator(,) integer(112)operator(,) integer(29)operator(,) integer(31)operator(,) integer(74)operator(,) integer(91)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) + integer(22)operator(,) integer(88)operator(,) integer(117)operator(,) integer(92)operator(,) integer(81)operator(,) integer(32)operator(,) integer(23)operator(,) integer(25)operator(,) integer(80)operator(,) integer(123)operator(,) + integer(29)operator(,) integer(31)operator(,) integer(100)operator(,) integer(125)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(126)operator(,) integer(23)operator(,) + integer(25)operator(,) integer(109)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) integer(91)operator(,) integer(128)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) + integer(22)operator(,) integer(129)operator(,) integer(27)operator(,) integer(23)operator(,) integer(25)operator(,) integer(32)operator(,) integer(101)operator(,) integer(29)operator(,) integer(31)operator(,) integer(101)operator(,) + integer(130)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(79)operator(,) integer(52)operator(,) integer(23)operator(,) integer(25)operator(,) integer(32)operator(,) + integer(78)operator(,) integer(29)operator(,) integer(31)operator(,) integer(133)operator(,) integer(78)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(77)operator(,) + integer(23)operator(,) integer(25)operator(,) integer(75)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) integer(65)operator(,) integer(62)operator(,) integer(16)operator(,) integer(17)operator(,) + integer(20)operator(,) integer(22)operator(,) integer(139)operator(,) integer(23)operator(,) integer(25)operator(,) integer(101)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) integer(60)operator(,) + integer(100)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(44)operator(,) integer(27)operator(,) integer(101)operator(,) integer(148)operator(,) integer(32)operator(,) + integer(23)operator(,) integer(25)operator(,) integer(120)operator(,) integer(149)operator(,) integer(29)operator(,) integer(31)operator(,) integer(152)operator(,) integer(153)operator(,) integer(16)operator(,) integer(17)operator(,) + integer(20)operator(,) integer(22)operator(,) integer(42)operator(,) integer(27)operator(,) integer(157)operator(,) integer(159)operator(,) integer(32)operator(,) integer(23)operator(,) integer(25)operator(,) integer(120)operator(,) + integer(40)operator(,) integer(29)operator(,) integer(31)operator(,) integer(15)operator(,) integer(164)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(40)operator(,) + integer(27)operator(,) integer(23)operator(,) integer(25)operator(,) integer(32)operator(,) integer(68)operator(,) integer(29)operator(,) integer(31)operator(,) integer(166)operator(,) integer(167)operator(,) integer(16)operator(,) + integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) integer(27)operator(,) integer(23)operator(,) integer(25)operator(,) integer(32)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) + integer(31)operator(,) integer(74)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) integer(23)operator(,) integer(25)operator(,) + pre_constant(nil)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) + pre_constant(nil)operator(,) integer(23)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) + integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) integer(23)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) integer(23)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) + integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) + integer(27)operator(,) integer(23)operator(,) integer(25)operator(,) integer(32)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) + integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) integer(23)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) integer(23)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) + integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) pre_constant(nil)operator(,) + integer(84)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) integer(32)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) integer(87)operator(,) integer(16)operator(,) integer(17)operator(,) + integer(20)operator(,) integer(22)operator(,) integer(4)operator(,) integer(6)operator(,) integer(7)operator(,) integer(8)operator(,) integer(9)operator(,) integer(10)operator(,) integer(11)operator(,) integer(12)operator(,) + integer(13)operator(,) integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) integer(84)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) integer(31)operator(,) + pre_constant(nil)operator(,) integer(87)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(84)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) integer(87)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(84)operator(,) integer(25)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) integer(87)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) + integer(84)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) integer(87)operator(,) integer(16)operator(,) integer(17)operator(,) + integer(20)operator(,) integer(22)operator(,) integer(84)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) integer(87)operator(,) + integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22)operator(,) integer(84)operator(,) integer(25)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(29)operator(,) integer(31)operator(,) + pre_constant(nil)operator(,) integer(87)operator(,) integer(16)operator(,) integer(17)operator(,) integer(20)operator(,) integer(22) operator(]) + +ident(racc_action_check) operator(=) operator([) + integer(75)operator(,) integer(28)operator(,) integer(68)operator(,) integer(68)operator(,) integer(136)operator(,) integer(136)operator(,) integer(68)operator(,) integer(68)operator(,) integer(72)operator(,) integer(72)operator(,) + integer(68)operator(,) integer(68)operator(,) integer(68)operator(,) integer(68)operator(,) integer(126)operator(,) integer(68)operator(,) integer(75)operator(,) integer(28)operator(,) integer(68)operator(,) integer(67)operator(,) + integer(75)operator(,) integer(28)operator(,) integer(143)operator(,) integer(66)operator(,) integer(86)operator(,) integer(86)operator(,) integer(75)operator(,) integer(28)operator(,) integer(75)operator(,) integer(75)operator(,) + integer(28)operator(,) integer(3)operator(,) integer(3)operator(,) integer(86)operator(,) integer(143)operator(,) integer(3)operator(,) integer(3)operator(,) integer(134)operator(,) integer(134)operator(,) integer(3)operator(,) + integer(3)operator(,) integer(3)operator(,) integer(3)operator(,) integer(73)operator(,) integer(3)operator(,) integer(152)operator(,) integer(152)operator(,) integer(3)operator(,) integer(62)operator(,) integer(152)operator(,) + integer(152)operator(,) integer(60)operator(,) integer(56)operator(,) integer(152)operator(,) integer(152)operator(,) integer(152)operator(,) integer(152)operator(,) integer(51)operator(,) integer(152)operator(,) integer(52)operator(,) + integer(52)operator(,) integer(152)operator(,) integer(80)operator(,) integer(52)operator(,) integer(52)operator(,) integer(52)operator(,) integer(50)operator(,) integer(52)operator(,) integer(52)operator(,) integer(52)operator(,) + integer(52)operator(,) integer(45)operator(,) integer(89)operator(,) integer(52)operator(,) integer(42)operator(,) integer(52)operator(,) integer(71)operator(,) integer(71)operator(,) integer(41)operator(,) integer(96)operator(,) + integer(71)operator(,) integer(71)operator(,) integer(97)operator(,) integer(98)operator(,) integer(71)operator(,) integer(71)operator(,) integer(71)operator(,) integer(71)operator(,) integer(100)operator(,) integer(7)operator(,) + integer(7)operator(,) integer(101)operator(,) integer(71)operator(,) integer(7)operator(,) integer(7)operator(,) integer(102)operator(,) integer(104)operator(,) integer(7)operator(,) integer(7)operator(,) integer(7)operator(,) + integer(7)operator(,) integer(105)operator(,) integer(7)operator(,) integer(8)operator(,) integer(8)operator(,) integer(7)operator(,) integer(108)operator(,) integer(8)operator(,) integer(8)operator(,) integer(111)operator(,) + integer(112)operator(,) integer(8)operator(,) integer(8)operator(,) integer(8)operator(,) integer(8)operator(,) integer(40)operator(,) integer(8)operator(,) integer(9)operator(,) integer(9)operator(,) integer(8)operator(,) + integer(36)operator(,) integer(9)operator(,) integer(9)operator(,) integer(117)operator(,) integer(121)operator(,) integer(9)operator(,) integer(9)operator(,) integer(9)operator(,) integer(9)operator(,) integer(33)operator(,) + integer(10)operator(,) integer(10)operator(,) integer(70)operator(,) integer(9)operator(,) integer(10)operator(,) integer(10)operator(,) integer(13)operator(,) integer(12)operator(,) integer(10)operator(,) integer(10)operator(,) + integer(10)operator(,) integer(10)operator(,) integer(130)operator(,) integer(2)operator(,) integer(2)operator(,) integer(131)operator(,) integer(10)operator(,) integer(2)operator(,) integer(2)operator(,) integer(11)operator(,) + integer(135)operator(,) integer(2)operator(,) integer(2)operator(,) integer(2)operator(,) integer(2)operator(,) integer(6)operator(,) integer(2)operator(,) integer(138)operator(,) integer(139)operator(,) integer(2)operator(,) + integer(90)operator(,) integer(90)operator(,) integer(90)operator(,) integer(140)operator(,) integer(90)operator(,) integer(90)operator(,) integer(141)operator(,) integer(142)operator(,) integer(90)operator(,) integer(90)operator(,) + integer(90)operator(,) integer(90)operator(,) integer(5)operator(,) integer(90)operator(,) integer(148)operator(,) integer(151)operator(,) integer(90)operator(,) integer(127)operator(,) integer(127)operator(,) integer(127)operator(,) + integer(4)operator(,) integer(127)operator(,) integer(127)operator(,) integer(1)operator(,) integer(157)operator(,) integer(127)operator(,) integer(127)operator(,) integer(127)operator(,) integer(127)operator(,) integer(159)operator(,) + integer(127)operator(,) integer(26)operator(,) integer(26)operator(,) integer(127)operator(,) integer(26)operator(,) integer(26)operator(,) integer(26)operator(,) integer(163)operator(,) integer(164)operator(,) integer(26)operator(,) + integer(26)operator(,) integer(26)operator(,) integer(26)operator(,) pre_constant(nil)operator(,) integer(26)operator(,) integer(27)operator(,) integer(27)operator(,) integer(26)operator(,) pre_constant(nil)operator(,) integer(27)operator(,) + integer(27)operator(,) integer(27)operator(,) pre_constant(nil)operator(,) integer(27)operator(,) integer(27)operator(,) integer(27)operator(,) integer(27)operator(,) pre_constant(nil)operator(,) integer(155)operator(,) integer(155)operator(,) + pre_constant(nil)operator(,) integer(27)operator(,) integer(155)operator(,) integer(155)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(155)operator(,) integer(155)operator(,) integer(155)operator(,) integer(155)operator(,) + pre_constant(nil)operator(,) integer(122)operator(,) integer(122)operator(,) pre_constant(nil)operator(,) integer(155)operator(,) integer(122)operator(,) integer(122)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(122)operator(,) + integer(122)operator(,) integer(122)operator(,) integer(122)operator(,) pre_constant(nil)operator(,) integer(76)operator(,) integer(76)operator(,) pre_constant(nil)operator(,) integer(122)operator(,) integer(76)operator(,) integer(76)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(76)operator(,) integer(76)operator(,) integer(76)operator(,) integer(76)operator(,) pre_constant(nil)operator(,) integer(38)operator(,) integer(38)operator(,) pre_constant(nil)operator(,) + integer(76)operator(,) integer(38)operator(,) integer(38)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(38)operator(,) integer(38)operator(,) integer(38)operator(,) integer(38)operator(,) pre_constant(nil)operator(,) + integer(38)operator(,) integer(55)operator(,) integer(55)operator(,) integer(38)operator(,) pre_constant(nil)operator(,) integer(55)operator(,) integer(55)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(55)operator(,) + integer(55)operator(,) integer(55)operator(,) integer(55)operator(,) pre_constant(nil)operator(,) integer(94)operator(,) integer(94)operator(,) pre_constant(nil)operator(,) integer(55)operator(,) integer(94)operator(,) integer(94)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(94)operator(,) integer(94)operator(,) integer(94)operator(,) integer(94)operator(,) pre_constant(nil)operator(,) integer(59)operator(,) integer(59)operator(,) pre_constant(nil)operator(,) + integer(94)operator(,) integer(59)operator(,) integer(59)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(59)operator(,) integer(59)operator(,) integer(59)operator(,) integer(59)operator(,) pre_constant(nil)operator(,) + integer(114)operator(,) integer(114)operator(,) pre_constant(nil)operator(,) integer(59)operator(,) integer(114)operator(,) integer(114)operator(,) pre_constant(nil)operator(,) integer(114)operator(,) integer(114)operator(,) integer(114)operator(,) + integer(114)operator(,) integer(114)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) + integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(0)operator(,) integer(77)operator(,) integer(77)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(77)operator(,) integer(77)operator(,) + pre_constant(nil)operator(,) integer(77)operator(,) integer(77)operator(,) integer(77)operator(,) integer(77)operator(,) integer(77)operator(,) integer(44)operator(,) integer(44)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + integer(44)operator(,) integer(44)operator(,) pre_constant(nil)operator(,) integer(44)operator(,) integer(44)operator(,) integer(44)operator(,) integer(44)operator(,) integer(44)operator(,) integer(113)operator(,) integer(113)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(113)operator(,) integer(113)operator(,) pre_constant(nil)operator(,) integer(113)operator(,) integer(113)operator(,) integer(113)operator(,) integer(113)operator(,) integer(113)operator(,) + integer(88)operator(,) integer(88)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(88)operator(,) integer(88)operator(,) pre_constant(nil)operator(,) integer(88)operator(,) integer(88)operator(,) integer(88)operator(,) + integer(88)operator(,) integer(88)operator(,) integer(74)operator(,) integer(74)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(74)operator(,) integer(74)operator(,) pre_constant(nil)operator(,) integer(74)operator(,) + integer(74)operator(,) integer(74)operator(,) integer(74)operator(,) integer(74)operator(,) integer(129)operator(,) integer(129)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(129)operator(,) integer(129)operator(,) + pre_constant(nil)operator(,) integer(129)operator(,) integer(129)operator(,) integer(129)operator(,) integer(129)operator(,) integer(129) operator(]) + +ident(racc_action_pointer) operator(=) operator([) + integer(320)operator(,) integer(152)operator(,) integer(129)operator(,) integer(17)operator(,) integer(165)operator(,) integer(172)operator(,) integer(137)operator(,) integer(75)operator(,) integer(89)operator(,) integer(103)operator(,) + integer(116)operator(,) integer(135)operator(,) integer(106)operator(,) integer(105)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(177)operator(,) integer(191)operator(,) integer(1)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(109)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(94)operator(,) pre_constant(nil)operator(,) integer(243)operator(,) pre_constant(nil)operator(,) + integer(99)operator(,) integer(64)operator(,) integer(74)operator(,) pre_constant(nil)operator(,) integer(332)operator(,) integer(52)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + integer(50)operator(,) integer(31)operator(,) integer(45)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(257)operator(,) integer(36)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(283)operator(,) + integer(22)operator(,) pre_constant(nil)operator(,) integer(16)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(-3)operator(,) integer(-10)operator(,) integer(-12)operator(,) pre_constant(nil)operator(,) + integer(103)operator(,) integer(62)operator(,) integer(-8)operator(,) integer(15)operator(,) integer(368)operator(,) integer(0)operator(,) integer(230)operator(,) integer(320)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + integer(47)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(4)operator(,) pre_constant(nil)operator(,) integer(356)operator(,) integer(50)operator(,) + integer(146)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(270)operator(,) pre_constant(nil)operator(,) integer(65)operator(,) integer(56)operator(,) integer(52)operator(,) pre_constant(nil)operator(,) + integer(57)operator(,) integer(62)operator(,) integer(79)operator(,) pre_constant(nil)operator(,) integer(68)operator(,) integer(81)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(77)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) integer(80)operator(,) integer(96)operator(,) integer(344)operator(,) integer(296)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(108)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) integer(98)operator(,) integer(217)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(-19)operator(,) integer(163)operator(,) pre_constant(nil)operator(,) integer(380)operator(,) + integer(128)operator(,) integer(116)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(14)operator(,) integer(124)operator(,) integer(-26)operator(,) pre_constant(nil)operator(,) integer(128)operator(,) integer(141)operator(,) + integer(148)operator(,) integer(141)operator(,) integer(152)operator(,) integer(7)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(160)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) integer(149)operator(,) integer(31)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(204)operator(,) pre_constant(nil)operator(,) integer(167)operator(,) pre_constant(nil)operator(,) integer(174)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(169)operator(,) integer(184)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil) operator(]) + +ident(racc_action_default) operator(=) operator([) + integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-14)operator(,) integer(-110)operator(,) integer(-20)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) + integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-10)operator(,) integer(-95)operator(,) integer(-106)operator(,) integer(-107)operator(,) integer(-77)operator(,) integer(-44)operator(,) + integer(-108)operator(,) integer(-11)operator(,) integer(-109)operator(,) integer(-79)operator(,) integer(-43)operator(,) integer(-103)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-60)operator(,) integer(-104)operator(,) + integer(-55)operator(,) integer(-105)operator(,) integer(-78)operator(,) integer(-68)operator(,) integer(-54)operator(,) integer(-71)operator(,) integer(-45)operator(,) integer(-12)operator(,) integer(-110)operator(,) integer(-1)operator(,) + integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-2)operator(,) integer(-110)operator(,) integer(-22)operator(,) integer(-51)operator(,) integer(-48)operator(,) integer(-50)operator(,) integer(-3)operator(,) + integer(-40)operator(,) integer(-41)operator(,) integer(-110)operator(,) integer(-46)operator(,) integer(-4)operator(,) integer(-86)operator(,) integer(-5)operator(,) integer(-88)operator(,) integer(-6)operator(,) integer(-90)operator(,) + integer(-110)operator(,) integer(-7)operator(,) integer(-95)operator(,) integer(-8)operator(,) integer(-9)operator(,) integer(-99)operator(,) integer(-101)operator(,) integer(-61)operator(,) integer(-59)operator(,) integer(-56)operator(,) + integer(-69)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-75)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-57)operator(,) integer(-15)operator(,) + integer(-110)operator(,) integer(168)operator(,) integer(-73)operator(,) integer(-80)operator(,) integer(-82)operator(,) integer(-21)operator(,) integer(-24)operator(,) integer(-81)operator(,) integer(-110)operator(,) integer(-27)operator(,) + integer(-110)operator(,) integer(-83)operator(,) integer(-47)operator(,) integer(-89)operator(,) integer(-110)operator(,) integer(-91)operator(,) integer(-110)operator(,) integer(-101)operator(,) integer(-110)operator(,) integer(-100)operator(,) + integer(-102)operator(,) integer(-75)operator(,) integer(-58)operator(,) integer(-52)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-64)operator(,) integer(-63)operator(,) integer(-65)operator(,) integer(-76)operator(,) + integer(-72)operator(,) integer(-67)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-26)operator(,) integer(-23)operator(,) integer(-110)operator(,) integer(-29)operator(,) integer(-49)operator(,) + integer(-84)operator(,) integer(-42)operator(,) integer(-87)operator(,) integer(-92)operator(,) integer(-94)operator(,) integer(-95)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-62)operator(,) integer(-110)operator(,) + integer(-110)operator(,) integer(-25)operator(,) integer(-74)operator(,) integer(-28)operator(,) integer(-31)operator(,) integer(-101)operator(,) integer(-110)operator(,) integer(-53)operator(,) integer(-66)operator(,) integer(-110)operator(,) + integer(-110)operator(,) integer(-34)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-93)operator(,) integer(-96)operator(,) integer(-98)operator(,) integer(-97)operator(,) integer(-110)operator(,) integer(-18)operator(,) + integer(-13)operator(,) integer(-38)operator(,) integer(-110)operator(,) integer(-30)operator(,) integer(-33)operator(,) integer(-110)operator(,) integer(-32)operator(,) integer(-16)operator(,) integer(-19)operator(,) integer(-14)operator(,) + integer(-35)operator(,) integer(-36)operator(,) integer(-37)operator(,) integer(-110)operator(,) integer(-110)operator(,) integer(-39)operator(,) integer(-85)operator(,) integer(-17) operator(]) + +ident(racc_goto_table) operator(=) operator([) + integer(39)operator(,) integer(67)operator(,) integer(70)operator(,) integer(73)operator(,) integer(24)operator(,) integer(37)operator(,) integer(69)operator(,) integer(66)operator(,) integer(36)operator(,) integer(38)operator(,) + integer(57)operator(,) integer(59)operator(,) integer(55)operator(,) integer(67)operator(,) integer(108)operator(,) integer(83)operator(,) integer(90)operator(,) integer(111)operator(,) integer(69)operator(,) integer(99)operator(,) + integer(85)operator(,) integer(49)operator(,) integer(53)operator(,) integer(76)operator(,) integer(158)operator(,) integer(134)operator(,) integer(141)operator(,) integer(70)operator(,) integer(73)operator(,) integer(151)operator(,) + integer(118)operator(,) integer(89)operator(,) integer(45)operator(,) integer(156)operator(,) integer(160)operator(,) integer(150)operator(,) integer(140)operator(,) integer(21)operator(,) integer(14)operator(,) integer(19)operator(,) + integer(119)operator(,) integer(102)operator(,) integer(64)operator(,) integer(63)operator(,) integer(61)operator(,) integer(83)operator(,) integer(70)operator(,) integer(104)operator(,) integer(83)operator(,) integer(58)operator(,) + integer(124)operator(,) integer(132)operator(,) integer(56)operator(,) integer(131)operator(,) integer(97)operator(,) integer(54)operator(,) integer(93)operator(,) integer(43)operator(,) integer(5)operator(,) integer(83)operator(,) + integer(95)operator(,) integer(145)operator(,) integer(76)operator(,) pre_constant(nil)operator(,) integer(116)operator(,) integer(76)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(127)operator(,) integer(138)operator(,) + integer(103)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(38)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(110)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(83)operator(,) integer(83)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(144)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(57)operator(,) integer(121)operator(,) integer(122)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + integer(83)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(135)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(93)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(70)operator(,) integer(162)operator(,) integer(137)operator(,) + integer(70)operator(,) integer(163)operator(,) integer(161)operator(,) integer(38)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(165) operator(]) + +ident(racc_goto_check) operator(=) operator([) + integer(2)operator(,) integer(37)operator(,) integer(37)operator(,) integer(29)operator(,) integer(13)operator(,) integer(13)operator(,) integer(28)operator(,) integer(46)operator(,) integer(31)operator(,) integer(36)operator(,) + integer(41)operator(,) integer(41)operator(,) integer(45)operator(,) integer(37)operator(,) integer(25)operator(,) integer(44)operator(,) integer(32)operator(,) integer(25)operator(,) integer(28)operator(,) integer(47)operator(,) + integer(24)operator(,) integer(4)operator(,) integer(4)operator(,) integer(42)operator(,) integer(23)operator(,) integer(20)operator(,) integer(21)operator(,) integer(37)operator(,) integer(29)operator(,) integer(22)operator(,) + integer(19)operator(,) integer(18)operator(,) integer(17)operator(,) integer(26)operator(,) integer(27)operator(,) integer(16)operator(,) integer(15)operator(,) integer(12)operator(,) integer(11)operator(,) integer(33)operator(,) + integer(34)operator(,) integer(35)operator(,) integer(10)operator(,) integer(9)operator(,) integer(8)operator(,) integer(44)operator(,) integer(37)operator(,) integer(29)operator(,) integer(44)operator(,) integer(7)operator(,) + integer(47)operator(,) integer(43)operator(,) integer(6)operator(,) integer(25)operator(,) integer(46)operator(,) integer(5)operator(,) integer(41)operator(,) integer(3)operator(,) integer(1)operator(,) integer(44)operator(,) + integer(41)operator(,) integer(48)operator(,) integer(42)operator(,) pre_constant(nil)operator(,) integer(24)operator(,) integer(42)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(32)operator(,) integer(25)operator(,) + integer(13)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(36)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(41)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(44)operator(,) integer(44)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(47)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(41)operator(,) integer(31)operator(,) integer(45)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + integer(44)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(46)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(41)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(37)operator(,) integer(29)operator(,) integer(13)operator(,) + integer(37)operator(,) integer(29)operator(,) integer(28)operator(,) integer(36)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(2) operator(]) + +ident(racc_goto_pointer) operator(=) operator([) + pre_constant(nil)operator(,) integer(58)operator(,) integer(-4)operator(,) integer(51)operator(,) integer(14)operator(,) integer(47)operator(,) integer(43)operator(,) integer(39)operator(,) integer(33)operator(,) integer(31)operator(,) + integer(29)operator(,) integer(37)operator(,) integer(35)operator(,) integer(2)operator(,) pre_constant(nil)operator(,) integer(-94)operator(,) integer(-105)operator(,) integer(26)operator(,) integer(-14)operator(,) integer(-59)operator(,) + integer(-93)operator(,) integer(-108)operator(,) integer(-112)operator(,) integer(-127)operator(,) integer(-24)operator(,) integer(-60)operator(,) integer(-110)operator(,) integer(-118)operator(,) integer(-20)operator(,) integer(-24)operator(,) + pre_constant(nil)operator(,) integer(6)operator(,) integer(-34)operator(,) integer(37)operator(,) integer(-50)operator(,) integer(-27)operator(,) integer(6)operator(,) integer(-25)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) integer(1)operator(,) integer(-5)operator(,) integer(-63)operator(,) integer(-29)operator(,) integer(3)operator(,) integer(-8)operator(,) integer(-47)operator(,) integer(-75) operator(]) + +ident(racc_goto_default) operator(=) operator([) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(48)operator(,) integer(41)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) + pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(86)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) integer(30)operator(,) integer(34)operator(,) + integer(50)operator(,) integer(51)operator(,) pre_constant(nil)operator(,) integer(46)operator(,) integer(47)operator(,) pre_constant(nil)operator(,) integer(26)operator(,) integer(28)operator(,) integer(71)operator(,) integer(72)operator(,) + integer(33)operator(,) integer(35)operator(,) integer(114)operator(,) integer(82)operator(,) integer(18)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil) operator(]) + +ident(racc_token_table) operator(=) operator({) + pre_constant(false) operator(=)operator(>) integer(0)operator(,) + constant(Object)operator(.)ident(new) operator(=)operator(>) integer(1)operator(,) + symbol(:DATETIME) operator(=)operator(>) integer(2)operator(,) + symbol(:RECEIVED) operator(=)operator(>) integer(3)operator(,) + symbol(:MADDRESS) operator(=)operator(>) integer(4)operator(,) + symbol(:RETPATH) operator(=)operator(>) integer(5)operator(,) + symbol(:KEYWORDS) operator(=)operator(>) integer(6)operator(,) + symbol(:ENCRYPTED) operator(=)operator(>) integer(7)operator(,) + symbol(:MIMEVERSION) operator(=)operator(>) integer(8)operator(,) + symbol(:CTYPE) operator(=)operator(>) integer(9)operator(,) + symbol(:CENCODING) operator(=)operator(>) integer(10)operator(,) + symbol(:CDISPOSITION) operator(=)operator(>) integer(11)operator(,) + symbol(:ADDRESS) operator(=)operator(>) integer(12)operator(,) + symbol(:MAILBOX) operator(=)operator(>) integer(13)operator(,) + symbol(:DIGIT) operator(=)operator(>) integer(14)operator(,) + symbol(:ATOM) operator(=)operator(>) integer(15)operator(,) + string<delimiter(")content(,)delimiter(")> operator(=)operator(>) integer(16)operator(,) + string<delimiter(")content(:)delimiter(")> operator(=)operator(>) integer(17)operator(,) + symbol(:FROM) operator(=)operator(>) integer(18)operator(,) + symbol(:BY) operator(=)operator(>) integer(19)operator(,) + string<delimiter(")content(@)delimiter(")> operator(=)operator(>) integer(20)operator(,) + symbol(:DOMLIT) operator(=)operator(>) integer(21)operator(,) + symbol(:VIA) operator(=)operator(>) integer(22)operator(,) + symbol(:WITH) operator(=)operator(>) integer(23)operator(,) + symbol(:ID) operator(=)operator(>) integer(24)operator(,) + symbol(:FOR) operator(=)operator(>) integer(25)operator(,) + string<delimiter(")content(;)delimiter(")> operator(=)operator(>) integer(26)operator(,) + string<delimiter(")content(<)delimiter(")> operator(=)operator(>) integer(27)operator(,) + string<delimiter(")content(>)delimiter(")> operator(=)operator(>) integer(28)operator(,) + string<delimiter(")content(.)delimiter(")> operator(=)operator(>) integer(29)operator(,) + symbol(:QUOTED) operator(=)operator(>) integer(30)operator(,) + symbol(:TOKEN) operator(=)operator(>) integer(31)operator(,) + string<delimiter(")content(/)delimiter(")> operator(=)operator(>) integer(32)operator(,) + string<delimiter(")content(=)delimiter(")> operator(=)operator(>) integer(33) operator(}) + +ident(racc_use_result_var) operator(=) pre_constant(false) + +ident(racc_nt_base) operator(=) integer(34) + +constant(Racc_arg) operator(=) operator([) + ident(racc_action_table)operator(,) + ident(racc_action_check)operator(,) + ident(racc_action_default)operator(,) + ident(racc_action_pointer)operator(,) + ident(racc_goto_table)operator(,) + ident(racc_goto_check)operator(,) + ident(racc_goto_default)operator(,) + ident(racc_goto_pointer)operator(,) + ident(racc_nt_base)operator(,) + ident(racc_reduce_table)operator(,) + ident(racc_token_table)operator(,) + ident(racc_shift_n)operator(,) + ident(racc_reduce_n)operator(,) + ident(racc_use_result_var) operator(]) + +constant(Racc_token_to_s_table) operator(=) operator([) +string<delimiter(')content($end)delimiter(')>operator(,) +string<delimiter(')content(error)delimiter(')>operator(,) +string<delimiter(')content(DATETIME)delimiter(')>operator(,) +string<delimiter(')content(RECEIVED)delimiter(')>operator(,) +string<delimiter(')content(MADDRESS)delimiter(')>operator(,) +string<delimiter(')content(RETPATH)delimiter(')>operator(,) +string<delimiter(')content(KEYWORDS)delimiter(')>operator(,) +string<delimiter(')content(ENCRYPTED)delimiter(')>operator(,) +string<delimiter(')content(MIMEVERSION)delimiter(')>operator(,) +string<delimiter(')content(CTYPE)delimiter(')>operator(,) +string<delimiter(')content(CENCODING)delimiter(')>operator(,) +string<delimiter(')content(CDISPOSITION)delimiter(')>operator(,) +string<delimiter(')content(ADDRESS)delimiter(')>operator(,) +string<delimiter(')content(MAILBOX)delimiter(')>operator(,) +string<delimiter(')content(DIGIT)delimiter(')>operator(,) +string<delimiter(')content(ATOM)delimiter(')>operator(,) +string<delimiter(')content(",")delimiter(')>operator(,) +string<delimiter(')content(":")delimiter(')>operator(,) +string<delimiter(')content(FROM)delimiter(')>operator(,) +string<delimiter(')content(BY)delimiter(')>operator(,) +string<delimiter(')content("@")delimiter(')>operator(,) +string<delimiter(')content(DOMLIT)delimiter(')>operator(,) +string<delimiter(')content(VIA)delimiter(')>operator(,) +string<delimiter(')content(WITH)delimiter(')>operator(,) +string<delimiter(')content(ID)delimiter(')>operator(,) +string<delimiter(')content(FOR)delimiter(')>operator(,) +string<delimiter(')content(";")delimiter(')>operator(,) +string<delimiter(')content("<")delimiter(')>operator(,) +string<delimiter(')content(">")delimiter(')>operator(,) +string<delimiter(')content(".")delimiter(')>operator(,) +string<delimiter(')content(QUOTED)delimiter(')>operator(,) +string<delimiter(')content(TOKEN)delimiter(')>operator(,) +string<delimiter(')content("/")delimiter(')>operator(,) +string<delimiter(')content("=")delimiter(')>operator(,) +string<delimiter(')content($start)delimiter(')>operator(,) +string<delimiter(')content(content)delimiter(')>operator(,) +string<delimiter(')content(datetime)delimiter(')>operator(,) +string<delimiter(')content(received)delimiter(')>operator(,) +string<delimiter(')content(addrs_TOP)delimiter(')>operator(,) +string<delimiter(')content(retpath)delimiter(')>operator(,) +string<delimiter(')content(keys)delimiter(')>operator(,) +string<delimiter(')content(enc)delimiter(')>operator(,) +string<delimiter(')content(version)delimiter(')>operator(,) +string<delimiter(')content(ctype)delimiter(')>operator(,) +string<delimiter(')content(cencode)delimiter(')>operator(,) +string<delimiter(')content(cdisp)delimiter(')>operator(,) +string<delimiter(')content(addr_TOP)delimiter(')>operator(,) +string<delimiter(')content(mbox)delimiter(')>operator(,) +string<delimiter(')content(day)delimiter(')>operator(,) +string<delimiter(')content(hour)delimiter(')>operator(,) +string<delimiter(')content(zone)delimiter(')>operator(,) +string<delimiter(')content(from)delimiter(')>operator(,) +string<delimiter(')content(by)delimiter(')>operator(,) +string<delimiter(')content(via)delimiter(')>operator(,) +string<delimiter(')content(with)delimiter(')>operator(,) +string<delimiter(')content(id)delimiter(')>operator(,) +string<delimiter(')content(for)delimiter(')>operator(,) +string<delimiter(')content(received_datetime)delimiter(')>operator(,) +string<delimiter(')content(received_domain)delimiter(')>operator(,) +string<delimiter(')content(domain)delimiter(')>operator(,) +string<delimiter(')content(msgid)delimiter(')>operator(,) +string<delimiter(')content(received_addrspec)delimiter(')>operator(,) +string<delimiter(')content(routeaddr)delimiter(')>operator(,) +string<delimiter(')content(spec)delimiter(')>operator(,) +string<delimiter(')content(addrs)delimiter(')>operator(,) +string<delimiter(')content(group_bare)delimiter(')>operator(,) +string<delimiter(')content(commas)delimiter(')>operator(,) +string<delimiter(')content(group)delimiter(')>operator(,) +string<delimiter(')content(addr)delimiter(')>operator(,) +string<delimiter(')content(mboxes)delimiter(')>operator(,) +string<delimiter(')content(addr_phrase)delimiter(')>operator(,) +string<delimiter(')content(local_head)delimiter(')>operator(,) +string<delimiter(')content(routes)delimiter(')>operator(,) +string<delimiter(')content(at_domains)delimiter(')>operator(,) +string<delimiter(')content(local)delimiter(')>operator(,) +string<delimiter(')content(word)delimiter(')>operator(,) +string<delimiter(')content(dots)delimiter(')>operator(,) +string<delimiter(')content(domword)delimiter(')>operator(,) +string<delimiter(')content(atom)delimiter(')>operator(,) +string<delimiter(')content(phrase)delimiter(')>operator(,) +string<delimiter(')content(params)delimiter(')>operator(,) +string<delimiter(')content(opt_semicolon)delimiter(')>operator(,) +string<delimiter(')content(value)delimiter(')>operator(]) + +constant(Racc_debug_parser) operator(=) pre_constant(false) + +comment(##### racc system variables end #####) + + comment(# reduce 0 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(16)string<content( + def _reduce_1( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(17)string<content( + def _reduce_2( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(18)string<content( + def _reduce_3( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(19)string<content( + def _reduce_4( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(20)string<content( + def _reduce_5( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(21)string<content( + def _reduce_6( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(22)string<content( + def _reduce_7( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(23)string<content( + def _reduce_8( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(24)string<content( + def _reduce_9( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(25)string<content( + def _reduce_10( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(26)string<content( + def _reduce_11( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(27)string<content( + def _reduce_12( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(33)string<content( + def _reduce_13( val, _values\) + t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0\) + (t + val[4] - val[5]\).localtime + end)delimiter( +.,.,)> + + comment(# reduce 14 omitted) + + comment(# reduce 15 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(42)string<content( + def _reduce_16( val, _values\) + (val[0].to_i * 60 * 60\) + + (val[2].to_i * 60\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(47)string<content( + def _reduce_17( val, _values\) + (val[0].to_i * 60 * 60\) + + (val[2].to_i * 60\) + + (val[4].to_i\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(54)string<content( + def _reduce_18( val, _values\) + timezone_string_to_unixtime(val[0]\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(59)string<content( + def _reduce_19( val, _values\) + val + end)delimiter( +.,.,)> + + comment(# reduce 20 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(65)string<content( + def _reduce_21( val, _values\) + val[1] + end)delimiter( +.,.,)> + + comment(# reduce 22 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(71)string<content( + def _reduce_23( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(77)string<content( + def _reduce_24( val, _values\) + join_domain(val[0]\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(81)string<content( + def _reduce_25( val, _values\) + join_domain(val[2]\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(85)string<content( + def _reduce_26( val, _values\) + join_domain(val[0]\) + end)delimiter( +.,.,)> + + comment(# reduce 27 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(91)string<content( + def _reduce_28( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(96)string<content( + def _reduce_29( val, _values\) + [] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(100)string<content( + def _reduce_30( val, _values\) + val[0].push val[2] + val[0] + end)delimiter( +.,.,)> + + comment(# reduce 31 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(107)string<content( + def _reduce_32( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(111)string<content( + def _reduce_33( val, _values\) + val[1] + end)delimiter( +.,.,)> + + comment(# reduce 34 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(117)string<content( + def _reduce_35( val, _values\) + val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(123)string<content( + def _reduce_36( val, _values\) + val[0].spec + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(127)string<content( + def _reduce_37( val, _values\) + val[0].spec + end)delimiter( +.,.,)> + + comment(# reduce 38 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(134)string<content( + def _reduce_39( val, _values\) + val[1] + end)delimiter( +.,.,)> + + comment(# reduce 40 omitted) + + comment(# reduce 41 omitted) + + comment(# reduce 42 omitted) + + comment(# reduce 43 omitted) + + comment(# reduce 44 omitted) + + comment(# reduce 45 omitted) + + comment(# reduce 46 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(146)string<content( + def _reduce_47( val, _values\) + [ Address.new(nil, nil\) ] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(148)string<content( + def _reduce_48( val, _values\) + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(149)string<content( + def _reduce_49( val, _values\) + val[0].push val[2]; val[0] + end)delimiter( +.,.,)> + + comment(# reduce 50 omitted) + + comment(# reduce 51 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(156)string<content( + def _reduce_52( val, _values\) + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(160)string<content( + def _reduce_53( val, _values\) + val[0].push val[2] + val[0] + end)delimiter( +.,.,)> + + comment(# reduce 54 omitted) + + comment(# reduce 55 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(168)string<content( + def _reduce_56( val, _values\) + val[1].phrase = Decoder.decode(val[0]\) + val[1] + end)delimiter( +.,.,)> + + comment(# reduce 57 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(176)string<content( + def _reduce_58( val, _values\) + AddressGroup.new(val[0], val[2]\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(178)string<content( + def _reduce_59( val, _values\) + AddressGroup.new(val[0], []\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(181)string<content( + def _reduce_60( val, _values\) + val[0].join('.'\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(182)string<content( + def _reduce_61( val, _values\) + val[0] << ' ' << val[1].join('.'\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(186)string<content( + def _reduce_62( val, _values\) + val[2].routes.replace val[1] + val[2] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(191)string<content( + def _reduce_63( val, _values\) + val[1] + end)delimiter( +.,.,)> + + comment(# reduce 64 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(196)string<content( + def _reduce_65( val, _values\) + [ val[1].join('.'\) ] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(197)string<content( + def _reduce_66( val, _values\) + val[0].push val[3].join('.'\); val[0] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(199)string<content( + def _reduce_67( val, _values\) + Address.new( val[0], val[2] \) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(200)string<content( + def _reduce_68( val, _values\) + Address.new( val[0], nil \) + end)delimiter( +.,.,)> + + comment(# reduce 69 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(203)string<content( + def _reduce_70( val, _values\) + val[0].push ''; val[0] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(206)string<content( + def _reduce_71( val, _values\) + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(209)string<content( + def _reduce_72( val, _values\) + val[1].times do + val[0].push '' + end + val[0].push val[2] + val[0] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(217)string<content( + def _reduce_73( val, _values\) + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(220)string<content( + def _reduce_74( val, _values\) + val[1].times do + val[0].push '' + end + val[0].push val[2] + val[0] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(227)string<content( + def _reduce_75( val, _values\) + 0 + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(228)string<content( + def _reduce_76( val, _values\) + 1 + end)delimiter( +.,.,)> + + comment(# reduce 77 omitted) + + comment(# reduce 78 omitted) + + comment(# reduce 79 omitted) + + comment(# reduce 80 omitted) + + comment(# reduce 81 omitted) + + comment(# reduce 82 omitted) + + comment(# reduce 83 omitted) + + comment(# reduce 84 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(243)string<content( + def _reduce_85( val, _values\) + val[1] = val[1].spec + val.join(''\) + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(247)string<content( + def _reduce_86( val, _values\) + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(248)string<content( + def _reduce_87( val, _values\) + val[0].push val[2]; val[0] + end)delimiter( +.,.,)> + + comment(# reduce 88 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(251)string<content( + def _reduce_89( val, _values\) + val[0] << ' ' << val[1] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(255)string<content( + def _reduce_90( val, _values\) + val.push nil + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(260)string<content( + def _reduce_91( val, _values\) + val + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(265)string<content( + def _reduce_92( val, _values\) + [ val[0].to_i, val[2].to_i ] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(270)string<content( + def _reduce_93( val, _values\) + [ val[0].downcase, val[2].downcase, decode_params(val[3]\) ] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(274)string<content( + def _reduce_94( val, _values\) + [ val[0].downcase, nil, decode_params(val[1]\) ] + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(279)string<content( + def _reduce_95( val, _values\) + {} + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(283)string<content( + def _reduce_96( val, _values\) + val[0][ val[2].downcase ] = val[4] + val[0] + end)delimiter( +.,.,)> + + comment(# reduce 97 omitted) + + comment(# reduce 98 omitted) + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(292)string<content( + def _reduce_99( val, _values\) + val[0].downcase + end)delimiter( +.,.,)> + +ident(module_eval) string<delimiter(<<'.,.,')>operator(,) string<delimiter(')content(parser.y)delimiter(')>operator(,) integer(297)string<content( + def _reduce_100( val, _values\) + [ val[0].downcase, decode_params(val[1]\) ] + end)delimiter( +.,.,)> + + comment(# reduce 101 omitted) + + comment(# reduce 102 omitted) + + comment(# reduce 103 omitted) + + comment(# reduce 104 omitted) + + comment(# reduce 105 omitted) + + comment(# reduce 106 omitted) + + comment(# reduce 107 omitted) + + comment(# reduce 108 omitted) + + comment(# reduce 109 omitted) + + reserved(def) method(_reduce_none)operator(() ident(val)operator(,) ident(_values)operator(\)) + ident(val)operator([)integer(0)operator(]) + reserved(end) + + reserved(end) comment(# class Parser) + +reserved(end) comment(# module TMail) +comment(#) +comment(# port.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/stringio)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Port) + reserved(def) method(reproducible?) + pre_constant(false) + reserved(end) + reserved(end) + + + comment(###) + comment(### FilePort) + comment(###) + + reserved(class) class(FilePort) operator(<) constant(Port) + + reserved(def) method(initialize)operator(() ident(fname) operator(\)) + instance_variable(@filename) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(fname)operator(\)) + reserved(super)operator(()operator(\)) + reserved(end) + + ident(attr_reader) symbol(:filename) + + reserved(alias) method(ident) method(filename) + + reserved(def) method(==)operator(() ident(other) operator(\)) + ident(other)operator(.)ident(respond_to?)operator(()symbol(:filename)operator(\)) reserved(and) instance_variable(@filename) operator(==) ident(other)operator(.)ident(filename) + reserved(end) + + reserved(alias) method(eql?) method(==) + + reserved(def) method(hash) + instance_variable(@filename)operator(.)ident(hash) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@filename)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(reproducible?) + pre_constant(true) + reserved(end) + + reserved(def) method(size) + constant(File)operator(.)ident(size) instance_variable(@filename) + reserved(end) + + + reserved(def) method(ropen)operator(() operator(&)ident(block) operator(\)) + constant(File)operator(.)ident(open)operator(()instance_variable(@filename)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(wopen)operator(() operator(&)ident(block) operator(\)) + constant(File)operator(.)ident(open)operator(()instance_variable(@filename)operator(,) string<delimiter(')content(w)delimiter(')>operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(aopen)operator(() operator(&)ident(block) operator(\)) + constant(File)operator(.)ident(open)operator(()instance_variable(@filename)operator(,) string<delimiter(')content(a)delimiter(')>operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + + reserved(def) method(read_all) + ident(ropen) operator({)operator(|)ident(f)operator(|) + reserved(return) ident(f)operator(.)ident(read) + operator(}) + reserved(end) + + + reserved(def) method(remove) + constant(File)operator(.)ident(unlink) instance_variable(@filename) + reserved(end) + + reserved(def) method(move_to)operator(() ident(port) operator(\)) + reserved(begin) + constant(File)operator(.)ident(link) instance_variable(@filename)operator(,) ident(port)operator(.)ident(filename) + reserved(rescue) constant(Errno)operator(::)constant(EXDEV) + ident(copy_to) ident(port) + reserved(end) + constant(File)operator(.)ident(unlink) instance_variable(@filename) + reserved(end) + + reserved(alias) method(mv) method(move_to) + + reserved(def) method(copy_to)operator(() ident(port) operator(\)) + reserved(if) constant(FilePort) operator(===) ident(port) + ident(copy_file) instance_variable(@filename)operator(,) ident(port)operator(.)ident(filename) + reserved(else) + constant(File)operator(.)ident(open)operator(()instance_variable(@filename)operator(\)) operator({)operator(|)ident(r)operator(|) + ident(port)operator(.)ident(wopen) operator({)operator(|)ident(w)operator(|) + reserved(while) ident(s) operator(=) ident(r)operator(.)ident(sysread)operator(()integer(4096)operator(\)) + ident(w)operator(.)ident(write) operator(<<) ident(s) + reserved(end) + operator(}) operator(}) + reserved(end) + reserved(end) + + reserved(alias) method(cp) method(copy_to) + + ident(private) + + comment(# from fileutils.rb) + reserved(def) method(copy_file)operator(() ident(src)operator(,) ident(dest) operator(\)) + ident(st) operator(=) ident(r) operator(=) ident(w) operator(=) pre_constant(nil) + + constant(File)operator(.)ident(open)operator(()ident(src)operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) operator({)operator(|)ident(r)operator(|) + constant(File)operator(.)ident(open)operator(()ident(dest)operator(,) string<delimiter(')content(wb)delimiter(')>operator(\)) operator({)operator(|)ident(w)operator(|) + ident(st) operator(=) ident(r)operator(.)ident(stat) + reserved(begin) + reserved(while) pre_constant(true) + ident(w)operator(.)ident(write) ident(r)operator(.)ident(sysread)operator(()ident(st)operator(.)ident(blksize)operator(\)) + reserved(end) + reserved(rescue) constant(EOFError) + reserved(end) + operator(}) operator(}) + reserved(end) + + reserved(end) + + + reserved(module) class(MailFlags) + + reserved(def) method(seen=)operator(() ident(b) operator(\)) + ident(set_status) string<delimiter(')content(S)delimiter(')>operator(,) ident(b) + reserved(end) + + reserved(def) method(seen?) + ident(get_status) string<delimiter(')content(S)delimiter(')> + reserved(end) + + reserved(def) method(replied=)operator(() ident(b) operator(\)) + ident(set_status) string<delimiter(')content(R)delimiter(')>operator(,) ident(b) + reserved(end) + + reserved(def) method(replied?) + ident(get_status) string<delimiter(')content(R)delimiter(')> + reserved(end) + + reserved(def) method(flagged=)operator(() ident(b) operator(\)) + ident(set_status) string<delimiter(')content(F)delimiter(')>operator(,) ident(b) + reserved(end) + + reserved(def) method(flagged?) + ident(get_status) string<delimiter(')content(F)delimiter(')> + reserved(end) + + ident(private) + + reserved(def) method(procinfostr)operator(() ident(str)operator(,) ident(tag)operator(,) ident(true_p) operator(\)) + ident(a) operator(=) ident(str)operator(.)ident(upcase)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\)) + ident(a)operator(.)ident(push) ident(true_p) operator(?) ident(tag) operator(:) pre_constant(nil) + ident(a)operator(.)ident(delete) ident(tag) reserved(unless) ident(true_p) + ident(a)operator(.)ident(compact)operator(.)ident(sort)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\))operator(.)ident(squeeze) + reserved(end) + + reserved(end) + + + reserved(class) class(MhPort) operator(<) constant(FilePort) + + ident(include) constant(MailFlags) + + ident(private) + + reserved(def) method(set_status)operator(() ident(tag)operator(,) ident(flag) operator(\)) + reserved(begin) + ident(tmpfile) operator(=) instance_variable(@filename) operator(+) string<delimiter(')content(.tmailtmp.)delimiter(')> operator(+) global_variable($$)operator(.)ident(to_s) + constant(File)operator(.)ident(open)operator(()ident(tmpfile)operator(,) string<delimiter(')content(w)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) + ident(write_status) ident(f)operator(,) ident(tag)operator(,) ident(flag) + operator(}) + constant(File)operator(.)ident(unlink) instance_variable(@filename) + constant(File)operator(.)ident(link) ident(tmpfile)operator(,) instance_variable(@filename) + reserved(ensure) + constant(File)operator(.)ident(unlink) ident(tmpfile) + reserved(end) + reserved(end) + + reserved(def) method(write_status)operator(() ident(f)operator(,) ident(tag)operator(,) ident(flag) operator(\)) + ident(stat) operator(=) string<delimiter(')delimiter(')> + constant(File)operator(.)ident(open)operator(()instance_variable(@filename)operator(\)) operator({)operator(|)ident(r)operator(|) + reserved(while) ident(line) operator(=) ident(r)operator(.)ident(gets) + reserved(if) ident(line)operator(.)ident(strip)operator(.)ident(empty?) + reserved(break) + reserved(elsif) ident(m) operator(=) regexp<delimiter(/)char(\\A)content(X-TMail-Status:)delimiter(/)modifier(i)>operator(.)ident(match)operator(()ident(line)operator(\)) + ident(stat) operator(=) ident(m)operator(.)ident(post_match)operator(.)ident(strip) + reserved(else) + ident(f)operator(.)ident(print) ident(line) + reserved(end) + reserved(end) + + ident(s) operator(=) ident(procinfostr)operator(()ident(stat)operator(,) ident(tag)operator(,) ident(flag)operator(\)) + ident(f)operator(.)ident(puts) string<delimiter(')content(X-TMail-Status: )delimiter(')> operator(+) ident(s) reserved(unless) ident(s)operator(.)ident(empty?) + ident(f)operator(.)ident(puts) + + reserved(while) ident(s) operator(=) ident(r)operator(.)ident(read)operator(()integer(2048)operator(\)) + ident(f)operator(.)ident(write) ident(s) + reserved(end) + operator(}) + reserved(end) + + reserved(def) method(get_status)operator(() ident(tag) operator(\)) + constant(File)operator(.)ident(foreach)operator(()instance_variable(@filename)operator(\)) operator({)operator(|)ident(line)operator(|) + reserved(return) pre_constant(false) reserved(if) ident(line)operator(.)ident(strip)operator(.)ident(empty?) + reserved(if) ident(m) operator(=) regexp<delimiter(/)char(\\A)content(X-TMail-Status:)delimiter(/)modifier(i)>operator(.)ident(match)operator(()ident(line)operator(\)) + reserved(return) ident(m)operator(.)ident(post_match)operator(.)ident(strip)operator(.)ident(include?)operator(()ident(tag)operator([)integer(0)operator(])operator(\)) + reserved(end) + operator(}) + pre_constant(false) + reserved(end) + + reserved(end) + + + reserved(class) class(MaildirPort) operator(<) constant(FilePort) + + reserved(def) method(move_to_new) + ident(new) operator(=) ident(replace_dir)operator(()instance_variable(@filename)operator(,) string<delimiter(')content(new)delimiter(')>operator(\)) + constant(File)operator(.)ident(rename) instance_variable(@filename)operator(,) ident(new) + instance_variable(@filename) operator(=) ident(new) + reserved(end) + + reserved(def) method(move_to_cur) + ident(new) operator(=) ident(replace_dir)operator(()instance_variable(@filename)operator(,) string<delimiter(')content(cur)delimiter(')>operator(\)) + constant(File)operator(.)ident(rename) instance_variable(@filename)operator(,) ident(new) + instance_variable(@filename) operator(=) ident(new) + reserved(end) + + reserved(def) method(replace_dir)operator(() ident(path)operator(,) ident(dir) operator(\)) + string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname) constant(File)operator(.)ident(dirname)operator(()ident(path)operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(dir)inline_delimiter(})>content(/)inline<inline_delimiter(#{)constant(File)operator(.)ident(basename) ident(path)inline_delimiter(})>delimiter(")> + reserved(end) + ident(private) symbol(:replace_dir) + + + ident(include) constant(MailFlags) + + ident(private) + + constant(MAIL_FILE) operator(=) regexp<delimiter(/)char(\\A)content(()char(\\d)content(+)char(\\.)content([)char(\\d)content(_]+)char(\\.)content([^:]+\)(?:)char(\\:)content(()char(\\d)content(\),()char(\\w)content(+\)?\)?)char(\\z)delimiter(/)> + + reserved(def) method(set_status)operator(() ident(tag)operator(,) ident(flag) operator(\)) + reserved(if) ident(m) operator(=) constant(MAIL_FILE)operator(.)ident(match)operator(()constant(File)operator(.)ident(basename)operator(()instance_variable(@filename)operator(\))operator(\)) + ident(s)operator(,) ident(uniq)operator(,) ident(type)operator(,) ident(info)operator(,) operator(=) ident(m)operator(.)ident(to_a) + reserved(return) reserved(if) ident(type) reserved(and) ident(type) operator(!=) string<delimiter(')content(2)delimiter(')> comment(# do not change anything) + ident(newname) operator(=) constant(File)operator(.)ident(dirname)operator(()instance_variable(@filename)operator(\)) operator(+) string<delimiter(')content(/)delimiter(')> operator(+) + ident(uniq) operator(+) string<delimiter(')content(:2,)delimiter(')> operator(+) ident(procinfostr)operator(()ident(info)operator(.)ident(to_s)operator(,) ident(tag)operator(,) ident(flag)operator(\)) + reserved(else) + ident(newname) operator(=) instance_variable(@filename) operator(+) string<delimiter(')content(:2,)delimiter(')> operator(+) ident(tag) + reserved(end) + + constant(File)operator(.)ident(link) instance_variable(@filename)operator(,) ident(newname) + constant(File)operator(.)ident(unlink) instance_variable(@filename) + instance_variable(@filename) operator(=) ident(newname) + reserved(end) + + reserved(def) method(get_status)operator(() ident(tag) operator(\)) + ident(m) operator(=) constant(MAIL_FILE)operator(.)ident(match)operator(()constant(File)operator(.)ident(basename)operator(()instance_variable(@filename)operator(\))operator(\)) reserved(or) reserved(return) pre_constant(false) + ident(m)operator([)integer(2)operator(]) operator(==) string<delimiter(')content(2)delimiter(')> reserved(and) ident(m)operator([)integer(3)operator(])operator(.)ident(to_s)operator(.)ident(include?)operator(()ident(tag)operator([)integer(0)operator(])operator(\)) + reserved(end) + + reserved(end) + + + comment(###) + comment(### StringPort) + comment(###) + + reserved(class) class(StringPort) operator(<) constant(Port) + + reserved(def) method(initialize)operator(() ident(str) operator(=) string<delimiter(')delimiter(')> operator(\)) + instance_variable(@buffer) operator(=) ident(str) + reserved(super)operator(()operator(\)) + reserved(end) + + reserved(def) method(string) + instance_variable(@buffer) + reserved(end) + + reserved(def) method(to_s) + instance_variable(@buffer)operator(.)ident(dup) + reserved(end) + + reserved(alias) method(read_all) method(to_s) + + reserved(def) method(size) + instance_variable(@buffer)operator(.)ident(size) + reserved(end) + + reserved(def) method(==)operator(() ident(other) operator(\)) + constant(StringPort) operator(===) ident(other) reserved(and) instance_variable(@buffer)operator(.)ident(equal?) ident(other)operator(.)ident(string) + reserved(end) + + reserved(alias) method(eql?) method(==) + + reserved(def) method(hash) + instance_variable(@buffer)operator(.)ident(object_id)operator(.)ident(hash) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(:id=)inline<inline_delimiter(#{)ident(sprintf) string<delimiter(')content(0x%x)delimiter(')>operator(,) instance_variable(@buffer)operator(.)ident(object_id)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(reproducible?) + pre_constant(true) + reserved(end) + + reserved(def) method(ropen)operator(() operator(&)ident(block) operator(\)) + instance_variable(@buffer) reserved(or) ident(raise) constant(Errno)operator(::)constant(ENOENT)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(inspect)inline_delimiter(})>content( is already removed)delimiter(")> + constant(StringInput)operator(.)ident(open)operator(()instance_variable(@buffer)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(wopen)operator(() operator(&)ident(block) operator(\)) + instance_variable(@buffer) operator(=) string<delimiter(')delimiter(')> + constant(StringOutput)operator(.)ident(new)operator(()instance_variable(@buffer)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(aopen)operator(() operator(&)ident(block) operator(\)) + instance_variable(@buffer) operator(||=) string<delimiter(')delimiter(')> + constant(StringOutput)operator(.)ident(new)operator(()instance_variable(@buffer)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(remove) + instance_variable(@buffer) operator(=) pre_constant(nil) + reserved(end) + + reserved(alias) method(rm) method(remove) + + reserved(def) method(copy_to)operator(() ident(port) operator(\)) + ident(port)operator(.)ident(wopen) operator({)operator(|)ident(f)operator(|) + ident(f)operator(.)ident(write) instance_variable(@buffer) + operator(}) + reserved(end) + + reserved(alias) method(cp) method(copy_to) + + reserved(def) method(move_to)operator(() ident(port) operator(\)) + reserved(if) constant(StringPort) operator(===) ident(port) + ident(str) operator(=) instance_variable(@buffer) + ident(port)operator(.)ident(instance_eval) operator({) instance_variable(@buffer) operator(=) ident(str) operator(}) + reserved(else) + ident(copy_to) ident(port) + reserved(end) + ident(remove) + reserved(end) + + reserved(end) + +reserved(end) comment(# module TMail) +reserved(module) class(TMail) + reserved(class) class(Mail) + reserved(def) method(subject)operator(()ident(to_charset) operator(=) string<delimiter(')content(utf-8)delimiter(')>operator(\)) + constant(Unquoter)operator(.)ident(unquote_and_convert_to)operator(()ident(quoted_subject)operator(,) ident(to_charset)operator(\)) + reserved(end) + + reserved(def) method(unquoted_body)operator(()ident(to_charset) operator(=) string<delimiter(')content(utf-8)delimiter(')>operator(\)) + ident(from_charset) operator(=) ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + reserved(case) operator(()ident(content_transfer_encoding) operator(||) string<delimiter(")content(7bit)delimiter(")>operator(\))operator(.)ident(downcase) + reserved(when) string<delimiter(")content(quoted-printable)delimiter(")> + constant(Unquoter)operator(.)ident(unquote_quoted_printable_and_convert_to)operator(()ident(quoted_body)operator(,) + ident(to_charset)operator(,) ident(from_charset)operator(,) pre_constant(true)operator(\)) + reserved(when) string<delimiter(")content(base64)delimiter(")> + constant(Unquoter)operator(.)ident(unquote_base64_and_convert_to)operator(()ident(quoted_body)operator(,) ident(to_charset)operator(,) + ident(from_charset)operator(\)) + reserved(when) string<delimiter(")content(7bit)delimiter(")>operator(,) string<delimiter(")content(8bit)delimiter(")> + constant(Unquoter)operator(.)ident(convert_to)operator(()ident(quoted_body)operator(,) ident(to_charset)operator(,) ident(from_charset)operator(\)) + reserved(when) string<delimiter(")content(binary)delimiter(")> + ident(quoted_body) + reserved(else) + ident(quoted_body) + reserved(end) + reserved(end) + + reserved(def) method(body)operator(()ident(to_charset) operator(=) string<delimiter(')content(utf-8)delimiter(')>operator(,) operator(&)ident(block)operator(\)) + ident(attachment_presenter) operator(=) ident(block) operator(||) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(file_name)operator(|) string<delimiter(")content(Attachment: )inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>char(\\n)delimiter(")> operator(}) + + reserved(if) ident(multipart?) + ident(parts)operator(.)ident(collect) operator({) operator(|)ident(part)operator(|) + ident(header) operator(=) ident(part)operator([)string<delimiter(")content(content-type)delimiter(")>operator(]) + + reserved(if) ident(part)operator(.)ident(multipart?) + ident(part)operator(.)ident(body)operator(()ident(to_charset)operator(,) operator(&)ident(attachment_presenter)operator(\)) + reserved(elsif) ident(header)operator(.)ident(nil?) + string<delimiter(")delimiter(")> + reserved(elsif) operator(!)ident(attachment?)operator(()ident(part)operator(\)) + ident(part)operator(.)ident(unquoted_body)operator(()ident(to_charset)operator(\)) + reserved(else) + ident(attachment_presenter)operator(.)ident(call)operator(()ident(header)operator([)string<delimiter(")content(name)delimiter(")>operator(]) operator(||) string<delimiter(")content((unnamed\))delimiter(")>operator(\)) + reserved(end) + operator(})operator(.)ident(join) + reserved(else) + ident(unquoted_body)operator(()ident(to_charset)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Unquoter) + reserved(class) operator(<<) class(self) + reserved(def) method(unquote_and_convert_to)operator(()ident(text)operator(,) ident(to_charset)operator(,) ident(from_charset) operator(=) string<delimiter(")content(iso-8859-1)delimiter(")>operator(,) ident(preserve_underscores)operator(=)pre_constant(false)operator(\)) + reserved(return) string<delimiter(")delimiter(")> reserved(if) ident(text)operator(.)ident(nil?) + reserved(if) ident(text) operator(=)operator(~) regexp<delimiter(/)content(^=)char(\\?)content((.*?\))char(\\?)content((.\))char(\\?)content((.*\))char(\\?)content(=$)delimiter(/)> + ident(from_charset) operator(=) global_variable($1) + ident(quoting_method) operator(=) global_variable($2) + ident(text) operator(=) global_variable($3) + reserved(case) ident(quoting_method)operator(.)ident(upcase) + reserved(when) string<delimiter(")content(Q)delimiter(")> reserved(then) + ident(unquote_quoted_printable_and_convert_to)operator(()ident(text)operator(,) ident(to_charset)operator(,) ident(from_charset)operator(,) ident(preserve_underscores)operator(\)) + reserved(when) string<delimiter(")content(B)delimiter(")> reserved(then) + ident(unquote_base64_and_convert_to)operator(()ident(text)operator(,) ident(to_charset)operator(,) ident(from_charset)operator(\)) + reserved(else) + ident(raise) string<delimiter(")content(unknown quoting method )inline<inline_delimiter(#{)ident(quoting_method)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(else) + ident(convert_to)operator(()ident(text)operator(,) ident(to_charset)operator(,) ident(from_charset)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(unquote_quoted_printable_and_convert_to)operator(()ident(text)operator(,) ident(to)operator(,) ident(from)operator(,) ident(preserve_underscores)operator(=)pre_constant(false)operator(\)) + ident(text) operator(=) ident(text)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(_)delimiter(/)>operator(,) string<delimiter(")content( )delimiter(")>operator(\)) reserved(unless) ident(preserve_underscores) + ident(convert_to)operator(()ident(text)operator(.)ident(unpack)operator(()string<delimiter(")content(M*)delimiter(")>operator(\))operator(.)ident(first)operator(,) ident(to)operator(,) ident(from)operator(\)) + reserved(end) + + reserved(def) method(unquote_base64_and_convert_to)operator(()ident(text)operator(,) ident(to)operator(,) ident(from)operator(\)) + ident(convert_to)operator(()constant(Base64)operator(.)ident(decode)operator(()ident(text)operator(\))operator(.)ident(first)operator(,) ident(to)operator(,) ident(from)operator(\)) + reserved(end) + + reserved(begin) + ident(require) string<delimiter(')content(iconv)delimiter(')> + reserved(def) method(convert_to)operator(()ident(text)operator(,) ident(to)operator(,) ident(from)operator(\)) + reserved(return) ident(text) reserved(unless) ident(to) operator(&&) ident(from) + ident(text) operator(?) constant(Iconv)operator(.)ident(iconv)operator(()ident(to)operator(,) ident(from)operator(,) ident(text)operator(\))operator(.)ident(first) operator(:) string<delimiter(")delimiter(")> + reserved(rescue) constant(Iconv)operator(::)constant(IllegalSequence)operator(,) constant(Errno)operator(::)constant(EINVAL) + comment(# the 'from' parameter specifies a charset other than what the text) + comment(# actually is...not much we can do in this case but just return the) + comment(# unconverted text.) + comment(#) + comment(# Ditto if either parameter represents an unknown charset, like) + comment(# X-UNKNOWN.) + ident(text) + reserved(end) + reserved(rescue) constant(LoadError) + comment(# Not providing quoting support) + reserved(def) method(convert_to)operator(()ident(text)operator(,) ident(to)operator(,) ident(from)operator(\)) + ident(warn) string<delimiter(")content(Action Mailer: iconv not loaded; ignoring conversion from )inline<inline_delimiter(#{)ident(from)inline_delimiter(})>content( to )inline<inline_delimiter(#{)ident(to)inline_delimiter(})>content( ()inline<inline_delimiter(#{)pre_constant(__FILE__)inline_delimiter(})>content(:)inline<inline_delimiter(#{)pre_constant(__LINE__)inline_delimiter(})>content(\))delimiter(")> + ident(text) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) + +reserved(if) pre_constant(__FILE__) operator(==) global_variable($0) + ident(require) string<delimiter(')content(test/unit)delimiter(')> + + reserved(class) class(TC_Unquoter) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_unquote_quoted_printable) + ident(a) operator(=)string<delimiter(")content(=?ISO-8859-1?Q?[166417]_Bekr=E6ftelse_fra_Rejsefeber?=)delimiter(")> + ident(b) operator(=) constant(TMail)operator(::)constant(Unquoter)operator(.)ident(unquote_and_convert_to)operator(()ident(a)operator(,) string<delimiter(')content(utf-8)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content([166417] Bekr)char(\\303)char(\\246)content(ftelse fra Rejsefeber)delimiter(")>operator(,) ident(b) + reserved(end) + + reserved(def) method(test_unquote_base64) + ident(a) operator(=)string<delimiter(")content(=?ISO-8859-1?B?WzE2NjQxN10gQmVrcuZmdGVsc2UgZnJhIFJlanNlZmViZXI=?=)delimiter(")> + ident(b) operator(=) constant(TMail)operator(::)constant(Unquoter)operator(.)ident(unquote_and_convert_to)operator(()ident(a)operator(,) string<delimiter(')content(utf-8)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content([166417] Bekr)char(\\303)char(\\246)content(ftelse fra Rejsefeber)delimiter(")>operator(,) ident(b) + reserved(end) + + reserved(def) method(test_unquote_without_charset) + ident(a) operator(=)string<delimiter(")content([166417]_Bekr=E6ftelse_fra_Rejsefeber)delimiter(")> + ident(b) operator(=) constant(TMail)operator(::)constant(Unquoter)operator(.)ident(unquote_and_convert_to)operator(()ident(a)operator(,) string<delimiter(')content(utf-8)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content([166417]_Bekr=E6ftelse_fra_Rejsefeber)delimiter(")>operator(,) ident(b) + reserved(end) + reserved(end) +reserved(end) +comment(#) +comment(# scanner.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/utils)delimiter(')> + +reserved(module) class(TMail) + ident(require) string<delimiter(')content(tmail/scanner_r.rb)delimiter(')> + reserved(begin) + ident(raise) constant(LoadError)operator(,) string<delimiter(')content(Turn off Ruby extention by user choice)delimiter(')> reserved(if) constant(ENV)operator([)string<delimiter(')content(NORUBYEXT)delimiter(')>operator(]) + ident(require) string<delimiter(')content(tmail/scanner_c.so)delimiter(')> + constant(Scanner) operator(=) constant(Scanner_C) + reserved(rescue) constant(LoadError) + constant(Scanner) operator(=) constant(Scanner_R) + reserved(end) +reserved(end) +comment(#) +comment(# scanner_r.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +ident(require) string<delimiter(')content(tmail/config)delimiter(')> + + +reserved(module) class(TMail) + + reserved(class) class(Scanner_R) + + constant(Version) operator(=) string<delimiter(')content(0.10.7)delimiter(')> + constant(Version)operator(.)ident(freeze) + + constant(MIME_HEADERS) operator(=) operator({) + symbol(:CTYPE) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:CENCODING) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:CDISPOSITION) operator(=)operator(>) pre_constant(true) + operator(}) + + ident(alnum) operator(=) string<delimiter(')content(a-zA-Z0-9)delimiter(')> + ident(atomsyms) operator(=) string<delimiter(%q[)content( _#!$%&`'*+-{|}~^@/=? )delimiter(])>operator(.)ident(strip) + ident(tokensyms) operator(=) string<delimiter(%q[)content( _#!$%&`'*+-{|}~^@. )delimiter(])>operator(.)ident(strip) + + ident(atomchars) operator(=) ident(alnum) operator(+) constant(Regexp)operator(.)ident(quote)operator(()ident(atomsyms)operator(\)) + ident(tokenchars) operator(=) ident(alnum) operator(+) constant(Regexp)operator(.)ident(quote)operator(()ident(tokensyms)operator(\)) + ident(iso2022str) operator(=) string<delimiter(')content(\\e)content((?!)content(\\()content(B\)..(?:[^)content(\\e)content(]+|)content(\\e)content((?!)content(\\()content(B\)..\)*)content(\\e)content(\\()content(B)delimiter(')> + + ident(eucstr) operator(=) string<delimiter(')content((?:[)content(\\x)content(a1-)content(\\x)content(fe][)content(\\x)content(a1-)content(\\x)content(fe]\)+)delimiter(')> + ident(sjisstr) operator(=) string<delimiter(')content((?:[)content(\\x)content(81-)content(\\x)content(9f)content(\\x)content(e0-)content(\\x)content(ef][)content(\\x)content(40-)content(\\x)content(7e)content(\\x)content(80-)content(\\x)content(fc]\)+)delimiter(')> + ident(utf8str) operator(=) string<delimiter(')content((?:[)content(\\x)content(c0-)content(\\x)content(df][)content(\\x)content(80-)content(\\x)content(bf]|[)content(\\x)content(e0-)content(\\x)content(ef][)content(\\x)content(80-)content(\\x)content(bf][)content(\\x)content(80-)content(\\x)content(bf]\)+)delimiter(')> + + ident(quoted_with_iso2022) operator(=) regexp<delimiter(/)char(\\A)content((?:[^)char(\\\\)char(\\e)content("]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)> + ident(domlit_with_iso2022) operator(=) regexp<delimiter(/)char(\\A)content((?:[^)char(\\\\)char(\\e)char(\\])content(]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)> + ident(comment_with_iso2022) operator(=) regexp<delimiter(/)char(\\A)content((?:[^)char(\\\\)char(\\e)content((\)]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)> + + ident(quoted_without_iso2022) operator(=) regexp<delimiter(/)char(\\A)content([^)char(\\\\)content("]+)delimiter(/)modifier(n)> + ident(domlit_without_iso2022) operator(=) regexp<delimiter(/)char(\\A)content([^)char(\\\\)char(\\])content(]+)delimiter(/)modifier(n)> + ident(comment_without_iso2022) operator(=) regexp<delimiter(/)char(\\A)content([^)char(\\\\)content((\)]+)delimiter(/)modifier(n)> + + constant(PATTERN_TABLE) operator(=) operator({)operator(}) + constant(PATTERN_TABLE)operator([)string<delimiter(')content(EUC)delimiter(')>operator(]) operator(=) + operator([) + regexp<delimiter(/)char(\\A)content((?:[)inline<inline_delimiter(#{)ident(atomchars)inline_delimiter(})>content(]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(|)inline<inline_delimiter(#{)ident(eucstr)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)>operator(,) + regexp<delimiter(/)char(\\A)content((?:[)inline<inline_delimiter(#{)ident(tokenchars)inline_delimiter(})>content(]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(|)inline<inline_delimiter(#{)ident(eucstr)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)>operator(,) + ident(quoted_with_iso2022)operator(,) + ident(domlit_with_iso2022)operator(,) + ident(comment_with_iso2022) + operator(]) + constant(PATTERN_TABLE)operator([)string<delimiter(')content(SJIS)delimiter(')>operator(]) operator(=) + operator([) + regexp<delimiter(/)char(\\A)content((?:[)inline<inline_delimiter(#{)ident(atomchars)inline_delimiter(})>content(]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(|)inline<inline_delimiter(#{)ident(sjisstr)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)>operator(,) + regexp<delimiter(/)char(\\A)content((?:[)inline<inline_delimiter(#{)ident(tokenchars)inline_delimiter(})>content(]+|)inline<inline_delimiter(#{)ident(iso2022str)inline_delimiter(})>content(|)inline<inline_delimiter(#{)ident(sjisstr)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)>operator(,) + ident(quoted_with_iso2022)operator(,) + ident(domlit_with_iso2022)operator(,) + ident(comment_with_iso2022) + operator(]) + constant(PATTERN_TABLE)operator([)string<delimiter(')content(UTF8)delimiter(')>operator(]) operator(=) + operator([) + regexp<delimiter(/)char(\\A)content((?:[)inline<inline_delimiter(#{)ident(atomchars)inline_delimiter(})>content(]+|)inline<inline_delimiter(#{)ident(utf8str)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)>operator(,) + regexp<delimiter(/)char(\\A)content((?:[)inline<inline_delimiter(#{)ident(tokenchars)inline_delimiter(})>content(]+|)inline<inline_delimiter(#{)ident(utf8str)inline_delimiter(})>content(\)+)delimiter(/)modifier(n)>operator(,) + ident(quoted_without_iso2022)operator(,) + ident(domlit_without_iso2022)operator(,) + ident(comment_without_iso2022) + operator(]) + constant(PATTERN_TABLE)operator([)string<delimiter(')content(NONE)delimiter(')>operator(]) operator(=) + operator([) + regexp<delimiter(/)char(\\A)content([)inline<inline_delimiter(#{)ident(atomchars)inline_delimiter(})>content(]+)delimiter(/)modifier(n)>operator(,) + regexp<delimiter(/)char(\\A)content([)inline<inline_delimiter(#{)ident(tokenchars)inline_delimiter(})>content(]+)delimiter(/)modifier(n)>operator(,) + ident(quoted_without_iso2022)operator(,) + ident(domlit_without_iso2022)operator(,) + ident(comment_without_iso2022) + operator(]) + + + reserved(def) method(initialize)operator(() ident(str)operator(,) ident(scantype)operator(,) ident(comments) operator(\)) + ident(init_scanner) ident(str) + instance_variable(@comments) operator(=) ident(comments) operator(||) operator([)operator(]) + instance_variable(@debug) operator(=) pre_constant(false) + + comment(# fix scanner mode) + instance_variable(@received) operator(=) operator(()ident(scantype) operator(==) symbol(:RECEIVED)operator(\)) + instance_variable(@is_mime_header) operator(=) constant(MIME_HEADERS)operator([)ident(scantype)operator(]) + + ident(atom)operator(,) ident(token)operator(,) instance_variable(@quoted_re)operator(,) instance_variable(@domlit_re)operator(,) instance_variable(@comment_re) operator(=) constant(PATTERN_TABLE)operator([)global_variable($KCODE)operator(]) + instance_variable(@word_re) operator(=) operator(()constant(MIME_HEADERS)operator([)ident(scantype)operator(]) operator(?) ident(token) operator(:) ident(atom)operator(\)) + reserved(end) + + ident(attr_accessor) symbol(:debug) + + reserved(def) method(scan)operator(() operator(&)ident(block) operator(\)) + reserved(if) instance_variable(@debug) + ident(scan_main) reserved(do) operator(|)ident(arr)operator(|) + ident(s)operator(,) ident(v) operator(=) ident(arr) + ident(printf) string<delimiter(")content(%7d %-10s %s)char(\\n)delimiter(")>operator(,) + ident(rest_size)operator(()operator(\))operator(,) + ident(s)operator(.)ident(respond_to?)operator(()symbol(:id2name)operator(\)) operator(?) ident(s)operator(.)ident(id2name) operator(:) ident(s)operator(.)ident(inspect)operator(,) + ident(v)operator(.)ident(inspect) + reserved(yield) ident(arr) + reserved(end) + reserved(else) + ident(scan_main)operator(()operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + ident(private) + + constant(RECV_TOKEN) operator(=) operator({) + string<delimiter(')content(from)delimiter(')> operator(=)operator(>) symbol(:FROM)operator(,) + string<delimiter(')content(by)delimiter(')> operator(=)operator(>) symbol(:BY)operator(,) + string<delimiter(')content(via)delimiter(')> operator(=)operator(>) symbol(:VIA)operator(,) + string<delimiter(')content(with)delimiter(')> operator(=)operator(>) symbol(:WITH)operator(,) + string<delimiter(')content(id)delimiter(')> operator(=)operator(>) symbol(:ID)operator(,) + string<delimiter(')content(for)delimiter(')> operator(=)operator(>) symbol(:FOR) + operator(}) + + reserved(def) method(scan_main) + reserved(until) ident(eof?) + reserved(if) ident(skip)operator(()regexp<delimiter(/)char(\\A)content([)char(\\n)char(\\r)char(\\t)content( ]+)delimiter(/)modifier(n)>operator(\)) comment(# LWSP) + reserved(break) reserved(if) ident(eof?) + reserved(end) + + reserved(if) ident(s) operator(=) ident(readstr)operator(()instance_variable(@word_re)operator(\)) + reserved(if) instance_variable(@is_mime_header) + reserved(yield) symbol(:TOKEN)operator(,) ident(s) + reserved(else) + comment(# atom) + reserved(if) regexp<delimiter(/)char(\\A)char(\\d)content(+)char(\\z)delimiter(/)> operator(===) ident(s) + reserved(yield) symbol(:DIGIT)operator(,) ident(s) + reserved(elsif) instance_variable(@received) + reserved(yield) constant(RECV_TOKEN)operator([)ident(s)operator(.)ident(downcase)operator(]) operator(||) symbol(:ATOM)operator(,) ident(s) + reserved(else) + reserved(yield) symbol(:ATOM)operator(,) ident(s) + reserved(end) + reserved(end) + + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)content(")delimiter(/)>operator(\)) + reserved(yield) symbol(:QUOTED)operator(,) ident(scan_quoted_word)operator(()operator(\)) + + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)char(\\[)delimiter(/)>operator(\)) + reserved(yield) symbol(:DOMLIT)operator(,) ident(scan_domain_literal)operator(()operator(\)) + + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)char(\\()delimiter(/)>operator(\)) + instance_variable(@comments)operator(.)ident(push) ident(scan_comment)operator(()operator(\)) + + reserved(else) + ident(c) operator(=) ident(readchar)operator(()operator(\)) + reserved(yield) ident(c)operator(,) ident(c) + reserved(end) + reserved(end) + + reserved(yield) pre_constant(false)operator(,) string<delimiter(')content($)delimiter(')> + reserved(end) + + reserved(def) method(scan_quoted_word) + ident(scan_qstr)operator(()instance_variable(@quoted_re)operator(,) regexp<delimiter(/)char(\\A)content(")delimiter(/)>operator(,) string<delimiter(')content(quoted-word)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(scan_domain_literal) + string<delimiter(')content([)delimiter(')> operator(+) ident(scan_qstr)operator(()instance_variable(@domlit_re)operator(,) regexp<delimiter(/)char(\\A)char(\\])delimiter(/)>operator(,) string<delimiter(')content(domain-literal)delimiter(')>operator(\)) operator(+) string<delimiter(')content(])delimiter(')> + reserved(end) + + reserved(def) method(scan_qstr)operator(() ident(pattern)operator(,) ident(terminal)operator(,) ident(type) operator(\)) + ident(result) operator(=) string<delimiter(')delimiter(')> + reserved(until) ident(eof?) + reserved(if) ident(s) operator(=) ident(readstr)operator(()ident(pattern)operator(\)) reserved(then) ident(result) operator(<<) ident(s) + reserved(elsif) ident(skip)operator(()ident(terminal)operator(\)) reserved(then) reserved(return) ident(result) + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)char(\\\\)delimiter(/)>operator(\)) reserved(then) ident(result) operator(<<) ident(readchar)operator(()operator(\)) + reserved(else) + ident(raise) string<delimiter(")content(TMail FATAL: not match in )inline<inline_delimiter(#{)ident(type)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + ident(scan_error!) string<delimiter(")content(found unterminated )inline<inline_delimiter(#{)ident(type)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(scan_comment) + ident(result) operator(=) string<delimiter(')delimiter(')> + ident(nest) operator(=) integer(1) + ident(content) operator(=) instance_variable(@comment_re) + + reserved(until) ident(eof?) + reserved(if) ident(s) operator(=) ident(readstr)operator(()ident(content)operator(\)) reserved(then) ident(result) operator(<<) ident(s) + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)char(\\\))delimiter(/)>operator(\)) reserved(then) ident(nest) operator(-=) integer(1) + reserved(return) ident(result) reserved(if) ident(nest) operator(==) integer(0) + ident(result) operator(<<) string<delimiter(')content(\))delimiter(')> + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)char(\\()delimiter(/)>operator(\)) reserved(then) ident(nest) operator(+=) integer(1) + ident(result) operator(<<) string<delimiter(')content(()delimiter(')> + reserved(elsif) ident(skip)operator(()regexp<delimiter(/)char(\\A)char(\\\\)delimiter(/)>operator(\)) reserved(then) ident(result) operator(<<) ident(readchar)operator(()operator(\)) + reserved(else) + ident(raise) string<delimiter(')content(TMail FATAL: not match in comment)delimiter(')> + reserved(end) + reserved(end) + ident(scan_error!) string<delimiter(')content(found unterminated comment)delimiter(')> + reserved(end) + + comment(# string scanner) + + reserved(def) method(init_scanner)operator(() ident(str) operator(\)) + instance_variable(@src) operator(=) ident(str) + reserved(end) + + reserved(def) method(eof?) + instance_variable(@src)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(rest_size) + instance_variable(@src)operator(.)ident(size) + reserved(end) + + reserved(def) method(readstr)operator(() ident(re) operator(\)) + reserved(if) ident(m) operator(=) ident(re)operator(.)ident(match)operator(()instance_variable(@src)operator(\)) + instance_variable(@src) operator(=) ident(m)operator(.)ident(post_match) + ident(m)operator([)integer(0)operator(]) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(readchar) + ident(readstr)operator(()regexp<delimiter(/)char(\\A)content(.)delimiter(/)>operator(\)) + reserved(end) + + reserved(def) method(skip)operator(() ident(re) operator(\)) + reserved(if) ident(m) operator(=) ident(re)operator(.)ident(match)operator(()instance_variable(@src)operator(\)) + instance_variable(@src) operator(=) ident(m)operator(.)ident(post_match) + pre_constant(true) + reserved(else) + pre_constant(false) + reserved(end) + reserved(end) + + reserved(def) method(scan_error!)operator(() ident(msg) operator(\)) + ident(raise) constant(SyntaxError)operator(,) ident(msg) + reserved(end) + + reserved(end) + +reserved(end) comment(# module TMail) +comment(#) +comment(# stringio.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +reserved(class) class(StringInput)comment(#:nodoc:) + + ident(include) constant(Enumerable) + + reserved(class) operator(<<) class(self) + + reserved(def) method(new)operator(() ident(str) operator(\)) + reserved(if) ident(block_given?) + reserved(begin) + ident(f) operator(=) reserved(super) + reserved(yield) ident(f) + reserved(ensure) + ident(f)operator(.)ident(close) reserved(if) ident(f) + reserved(end) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(alias) method(open) method(new) + + reserved(end) + + reserved(def) method(initialize)operator(() ident(str) operator(\)) + instance_variable(@src) operator(=) ident(str) + instance_variable(@pos) operator(=) integer(0) + instance_variable(@closed) operator(=) pre_constant(false) + instance_variable(@lineno) operator(=) integer(0) + reserved(end) + + ident(attr_reader) symbol(:lineno) + + reserved(def) method(string) + instance_variable(@src) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@closed) operator(?) string<delimiter(')content(closed)delimiter(')> operator(:) string<delimiter(')content(open)delimiter(')>inline_delimiter(})>content(,src=)inline<inline_delimiter(#{)instance_variable(@src)operator([)integer(0)operator(,)integer(30)operator(])operator(.)ident(inspect)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(close) + ident(stream_check!) + instance_variable(@pos) operator(=) pre_constant(nil) + instance_variable(@closed) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(closed?) + instance_variable(@closed) + reserved(end) + + reserved(def) method(pos) + ident(stream_check!) + operator([)instance_variable(@pos)operator(,) instance_variable(@src)operator(.)ident(size)operator(])operator(.)ident(min) + reserved(end) + + reserved(alias) method(tell) method(pos) + + reserved(def) method(seek)operator(() ident(offset)operator(,) ident(whence) operator(=) constant(IO)operator(::)constant(SEEK_SET) operator(\)) + ident(stream_check!) + reserved(case) ident(whence) + reserved(when) constant(IO)operator(::)constant(SEEK_SET) + instance_variable(@pos) operator(=) ident(offset) + reserved(when) constant(IO)operator(::)constant(SEEK_CUR) + instance_variable(@pos) operator(+=) ident(offset) + reserved(when) constant(IO)operator(::)constant(SEEK_END) + instance_variable(@pos) operator(=) instance_variable(@src)operator(.)ident(size) operator(-) ident(offset) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(unknown seek flag: )inline<inline_delimiter(#{)ident(whence)inline_delimiter(})>delimiter(")> + reserved(end) + instance_variable(@pos) operator(=) integer(0) reserved(if) instance_variable(@pos) operator(<) integer(0) + instance_variable(@pos) operator(=) operator([)instance_variable(@pos)operator(,) instance_variable(@src)operator(.)ident(size) operator(+) integer(1)operator(])operator(.)ident(min) + ident(offset) + reserved(end) + + reserved(def) method(rewind) + ident(stream_check!) + instance_variable(@pos) operator(=) integer(0) + reserved(end) + + reserved(def) method(eof?) + ident(stream_check!) + instance_variable(@pos) operator(>) instance_variable(@src)operator(.)ident(size) + reserved(end) + + reserved(def) method(each)operator(() operator(&)ident(block) operator(\)) + ident(stream_check!) + reserved(begin) + instance_variable(@src)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(ensure) + instance_variable(@pos) operator(=) integer(0) + reserved(end) + reserved(end) + + reserved(def) method(gets) + ident(stream_check!) + reserved(if) ident(idx) operator(=) instance_variable(@src)operator(.)ident(index)operator(()integer(?\\n)operator(,) instance_variable(@pos)operator(\)) + ident(idx) operator(+=) integer(1) comment(# "\\n".size) + ident(line) operator(=) instance_variable(@src)operator([) instance_variable(@pos) operator(...) ident(idx) operator(]) + instance_variable(@pos) operator(=) ident(idx) + instance_variable(@pos) operator(+=) integer(1) reserved(if) instance_variable(@pos) operator(==) instance_variable(@src)operator(.)ident(size) + reserved(else) + ident(line) operator(=) instance_variable(@src)operator([) instance_variable(@pos) operator(..) integer(-1) operator(]) + instance_variable(@pos) operator(=) instance_variable(@src)operator(.)ident(size) operator(+) integer(1) + reserved(end) + instance_variable(@lineno) operator(+=) integer(1) + + ident(line) + reserved(end) + + reserved(def) method(getc) + ident(stream_check!) + ident(ch) operator(=) instance_variable(@src)operator([)instance_variable(@pos)operator(]) + instance_variable(@pos) operator(+=) integer(1) + instance_variable(@pos) operator(+=) integer(1) reserved(if) instance_variable(@pos) operator(==) instance_variable(@src)operator(.)ident(size) + ident(ch) + reserved(end) + + reserved(def) method(read)operator(() ident(len) operator(=) pre_constant(nil) operator(\)) + ident(stream_check!) + reserved(return) ident(read_all) reserved(unless) ident(len) + ident(str) operator(=) instance_variable(@src)operator([)instance_variable(@pos)operator(,) ident(len)operator(]) + instance_variable(@pos) operator(+=) ident(len) + instance_variable(@pos) operator(+=) integer(1) reserved(if) instance_variable(@pos) operator(==) instance_variable(@src)operator(.)ident(size) + ident(str) + reserved(end) + + reserved(alias) method(sysread) method(read) + + reserved(def) method(read_all) + ident(stream_check!) + reserved(return) pre_constant(nil) reserved(if) ident(eof?) + ident(rest) operator(=) instance_variable(@src)operator([)instance_variable(@pos) operator(...) instance_variable(@src)operator(.)ident(size)operator(]) + instance_variable(@pos) operator(=) instance_variable(@src)operator(.)ident(size) operator(+) integer(1) + ident(rest) + reserved(end) + + reserved(def) method(stream_check!) + instance_variable(@closed) reserved(and) ident(raise) constant(IOError)operator(,) string<delimiter(')content(closed stream)delimiter(')> + reserved(end) + +reserved(end) + + +reserved(class) class(StringOutput)comment(#:nodoc:) + + reserved(class) operator(<<) class(self) + + reserved(def) method(new)operator(() ident(str) operator(=) string<delimiter(')delimiter(')> operator(\)) + reserved(if) ident(block_given?) + reserved(begin) + ident(f) operator(=) reserved(super) + reserved(yield) ident(f) + reserved(ensure) + ident(f)operator(.)ident(close) reserved(if) ident(f) + reserved(end) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(alias) method(open) method(new) + + reserved(end) + + reserved(def) method(initialize)operator(() ident(str) operator(=) string<delimiter(')delimiter(')> operator(\)) + instance_variable(@dest) operator(=) ident(str) + instance_variable(@closed) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(close) + instance_variable(@closed) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(closed?) + instance_variable(@closed) + reserved(end) + + reserved(def) method(string) + instance_variable(@dest) + reserved(end) + + reserved(alias) method(value) method(string) + reserved(alias) method(to_str) method(string) + + reserved(def) method(size) + instance_variable(@dest)operator(.)ident(size) + reserved(end) + + reserved(alias) method(pos) method(size) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@dest) operator(?) string<delimiter(')content(open)delimiter(')> operator(:) string<delimiter(')content(closed)delimiter(')>inline_delimiter(})>content(,)inline<inline_delimiter(#{)ident(id)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(print)operator(() operator(*)ident(args) operator(\)) + ident(stream_check!) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(wrong # of argument (0 for >1\))delimiter(')> reserved(if) ident(args)operator(.)ident(empty?) + ident(args)operator(.)ident(each) reserved(do) operator(|)ident(s)operator(|) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(nil not allowed)delimiter(')> reserved(if) ident(s)operator(.)ident(nil?) + instance_variable(@dest) operator(<<) ident(s)operator(.)ident(to_s) + reserved(end) + pre_constant(nil) + reserved(end) + + reserved(def) method(puts)operator(() operator(*)ident(args) operator(\)) + ident(stream_check!) + ident(args)operator(.)ident(each) reserved(do) operator(|)ident(str)operator(|) + instance_variable(@dest) operator(<<) operator(()ident(s) operator(=) ident(str)operator(.)ident(to_s)operator(\)) + instance_variable(@dest) operator(<<) string<delimiter(")char(\\n)delimiter(")> reserved(unless) ident(s)operator([)integer(-1)operator(]) operator(==) integer(?\\n) + reserved(end) + instance_variable(@dest) operator(<<) string<delimiter(")char(\\n)delimiter(")> reserved(if) ident(args)operator(.)ident(empty?) + pre_constant(nil) + reserved(end) + + reserved(def) method(putc)operator(() ident(ch) operator(\)) + ident(stream_check!) + instance_variable(@dest) operator(<<) ident(ch)operator(.)ident(chr) + pre_constant(nil) + reserved(end) + + reserved(def) method(printf)operator(() operator(*)ident(args) operator(\)) + ident(stream_check!) + instance_variable(@dest) operator(<<) ident(sprintf)operator(()operator(*)ident(args)operator(\)) + pre_constant(nil) + reserved(end) + + reserved(def) method(write)operator(() ident(str) operator(\)) + ident(stream_check!) + ident(s) operator(=) ident(str)operator(.)ident(to_s) + instance_variable(@dest) operator(<<) ident(s) + ident(s)operator(.)ident(size) + reserved(end) + + reserved(alias) method(syswrite) method(write) + + reserved(def) method(<<)operator(() ident(str) operator(\)) + ident(stream_check!) + instance_variable(@dest) operator(<<) ident(str)operator(.)ident(to_s) + pre_constant(self) + reserved(end) + + ident(private) + + reserved(def) method(stream_check!) + instance_variable(@closed) reserved(and) ident(raise) constant(IOError)operator(,) string<delimiter(')content(closed stream)delimiter(')> + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(tmail)delimiter(')> +comment(#) +comment(# utils.rb) +comment(#) +comment(#--) +comment(# Copyright (c\) 1998-2003 Minero Aoki <aamine@loveruby.net>) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) +comment(#++) + +reserved(module) class(TMail) + + reserved(class) class(SyntaxError) operator(<) constant(StandardError)operator(;) reserved(end) + + + reserved(def) constant(TMail)operator(.)ident(new_boundary) + string<delimiter(')content(mimepart_)delimiter(')> operator(+) ident(random_tag) + reserved(end) + + reserved(def) constant(TMail)operator(.)ident(new_message_id)operator(() ident(fqdn) operator(=) pre_constant(nil) operator(\)) + ident(fqdn) operator(||=) operator(::)constant(Socket)operator(.)ident(gethostname) + string<delimiter(")content(<)inline<inline_delimiter(#{)ident(random_tag)operator(()operator(\))inline_delimiter(})>content(@)inline<inline_delimiter(#{)ident(fqdn)inline_delimiter(})>content(.tmail>)delimiter(")> + reserved(end) + + reserved(def) constant(TMail)operator(.)ident(random_tag) + instance_variable(@uniq) operator(+=) integer(1) + ident(t) operator(=) constant(Time)operator(.)ident(now) + ident(sprintf)operator(()string<delimiter(')content(%x%x_%x%x%d%x)delimiter(')>operator(,) + ident(t)operator(.)ident(to_i)operator(,) ident(t)operator(.)ident(tv_usec)operator(,) + global_variable($$)operator(,) constant(Thread)operator(.)ident(current)operator(.)ident(object_id)operator(,) instance_variable(@uniq)operator(,) ident(rand)operator(()integer(255)operator(\))operator(\)) + reserved(end) + ident(private_class_method) symbol(:random_tag) + + instance_variable(@uniq) operator(=) integer(0) + + + reserved(module) class(TextUtils) + + ident(aspecial) operator(=) string<delimiter(')content((\)<>[]:;.)char(\\\\)content(,")delimiter(')> + ident(tspecial) operator(=) string<delimiter(')content((\)<>[];:)char(\\\\)content(,"/?=)delimiter(')> + ident(lwsp) operator(=) string<delimiter(")content( )char(\\t)char(\\r)char(\\n)delimiter(")> + ident(control) operator(=) string<delimiter(')content(\\x)content(00-)content(\\x)content(1f)content(\\x)content(7f-)content(\\x)content(ff)delimiter(')> + + constant(ATOM_UNSAFE) operator(=) regexp<delimiter(/)content([)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote) ident(aspecial)inline_delimiter(})>inline<inline_delimiter(#{)ident(control)inline_delimiter(})>inline<inline_delimiter(#{)ident(lwsp)inline_delimiter(})>content(])delimiter(/)modifier(n)> + constant(PHRASE_UNSAFE) operator(=) regexp<delimiter(/)content([)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote) ident(aspecial)inline_delimiter(})>inline<inline_delimiter(#{)ident(control)inline_delimiter(})>content(])delimiter(/)modifier(n)> + constant(TOKEN_UNSAFE) operator(=) regexp<delimiter(/)content([)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote) ident(tspecial)inline_delimiter(})>inline<inline_delimiter(#{)ident(control)inline_delimiter(})>inline<inline_delimiter(#{)ident(lwsp)inline_delimiter(})>content(])delimiter(/)modifier(n)> + constant(CONTROL_CHAR) operator(=) regexp<delimiter(/)content([)inline<inline_delimiter(#{)ident(control)inline_delimiter(})>content(])delimiter(/)modifier(n)> + + reserved(def) method(atom_safe?)operator(() ident(str) operator(\)) + reserved(not) constant(ATOM_UNSAFE) operator(===) ident(str) + reserved(end) + + reserved(def) method(quote_atom)operator(() ident(str) operator(\)) + operator(()constant(ATOM_UNSAFE) operator(===) ident(str)operator(\)) operator(?) ident(dquote)operator(()ident(str)operator(\)) operator(:) ident(str) + reserved(end) + + reserved(def) method(quote_phrase)operator(() ident(str) operator(\)) + operator(()constant(PHRASE_UNSAFE) operator(===) ident(str)operator(\)) operator(?) ident(dquote)operator(()ident(str)operator(\)) operator(:) ident(str) + reserved(end) + + reserved(def) method(token_safe?)operator(() ident(str) operator(\)) + reserved(not) constant(TOKEN_UNSAFE) operator(===) ident(str) + reserved(end) + + reserved(def) method(quote_token)operator(() ident(str) operator(\)) + operator(()constant(TOKEN_UNSAFE) operator(===) ident(str)operator(\)) operator(?) ident(dquote)operator(()ident(str)operator(\)) operator(:) ident(str) + reserved(end) + + reserved(def) method(dquote)operator(() ident(str) operator(\)) + string<delimiter(')content(")delimiter(')> operator(+) ident(str)operator(.)ident(gsub)operator(()regexp<delimiter(/)content([")char(\\\\)content(])delimiter(/)modifier(n)>operator(\)) operator({)operator(|)ident(s)operator(|) string<delimiter(')char(\\\\)delimiter(')> operator(+) ident(s) operator(}) operator(+) string<delimiter(')content(")delimiter(')> + reserved(end) + ident(private) symbol(:dquote) + + + reserved(def) method(join_domain)operator(() ident(arr) operator(\)) + ident(arr)operator(.)ident(map) operator({)operator(|)ident(i)operator(|) + reserved(if) regexp<delimiter(/)char(\\A)char(\\[)content(.*)char(\\])char(\\z)delimiter(/)> operator(===) ident(i) + ident(i) + reserved(else) + ident(quote_atom)operator(()ident(i)operator(\)) + reserved(end) + operator(})operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) + + + constant(ZONESTR_TABLE) operator(=) operator({) + string<delimiter(')content(jst)delimiter(')> operator(=)operator(>) integer(9) operator(*) integer(60)operator(,) + string<delimiter(')content(eet)delimiter(')> operator(=)operator(>) integer(2) operator(*) integer(60)operator(,) + string<delimiter(')content(bst)delimiter(')> operator(=)operator(>) integer(1) operator(*) integer(60)operator(,) + string<delimiter(')content(met)delimiter(')> operator(=)operator(>) integer(1) operator(*) integer(60)operator(,) + string<delimiter(')content(gmt)delimiter(')> operator(=)operator(>) integer(0)operator(,) + string<delimiter(')content(utc)delimiter(')> operator(=)operator(>) integer(0)operator(,) + string<delimiter(')content(ut)delimiter(')> operator(=)operator(>) integer(0)operator(,) + string<delimiter(')content(nst)delimiter(')> operator(=)operator(>) operator(-)operator(()integer(3) operator(*) integer(60) operator(+) integer(30)operator(\))operator(,) + string<delimiter(')content(ast)delimiter(')> operator(=)operator(>) integer(-4) operator(*) integer(60)operator(,) + string<delimiter(')content(edt)delimiter(')> operator(=)operator(>) integer(-4) operator(*) integer(60)operator(,) + string<delimiter(')content(est)delimiter(')> operator(=)operator(>) integer(-5) operator(*) integer(60)operator(,) + string<delimiter(')content(cdt)delimiter(')> operator(=)operator(>) integer(-5) operator(*) integer(60)operator(,) + string<delimiter(')content(cst)delimiter(')> operator(=)operator(>) integer(-6) operator(*) integer(60)operator(,) + string<delimiter(')content(mdt)delimiter(')> operator(=)operator(>) integer(-6) operator(*) integer(60)operator(,) + string<delimiter(')content(mst)delimiter(')> operator(=)operator(>) integer(-7) operator(*) integer(60)operator(,) + string<delimiter(')content(pdt)delimiter(')> operator(=)operator(>) integer(-7) operator(*) integer(60)operator(,) + string<delimiter(')content(pst)delimiter(')> operator(=)operator(>) integer(-8) operator(*) integer(60)operator(,) + string<delimiter(')content(a)delimiter(')> operator(=)operator(>) integer(-1) operator(*) integer(60)operator(,) + string<delimiter(')content(b)delimiter(')> operator(=)operator(>) integer(-2) operator(*) integer(60)operator(,) + string<delimiter(')content(c)delimiter(')> operator(=)operator(>) integer(-3) operator(*) integer(60)operator(,) + string<delimiter(')content(d)delimiter(')> operator(=)operator(>) integer(-4) operator(*) integer(60)operator(,) + string<delimiter(')content(e)delimiter(')> operator(=)operator(>) integer(-5) operator(*) integer(60)operator(,) + string<delimiter(')content(f)delimiter(')> operator(=)operator(>) integer(-6) operator(*) integer(60)operator(,) + string<delimiter(')content(g)delimiter(')> operator(=)operator(>) integer(-7) operator(*) integer(60)operator(,) + string<delimiter(')content(h)delimiter(')> operator(=)operator(>) integer(-8) operator(*) integer(60)operator(,) + string<delimiter(')content(i)delimiter(')> operator(=)operator(>) integer(-9) operator(*) integer(60)operator(,) + comment(# j not use) + string<delimiter(')content(k)delimiter(')> operator(=)operator(>) integer(-10) operator(*) integer(60)operator(,) + string<delimiter(')content(l)delimiter(')> operator(=)operator(>) integer(-11) operator(*) integer(60)operator(,) + string<delimiter(')content(m)delimiter(')> operator(=)operator(>) integer(-12) operator(*) integer(60)operator(,) + string<delimiter(')content(n)delimiter(')> operator(=)operator(>) integer(1) operator(*) integer(60)operator(,) + string<delimiter(')content(o)delimiter(')> operator(=)operator(>) integer(2) operator(*) integer(60)operator(,) + string<delimiter(')content(p)delimiter(')> operator(=)operator(>) integer(3) operator(*) integer(60)operator(,) + string<delimiter(')content(q)delimiter(')> operator(=)operator(>) integer(4) operator(*) integer(60)operator(,) + string<delimiter(')content(r)delimiter(')> operator(=)operator(>) integer(5) operator(*) integer(60)operator(,) + string<delimiter(')content(s)delimiter(')> operator(=)operator(>) integer(6) operator(*) integer(60)operator(,) + string<delimiter(')content(t)delimiter(')> operator(=)operator(>) integer(7) operator(*) integer(60)operator(,) + string<delimiter(')content(u)delimiter(')> operator(=)operator(>) integer(8) operator(*) integer(60)operator(,) + string<delimiter(')content(v)delimiter(')> operator(=)operator(>) integer(9) operator(*) integer(60)operator(,) + string<delimiter(')content(w)delimiter(')> operator(=)operator(>) integer(10) operator(*) integer(60)operator(,) + string<delimiter(')content(x)delimiter(')> operator(=)operator(>) integer(11) operator(*) integer(60)operator(,) + string<delimiter(')content(y)delimiter(')> operator(=)operator(>) integer(12) operator(*) integer(60)operator(,) + string<delimiter(')content(z)delimiter(')> operator(=)operator(>) integer(0) operator(*) integer(60) + operator(}) + + reserved(def) method(timezone_string_to_unixtime)operator(() ident(str) operator(\)) + reserved(if) ident(m) operator(=) regexp<delimiter(/)content(([)char(\\+)char(\\-)content(]\)()char(\\d)char(\\d)content(?\)()char(\\d)char(\\d)content(\))delimiter(/)>operator(.)ident(match)operator(()ident(str)operator(\)) + ident(sec) operator(=) operator(()ident(m)operator([)integer(2)operator(])operator(.)ident(to_i) operator(*) integer(60) operator(+) ident(m)operator([)integer(3)operator(])operator(.)ident(to_i)operator(\)) operator(*) integer(60) + ident(m)operator([)integer(1)operator(]) operator(==) string<delimiter(')content(-)delimiter(')> operator(?) operator(-)ident(sec) operator(:) ident(sec) + reserved(else) + ident(min) operator(=) constant(ZONESTR_TABLE)operator([)ident(str)operator(.)ident(downcase)operator(]) reserved(or) + ident(raise) constant(SyntaxError)operator(,) string<delimiter(")content(wrong timezone format ')inline<inline_delimiter(#{)ident(str)inline_delimiter(})>content(')delimiter(")> + ident(min) operator(*) integer(60) + reserved(end) + reserved(end) + + + constant(WDAY) operator(=) string<delimiter(%w()content( Sun Mon Tue Wed Thu Fri Sat TMailBUG )delimiter(\))> + constant(MONTH) operator(=) string<delimiter(%w()content( TMailBUG Jan Feb Mar Apr May Jun + Jul Aug Sep Oct Nov Dec TMailBUG )delimiter(\))> + + reserved(def) method(time2str)operator(() ident(tm) operator(\)) + comment(# [ruby-list:7928]) + ident(gmt) operator(=) constant(Time)operator(.)ident(at)operator(()ident(tm)operator(.)ident(to_i)operator(\)) + ident(gmt)operator(.)ident(gmtime) + ident(offset) operator(=) ident(tm)operator(.)ident(to_i) operator(-) constant(Time)operator(.)ident(local)operator(()operator(*)ident(gmt)operator(.)ident(to_a)operator([)integer(0)operator(,)integer(6)operator(])operator(.)ident(reverse)operator(\))operator(.)ident(to_i) + + comment(# DO NOT USE strftime: setlocale(\) breaks it) + ident(sprintf) string<delimiter(')content(%s, %s %s %d %02d:%02d:%02d %+.2d%.2d)delimiter(')>operator(,) + constant(WDAY)operator([)ident(tm)operator(.)ident(wday)operator(])operator(,) ident(tm)operator(.)ident(mday)operator(,) constant(MONTH)operator([)ident(tm)operator(.)ident(month)operator(])operator(,) + ident(tm)operator(.)ident(year)operator(,) ident(tm)operator(.)ident(hour)operator(,) ident(tm)operator(.)ident(min)operator(,) ident(tm)operator(.)ident(sec)operator(,) + operator(*)operator(()ident(offset) operator(/) integer(60)operator(\))operator(.)ident(divmod)operator(()integer(60)operator(\)) + reserved(end) + + + constant(MESSAGE_ID) operator(=) regexp<delimiter(/)content(<[^)char(\\@)content(>]+)char(\\@)content([^>)char(\\@)content(]+>)delimiter(/)> + + reserved(def) method(message_id?)operator(() ident(str) operator(\)) + constant(MESSAGE_ID) operator(===) ident(str) + reserved(end) + + + constant(MIME_ENCODED) operator(=) regexp<delimiter(/)content(=)char(\\?)content([^)char(\\s)content(?=]+)char(\\?)content([QB])char(\\?)content([^)char(\\s)content(?=]+)char(\\?)content(=)delimiter(/)modifier(i)> + + reserved(def) method(mime_encoded?)operator(() ident(str) operator(\)) + constant(MIME_ENCODED) operator(===) ident(str) + reserved(end) + + + reserved(def) method(decode_params)operator(() ident(hash) operator(\)) + ident(new) operator(=) constant(Hash)operator(.)ident(new) + ident(encoded) operator(=) pre_constant(nil) + ident(hash)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) ident(m) operator(=) regexp<delimiter(/)char(\\*)content((?:()char(\\d)content(+\))char(\\*)content(\)?)char(\\z)delimiter(/)>operator(.)ident(match)operator(()ident(key)operator(\)) + operator(()operator(()ident(encoded) operator(||=) operator({)operator(})operator(\))operator([)ident(m)operator(.)ident(pre_match)operator(]) operator(||=) operator([)operator(])operator(\))operator([)operator(()ident(m)operator([)integer(1)operator(]) operator(||) integer(0)operator(\))operator(.)ident(to_i)operator(]) operator(=) ident(value) + reserved(else) + ident(new)operator([)ident(key)operator(]) operator(=) ident(to_kcode)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) + reserved(if) ident(encoded) + ident(encoded)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(strings)operator(|) + ident(new)operator([)ident(key)operator(]) operator(=) ident(decode_RFC2231)operator(()ident(strings)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\))operator(\)) + reserved(end) + reserved(end) + + ident(new) + reserved(end) + + constant(NKF_FLAGS) operator(=) operator({) + string<delimiter(')content(EUC)delimiter(')> operator(=)operator(>) string<delimiter(')content(-e -m)delimiter(')>operator(,) + string<delimiter(')content(SJIS)delimiter(')> operator(=)operator(>) string<delimiter(')content(-s -m)delimiter(')> + operator(}) + + reserved(def) method(to_kcode)operator(() ident(str) operator(\)) + ident(flag) operator(=) constant(NKF_FLAGS)operator([)global_variable($KCODE)operator(]) reserved(or) reserved(return) ident(str) + constant(NKF)operator(.)ident(nkf)operator(()ident(flag)operator(,) ident(str)operator(\)) + reserved(end) + + constant(RFC2231_ENCODED) operator(=) regexp<delimiter(/)char(\\A)content((?:iso-2022-jp|euc-jp|shift_jis|us-ascii\)?'[a-z]*')delimiter(/)modifier(in)> + + reserved(def) method(decode_RFC2231)operator(() ident(str) operator(\)) + ident(m) operator(=) constant(RFC2231_ENCODED)operator(.)ident(match)operator(()ident(str)operator(\)) reserved(or) reserved(return) ident(str) + reserved(begin) + constant(NKF)operator(.)ident(nkf)operator(()constant(NKF_FLAGS)operator([)global_variable($KCODE)operator(])operator(,) + ident(m)operator(.)ident(post_match)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(%[)char(\\d)content(a-f]{2})delimiter(/)modifier(in)>operator(\)) operator({)operator(|)ident(s)operator(|) ident(s)operator([)integer(1)operator(,)integer(2)operator(])operator(.)ident(hex)operator(.)ident(chr) operator(})operator(\)) + reserved(rescue) + ident(m)operator(.)ident(post_match)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(%[)char(\\d)content(a-f]{2})delimiter(/)modifier(in)>operator(,) string<delimiter(")delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(tmail/info)delimiter(')> +ident(require) string<delimiter(')content(tmail/mail)delimiter(')> +ident(require) string<delimiter(')content(tmail/mailbox)delimiter(')> +reserved(module) class(ActionMailer) + reserved(module) class(VERSION) comment(#:nodoc:) + constant(MAJOR) operator(=) integer(1) + constant(MINOR) operator(=) integer(2) + constant(TINY) operator(=) integer(5) + + constant(STRING) operator(=) operator([)constant(MAJOR)operator(,) constant(MINOR)operator(,) constant(TINY)operator(])operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) +reserved(end) +comment(#--) +comment(# Copyright (c\) 2004 David Heinemeier Hansson) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +reserved(begin) + ident(require) string<delimiter(')content(action_controller)delimiter(')> +reserved(rescue) constant(LoadError) + reserved(begin) + ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../actionpack/lib/action_controller)delimiter(')> + reserved(rescue) constant(LoadError) + ident(require) string<delimiter(')content(rubygems)delimiter(')> + ident(require_gem) string<delimiter(')content(actionpack)delimiter(')>operator(,) string<delimiter(')content(>= 1.9.1)delimiter(')> + reserved(end) +reserved(end) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/action_mailer/vendor/)delimiter(")>operator(\)) + +ident(require) string<delimiter(')content(action_mailer/base)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/helpers)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/mail_helper)delimiter(')> +ident(require) string<delimiter(')content(action_mailer/quoting)delimiter(')> +ident(require) string<delimiter(')content(tmail)delimiter(')> +ident(require) string<delimiter(')content(net/smtp)delimiter(')> + +constant(ActionMailer)operator(::)constant(Base)operator(.)ident(class_eval) reserved(do) + ident(include) constant(ActionMailer)operator(::)constant(Quoting) + ident(include) constant(ActionMailer)operator(::)constant(Helpers) + + ident(helper) constant(MailHelper) +reserved(end) + +ident(silence_warnings) operator({) constant(TMail)operator(::)constant(Encoder)operator(.)ident(const_set)operator(()string<delimiter(")content(MAX_LINE_LEN)delimiter(")>operator(,) integer(200)operator(\)) operator(})reserved(module) class(TestHelper) + reserved(def) method(test_format)operator(()ident(text)operator(\)) + string<delimiter(")content(<em><strong><small>)inline<inline_delimiter(#{)ident(text)inline_delimiter(})>content(</small></strong></em>)delimiter(")> + reserved(end) +reserved(end) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib/)delimiter(")>operator(\)) +global_variable($:)operator(.)ident(unshift) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/helpers)delimiter(")> + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(action_mailer)delimiter(')> + +reserved(module) class(MailerHelper) + reserved(def) method(person_name) + string<delimiter(")content(Mr. Joe Person)delimiter(")> + reserved(end) +reserved(end) + +reserved(class) class(HelperMailer) operator(<) constant(ActionMailer)operator(::)constant(Base) + ident(helper) constant(MailerHelper) + ident(helper) symbol(:test) + + reserved(def) method(use_helper)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(using helpers)delimiter(")> + ident(from) string<delimiter(")content(tester@example.com)delimiter(")> + reserved(end) + + reserved(def) method(use_test_helper)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(using helpers)delimiter(")> + ident(from) string<delimiter(")content(tester@example.com)delimiter(")> + pre_constant(self)operator(.)ident(body) operator(=) operator({) symbol(:text) operator(=)operator(>) string<delimiter(")content(emphasize me!)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(use_mail_helper)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(using mailing helpers)delimiter(")> + ident(from) string<delimiter(")content(tester@example.com)delimiter(")> + pre_constant(self)operator(.)ident(body) operator(=) operator({) symbol(:text) operator(=)operator(>) + string<delimiter(")content(But soft! What light through yonder window breaks? It is the east, )delimiter(")> operator(+) + string<delimiter(")content(and Juliet is the sun. Arise, fair sun, and kill the envious moon, )delimiter(")> operator(+) + string<delimiter(")content(which is sick and pale with grief that thou, her maid, art far more )delimiter(")> operator(+) + string<delimiter(")content(fair than she. Be not her maid, for she is envious! Her vestal )delimiter(")> operator(+) + string<delimiter(")content(livery is but sick and green, and none but fools do wear it. Cast )delimiter(")> operator(+) + string<delimiter(")content(it off!)delimiter(")> + operator(}) + reserved(end) + + reserved(def) method(use_helper_method)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(using helpers)delimiter(")> + ident(from) string<delimiter(")content(tester@example.com)delimiter(")> + pre_constant(self)operator(.)ident(body) operator(=) operator({) symbol(:text) operator(=)operator(>) string<delimiter(")content(emphasize me!)delimiter(")> operator(}) + reserved(end) + + ident(private) + + reserved(def) method(name_of_the_mailer_class) + pre_constant(self)operator(.)ident(class)operator(.)ident(name) + reserved(end) + ident(helper_method) symbol(:name_of_the_mailer_class) +reserved(end) + +constant(HelperMailer)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures)delimiter(")> + +reserved(class) class(MailerHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(new_mail)operator(() ident(charset)operator(=)string<delimiter(")content(utf-8)delimiter(")> operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + ident(mail)operator(.)ident(set_content_type) string<delimiter(")content(text)delimiter(")>operator(,) string<delimiter(")content(plain)delimiter(")>operator(,) operator({) string<delimiter(")content(charset)delimiter(")> operator(=)operator(>) ident(charset) operator(}) reserved(if) ident(charset) + ident(mail) + reserved(end) + + reserved(def) method(setup) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(delivery_method) operator(=) symbol(:test) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(perform_deliveries) operator(=) pre_constant(true) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries) operator(=) operator([)operator(]) + + instance_variable(@recipient) operator(=) string<delimiter(')content(test@localhost)delimiter(')> + reserved(end) + + reserved(def) method(test_use_helper) + ident(mail) operator(=) constant(HelperMailer)operator(.)ident(create_use_helper)operator(()instance_variable(@recipient)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content(Mr. Joe Person)delimiter(})>operator(,) ident(mail)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_use_test_helper) + ident(mail) operator(=) constant(HelperMailer)operator(.)ident(create_use_test_helper)operator(()instance_variable(@recipient)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content(<em><strong><small>emphasize me!)delimiter(})>operator(,) ident(mail)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_use_helper_method) + ident(mail) operator(=) constant(HelperMailer)operator(.)ident(create_use_helper_method)operator(()instance_variable(@recipient)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content(HelperMailer)delimiter(})>operator(,) ident(mail)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_use_mail_helper) + ident(mail) operator(=) constant(HelperMailer)operator(.)ident(create_use_mail_helper)operator(()instance_variable(@recipient)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content( But soft!)delimiter(})>operator(,) ident(mail)operator(.)ident(encoded) + ident(assert_match) regexp<delimiter(%r{)content(east, and)char(\\n)content( Juliet)delimiter(})>operator(,) ident(mail)operator(.)ident(encoded) + reserved(end) +reserved(end) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib/)delimiter(")>operator(\)) + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(action_mailer)delimiter(')> + +reserved(class) class(RenderMailer) operator(<) constant(ActionMailer)operator(::)constant(Base) + reserved(def) method(inline_template)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(using helpers)delimiter(")> + ident(from) string<delimiter(")content(tester@example.com)delimiter(")> + ident(body) ident(render)operator(()symbol(:inline) operator(=)operator(>) string<delimiter(")content(Hello, <%= @world %>)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) operator({) symbol(:world) operator(=)operator(>) string<delimiter(")content(Earth)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(file_template)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(using helpers)delimiter(")> + ident(from) string<delimiter(")content(tester@example.com)delimiter(")> + ident(body) ident(render)operator(()symbol(:file) operator(=)operator(>) string<delimiter(")content(signed_up)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) operator({) symbol(:recipient) operator(=)operator(>) ident(recipient) operator(})operator(\)) + reserved(end) + + reserved(def) method(initialize_defaults)operator(()ident(method_name)operator(\)) + reserved(super) + ident(mailer_name) string<delimiter(")content(test_mailer)delimiter(")> + reserved(end) +reserved(end) + +constant(RenderMailer)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures)delimiter(")> + +reserved(class) class(RenderHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(delivery_method) operator(=) symbol(:test) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(perform_deliveries) operator(=) pre_constant(true) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries) operator(=) operator([)operator(]) + + instance_variable(@recipient) operator(=) string<delimiter(')content(test@localhost)delimiter(')> + reserved(end) + + reserved(def) method(test_inline_template) + ident(mail) operator(=) constant(RenderMailer)operator(.)ident(create_inline_template)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) string<delimiter(")content(Hello, Earth)delimiter(")>operator(,) ident(mail)operator(.)ident(body)operator(.)ident(strip) + reserved(end) + + reserved(def) method(test_file_template) + ident(mail) operator(=) constant(RenderMailer)operator(.)ident(create_file_template)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) string<delimiter(")content(Hello there, )char(\\n)char(\\n)content(Mr. test@localhost)delimiter(")>operator(,) ident(mail)operator(.)ident(body)operator(.)ident(strip) + reserved(end) +reserved(end) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib/)delimiter(")>operator(\)) + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(action_mailer)delimiter(')> + +reserved(class) class(MockSMTP) + reserved(def) pre_constant(self)operator(.)ident(deliveries) + class_variable(@@deliveries) + reserved(end) + + reserved(def) method(initialize) + class_variable(@@deliveries) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(sendmail)operator(()ident(mail)operator(,) ident(from)operator(,) ident(to)operator(\)) + class_variable(@@deliveries) operator(<<) operator([)ident(mail)operator(,) ident(from)operator(,) ident(to)operator(]) + reserved(end) +reserved(end) + +reserved(class) class(Net::SMTP) + reserved(def) pre_constant(self)operator(.)ident(start)operator(()operator(*)ident(args)operator(\)) + reserved(yield) constant(MockSMTP)operator(.)ident(new) + reserved(end) +reserved(end) + +reserved(class) class(FunkyPathMailer) operator(<) constant(ActionMailer)operator(::)constant(Base) + pre_constant(self)operator(.)ident(template_root) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/path.with.dots)delimiter(")> + + reserved(def) method(multipart_with_template_path_with_dots)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(Have a lovely picture)delimiter(")> + ident(from) string<delimiter(")content(Chad Fowler <chad@chadfowler.com>)delimiter(")> + ident(attachment) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(image/jpeg)delimiter(")>operator(,) + symbol(:body) operator(=)operator(>) string<delimiter(")content(not really a jpeg, we're only testing, after all)delimiter(")> + reserved(end) + + reserved(def) method(template_path) + string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/path.with.dots)delimiter(")> + reserved(end) +reserved(end) + +reserved(class) class(TestMailer) operator(<) constant(ActionMailer)operator(::)constant(Base) + + reserved(def) method(signed_up)operator(()ident(recipient)operator(\)) + instance_variable(@recipients) operator(=) ident(recipient) + instance_variable(@subject) operator(=) string<delimiter(")content([Signed up] Welcome )inline<inline_delimiter(#{)ident(recipient)inline_delimiter(})>delimiter(")> + instance_variable(@from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + instance_variable(@sent_on) operator(=) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + instance_variable(@body)operator([)string<delimiter(")content(recipient)delimiter(")>operator(]) operator(=) ident(recipient) + reserved(end) + + reserved(def) method(cancelled_account)operator(()ident(recipient)operator(\)) + pre_constant(self)operator(.)ident(recipients) operator(=) ident(recipient) + pre_constant(self)operator(.)ident(subject) operator(=) string<delimiter(")content([Cancelled] Goodbye )inline<inline_delimiter(#{)ident(recipient)inline_delimiter(})>delimiter(")> + pre_constant(self)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + pre_constant(self)operator(.)ident(sent_on) operator(=) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + pre_constant(self)operator(.)ident(body) operator(=) string<delimiter(")content(Goodbye, Mr. )inline<inline_delimiter(#{)ident(recipient)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(cc_bcc)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(testing bcc/cc)delimiter(")> + ident(from) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(sent_on) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + ident(cc) string<delimiter(")content(nobody@loudthinking.com)delimiter(")> + ident(bcc) string<delimiter(")content(root@loudthinking.com)delimiter(")> + ident(body) string<delimiter(")content(Nothing to see here.)delimiter(")> + reserved(end) + + reserved(def) method(iso_charset)operator(()ident(recipient)operator(\)) + instance_variable(@recipients) operator(=) ident(recipient) + instance_variable(@subject) operator(=) string<delimiter(")content(testing isø charsets)delimiter(")> + instance_variable(@from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + instance_variable(@sent_on) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + instance_variable(@cc) operator(=) string<delimiter(")content(nobody@loudthinking.com)delimiter(")> + instance_variable(@bcc) operator(=) string<delimiter(")content(root@loudthinking.com)delimiter(")> + instance_variable(@body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + instance_variable(@charset) operator(=) string<delimiter(")content(iso-8859-1)delimiter(")> + reserved(end) + + reserved(def) method(unencoded_subject)operator(()ident(recipient)operator(\)) + instance_variable(@recipients) operator(=) ident(recipient) + instance_variable(@subject) operator(=) string<delimiter(")content(testing unencoded subject)delimiter(")> + instance_variable(@from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + instance_variable(@sent_on) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + instance_variable(@cc) operator(=) string<delimiter(")content(nobody@loudthinking.com)delimiter(")> + instance_variable(@bcc) operator(=) string<delimiter(")content(root@loudthinking.com)delimiter(")> + instance_variable(@body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + reserved(end) + + reserved(def) method(extended_headers)operator(()ident(recipient)operator(\)) + instance_variable(@recipients) operator(=) ident(recipient) + instance_variable(@subject) operator(=) string<delimiter(")content(testing extended headers)delimiter(")> + instance_variable(@from) operator(=) string<delimiter(")content(Grytøyr <stian1@example.net>)delimiter(")> + instance_variable(@sent_on) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + instance_variable(@cc) operator(=) string<delimiter(")content(Grytøyr <stian2@example.net>)delimiter(")> + instance_variable(@bcc) operator(=) string<delimiter(")content(Grytøyr <stian3@example.net>)delimiter(")> + instance_variable(@body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + instance_variable(@charset) operator(=) string<delimiter(")content(iso-8859-1)delimiter(")> + reserved(end) + + reserved(def) method(utf8_body)operator(()ident(recipient)operator(\)) + instance_variable(@recipients) operator(=) ident(recipient) + instance_variable(@subject) operator(=) string<delimiter(")content(testing utf-8 body)delimiter(")> + instance_variable(@from) operator(=) string<delimiter(")content(Foo áëô îü <extended@example.net>)delimiter(")> + instance_variable(@sent_on) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + instance_variable(@cc) operator(=) string<delimiter(")content(Foo áëô îü <extended@example.net>)delimiter(")> + instance_variable(@bcc) operator(=) string<delimiter(")content(Foo áëô îü <extended@example.net>)delimiter(")> + instance_variable(@body) operator(=) string<delimiter(")content(åœö blah)delimiter(")> + instance_variable(@charset) operator(=) string<delimiter(")content(utf-8)delimiter(")> + reserved(end) + + reserved(def) method(multipart_with_mime_version)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(multipart with mime_version)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(sent_on) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + ident(mime_version) string<delimiter(")content(1.1)delimiter(")> + ident(content_type) string<delimiter(")content(multipart/alternative)delimiter(")> + + ident(part) string<delimiter(")content(text/plain)delimiter(")> reserved(do) operator(|)ident(p)operator(|) + ident(p)operator(.)ident(body) operator(=) string<delimiter(")content(blah)delimiter(")> + reserved(end) + + ident(part) string<delimiter(")content(text/html)delimiter(")> reserved(do) operator(|)ident(p)operator(|) + ident(p)operator(.)ident(body) operator(=) string<delimiter(")content(<b>blah</b>)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(multipart_with_utf8_subject)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(Foo áëô îü)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(charset) string<delimiter(")content(utf-8)delimiter(")> + + ident(part) string<delimiter(")content(text/plain)delimiter(")> reserved(do) operator(|)ident(p)operator(|) + ident(p)operator(.)ident(body) operator(=) string<delimiter(")content(blah)delimiter(")> + reserved(end) + + ident(part) string<delimiter(")content(text/html)delimiter(")> reserved(do) operator(|)ident(p)operator(|) + ident(p)operator(.)ident(body) operator(=) string<delimiter(")content(<b>blah</b>)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(explicitly_multipart_example)operator(()ident(recipient)operator(,) ident(ct)operator(=)pre_constant(nil)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(multipart example)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(sent_on) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + ident(body) string<delimiter(")content(plain text default)delimiter(")> + ident(content_type) ident(ct) reserved(if) ident(ct) + + ident(part) string<delimiter(")content(text/html)delimiter(")> reserved(do) operator(|)ident(p)operator(|) + ident(p)operator(.)ident(charset) operator(=) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(p)operator(.)ident(body) operator(=) string<delimiter(")content(blah)delimiter(")> + reserved(end) + + ident(attachment) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(image/jpeg)delimiter(")>operator(,) symbol(:filename) operator(=)operator(>) string<delimiter(")content(foo.jpg)delimiter(")>operator(,) + symbol(:body) operator(=)operator(>) string<delimiter(")content(123456789)delimiter(")> + reserved(end) + + reserved(def) method(implicitly_multipart_example)operator(()ident(recipient)operator(,) ident(cs) operator(=) pre_constant(nil)operator(,) ident(order) operator(=) pre_constant(nil)operator(\)) + instance_variable(@recipients) operator(=) ident(recipient) + instance_variable(@subject) operator(=) string<delimiter(")content(multipart example)delimiter(")> + instance_variable(@from) operator(=) string<delimiter(")content(test@example.com)delimiter(")> + instance_variable(@sent_on) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + instance_variable(@body) operator(=) operator({) string<delimiter(")content(recipient)delimiter(")> operator(=)operator(>) ident(recipient) operator(}) + instance_variable(@charset) operator(=) ident(cs) reserved(if) ident(cs) + instance_variable(@implicit_parts_order) operator(=) ident(order) reserved(if) ident(order) + reserved(end) + + reserved(def) method(implicitly_multipart_with_utf8) + ident(recipients) string<delimiter(")content(no.one@nowhere.test)delimiter(")> + ident(subject) string<delimiter(")content(Foo áëô îü)delimiter(")> + ident(from) string<delimiter(")content(some.one@somewhere.test)delimiter(")> + ident(template) string<delimiter(")content(implicitly_multipart_example)delimiter(")> + ident(body) operator(()operator({) string<delimiter(")content(recipient)delimiter(")> operator(=)operator(>) string<delimiter(")content(no.one@nowhere.test)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(html_mail)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(html mail)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(body) string<delimiter(")content(<em>Emphasize</em> <strong>this</strong>)delimiter(")> + ident(content_type) string<delimiter(")content(text/html)delimiter(")> + reserved(end) + + reserved(def) method(html_mail_with_underscores)operator(()ident(recipient)operator(\)) + ident(subject) string<delimiter(")content(html mail with underscores)delimiter(")> + ident(body) string<delimiter(%{)content(<a href="http://google.com" target="_blank">_Google</a>)delimiter(})> + reserved(end) + + reserved(def) method(custom_template)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content([Signed up] Welcome )inline<inline_delimiter(#{)ident(recipient)inline_delimiter(})>delimiter(")> + ident(from) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(sent_on) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + ident(template) string<delimiter(")content(signed_up)delimiter(")> + + ident(body)operator([)string<delimiter(")content(recipient)delimiter(")>operator(]) operator(=) ident(recipient) + reserved(end) + + reserved(def) method(various_newlines)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(various newlines)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(body) string<delimiter(")content(line #1)char(\\n)content(line #2)char(\\r)content(line #3)char(\\r)char(\\n)content(line #4)char(\\r)char(\\r)delimiter(")> operator(+) + string<delimiter(")content(line #5)char(\\n)char(\\n)content(line#6)char(\\r)char(\\n)char(\\r)char(\\n)content(line #7)delimiter(")> + reserved(end) + + reserved(def) method(various_newlines_multipart)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(various newlines multipart)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(content_type) string<delimiter(")content(multipart/alternative)delimiter(")> + ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(text/plain)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(line #1)char(\\n)content(line #2)char(\\r)content(line #3)char(\\r)char(\\n)content(line #4)char(\\r)char(\\r)delimiter(")> + ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(text/html)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(<p>line #1</p>)char(\\n)content(<p>line #2</p>)char(\\r)content(<p>line #3</p>)char(\\r)char(\\n)content(<p>line #4</p>)char(\\r)char(\\r)delimiter(")> + reserved(end) + + reserved(def) method(nested_multipart)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(nested multipart)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(content_type) string<delimiter(")content(multipart/mixed)delimiter(")> + ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(multipart/alternative)delimiter(")>operator(,) symbol(:content_disposition) operator(=)operator(>) string<delimiter(")content(inline)delimiter(")> reserved(do) operator(|)ident(p)operator(|) + ident(p)operator(.)ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(text/plain)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(test text)char(\\n)content(line #2)delimiter(")> + ident(p)operator(.)ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(text/html)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(<b>test</b> HTML<br/>)char(\\n)content(line #2)delimiter(")> + reserved(end) + ident(attachment) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(application/octet-stream)delimiter(")>operator(,)symbol(:filename) operator(=)operator(>) string<delimiter(")content(test.txt)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(test abcdefghijklmnopqstuvwxyz)delimiter(")> + reserved(end) + + reserved(def) method(attachment_with_custom_header)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(custom header in attachment)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(content_type) string<delimiter(")content(multipart/related)delimiter(")> + ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(text/html)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(')content(yo)delimiter(')> + ident(attachment) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(image/jpeg)delimiter(")>operator(,)symbol(:filename) operator(=)operator(>) string<delimiter(")content(test.jpeg)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(i am not a real picture)delimiter(")>operator(,) symbol(:headers) operator(=)operator(>) operator({) string<delimiter(')content(Content-ID)delimiter(')> operator(=)operator(>) string<delimiter(')content(<test@test.com>)delimiter(')> operator(}) + reserved(end) + + reserved(def) method(unnamed_attachment)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(nested multipart)delimiter(")> + ident(from) string<delimiter(")content(test@example.com)delimiter(")> + ident(content_type) string<delimiter(")content(multipart/mixed)delimiter(")> + ident(part) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(text/plain)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(hullo)delimiter(")> + ident(attachment) symbol(:content_type) operator(=)operator(>) string<delimiter(")content(application/octet-stream)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(test abcdefghijklmnopqstuvwxyz)delimiter(")> + reserved(end) + + reserved(def) method(headers_with_nonalpha_chars)operator(()ident(recipient)operator(\)) + ident(recipients) ident(recipient) + ident(subject) string<delimiter(")content(nonalpha chars)delimiter(")> + ident(from) string<delimiter(")content(One: Two <test@example.com>)delimiter(")> + ident(cc) string<delimiter(")content(Three: Four <test@example.com>)delimiter(")> + ident(bcc) string<delimiter(")content(Five: Six <test@example.com>)delimiter(")> + ident(body) string<delimiter(")content(testing)delimiter(")> + reserved(end) + + reserved(def) method(custom_content_type_attributes) + ident(recipients) string<delimiter(")content(no.one@nowhere.test)delimiter(")> + ident(subject) string<delimiter(")content(custom content types)delimiter(")> + ident(from) string<delimiter(")content(some.one@somewhere.test)delimiter(")> + ident(content_type) string<delimiter(")content(text/plain; format=flowed)delimiter(")> + ident(body) string<delimiter(")content(testing)delimiter(")> + reserved(end) + + reserved(class) operator(<<)class(self) + ident(attr_accessor) symbol(:received_body) + reserved(end) + + reserved(def) method(receive)operator(()ident(mail)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(received_body) operator(=) ident(mail)operator(.)ident(body) + reserved(end) +reserved(end) + +constant(TestMailer)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures)delimiter(")> + +reserved(class) class(ActionMailerTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionMailer)operator(::)constant(Quoting) + + reserved(def) method(encode)operator(() ident(text)operator(,) ident(charset)operator(=)string<delimiter(")content(utf-8)delimiter(")> operator(\)) + ident(quoted_printable)operator(() ident(text)operator(,) ident(charset) operator(\)) + reserved(end) + + reserved(def) method(new_mail)operator(() ident(charset)operator(=)string<delimiter(")content(utf-8)delimiter(")> operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + reserved(if) ident(charset) + ident(mail)operator(.)ident(set_content_type) string<delimiter(")content(text)delimiter(")>operator(,) string<delimiter(")content(plain)delimiter(")>operator(,) operator({) string<delimiter(")content(charset)delimiter(")> operator(=)operator(>) ident(charset) operator(}) + reserved(end) + ident(mail) + reserved(end) + + reserved(def) method(setup) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(delivery_method) operator(=) symbol(:test) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(perform_deliveries) operator(=) pre_constant(true) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries) operator(=) operator([)operator(]) + + instance_variable(@recipient) operator(=) string<delimiter(')content(test@localhost)delimiter(')> + reserved(end) + + reserved(def) method(test_nested_parts) + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(created) operator(=) constant(TestMailer)operator(.)ident(create_nested_multipart)operator(()instance_variable(@recipient)operator(\))operator(}) + ident(assert_equal) integer(2)operator(,)ident(created)operator(.)ident(parts)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,)ident(created)operator(.)ident(parts)operator(.)ident(first)operator(.)ident(parts)operator(.)ident(size) + + ident(assert_equal) string<delimiter(")content(multipart/mixed)delimiter(")>operator(,) ident(created)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(multipart/alternative)delimiter(")>operator(,) ident(created)operator(.)ident(parts)operator(.)ident(first)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(text/plain)delimiter(")>operator(,) ident(created)operator(.)ident(parts)operator(.)ident(first)operator(.)ident(parts)operator(.)ident(first)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(text/html)delimiter(")>operator(,) ident(created)operator(.)ident(parts)operator(.)ident(first)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(application/octet-stream)delimiter(")>operator(,) ident(created)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(content_type) + reserved(end) + + reserved(def) method(test_attachment_with_custom_header) + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(created) operator(=) constant(TestMailer)operator(.)ident(create_attachment_with_custom_header)operator(()instance_variable(@recipient)operator(\))operator(}) + ident(assert_equal) string<delimiter(")content(<test@test.com>)delimiter(")>operator(,) ident(created)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(header)operator([)string<delimiter(')content(content-id)delimiter(')>operator(])operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_signed_up) + ident(expected) operator(=) ident(new_mail) + ident(expected)operator(.)ident(to) operator(=) instance_variable(@recipient) + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content([Signed up] Welcome )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Hello there, )char(\\n)char(\\n)content(Mr. )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(")> + ident(expected)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + ident(expected)operator(.)ident(mime_version) operator(=) pre_constant(nil) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(created) operator(=) constant(TestMailer)operator(.)ident(create_signed_up)operator(()instance_variable(@recipient)operator(\)) operator(}) + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + + ident(assert_nothing_raised) operator({) constant(TestMailer)operator(.)ident(deliver_signed_up)operator(()instance_variable(@recipient)operator(\)) operator(}) + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_custom_template) + ident(expected) operator(=) ident(new_mail) + ident(expected)operator(.)ident(to) operator(=) instance_variable(@recipient) + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content([Signed up] Welcome )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Hello there, )char(\\n)char(\\n)content(Mr. )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(")> + ident(expected)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(created) operator(=) constant(TestMailer)operator(.)ident(create_custom_template)operator(()instance_variable(@recipient)operator(\)) operator(}) + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_cancelled_account) + ident(expected) operator(=) ident(new_mail) + ident(expected)operator(.)ident(to) operator(=) instance_variable(@recipient) + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content([Cancelled] Goodbye )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Goodbye, Mr. )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(")> + ident(expected)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(12)operator(,) integer(12)operator(\)) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(created) operator(=) constant(TestMailer)operator(.)ident(create_cancelled_account)operator(()instance_variable(@recipient)operator(\)) operator(}) + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + + ident(assert_nothing_raised) operator({) constant(TestMailer)operator(.)ident(deliver_cancelled_account)operator(()instance_variable(@recipient)operator(\)) operator(}) + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_cc_bcc) + ident(expected) operator(=) ident(new_mail) + ident(expected)operator(.)ident(to) operator(=) instance_variable(@recipient) + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content(testing bcc/cc)delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + ident(expected)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(cc) operator(=) string<delimiter(")content(nobody@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(bcc) operator(=) string<delimiter(")content(root@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(created) operator(=) constant(TestMailer)operator(.)ident(create_cc_bcc) instance_variable(@recipient) + reserved(end) + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + + ident(assert_nothing_raised) reserved(do) + constant(TestMailer)operator(.)ident(deliver_cc_bcc) instance_variable(@recipient) + reserved(end) + + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_iso_charset) + ident(expected) operator(=) ident(new_mail)operator(() string<delimiter(")content(iso-8859-1)delimiter(")> operator(\)) + ident(expected)operator(.)ident(to) operator(=) instance_variable(@recipient) + ident(expected)operator(.)ident(subject) operator(=) ident(encode) string<delimiter(")content(testing isø charsets)delimiter(")>operator(,) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + ident(expected)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(cc) operator(=) string<delimiter(")content(nobody@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(bcc) operator(=) string<delimiter(")content(root@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(created) operator(=) constant(TestMailer)operator(.)ident(create_iso_charset) instance_variable(@recipient) + reserved(end) + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + + ident(assert_nothing_raised) reserved(do) + constant(TestMailer)operator(.)ident(deliver_iso_charset) instance_variable(@recipient) + reserved(end) + + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_unencoded_subject) + ident(expected) operator(=) ident(new_mail) + ident(expected)operator(.)ident(to) operator(=) instance_variable(@recipient) + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content(testing unencoded subject)delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + ident(expected)operator(.)ident(from) operator(=) string<delimiter(")content(system@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(cc) operator(=) string<delimiter(")content(nobody@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(bcc) operator(=) string<delimiter(")content(root@loudthinking.com)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(created) operator(=) constant(TestMailer)operator(.)ident(create_unencoded_subject) instance_variable(@recipient) + reserved(end) + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + + ident(assert_nothing_raised) reserved(do) + constant(TestMailer)operator(.)ident(deliver_unencoded_subject) instance_variable(@recipient) + reserved(end) + + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_instances_are_nil) + ident(assert_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(new) + ident(assert_nil) constant(TestMailer)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_deliveries_array) + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries) + ident(assert_equal) integer(0)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(size) + constant(TestMailer)operator(.)ident(deliver_signed_up)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) integer(1)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(size) + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_perform_deliveries_flag) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(perform_deliveries) operator(=) pre_constant(false) + constant(TestMailer)operator(.)ident(deliver_signed_up)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) integer(0)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(size) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(perform_deliveries) operator(=) pre_constant(true) + constant(TestMailer)operator(.)ident(deliver_signed_up)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) integer(1)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_unquote_quoted_printable_subject) + ident(msg) operator(=) string<delimiter(<<EOF)>string<content( +From: me@example.com +Subject: =?utf-8?Q?testing_testing_=D6=A4?= +Content-Type: text/plain; charset=iso-8859-1 + +The body)delimiter( +EOF)> + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(msg)operator(\)) + ident(assert_equal) string<delimiter(")content(testing testing )char(\\326)char(\\244)delimiter(")>operator(,) ident(mail)operator(.)ident(subject) + ident(assert_equal) string<delimiter(")content(=?utf-8?Q?testing_testing_=D6=A4?=)delimiter(")>operator(,) ident(mail)operator(.)ident(quoted_subject) + reserved(end) + + reserved(def) method(test_unquote_7bit_subject) + ident(msg) operator(=) string<delimiter(<<EOF)>string<content( +From: me@example.com +Subject: this == working? +Content-Type: text/plain; charset=iso-8859-1 + +The body)delimiter( +EOF)> + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(msg)operator(\)) + ident(assert_equal) string<delimiter(")content(this == working?)delimiter(")>operator(,) ident(mail)operator(.)ident(subject) + ident(assert_equal) string<delimiter(")content(this == working?)delimiter(")>operator(,) ident(mail)operator(.)ident(quoted_subject) + reserved(end) + + reserved(def) method(test_unquote_7bit_body) + ident(msg) operator(=) string<delimiter(<<EOF)>string<content( +From: me@example.com +Subject: subject +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 7bit + +The=3Dbody)delimiter( +EOF)> + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(msg)operator(\)) + ident(assert_equal) string<delimiter(")content(The=3Dbody)delimiter(")>operator(,) ident(mail)operator(.)ident(body)operator(.)ident(strip) + ident(assert_equal) string<delimiter(")content(The=3Dbody)delimiter(")>operator(,) ident(mail)operator(.)ident(quoted_body)operator(.)ident(strip) + reserved(end) + + reserved(def) method(test_unquote_quoted_printable_body) + ident(msg) operator(=) string<delimiter(<<EOF)>string<content( +From: me@example.com +Subject: subject +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: quoted-printable + +The=3Dbody)delimiter( +EOF)> + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(msg)operator(\)) + ident(assert_equal) string<delimiter(")content(The=body)delimiter(")>operator(,) ident(mail)operator(.)ident(body)operator(.)ident(strip) + ident(assert_equal) string<delimiter(")content(The=3Dbody)delimiter(")>operator(,) ident(mail)operator(.)ident(quoted_body)operator(.)ident(strip) + reserved(end) + + reserved(def) method(test_unquote_base64_body) + ident(msg) operator(=) string<delimiter(<<EOF)>string<content( +From: me@example.com +Subject: subject +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: base64 + +VGhlIGJvZHk=)delimiter( +EOF)> + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(msg)operator(\)) + ident(assert_equal) string<delimiter(")content(The body)delimiter(")>operator(,) ident(mail)operator(.)ident(body)operator(.)ident(strip) + ident(assert_equal) string<delimiter(")content(VGhlIGJvZHk=)delimiter(")>operator(,) ident(mail)operator(.)ident(quoted_body)operator(.)ident(strip) + reserved(end) + + reserved(def) method(test_extended_headers) + instance_variable(@recipient) operator(=) string<delimiter(")content(Grytøyr <test@localhost>)delimiter(")> + + ident(expected) operator(=) ident(new_mail) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(expected)operator(.)ident(to) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content(testing extended headers)delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(Nothing to see here.)delimiter(")> + ident(expected)operator(.)ident(from) operator(=) ident(quote_address_if_necessary) string<delimiter(")content(Grytøyr <stian1@example.net>)delimiter(")>operator(,) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(expected)operator(.)ident(cc) operator(=) ident(quote_address_if_necessary) string<delimiter(")content(Grytøyr <stian2@example.net>)delimiter(")>operator(,) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(expected)operator(.)ident(bcc) operator(=) ident(quote_address_if_necessary) string<delimiter(")content(Grytøyr <stian3@example.net>)delimiter(")>operator(,) string<delimiter(")content(iso-8859-1)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + + ident(created) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(created) operator(=) constant(TestMailer)operator(.)ident(create_extended_headers) instance_variable(@recipient) + reserved(end) + + ident(assert_not_nil) ident(created) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) ident(created)operator(.)ident(encoded) + + ident(assert_nothing_raised) reserved(do) + constant(TestMailer)operator(.)ident(deliver_extended_headers) instance_variable(@recipient) + reserved(end) + + ident(assert_not_nil) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first) + ident(assert_equal) ident(expected)operator(.)ident(encoded)operator(,) constant(ActionMailer)operator(::)constant(Base)operator(.)ident(deliveries)operator(.)ident(first)operator(.)ident(encoded) + reserved(end) + + reserved(def) method(test_utf8_body_is_not_quoted) + instance_variable(@recipient) operator(=) string<delimiter(")content(Foo áëô îü <extended@example.net>)delimiter(")> + ident(expected) operator(=) ident(new_mail) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(to) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content(testing utf-8 body)delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(åœö blah)delimiter(")> + ident(expected)operator(.)ident(from) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(cc) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(bcc) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + + ident(created) operator(=) constant(TestMailer)operator(.)ident(create_utf8_body) instance_variable(@recipient) + ident(assert_match)operator(()regexp<delimiter(/)content(åœö blah)delimiter(/)>operator(,) ident(created)operator(.)ident(encoded)operator(\)) + reserved(end) + + reserved(def) method(test_multiple_utf8_recipients) + instance_variable(@recipient) operator(=) operator([)string<delimiter(")char(\\")content(Foo áëô îü)char(\\")content( <extended@example.net>)delimiter(")>operator(,) string<delimiter(")char(\\")content(Example Recipient)char(\\")content( <me@example.com>)delimiter(")>operator(]) + ident(expected) operator(=) ident(new_mail) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(to) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(subject) operator(=) string<delimiter(")content(testing utf-8 body)delimiter(")> + ident(expected)operator(.)ident(body) operator(=) string<delimiter(")content(åœö blah)delimiter(")> + ident(expected)operator(.)ident(from) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(.)ident(first)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(cc) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(bcc) operator(=) ident(quote_address_if_necessary) instance_variable(@recipient)operator(,) string<delimiter(")content(utf-8)delimiter(")> + ident(expected)operator(.)ident(date) operator(=) constant(Time)operator(.)ident(local) integer(2004)operator(,) integer(12)operator(,) integer(12) + + ident(created) operator(=) constant(TestMailer)operator(.)ident(create_utf8_body) instance_variable(@recipient) + ident(assert_match)operator(()regexp<delimiter(/)char(\\n)content(From: =)char(\\?)content(utf-8)char(\\?)content(Q)char(\\?)content(Foo_.*?)char(\\?)content(= <extended@example.net>)char(\\r)delimiter(/)>operator(,) ident(created)operator(.)ident(encoded)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)char(\\n)content(To: =)char(\\?)content(utf-8)char(\\?)content(Q)char(\\?)content(Foo_.*?)char(\\?)content(= <extended@example.net>, Example Recipient <me)delimiter(/)>operator(,) ident(created)operator(.)ident(encoded)operator(\)) + reserved(end) + + reserved(def) method(test_receive_decodes_base64_encoded_mail) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email)delimiter(")>operator(\)) + constant(TestMailer)operator(.)ident(receive)operator(()ident(fixture)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(Jamis)delimiter(/)>operator(,) constant(TestMailer)operator(.)ident(received_body)operator(\)) + reserved(end) + + reserved(def) method(test_receive_attachments) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email2)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(attachment) operator(=) ident(mail)operator(.)ident(attachments)operator(.)ident(last) + ident(assert_equal) string<delimiter(")content(smime.p7s)delimiter(")>operator(,) ident(attachment)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(")content(application/pkcs7-signature)delimiter(")>operator(,) ident(attachment)operator(.)ident(content_type) + reserved(end) + + reserved(def) method(test_decode_attachment_without_charset) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email3)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(attachment) operator(=) ident(mail)operator(.)ident(attachments)operator(.)ident(last) + ident(assert_equal) integer(1026)operator(,) ident(attachment)operator(.)ident(read)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_attachment_using_content_location) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email12)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(mail)operator(.)ident(attachments)operator(.)ident(length) + ident(assert_equal) string<delimiter(")content(Photo25.jpg)delimiter(")>operator(,) ident(mail)operator(.)ident(attachments)operator(.)ident(first)operator(.)ident(original_filename) + reserved(end) + + reserved(def) method(test_attachment_with_text_type) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email13)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert) ident(mail)operator(.)ident(has_attachments?) + ident(assert_equal) integer(1)operator(,) ident(mail)operator(.)ident(attachments)operator(.)ident(length) + ident(assert_equal) string<delimiter(")content(hello.rb)delimiter(")>operator(,) ident(mail)operator(.)ident(attachments)operator(.)ident(first)operator(.)ident(original_filename) + reserved(end) + + reserved(def) method(test_decode_part_without_content_type) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email4)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_nothing_raised) operator({) ident(mail)operator(.)ident(body) operator(}) + reserved(end) + + reserved(def) method(test_decode_message_without_content_type) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email5)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_nothing_raised) operator({) ident(mail)operator(.)ident(body) operator(}) + reserved(end) + + reserved(def) method(test_decode_message_with_incorrect_charset) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email6)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_nothing_raised) operator({) ident(mail)operator(.)ident(body) operator(}) + reserved(end) + + reserved(def) method(test_multipart_with_mime_version) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_multipart_with_mime_version)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) string<delimiter(")content(1.1)delimiter(")>operator(,) ident(mail)operator(.)ident(mime_version) + reserved(end) + + reserved(def) method(test_multipart_with_utf8_subject) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_multipart_with_utf8_subject)operator(()instance_variable(@recipient)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)char(\\n)content(Subject: =)char(\\?)content(utf-8)char(\\?)content(Q)char(\\?)content(Foo_.*?)char(\\?)content(=)delimiter(/)>operator(,) ident(mail)operator(.)ident(encoded)operator(\)) + reserved(end) + + reserved(def) method(test_implicitly_multipart_with_utf8) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_implicitly_multipart_with_utf8) + ident(assert_match)operator(()regexp<delimiter(/)char(\\n)content(Subject: =)char(\\?)content(utf-8)char(\\?)content(Q)char(\\?)content(Foo_.*?)char(\\?)content(=)delimiter(/)>operator(,) ident(mail)operator(.)ident(encoded)operator(\)) + reserved(end) + + reserved(def) method(test_explicitly_multipart_messages) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_explicitly_multipart_example)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(mail)operator(.)ident(parts)operator(.)ident(length) + ident(assert_nil) ident(mail)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(text/plain)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(0)operator(])operator(.)ident(content_type) + + ident(assert_equal) string<delimiter(")content(text/html)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(iso-8859-1)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(inline)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(content_disposition) + + ident(assert_equal) string<delimiter(")content(image/jpeg)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(attachment)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(content_disposition) + ident(assert_equal) string<delimiter(")content(foo.jpg)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-disposition)delimiter(")>operator(,) string<delimiter(")content(filename)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(foo.jpg)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")>operator(\)) + ident(assert_nil) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_explicitly_multipart_with_content_type) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_explicitly_multipart_example)operator(()instance_variable(@recipient)operator(,) string<delimiter(")content(multipart/alternative)delimiter(")>operator(\)) + ident(assert_equal) integer(3)operator(,) ident(mail)operator(.)ident(parts)operator(.)ident(length) + ident(assert_equal) string<delimiter(")content(multipart/alternative)delimiter(")>operator(,) ident(mail)operator(.)ident(content_type) + reserved(end) + + reserved(def) method(test_explicitly_multipart_with_invalid_content_type) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_explicitly_multipart_example)operator(()instance_variable(@recipient)operator(,) string<delimiter(")content(text/xml)delimiter(")>operator(\)) + ident(assert_equal) integer(3)operator(,) ident(mail)operator(.)ident(parts)operator(.)ident(length) + ident(assert_nil) ident(mail)operator(.)ident(content_type) + reserved(end) + + reserved(def) method(test_implicitly_multipart_messages) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_implicitly_multipart_example)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(mail)operator(.)ident(parts)operator(.)ident(length) + ident(assert_equal) string<delimiter(")content(1.0)delimiter(")>operator(,) ident(mail)operator(.)ident(mime_version) + ident(assert_equal) string<delimiter(")content(multipart/alternative)delimiter(")>operator(,) ident(mail)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(text/yaml)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(0)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(utf-8)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(0)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(text/plain)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(utf-8)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(text/html)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(utf-8)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_implicitly_multipart_messages_with_custom_order) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_implicitly_multipart_example)operator(()instance_variable(@recipient)operator(,) pre_constant(nil)operator(,) operator([)string<delimiter(")content(text/yaml)delimiter(")>operator(,) string<delimiter(")content(text/plain)delimiter(")>operator(])operator(\)) + ident(assert_equal) integer(3)operator(,) ident(mail)operator(.)ident(parts)operator(.)ident(length) + ident(assert_equal) string<delimiter(")content(text/html)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(0)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(text/plain)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(content_type) + ident(assert_equal) string<delimiter(")content(text/yaml)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(content_type) + reserved(end) + + reserved(def) method(test_implicitly_multipart_messages_with_charset) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_implicitly_multipart_example)operator(()instance_variable(@recipient)operator(,) string<delimiter(')content(iso-8859-1)delimiter(')>operator(\)) + + ident(assert_equal) string<delimiter(")content(multipart/alternative)delimiter(")>operator(,) ident(mail)operator(.)ident(header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(body) + + ident(assert_equal) string<delimiter(')content(iso-8859-1)delimiter(')>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(0)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(')content(iso-8859-1)delimiter(')>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(')content(iso-8859-1)delimiter(')>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(2)operator(])operator(.)ident(sub_header)operator(()string<delimiter(")content(content-type)delimiter(")>operator(,) string<delimiter(")content(charset)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_html_mail) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_html_mail)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) string<delimiter(")content(text/html)delimiter(")>operator(,) ident(mail)operator(.)ident(content_type) + reserved(end) + + reserved(def) method(test_html_mail_with_underscores) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_html_mail_with_underscores)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) string<delimiter(%{)content(<a href="http://google.com" target="_blank">_Google</a>)delimiter(})>operator(,) ident(mail)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_various_newlines) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_various_newlines)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(line #1)char(\\n)content(line #2)char(\\n)content(line #3)char(\\n)content(line #4)char(\\n)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(line #5)char(\\n)char(\\n)content(line#6)char(\\n)char(\\n)content(line #7)delimiter(")>operator(,) ident(mail)operator(.)ident(body)operator(\)) + reserved(end) + + reserved(def) method(test_various_newlines_multipart) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_various_newlines_multipart)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) string<delimiter(")content(line #1)char(\\n)content(line #2)char(\\n)content(line #3)char(\\n)content(line #4)char(\\n)char(\\n)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(0)operator(])operator(.)ident(body) + ident(assert_equal) string<delimiter(")content(<p>line #1</p>)char(\\n)content(<p>line #2</p>)char(\\n)content(<p>line #3</p>)char(\\n)content(<p>line #4</p>)char(\\n)char(\\n)delimiter(")>operator(,) ident(mail)operator(.)ident(parts)operator([)integer(1)operator(])operator(.)ident(body) + reserved(end) + + reserved(def) method(test_headers_removed_on_smtp_delivery) + constant(ActionMailer)operator(::)constant(Base)operator(.)ident(delivery_method) operator(=) symbol(:smtp) + constant(TestMailer)operator(.)ident(deliver_cc_bcc)operator(()instance_variable(@recipient)operator(\)) + ident(assert) constant(MockSMTP)operator(.)ident(deliveries)operator([)integer(0)operator(])operator([)integer(2)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(root@loudthinking.com)delimiter(")>operator(\)) + ident(assert) constant(MockSMTP)operator(.)ident(deliveries)operator([)integer(0)operator(])operator([)integer(2)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(nobody@loudthinking.com)delimiter(")>operator(\)) + ident(assert) constant(MockSMTP)operator(.)ident(deliveries)operator([)integer(0)operator(])operator([)integer(2)operator(])operator(.)ident(include?)operator(()instance_variable(@recipient)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content(^Cc: nobody@loudthinking.com)delimiter(})>operator(,) constant(MockSMTP)operator(.)ident(deliveries)operator([)integer(0)operator(])operator([)integer(0)operator(]) + ident(assert_match) regexp<delimiter(%r{)content(^To: )inline<inline_delimiter(#{)instance_variable(@recipient)inline_delimiter(})>delimiter(})>operator(,) constant(MockSMTP)operator(.)ident(deliveries)operator([)integer(0)operator(])operator([)integer(0)operator(]) + ident(assert_no_match) regexp<delimiter(%r{)content(^Bcc: root@loudthinking.com)delimiter(})>operator(,) constant(MockSMTP)operator(.)ident(deliveries)operator([)integer(0)operator(])operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(test_recursive_multipart_processing) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email7)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_equal) string<delimiter(")content(This is the first part.)char(\\n)char(\\n)content(Attachment: test.rb)char(\\n)content(Attachment: test.pdf)char(\\n)char(\\n)char(\\n)content(Attachment: smime.p7s)char(\\n)delimiter(")>operator(,) ident(mail)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_decode_encoded_attachment_filename) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email8)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(attachment) operator(=) ident(mail)operator(.)ident(attachments)operator(.)ident(last) + ident(assert_equal) string<delimiter(")content(01QuienTeDijat.Pitbull.mp3)delimiter(")>operator(,) ident(attachment)operator(.)ident(original_filename) + reserved(end) + + reserved(def) method(test_wrong_mail_header) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email9)delimiter(")>operator(\)) + ident(assert_raise)operator(()constant(TMail)operator(::)constant(SyntaxError)operator(\)) operator({) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_decode_message_with_unknown_charset) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email10)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_nothing_raised) operator({) ident(mail)operator(.)ident(body) operator(}) + reserved(end) + + reserved(def) method(test_decode_message_with_unquoted_atchar_in_header) + ident(fixture) operator(=) constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/raw_email11)delimiter(")>operator(\)) + ident(mail) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(parse)operator(()ident(fixture)operator(\)) + ident(assert_not_nil) ident(mail)operator(.)ident(from) + reserved(end) + + reserved(def) method(test_empty_header_values_omitted) + ident(result) operator(=) constant(TestMailer)operator(.)ident(create_unnamed_attachment)operator(()instance_variable(@recipient)operator(\))operator(.)ident(encoded) + ident(assert_match) regexp<delimiter(%r{)content(Content-Type: application/octet-stream[^;])delimiter(})>operator(,) ident(result) + ident(assert_match) regexp<delimiter(%r{)content(Content-Disposition: attachment[^;])delimiter(})>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_headers_with_nonalpha_chars) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_headers_with_nonalpha_chars)operator(()instance_variable(@recipient)operator(\)) + ident(assert) operator(!)ident(mail)operator(.)ident(from_addrs)operator(.)ident(empty?) + ident(assert) operator(!)ident(mail)operator(.)ident(cc_addrs)operator(.)ident(empty?) + ident(assert) operator(!)ident(mail)operator(.)ident(bcc_addrs)operator(.)ident(empty?) + ident(assert_match)operator(()regexp<delimiter(/)content(:)delimiter(/)>operator(,) ident(mail)operator(.)ident(from_addrs)operator(.)ident(to_s)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(:)delimiter(/)>operator(,) ident(mail)operator(.)ident(cc_addrs)operator(.)ident(to_s)operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(:)delimiter(/)>operator(,) ident(mail)operator(.)ident(bcc_addrs)operator(.)ident(to_s)operator(\)) + reserved(end) + + reserved(def) method(test_deliver_with_mail_object) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_headers_with_nonalpha_chars)operator(()instance_variable(@recipient)operator(\)) + ident(assert_nothing_raised) operator({) constant(TestMailer)operator(.)ident(deliver)operator(()ident(mail)operator(\)) operator(}) + ident(assert_equal) integer(1)operator(,) constant(TestMailer)operator(.)ident(deliveries)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_multipart_with_template_path_with_dots) + ident(mail) operator(=) constant(FunkyPathMailer)operator(.)ident(create_multipart_with_template_path_with_dots)operator(()instance_variable(@recipient)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(mail)operator(.)ident(parts)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_custom_content_type_attributes) + ident(mail) operator(=) constant(TestMailer)operator(.)ident(create_custom_content_type_attributes) + ident(assert_match) regexp<delimiter(%r{)content(format=flowed)delimiter(})>operator(,) ident(mail)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(to_s) + ident(assert_match) regexp<delimiter(%r{)content(charset=utf-8)delimiter(})>operator(,) ident(mail)operator([)string<delimiter(')content(content-type)delimiter(')>operator(])operator(.)ident(to_s) + reserved(end) +reserved(end) + +reserved(class) class(InheritableTemplateRootTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_attr) + ident(expected) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/path.with.dots)delimiter(")> + ident(assert_equal) ident(expected)operator(,) constant(FunkyPathMailer)operator(.)ident(template_root) + + ident(sub) operator(=) constant(Class)operator(.)ident(new)operator(()constant(FunkyPathMailer)operator(\)) + ident(sub)operator(.)ident(template_root) operator(=) string<delimiter(')content(test/path)delimiter(')> + + ident(assert_equal) string<delimiter(')content(test/path)delimiter(')>operator(,) ident(sub)operator(.)ident(template_root) + ident(assert_equal) ident(expected)operator(,) constant(FunkyPathMailer)operator(.)ident(template_root) + reserved(end) +reserved(end) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib/)delimiter(")>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib/action_mailer/vendor)delimiter(")>operator(\)) + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(tmail)delimiter(')> +ident(require) string<delimiter(')content(tempfile)delimiter(')> + +reserved(class) class(QuotingTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_quote_multibyte_chars) + ident(original) operator(=) string<delimiter(")char(\\303)char(\\246)content( )char(\\303)char(\\270)content( and )char(\\303)char(\\245)delimiter(")> + + ident(result) operator(=) ident(execute_in_sandbox)operator(()string<delimiter(<<-CODE)>operator(\))string<content( + $:.unshift(File.dirname(__FILE__\) + "/../lib/"\) + $KCODE = 'u' + require 'jcode' + require 'action_mailer/quoting' + include ActionMailer::Quoting + quoted_printable()inline<inline_delimiter(#{)ident(original)operator(.)ident(inspect)inline_delimiter(})>content(, "UTF-8"\))delimiter( + CODE)> + + ident(unquoted) operator(=) constant(TMail)operator(::)constant(Unquoter)operator(.)ident(unquote_and_convert_to)operator(()ident(result)operator(,) pre_constant(nil)operator(\)) + ident(assert_equal) ident(unquoted)operator(,) ident(original) + reserved(end) + + ident(private) + + comment(# This whole thing *could* be much simpler, but I don't think Tempfile,) + comment(# popen and others exist on all platforms (like Windows\).) + reserved(def) method(execute_in_sandbox)operator(()ident(code)operator(\)) + ident(test_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/am-quoting-test.)inline<inline_delimiter(#{)global_variable($$)inline_delimiter(})>content(.rb)delimiter(")> + ident(res_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/am-quoting-test.)inline<inline_delimiter(#{)global_variable($$)inline_delimiter(})>content(.out)delimiter(")> + + constant(File)operator(.)ident(open)operator(()ident(test_name)operator(,) string<delimiter(")content(w+)delimiter(")>operator(\)) reserved(do) operator(|)ident(file)operator(|) + ident(file)operator(.)ident(write)operator(()string<delimiter(<<-CODE)>operator(\))string<content( + block = Proc.new do + )inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content( + end + puts block.call)delimiter( + CODE)> + reserved(end) + + ident(system)operator(()string<delimiter(")content(ruby )inline<inline_delimiter(#{)ident(test_name)inline_delimiter(})>content( > )inline<inline_delimiter(#{)ident(res_name)inline_delimiter(})>delimiter(")>operator(\)) reserved(or) ident(raise) string<delimiter(")content(could not run test in sandbox)delimiter(")> + constant(File)operator(.)ident(read)operator(()ident(res_name)operator(\)) + reserved(ensure) + constant(File)operator(.)ident(delete)operator(()ident(test_name)operator(\)) reserved(rescue) pre_constant(nil) + constant(File)operator(.)ident(delete)operator(()ident(res_name)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) +reserved(end) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib/)delimiter(")>operator(\)) +global_variable($:)operator(.)ident(unshift) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/helpers)delimiter(")> + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(action_mailer)delimiter(')> + +reserved(class) class(TMailMailTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_body) + ident(m) operator(=) constant(TMail)operator(::)constant(Mail)operator(.)ident(new) + ident(expected) operator(=) string<delimiter(')content(something_with_underscores)delimiter(')> + ident(m)operator(.)ident(encoding) operator(=) string<delimiter(')content(quoted-printable)delimiter(')> + ident(quoted_body) operator(=) operator([)ident(expected)operator(])operator(.)ident(pack)operator(()string<delimiter(')content(*M)delimiter(')>operator(\)) + ident(m)operator(.)ident(body) operator(=) ident(quoted_body) + ident(assert_equal) string<delimiter(")content(something_with_underscores=)char(\\n)delimiter(")>operator(,) ident(m)operator(.)ident(quoted_body) + ident(assert_equal) ident(expected)operator(,) ident(m)operator(.)ident(body) + reserved(end) +reserved(end) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib)delimiter(")>operator(\)) + +ident(require) string<delimiter(")content(action_controller)delimiter(")> +ident(require) string<delimiter(")content(action_controller/test_process)delimiter(")> + +constant(Person) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Person)delimiter(")>operator(,) symbol(:id)operator(,) symbol(:name)operator(,) symbol(:email_address)operator(,) symbol(:phone_number)operator(\)) + +reserved(class) class(AddressBookService) + ident(attr_reader) symbol(:people) + + reserved(def) method(initialize)operator(()operator(\)) instance_variable(@people) operator(=) operator([)operator(]) reserved(end) + reserved(def) method(create_person)operator(()ident(data)operator(\)) ident(people)operator(.)ident(unshift)operator(()constant(Person)operator(.)ident(new)operator(()ident(next_person_id)operator(,) ident(data)operator([)string<delimiter(")content(name)delimiter(")>operator(])operator(,) ident(data)operator([)string<delimiter(")content(email_address)delimiter(")>operator(])operator(,) ident(data)operator([)string<delimiter(")content(phone_number)delimiter(")>operator(])operator(\))operator(\)) reserved(end) + reserved(def) method(find_person)operator(()ident(topic_id)operator(\)) ident(people)operator(.)ident(select) operator({) operator(|)ident(person)operator(|) ident(person)operator(.)ident(id) operator(==) ident(person)operator(.)ident(to_i) operator(})operator(.)ident(first) reserved(end) + reserved(def) method(next_person_id)operator(()operator(\)) ident(people)operator(.)ident(first)operator(.)ident(id) operator(+) integer(1) reserved(end) +reserved(end) + +reserved(class) class(AddressBookController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(layout) string<delimiter(")content(address_book/layout)delimiter(")> + + ident(before_filter) symbol(:initialize_session_storage) + + comment(# Could also have used a proc) + comment(# before_filter proc { |c| c.instance_variable_set("@address_book", c.session["address_book"] ||= AddressBookService.new\) } ) + + reserved(def) method(index) + instance_variable(@title) operator(=) string<delimiter(")content(Address Book)delimiter(")> + instance_variable(@people) operator(=) instance_variable(@address_book)operator(.)ident(people) + reserved(end) + + reserved(def) method(person) + instance_variable(@person) operator(=) instance_variable(@address_book)operator(.)ident(find_person)operator(()instance_variable(@params)operator([)string<delimiter(")content(id)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(def) method(create_person) + instance_variable(@address_book)operator(.)ident(create_person)operator(()instance_variable(@params)operator([)string<delimiter(")content(person)delimiter(")>operator(])operator(\)) + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(index)delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(initialize_session_storage) + instance_variable(@address_book) operator(=) instance_variable(@session)operator([)string<delimiter(")content(address_book)delimiter(")>operator(]) operator(||=) constant(AddressBookService)operator(.)ident(new) + reserved(end) +reserved(end) + +constant(ActionController)operator(::)constant(Base)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) +comment(# ActionController::Base.logger = Logger.new("debug.log"\) # Remove first comment to turn on logging in current dir) + +reserved(begin) + constant(AddressBookController)operator(.)ident(process_cgi)operator(()constant(CGI)operator(.)ident(new)operator(\)) reserved(if) global_variable($0) operator(==) pre_constant(__FILE__) +reserved(rescue) operator(=)operator(>) ident(e) + constant(CGI)operator(.)ident(new)operator(.)ident(out) operator({) string<delimiter(")inline<inline_delimiter(#{)ident(e)operator(.)ident(class)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>delimiter(")> operator(}) +reserved(end)global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../lib)delimiter(")>operator(\)) + +ident(require) string<delimiter(")content(action_controller)delimiter(")> +ident(require) string<delimiter(')content(action_controller/test_process)delimiter(')> + +constant(Person) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Person)delimiter(")>operator(,) symbol(:name)operator(,) symbol(:address)operator(,) symbol(:age)operator(\)) + +reserved(class) class(BenchmarkController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(message) + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(list) + instance_variable(@people) operator(=) operator([) constant(Person)operator(.)ident(new)operator(()string<delimiter(")content(David)delimiter(")>operator(\))operator(,) constant(Person)operator(.)ident(new)operator(()string<delimiter(")content(Mary)delimiter(")>operator(\)) operator(]) + ident(render_template) string<delimiter(")content(hello: <% for person in @people %>Name: <%= person.name %><% end %>)delimiter(")> + reserved(end) + + reserved(def) method(form_helper) + instance_variable(@person) operator(=) constant(Person)operator(.)ident(new) string<delimiter(")content(david)delimiter(")>operator(,) string<delimiter(")content(hyacintvej)delimiter(")>operator(,) integer(24) + ident(render_template)operator(() + string<delimiter(")content(<% person = Person.new 'Mary', 'hyacintvej', 22 %> )delimiter(")> operator(+) + string<delimiter(")content(change the name <%= text_field 'person', 'name' %> and <%= text_field 'person', 'address' %> and <%= text_field 'person', 'age' %>)delimiter(")> + operator(\)) + reserved(end) +reserved(end) + +comment(#ActionController::Base.template_root = File.dirname(__FILE__\)) + +ident(require) string<delimiter(")content(benchmark)delimiter(")> + +constant(RUNS) operator(=) pre_constant(ARGV)operator([)integer(0)operator(]) operator(?) pre_constant(ARGV)operator([)integer(0)operator(])operator(.)ident(to_i) operator(:) integer(50) + +ident(require) string<delimiter(")content(profile)delimiter(")> reserved(if) pre_constant(ARGV)operator([)integer(1)operator(]) + +ident(runtime) operator(=) constant(Benchmark)operator(.)ident(measure) operator({) + constant(RUNS)operator(.)ident(times) operator({) constant(BenchmarkController)operator(.)ident(process_test)operator(()constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(()operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(list)delimiter(")> operator(})operator(\))operator(\)) operator(}) +operator(}) + +ident(puts) string<delimiter(")content(List: )inline<inline_delimiter(#{)constant(RUNS) operator(/) ident(runtime)operator(.)ident(real)inline_delimiter(})>delimiter(")> + + +ident(runtime) operator(=) constant(Benchmark)operator(.)ident(measure) operator({) + constant(RUNS)operator(.)ident(times) operator({) constant(BenchmarkController)operator(.)ident(process_test)operator(()constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(()operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(message)delimiter(")> operator(})operator(\))operator(\)) operator(}) +operator(}) + +ident(puts) string<delimiter(")content(Message: )inline<inline_delimiter(#{)constant(RUNS) operator(/) ident(runtime)operator(.)ident(real)inline_delimiter(})>delimiter(")> + +ident(runtime) operator(=) constant(Benchmark)operator(.)ident(measure) operator({) + constant(RUNS)operator(.)ident(times) operator({) constant(BenchmarkController)operator(.)ident(process_test)operator(()constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(()operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(form_helper)delimiter(")> operator(})operator(\))operator(\)) operator(}) +operator(}) + +ident(puts) string<delimiter(")content(Form helper: )inline<inline_delimiter(#{)constant(RUNS) operator(/) ident(runtime)operator(.)ident(real)inline_delimiter(})>delimiter(")> +ident(require) string<delimiter(')content(rbconfig)delimiter(')> +ident(require) string<delimiter(')content(find)delimiter(')> +ident(require) string<delimiter(')content(ftools)delimiter(')> + +ident(include) constant(Config) + +comment(# this was adapted from rdoc's install.rb by ways of Log4r) + +global_variable($sitedir) operator(=) constant(CONFIG)operator([)string<delimiter(")content(sitelibdir)delimiter(")>operator(]) +reserved(unless) global_variable($sitedir) + ident(version) operator(=) constant(CONFIG)operator([)string<delimiter(")content(MAJOR)delimiter(")>operator(]) operator(+) string<delimiter(")content(.)delimiter(")> operator(+) constant(CONFIG)operator([)string<delimiter(")content(MINOR)delimiter(")>operator(]) + global_variable($libdir) operator(=) constant(File)operator(.)ident(join)operator(()constant(CONFIG)operator([)string<delimiter(")content(libdir)delimiter(")>operator(])operator(,) string<delimiter(")content(ruby)delimiter(")>operator(,) ident(version)operator(\)) + global_variable($sitedir) operator(=) global_variable($:)operator(.)ident(find) operator({)operator(|)ident(x)operator(|) ident(x) operator(=)operator(~) regexp<delimiter(/)content(site_ruby)delimiter(/)> operator(}) + reserved(if) operator(!)global_variable($sitedir) + global_variable($sitedir) operator(=) constant(File)operator(.)ident(join)operator(()global_variable($libdir)operator(,) string<delimiter(")content(site_ruby)delimiter(")>operator(\)) + reserved(elsif) global_variable($sitedir) operator(!)operator(~) constant(Regexp)operator(.)ident(quote)operator(()ident(version)operator(\)) + global_variable($sitedir) operator(=) constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) ident(version)operator(\)) + reserved(end) +reserved(end) + +comment(# the acual gruntwork) +constant(Dir)operator(.)ident(chdir)operator(()string<delimiter(")content(lib)delimiter(")>operator(\)) + +constant(Find)operator(.)ident(find)operator(()string<delimiter(")content(action_controller)delimiter(")>operator(,) string<delimiter(")content(action_controller.rb)delimiter(")>operator(,) string<delimiter(")content(action_view)delimiter(")>operator(,) string<delimiter(")content(action_view.rb)delimiter(")>operator(\)) operator({) operator(|)ident(f)operator(|) + reserved(if) ident(f)operator([)integer(-3)operator(..)integer(-1)operator(]) operator(==) string<delimiter(")content(.rb)delimiter(")> + constant(File)operator(::)ident(install)operator(()ident(f)operator(,) constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) operator(*)ident(f)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator(\))operator(,) integer(0644)operator(,) pre_constant(true)operator(\)) + reserved(else) + constant(File)operator(::)ident(makedirs)operator(()constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) operator(*)ident(f)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator(\))operator(\)) + reserved(end) +operator(})ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(test/unit/assertions)delimiter(')> +ident(require) string<delimiter(')content(rexml/document)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/vendor/html-scanner/html/document)delimiter(")> + +reserved(module) class(Test) comment(#:nodoc:) + reserved(module) class(Unit) comment(#:nodoc:) + comment(# In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions) + comment(# can be used against. These collections are:) + comment(#) + comment(# * assigns: Instance variables assigned in the action that are available for the view.) + comment(# * session: Objects being saved in the session.) + comment(# * flash: The flash objects currently in the session.) + comment(# * cookies: Cookies being sent to the user on this request.) + comment(# ) + comment(# These collections can be used just like any other hash:) + comment(#) + comment(# assert_not_nil assigns(:person\) # makes sure that a @person instance variable was set) + comment(# assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave") + comment(# assert flash.empty? # makes sure that there's nothing in the flash) + comment(#) + comment(# For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To) + comment(# appease our yearning for symbols, though, an alternative accessor has been deviced using a method call instead of index referencing.) + comment(# So assigns(:person\) will work just like assigns["person"], but again, assigns[:person] will not work.) + comment(#) + comment(# On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url.) + comment(#) + comment(# For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another) + comment(# action call which can then be asserted against.) + comment(#) + comment(# == Manipulating the request collections) + comment(#) + comment(# The collections described above link to the response, so you can test if what the actions were expected to do happened. But) + comment(# sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions) + comment(# and cookies, though. For sessions, you just do:) + comment(#) + comment(# @request.session[:key] = "value") + comment(#) + comment(# For cookies, you need to manually create the cookie, like this:) + comment(#) + comment(# @request.cookies["key"] = CGI::Cookie.new("key", "value"\)) + comment(#) + comment(# == Testing named routes) + comment(#) + comment(# If you're using named routes, they can be easily tested using the original named routes methods straight in the test case.) + comment(# Example: ) + comment(#) + comment(# assert_redirected_to page_url(:title => 'foo'\)) + reserved(module) class(Assertions) + comment(# Asserts that the response is one of the following types:) + comment(# ) + comment(# * <tt>:success</tt>: Status code was 200) + comment(# * <tt>:redirect</tt>: Status code was in the 300-399 range) + comment(# * <tt>:missing</tt>: Status code was 404) + comment(# * <tt>:error</tt>: Status code was in the 500-599 range) + comment(#) + comment(# You can also pass an explicit status code number as the type, like assert_response(501\)) + reserved(def) method(assert_response)operator(()ident(type)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) + ident(clean_backtrace) reserved(do) + reserved(if) operator([) symbol(:success)operator(,) symbol(:missing)operator(,) symbol(:redirect)operator(,) symbol(:error) operator(])operator(.)ident(include?)operator(()ident(type)operator(\)) operator(&&) instance_variable(@response)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(type)inline_delimiter(})>content(?)delimiter(")>operator(\)) + ident(assert_block)operator(()string<delimiter(")delimiter(")>operator(\)) operator({) pre_constant(true) operator(}) comment(# to count the assertion) + reserved(elsif) ident(type)operator(.)ident(is_a?)operator(()constant(Fixnum)operator(\)) operator(&&) instance_variable(@response)operator(.)ident(response_code) operator(==) ident(type) + ident(assert_block)operator(()string<delimiter(")delimiter(")>operator(\)) operator({) pre_constant(true) operator(}) comment(# to count the assertion) + reserved(else) + ident(assert_block)operator(()ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(Expected response to be a <?>, but was <?>)delimiter(")>operator(,) ident(type)operator(,) instance_variable(@response)operator(.)ident(response_code)operator(\))operator(\)) operator({) pre_constant(false) operator(}) + reserved(end) + reserved(end) + reserved(end) + + comment(# Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial,) + comment(# such that assert_redirected_to(:controller => "weblog"\) will also match the redirection of ) + comment(# redirect_to(:controller => "weblog", :action => "show"\) and so on.) + reserved(def) method(assert_redirected_to)operator(()ident(options) operator(=) operator({)operator(})operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) + ident(clean_backtrace) reserved(do) + ident(assert_response)operator(()symbol(:redirect)operator(,) ident(message)operator(\)) + + reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(expected a redirect to <?>, found one to <?>)delimiter(")>operator(,) ident(options)operator(,) instance_variable(@response)operator(.)ident(redirect_url)operator(\)) + ident(url_regexp) operator(=) regexp<delimiter(%r{)content(^()char(\\w)content(+://.*?(/|$|)char(\\?)content(\)\)(.*\)$)delimiter(})> + ident(eurl)operator(,) ident(epath)operator(,) ident(url)operator(,) ident(path) operator(=) operator([)ident(options)operator(,) instance_variable(@response)operator(.)ident(redirect_url)operator(])operator(.)ident(collect) reserved(do) operator(|)ident(url)operator(|) + ident(u)operator(,) ident(p) operator(=) operator(()ident(url_regexp) operator(=)operator(~) ident(url)operator(\)) operator(?) operator([)global_variable($1)operator(,) global_variable($3)operator(]) operator(:) operator([)pre_constant(nil)operator(,) ident(url)operator(]) + operator([)ident(u)operator(,) operator(()ident(p)operator([)integer(0)operator(..)integer(0)operator(]) operator(==) string<delimiter(')content(/)delimiter(')>operator(\)) operator(?) ident(p) operator(:) string<delimiter(')content(/)delimiter(')> operator(+) ident(p)operator(]) + reserved(end)operator(.)ident(flatten) + + ident(assert_equal)operator(()ident(eurl)operator(,) ident(url)operator(,) ident(msg)operator(\)) reserved(if) ident(eurl) operator(&&) ident(url) + ident(assert_equal)operator(()ident(epath)operator(,) ident(path)operator(,) ident(msg)operator(\)) reserved(if) ident(epath) operator(&&) ident(path) + reserved(else) + instance_variable(@response_diff) operator(=) ident(options)operator(.)ident(diff)operator(()instance_variable(@response)operator(.)ident(redirected_to)operator(\)) reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(&&) instance_variable(@response)operator(.)ident(redirected_to)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(response is not a redirection to all of the options supplied (redirection is <?>\))inline<inline_delimiter(#{)string<delimiter(')content(, difference: <?>)delimiter(')> reserved(if) instance_variable(@response_diff)inline_delimiter(})>delimiter(")>operator(,) + instance_variable(@response)operator(.)ident(redirected_to) operator(||) instance_variable(@response)operator(.)ident(redirect_url)operator(,) instance_variable(@response_diff)operator(\)) + + ident(assert_block)operator(()ident(msg)operator(\)) reserved(do) + reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + instance_variable(@response)operator(.)ident(redirected_to) operator(==) ident(options) + reserved(else) + ident(options)operator(.)ident(keys)operator(.)ident(all?) reserved(do) operator(|)ident(k)operator(|) + reserved(if) ident(k) operator(==) symbol(:controller) reserved(then) ident(options)operator([)ident(k)operator(]) operator(==) constant(ActionController)operator(::)constant(Routing)operator(.)ident(controller_relative_to)operator(()instance_variable(@response)operator(.)ident(redirected_to)operator([)ident(k)operator(])operator(,) instance_variable(@controller)operator(.)ident(class)operator(.)ident(controller_path)operator(\)) + reserved(else) ident(options)operator([)ident(k)operator(]) operator(==) operator(()instance_variable(@response)operator(.)ident(redirected_to)operator([)ident(k)operator(])operator(.)ident(respond_to?)operator(()symbol(:to_param)operator(\)) operator(?) instance_variable(@response)operator(.)ident(redirected_to)operator([)ident(k)operator(])operator(.)ident(to_param) operator(:) instance_variable(@response)operator(.)ident(redirected_to)operator([)ident(k)operator(]) reserved(unless) instance_variable(@response)operator(.)ident(redirected_to)operator([)ident(k)operator(])operator(.)ident(nil?)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Asserts that the request was rendered with the appropriate template file.) + reserved(def) method(assert_template)operator(()ident(expected) operator(=) pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) + ident(clean_backtrace) reserved(do) + ident(rendered) operator(=) ident(expected) operator(?) instance_variable(@response)operator(.)ident(rendered_file)operator(()operator(!)ident(expected)operator(.)ident(include?)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator(\)) operator(:) instance_variable(@response)operator(.)ident(rendered_file) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(expecting <?> but rendering with <?>)delimiter(")>operator(,) ident(expected)operator(,) ident(rendered)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) reserved(do) + reserved(if) ident(expected)operator(.)ident(nil?) + operator(!)instance_variable(@response)operator(.)ident(rendered_with_file?) + reserved(else) + ident(expected) operator(==) ident(rendered) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Asserts that the routing of the given path was handled correctly and that the parsed options match.) + reserved(def) method(assert_recognizes)operator(()ident(expected_options)operator(,) ident(path)operator(,) ident(extras)operator(=)operator({)operator(})operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) + ident(clean_backtrace) reserved(do) + ident(path) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")> reserved(unless) ident(path)operator([)integer(0)operator(..)integer(0)operator(]) operator(==) string<delimiter(')content(/)delimiter(')> + comment(# Load routes.rb if it hasn't been loaded.) + constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(reload) reserved(if) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(empty?) + + comment(# Assume given controller) + ident(request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(()operator({)operator(})operator(,) operator({)operator(})operator(,) pre_constant(nil)operator(\)) + ident(request)operator(.)ident(path) operator(=) ident(path) + constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(recognize!)operator(()ident(request)operator(\)) + + ident(expected_options) operator(=) ident(expected_options)operator(.)ident(clone) + ident(extras)operator(.)ident(each_key) operator({) operator(|)ident(key)operator(|) ident(expected_options)operator(.)ident(delete) ident(key) operator(}) reserved(unless) ident(extras)operator(.)ident(nil?) + + ident(expected_options)operator(.)ident(stringify_keys!) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(The recognized options <?> did not match <?>)delimiter(")>operator(,) + ident(request)operator(.)ident(path_parameters)operator(,) ident(expected_options)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(request)operator(.)ident(path_parameters) operator(==) ident(expected_options) operator(}) + reserved(end) + reserved(end) + + comment(# Asserts that the provided options can be used to generate the provided path.) + reserved(def) method(assert_generates)operator(()ident(expected_path)operator(,) ident(options)operator(,) ident(defaults)operator(=)operator({)operator(})operator(,) ident(extras) operator(=) operator({)operator(})operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) + ident(clean_backtrace) reserved(do) + ident(expected_path) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(expected_path)inline_delimiter(})>delimiter(")> reserved(unless) ident(expected_path)operator([)integer(0)operator(]) operator(==) integer(?/) + comment(# Load routes.rb if it hasn't been loaded.) + constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(reload) reserved(if) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(empty?) + + ident(generated_path)operator(,) ident(extra_keys) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(generate)operator(()ident(options)operator(,) ident(extras)operator(\)) + ident(found_extras) operator(=) ident(options)operator(.)ident(reject) operator({)operator(|)ident(k)operator(,) ident(v)operator(|) operator(!) ident(extra_keys)operator(.)ident(include?) ident(k)operator(}) + + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(found extras <?>, not <?>)delimiter(")>operator(,) ident(found_extras)operator(,) ident(extras)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(found_extras) operator(==) ident(extras) operator(}) + + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(The generated path <?> did not match <?>)delimiter(")>operator(,) ident(generated_path)operator(,) + ident(expected_path)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(expected_path) operator(==) ident(generated_path) operator(}) + reserved(end) + reserved(end) + + comment(# Asserts that path and options match both ways; in other words, the URL generated from ) + comment(# options is the same as path, and also that the options recognized from path are the same as options) + reserved(def) method(assert_routing)operator(()ident(path)operator(,) ident(options)operator(,) ident(defaults)operator(=)operator({)operator(})operator(,) ident(extras)operator(=)operator({)operator(})operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) + ident(assert_recognizes)operator(()ident(options)operator(,) ident(path)operator(,) ident(extras)operator(,) ident(message)operator(\)) + + ident(controller)operator(,) ident(default_controller) operator(=) ident(options)operator([)symbol(:controller)operator(])operator(,) ident(defaults)operator([)symbol(:controller)operator(]) + reserved(if) ident(controller) operator(&&) ident(controller)operator(.)ident(include?)operator(()integer(?/)operator(\)) operator(&&) ident(default_controller) operator(&&) ident(default_controller)operator(.)ident(include?)operator(()integer(?/)operator(\)) + ident(options)operator([)symbol(:controller)operator(]) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(controller)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(assert_generates)operator(()ident(path)operator(,) ident(options)operator(,) ident(defaults)operator(,) ident(extras)operator(,) ident(message)operator(\)) + reserved(end) + + comment(# Asserts that there is a tag/node/element in the body of the response) + comment(# that meets all of the given conditions. The +conditions+ parameter must) + comment(# be a hash of any of the following keys (all are optional\):) + comment(#) + comment(# * <tt>:tag</tt>: the node type must match the corresponding value) + comment(# * <tt>:attributes</tt>: a hash. The node's attributes must match the) + comment(# corresponding values in the hash.) + comment(# * <tt>:parent</tt>: a hash. The node's parent must match the) + comment(# corresponding hash.) + comment(# * <tt>:child</tt>: a hash. At least one of the node's immediate children) + comment(# must meet the criteria described by the hash.) + comment(# * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must) + comment(# meet the criteria described by the hash.) + comment(# * <tt>:descendant</tt>: a hash. At least one of the node's descendants) + comment(# must meet the criteria described by the hash.) + comment(# * <tt>:sibling</tt>: a hash. At least one of the node's siblings must) + comment(# meet the criteria described by the hash.) + comment(# * <tt>:after</tt>: a hash. The node must be after any sibling meeting) + comment(# the criteria described by the hash, and at least one sibling must match.) + comment(# * <tt>:before</tt>: a hash. The node must be before any sibling meeting) + comment(# the criteria described by the hash, and at least one sibling must match.) + comment(# * <tt>:children</tt>: a hash, for counting children of a node. Accepts) + comment(# the keys:) + comment(# * <tt>:count</tt>: either a number or a range which must equal (or) + comment(# include\) the number of children that match.) + comment(# * <tt>:less_than</tt>: the number of matching children must be less) + comment(# than this number.) + comment(# * <tt>:greater_than</tt>: the number of matching children must be) + comment(# greater than this number.) + comment(# * <tt>:only</tt>: another hash consisting of the keys to use) + comment(# to match on the children, and only matching children will be) + comment(# counted.) + comment(# * <tt>:content</tt>: the textual content of the node must match the) + comment(# given value. This will not match HTML tags in the body of a) + comment(# tag--only text.) + comment(#) + comment(# Conditions are matched using the following algorithm:) + comment(#) + comment(# * if the condition is a string, it must be a substring of the value.) + comment(# * if the condition is a regexp, it must match the value.) + comment(# * if the condition is a number, the value must match number.to_s.) + comment(# * if the condition is +true+, the value must not be +nil+.) + comment(# * if the condition is +false+ or +nil+, the value must be +nil+.) + comment(#) + comment(# Usage:) + comment(#) + comment(# # assert that there is a "span" tag) + comment(# assert_tag :tag => "span") + comment(#) + comment(# # assert that there is a "span" tag with id="x") + comment(# assert_tag :tag => "span", :attributes => { :id => "x" }) + comment(#) + comment(# # assert that there is a "span" tag using the short-hand) + comment(# assert_tag :span) + comment(#) + comment(# # assert that there is a "span" tag with id="x" using the short-hand) + comment(# assert_tag :span, :attributes => { :id => "x" }) + comment(#) + comment(# # assert that there is a "span" inside of a "div") + comment(# assert_tag :tag => "span", :parent => { :tag => "div" }) + comment(#) + comment(# # assert that there is a "span" somewhere inside a table) + comment(# assert_tag :tag => "span", :ancestor => { :tag => "table" }) + comment(#) + comment(# # assert that there is a "span" with at least one "em" child) + comment(# assert_tag :tag => "span", :child => { :tag => "em" }) + comment(#) + comment(# # assert that there is a "span" containing a (possibly nested\)) + comment(# # "strong" tag.) + comment(# assert_tag :tag => "span", :descendant => { :tag => "strong" }) + comment(#) + comment(# # assert that there is a "span" containing between 2 and 4 "em" tags) + comment(# # as immediate children) + comment(# assert_tag :tag => "span",) + comment(# :children => { :count => 2..4, :only => { :tag => "em" } } ) + comment(#) + comment(# # get funky: assert that there is a "div", with an "ul" ancestor) + comment(# # and an "li" parent (with "class" = "enum"\), and containing a ) + comment(# # "span" descendant that contains text matching /hello world/) + comment(# assert_tag :tag => "div",) + comment(# :ancestor => { :tag => "ul" },) + comment(# :parent => { :tag => "li",) + comment(# :attributes => { :class => "enum" } },) + comment(# :descendant => { :tag => "span",) + comment(# :child => /hello world/ }) + comment(#) + comment(# <strong>Please note</strong: #assert_tag and #assert_no_tag only work) + comment(# with well-formed XHTML. They recognize a few tags as implicitly self-closing) + comment(# (like br and hr and such\) but will not work correctly with tags) + comment(# that allow optional closing tags (p, li, td\). <em>You must explicitly) + comment(# close all of your tags to use these assertions.</em>) + reserved(def) method(assert_tag)operator(()operator(*)ident(opts)operator(\)) + ident(clean_backtrace) reserved(do) + ident(opts) operator(=) ident(opts)operator(.)ident(size) operator(>) integer(1) operator(?) ident(opts)operator(.)ident(last)operator(.)ident(merge)operator(()operator({) symbol(:tag) operator(=)operator(>) ident(opts)operator(.)ident(first)operator(.)ident(to_s) operator(})operator(\)) operator(:) ident(opts)operator(.)ident(first) + ident(tag) operator(=) ident(find_tag)operator(()ident(opts)operator(\)) + ident(assert) ident(tag)operator(,) string<delimiter(")content(expected tag, but no tag found matching )inline<inline_delimiter(#{)ident(opts)operator(.)ident(inspect)inline_delimiter(})>content( in:)char(\\n)inline<inline_delimiter(#{)instance_variable(@response)operator(.)ident(body)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# Identical to #assert_tag, but asserts that a matching tag does _not_) + comment(# exist. (See #assert_tag for a full discussion of the syntax.\)) + reserved(def) method(assert_no_tag)operator(()operator(*)ident(opts)operator(\)) + ident(clean_backtrace) reserved(do) + ident(opts) operator(=) ident(opts)operator(.)ident(size) operator(>) integer(1) operator(?) ident(opts)operator(.)ident(last)operator(.)ident(merge)operator(()operator({) symbol(:tag) operator(=)operator(>) ident(opts)operator(.)ident(first)operator(.)ident(to_s) operator(})operator(\)) operator(:) ident(opts)operator(.)ident(first) + ident(tag) operator(=) ident(find_tag)operator(()ident(opts)operator(\)) + ident(assert) operator(!)ident(tag)operator(,) string<delimiter(")content(expected no tag, but found tag matching )inline<inline_delimiter(#{)ident(opts)operator(.)ident(inspect)inline_delimiter(})>content( in:)char(\\n)inline<inline_delimiter(#{)instance_variable(@response)operator(.)ident(body)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# test 2 html strings to be equivalent, i.e. identical up to reordering of attributes) + reserved(def) method(assert_dom_equal)operator(()ident(expected)operator(,) ident(actual)operator(,) ident(message)operator(=)string<delimiter(")delimiter(")>operator(\)) + ident(clean_backtrace) reserved(do) + ident(expected_dom) operator(=) constant(HTML)operator(::)constant(Document)operator(.)ident(new)operator(()ident(expected)operator(\))operator(.)ident(root) + ident(actual_dom) operator(=) constant(HTML)operator(::)constant(Document)operator(.)ident(new)operator(()ident(actual)operator(\))operator(.)ident(root) + ident(full_message) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> expected to be == to)char(\\n)content(<?>.)delimiter(")>operator(,) ident(expected_dom)operator(.)ident(to_s)operator(,) ident(actual_dom)operator(.)ident(to_s)operator(\)) + ident(assert_block)operator(()ident(full_message)operator(\)) operator({) ident(expected_dom) operator(==) ident(actual_dom) operator(}) + reserved(end) + reserved(end) + + comment(# negated form of +assert_dom_equivalent+) + reserved(def) method(assert_dom_not_equal)operator(()ident(expected)operator(,) ident(actual)operator(,) ident(message)operator(=)string<delimiter(")delimiter(")>operator(\)) + ident(clean_backtrace) reserved(do) + ident(expected_dom) operator(=) constant(HTML)operator(::)constant(Document)operator(.)ident(new)operator(()ident(expected)operator(\))operator(.)ident(root) + ident(actual_dom) operator(=) constant(HTML)operator(::)constant(Document)operator(.)ident(new)operator(()ident(actual)operator(\))operator(.)ident(root) + ident(full_message) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> expected to be != to)char(\\n)content(<?>.)delimiter(")>operator(,) ident(expected_dom)operator(.)ident(to_s)operator(,) ident(actual_dom)operator(.)ident(to_s)operator(\)) + ident(assert_block)operator(()ident(full_message)operator(\)) operator({) ident(expected_dom) operator(!=) ident(actual_dom) operator(}) + reserved(end) + reserved(end) + + comment(# ensures that the passed record is valid by active record standards. returns the error messages if not) + reserved(def) method(assert_valid)operator(()ident(record)operator(\)) + ident(clean_backtrace) reserved(do) + ident(assert) ident(record)operator(.)ident(valid?)operator(,) ident(record)operator(.)ident(errors)operator(.)ident(full_messages)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(clean_backtrace)operator(()operator(&)ident(block)operator(\)) + reserved(yield) + reserved(rescue) constant(AssertionFailedError) operator(=)operator(>) ident(e) + ident(path) operator(=) constant(File)operator(.)ident(expand_path)operator(()pre_constant(__FILE__)operator(\)) + ident(raise) constant(AssertionFailedError)operator(,) ident(e)operator(.)ident(message)operator(,) ident(e)operator(.)ident(backtrace)operator(.)ident(reject) operator({) operator(|)ident(line)operator(|) constant(File)operator(.)ident(expand_path)operator(()ident(line)operator(\)) operator(=)operator(~) regexp<delimiter(/)inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(/)> operator(}) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_controller/mime_type)delimiter(')> +ident(require) string<delimiter(')content(action_controller/request)delimiter(')> +ident(require) string<delimiter(')content(action_controller/response)delimiter(')> +ident(require) string<delimiter(')content(action_controller/routing)delimiter(')> +ident(require) string<delimiter(')content(action_controller/code_generation)delimiter(')> +ident(require) string<delimiter(')content(action_controller/url_rewriter)delimiter(')> +ident(require) string<delimiter(')content(drb)delimiter(')> +ident(require) string<delimiter(')content(set)delimiter(')> + +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(class) class(ActionControllerError) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + reserved(class) class(SessionRestoreError) operator(<) constant(ActionControllerError) comment(#:nodoc:) + reserved(end) + reserved(class) class(MissingTemplate) operator(<) constant(ActionControllerError) comment(#:nodoc:) + reserved(end) + reserved(class) class(RoutingError) operator(<) constant(ActionControllerError) comment(#:nodoc:) + ident(attr_reader) symbol(:failures) + reserved(def) method(initialize)operator(()ident(message)operator(,) ident(failures)operator(=)operator([)operator(])operator(\)) + reserved(super)operator(()ident(message)operator(\)) + instance_variable(@failures) operator(=) ident(failures) + reserved(end) + reserved(end) + reserved(class) class(UnknownController) operator(<) constant(ActionControllerError) comment(#:nodoc:) + reserved(end) + reserved(class) class(UnknownAction) operator(<) constant(ActionControllerError) comment(#:nodoc:) + reserved(end) + reserved(class) class(MissingFile) operator(<) constant(ActionControllerError) comment(#:nodoc:) + reserved(end) + reserved(class) class(SessionOverflowError) operator(<) constant(ActionControllerError) comment(#:nodoc:) + constant(DEFAULT_MESSAGE) operator(=) string<delimiter(')content(Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.)delimiter(')> + + reserved(def) method(initialize)operator(()ident(message) operator(=) pre_constant(nil)operator(\)) + reserved(super)operator(()ident(message) operator(||) constant(DEFAULT_MESSAGE)operator(\)) + reserved(end) + reserved(end) + reserved(class) class(DoubleRenderError) operator(<) constant(ActionControllerError) comment(#:nodoc:) + constant(DEFAULT_MESSAGE) operator(=) string<delimiter(")content(Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like )char(\\")content(redirect_to(...\) and return)char(\\")content(. Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so )char(\\")content(render(...\) and return false)char(\\")content(.)delimiter(")> + + reserved(def) method(initialize)operator(()ident(message) operator(=) pre_constant(nil)operator(\)) + reserved(super)operator(()ident(message) operator(||) constant(DEFAULT_MESSAGE)operator(\)) + reserved(end) + reserved(end) + reserved(class) class(RedirectBackError) operator(<) constant(ActionControllerError) comment(#:nodoc:) + constant(DEFAULT_MESSAGE) operator(=) string<delimiter(')content(No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify @request.env["HTTP_REFERER"].)delimiter(')> + + reserved(def) method(initialize)operator(()ident(message) operator(=) pre_constant(nil)operator(\)) + reserved(super)operator(()ident(message) operator(||) constant(DEFAULT_MESSAGE)operator(\)) + reserved(end) + reserved(end) + + comment(# Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed ) + comment(# on request and then either render a template or redirect to another action. An action is defined as a public method) + comment(# on the controller, which will automatically be made accessible to the web-server through Rails Routes. ) + comment(#) + comment(# A sample controller could look like this:) + comment(#) + comment(# class GuestBookController < ActionController::Base) + comment(# def index) + comment(# @entries = Entry.find(:all\)) + comment(# end) + comment(# ) + comment(# def sign) + comment(# Entry.create(params[:entry]\)) + comment(# redirect_to :action => "index") + comment(# end) + comment(# end) + comment(#) + comment(# Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action) + comment(# after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the ) + comment(# template <tt>app/views/guestbook/index.rhtml</tt> by default after populating the <tt>@entries</tt> instance variable.) + comment(#) + comment(# Unlike index, the sign action will not render a template. After performing its main purpose (creating a ) + comment(# new entry in the guest book\), it initiates a redirect instead. This redirect works by returning an external ) + comment(# "302 Moved" HTTP response that takes the user to the index action.) + comment(#) + comment(# The index and sign represent the two basic action archetypes used in Action Controllers. Get-and-show and do-and-redirect.) + comment(# Most actions are variations of these themes.) + comment(#) + comment(# == Requests) + comment(#) + comment(# Requests are processed by the Action Controller framework by extracting the value of the "action" key in the request parameters.) + comment(# This value should hold the name of the action to be performed. Once the action has been identified, the remaining) + comment(# request parameters, the session (if one is available\), and the full request with all the http headers are made available to) + comment(# the action through instance variables. Then the action is performed.) + comment(#) + comment(# The full request object is available with the request accessor and is primarily used to query for http headers. These queries) + comment(# are made by accessing the environment hash, like this:) + comment(#) + comment(# def server_ip) + comment(# location = request.env["SERVER_ADDR"]) + comment(# render :text => "This server hosted at #{location}") + comment(# end) + comment(#) + comment(# == Parameters) + comment(#) + comment(# All request parameters, whether they come from a GET or POST request, or from the URL, are available through the params method) + comment(# which returns a hash. For example, an action that was performed through <tt>/weblog/list?category=All&limit=5</tt> will include ) + comment(# <tt>{ "category" => "All", "limit" => 5 }</tt> in params.) + comment(#) + comment(# It's also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as:) + comment(#) + comment(# <input type="text" name="post[name]" value="david">) + comment(# <input type="text" name="post[address]" value="hyacintvej">) + comment(#) + comment(# A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.) + comment(# If the address input had been named "post[address][street]", the params would have included ) + comment(# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.) + comment(#) + comment(# == Sessions) + comment(#) + comment(# Sessions allows you to store objects in between requests. This is useful for objects that are not yet ready to be persisted,) + comment(# such as a Signup object constructed in a multi-paged process, or objects that don't change much and are needed all the time, such) + comment(# as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it's likely ) + comment(# they could be changed unknowingly. It's usually too much work to keep it all synchronized -- something databases already excel at.) + comment(#) + comment(# You can place objects in the session by using the <tt>session</tt> method, which accesses a hash:) + comment(#) + comment(# session[:person] = Person.authenticate(user_name, password\)) + comment(#) + comment(# And retrieved again through the same hash:) + comment(#) + comment(# Hello #{session[:person]}) + comment(#) + comment(# For removing objects from the session, you can either assign a single key to nil, like <tt>session[:person] = nil</tt>, or you can) + comment(# remove the entire session with reset_session.) + comment(#) + comment(# By default, sessions are stored on the file system in <tt>RAILS_ROOT/tmp/sessions</tt>. Any object can be placed in the session ) + comment(# (as long as it can be Marshalled\). But remember that 1000 active sessions each storing a 50kb object could lead to a 50MB store on the filesystem.) + comment(# In other words, think carefully about size and caching before resorting to the use of the session on the filesystem.) + comment(#) + comment(# An alternative to storing sessions on disk is to use ActiveRecordStore to store sessions in your database, which can solve problems) + comment(# caused by storing sessions in the file system and may speed up your application. To use ActiveRecordStore, uncomment the line:) + comment(# ) + comment(# config.action_controller.session_store = :active_record_store) + comment(#) + comment(# in your <tt>environment.rb</tt> and run <tt>rake db:sessions:create</tt>.) + comment(#) + comment(# == Responses) + comment(#) + comment(# Each action results in a response, which holds the headers and document to be sent to the user's browser. The actual response) + comment(# object is generated automatically through the use of renders and redirects and requires no user intervention.) + comment(#) + comment(# == Renders) + comment(#) + comment(# Action Controller sends content to the user by using one of five rendering methods. The most versatile and common is the rendering) + comment(# of a template. Included in the Action Pack is the Action View, which enables rendering of ERb templates. It's automatically configured.) + comment(# The controller passes objects to the view by assigning instance variables:) + comment(#) + comment(# def show) + comment(# @post = Post.find(params[:id]\)) + comment(# end) + comment(#) + comment(# Which are then automatically available to the view:) + comment(#) + comment(# Title: <%= @post.title %>) + comment(#) + comment(# You don't have to rely on the automated rendering. Especially actions that could result in the rendering of different templates will use) + comment(# the manual rendering methods:) + comment(#) + comment(# def search) + comment(# @results = Search.find(params[:query]\)) + comment(# case @results) + comment(# when 0 then render :action => "no_results") + comment(# when 1 then render :action => "show") + comment(# when 2..10 then render :action => "show_many") + comment(# end) + comment(# end) + comment(#) + comment(# Read more about writing ERb and Builder templates in link:classes/ActionView/Base.html.) + comment(#) + comment(# == Redirects) + comment(#) + comment(# Redirects are used to move from one action to another. For example, after a <tt>create</tt> action, which stores a blog entry to a database,) + comment(# we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself\), we're going to reuse (and redirect to\)) + comment(# a <tt>show</tt> action that we'll assume has already been created. The code might look like this:) + comment(#) + comment(# def create) + comment(# @entry = Entry.new(params[:entry]\)) + comment(# if @entry.save) + comment(# # The entry was saved correctly, redirect to show) + comment(# redirect_to :action => 'show', :id => @entry.id) + comment(# else) + comment(# # things didn't go so well, do something else) + comment(# end) + comment(# end) + comment(#) + comment(# In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method which is then executed.) + comment(#) + comment(# == Calling multiple redirects or renders) + comment(#) + comment(# An action should conclude with a single render or redirect. Attempting to try to do either again will result in a DoubleRenderError:) + comment(#) + comment(# def do_something) + comment(# redirect_to :action => "elsewhere") + comment(# render :action => "overthere" # raises DoubleRenderError) + comment(# end) + comment(#) + comment(# If you need to redirect on the condition of something, then be sure to add "and return" to halt execution.) + comment(#) + comment(# def do_something) + comment(# redirect_to(:action => "elsewhere"\) and return if monkeys.nil?) + comment(# render :action => "overthere" # won't be called unless monkeys is nil) + comment(# end) + comment(#) + reserved(class) class(Base) + constant(DEFAULT_RENDER_STATUS_CODE) operator(=) string<delimiter(")content(200 OK)delimiter(")> + + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + comment(# Determines whether the view has access to controller internals @request, @response, @session, and @template.) + comment(# By default, it does.) + class_variable(@@view_controller_internals) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:view_controller_internals) + + comment(# Protected instance variable cache) + class_variable(@@protected_variables_cache) operator(=) pre_constant(nil) + ident(cattr_accessor) symbol(:protected_variables_cache) + + comment(# Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets, ) + comment(# and images to a dedicated asset server away from the main web server. Example: ) + comment(# ActionController::Base.asset_host = "http://assets.example.com") + class_variable(@@asset_host) operator(=) string<delimiter(")delimiter(")> + ident(cattr_accessor) symbol(:asset_host) + + comment(# All requests are considered local by default, so everyone will be exposed to detailed debugging screens on errors.) + comment(# When the application is ready to go public, this should be set to false, and the protected method <tt>local_request?</tt>) + comment(# should instead be implemented in the controller to determine when debugging screens should be shown.) + class_variable(@@consider_all_requests_local) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:consider_all_requests_local) + + comment(# Enable or disable the collection of failure information for RoutingErrors.) + comment(# This information can be extremely useful when tweaking custom routes, but is) + comment(# pointless once routes have been tested and verified.) + class_variable(@@debug_routes) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:debug_routes) + + comment(# Controls whether the application is thread-safe, so multi-threaded servers like WEBrick know whether to apply a mutex) + comment(# around the performance of each action. Action Pack and Active Record are by default thread-safe, but many applications) + comment(# may not be. Turned off by default.) + class_variable(@@allow_concurrency) operator(=) pre_constant(false) + ident(cattr_accessor) symbol(:allow_concurrency) + + comment(# Modern REST web services often need to submit complex data to the web application. ) + comment(# The param_parsers hash lets you register handlers wich will process the http body and add parameters to the ) + comment(# <tt>params</tt> hash. These handlers are invoked for post and put requests.) + comment(#) + comment(# By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instanciated ) + comment(# in the <tt>params</tt>. This allows XML requests to mask themselves as regular form submissions, so you can have one) + comment(# action serve both regular forms and web service requests.) + comment(# ) + comment(# Example of doing your own parser for a custom content type:) + comment(#) + comment(# ActionController::Base.param_parsers[Mime::Type.lookup('application/atom+xml'\)] = Proc.new do |data| ) + comment(# node = REXML::Document.new(post\) ) + comment(# { node.root.name => node.root }) + comment(# end) + comment(#) + comment(# Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the ) + comment(# root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results) + comment(# in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can ) + comment(# re-register XmlSimple as application/xml handler ike this:) + comment(#) + comment(# ActionController::Base.param_parsers[Mime::XML] = ) + comment(# Proc.new { |data| XmlSimple.xml_in(data, 'ForceArray' => false\) }) + comment(#) + comment(# A YAML parser is also available and can be turned on with:) + comment(#) + comment(# ActionController::Base.param_parsers[Mime::YAML] = :yaml) + class_variable(@@param_parsers) operator(=) operator({) constant(Mime)operator(::)constant(XML) operator(=)operator(>) symbol(:xml_simple) operator(}) + ident(cattr_accessor) symbol(:param_parsers) + + comment(# Template root determines the base from which template references will be made. So a call to render("test/template"\)) + comment(# will be converted to "#{template_root}/test/template.rhtml".) + ident(class_inheritable_accessor) symbol(:template_root) + + comment(# The logger is used for generating information on the action run-time (including benchmarking\) if available.) + comment(# Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers.) + ident(cattr_accessor) symbol(:logger) + + comment(# Determines which template class should be used by ActionController.) + ident(cattr_accessor) symbol(:template_class) + + comment(# Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates.) + ident(cattr_accessor) symbol(:ignore_missing_templates) + + comment(# Holds the request object that's primarily used to get environment variables through access like) + comment(# <tt>request.env["REQUEST_URI"]</tt>.) + ident(attr_accessor) symbol(:request) + + comment(# Holds a hash of all the GET, POST, and Url parameters passed to the action. Accessed like <tt>params["post_id"]</tt>) + comment(# to get the post_id. No type casts are made, so all values are returned as strings.) + ident(attr_accessor) symbol(:params) + + comment(# Holds the response object that's primarily used to set additional HTTP headers through access like ) + comment(# <tt>response.headers["Cache-Control"] = "no-cache"</tt>. Can also be used to access the final body HTML after a template) + comment(# has been rendered through response.body -- useful for <tt>after_filter</tt>s that wants to manipulate the output,) + comment(# such as a OutputCompressionFilter.) + ident(attr_accessor) symbol(:response) + + comment(# Holds a hash of objects in the session. Accessed like <tt>session[:person]</tt> to get the object tied to the "person") + comment(# key. The session will hold any type of object as values, but the key should be a string or symbol.) + ident(attr_accessor) symbol(:session) + + comment(# Holds a hash of header names and values. Accessed like <tt>headers["Cache-Control"]</tt> to get the value of the Cache-Control) + comment(# directive. Values should always be specified as strings.) + ident(attr_accessor) symbol(:headers) + + comment(# Holds the hash of variables that are passed on to the template class to be made available to the view. This hash) + comment(# is generated by taking a snapshot of all the instance variables in the current scope just before a template is rendered.) + ident(attr_accessor) symbol(:assigns) + + comment(# Returns the name of the action this controller is processing.) + ident(attr_accessor) symbol(:action_name) + + reserved(class) operator(<<) class(self) + comment(# Factory for the standard create, process loop where the controller is discarded after processing.) + reserved(def) method(process)operator(()ident(request)operator(,) ident(response)operator(\)) comment(#:nodoc:) + ident(new)operator(.)ident(process)operator(()ident(request)operator(,) ident(response)operator(\)) + reserved(end) + + comment(# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".) + reserved(def) method(controller_class_name) + instance_variable(@controller_class_name) operator(||=) ident(name)operator(.)ident(demodulize) + reserved(end) + + comment(# Converts the class name from something like "OneModule::TwoModule::NeatController" to "neat".) + reserved(def) method(controller_name) + instance_variable(@controller_name) operator(||=) ident(controller_class_name)operator(.)ident(sub)operator(()regexp<delimiter(/)content(Controller$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(underscore) + reserved(end) + + comment(# Converts the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat".) + reserved(def) method(controller_path) + instance_variable(@controller_path) operator(||=) ident(name)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(Controller$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(underscore) + reserved(end) + + comment(# Return an array containing the names of public methods that have been marked hidden from the action processor.) + comment(# By default, all methods defined in ActionController::Base and included modules are hidden.) + comment(# More methods can be hidden using <tt>hide_actions</tt>.) + reserved(def) method(hidden_actions) + ident(write_inheritable_attribute)operator(()symbol(:hidden_actions)operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(public_instance_methods)operator(\)) reserved(unless) ident(read_inheritable_attribute)operator(()symbol(:hidden_actions)operator(\)) + ident(read_inheritable_attribute)operator(()symbol(:hidden_actions)operator(\)) + reserved(end) + + comment(# Hide each of the given methods from being callable as actions.) + reserved(def) method(hide_action)operator(()operator(*)ident(names)operator(\)) + ident(write_inheritable_attribute)operator(()symbol(:hidden_actions)operator(,) ident(hidden_actions) operator(|) ident(names)operator(.)ident(collect) operator({) operator(|)ident(n)operator(|) ident(n)operator(.)ident(to_s) operator(})operator(\)) + reserved(end) + + comment(# Replace sensitive paramater data from the request log.) + comment(# Filters paramaters that have any of the arguments as a substring.) + comment(# Looks in all subhashes of the param hash for keys to filter.) + comment(# If a block is given, each key and value of the paramater hash and all) + comment(# subhashes is passed to it, the value or key) + comment(# can be replaced using String#replace or similar method.) + comment(#) + comment(# Examples:) + comment(# filter_parameter_logging) + comment(# => Does nothing, just slows the logging process down) + comment(#) + comment(# filter_parameter_logging :password) + comment(# => replaces the value to all keys matching /password/i with "[FILTERED]") + comment(#) + comment(# filter_parameter_logging :foo, "bar") + comment(# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]") + comment(#) + comment(# filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i }) + comment(# => reverses the value to all keys matching /secret/i) + comment(#) + comment(# filter_parameter_logging(:foo, "bar"\) { |k,v| v.reverse! if k =~ /secret/i }) + comment(# => reverses the value to all keys matching /secret/i, and ) + comment(# replaces the value to all keys matching /foo|bar/i with "[FILTERED]") + reserved(def) method(filter_parameter_logging)operator(()operator(*)ident(filter_words)operator(,) operator(&)ident(block)operator(\)) + ident(parameter_filter) operator(=) constant(Regexp)operator(.)ident(new)operator(()ident(filter_words)operator(.)ident(collect)operator({) operator(|)ident(s)operator(|) ident(s)operator(.)ident(to_s) operator(})operator(.)ident(join)operator(()string<delimiter(')content(|)delimiter(')>operator(\))operator(,) pre_constant(true)operator(\)) reserved(if) ident(filter_words)operator(.)ident(length) operator(>) integer(0) + + ident(define_method)operator(()symbol(:filter_parameters)operator(\)) reserved(do) operator(|)ident(unfiltered_parameters)operator(|) + ident(filtered_parameters) operator(=) operator({)operator(}) + + ident(unfiltered_parameters)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) ident(key) operator(=)operator(~) ident(parameter_filter) + ident(filtered_parameters)operator([)ident(key)operator(]) operator(=) string<delimiter(')content([FILTERED])delimiter(')> + reserved(elsif) ident(value)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(filtered_parameters)operator([)ident(key)operator(]) operator(=) ident(filter_parameters)operator(()ident(value)operator(\)) + reserved(elsif) ident(block_given?) + ident(key)operator(,) ident(value) operator(=) ident(key)operator(.)ident(dup)operator(,) ident(value)operator(.)ident(dup) + reserved(yield) ident(key)operator(,) ident(value) + ident(filtered_parameters)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(else) + ident(filtered_parameters)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(end) + reserved(end) + + ident(filtered_parameters) + reserved(end) + reserved(end) + reserved(end) + + ident(public) + comment(# Extracts the action_name from the request parameters and performs that action.) + reserved(def) method(process)operator(()ident(request)operator(,) ident(response)operator(,) ident(method) operator(=) symbol(:perform_action)operator(,) operator(*)ident(arguments)operator(\)) comment(#:nodoc:) + ident(initialize_template_class)operator(()ident(response)operator(\)) + ident(assign_shortcuts)operator(()ident(request)operator(,) ident(response)operator(\)) + ident(initialize_current_url) + ident(assign_names) + ident(forget_variables_added_to_assigns) + + ident(log_processing) + ident(send)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(\)) + + ident(response) + reserved(ensure) + ident(process_cleanup) + reserved(end) + + comment(# Returns a URL that has been rewritten according to the options hash and the defined Routes. ) + comment(# (For doing a complete redirect, use redirect_to\).) + comment(#  ) + comment(# <tt>url_for</tt> is used to:) + comment(#  ) + comment(# All keys given to url_for are forwarded to the Route module, save for the following:) + comment(# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example, ) + comment(# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt> ) + comment(# will produce "/posts/show/10#comments".) + comment(# * <tt>:only_path</tt> -- if true, returns the absolute URL (omitting the protocol, host name, and port\)) + comment(# * <tt>:trailing_slash</tt> -- if true, adds a trailing slash, as in "/archive/2005/". Note that this) + comment(# is currently not recommended since it breaks caching.) + comment(# * <tt>:host</tt> -- overrides the default (current\) host if provided) + comment(# * <tt>:protocol</tt> -- overrides the default (current\) protocol if provided) + comment(#) + comment(# The URL is generated from the remaining keys in the hash. A URL contains two key parts: the <base> and a query string.) + comment(# Routes composes a query string as the key/value pairs not included in the <base>.) + comment(#) + comment(# The default Routes setup supports a typical Rails path of "controller/action/id" where action and id are optional, with) + comment(# action defaulting to 'index' when not given. Here are some typical url_for statements and their corresponding URLs:) + comment(#  ) + comment(# url_for :controller => 'posts', :action => 'recent' # => 'proto://host.com/posts/recent') + comment(# url_for :controller => 'posts', :action => 'index' # => 'proto://host.com/posts') + comment(# url_for :controller => 'posts', :action => 'show', :id => 10 # => 'proto://host.com/posts/show/10') + comment(#) + comment(# When generating a new URL, missing values may be filled in from the current request's parameters. For example,) + comment(# <tt>url_for :action => 'some_action'</tt> will retain the current controller, as expected. This behavior extends to) + comment(# other parameters, including <tt>:controller</tt>, <tt>:id</tt>, and any other parameters that are placed into a Route's) + comment(# path.) + comment(#  ) + comment(# The URL helpers such as <tt>url_for</tt> have a limited form of memory: when generating a new URL, they can look for) + comment(# missing values in the current request's parameters. Routes attempts to guess when a value should and should not be) + comment(# taken from the defaults. There are a few simple rules on how this is performed:) + comment(#) + comment(# * If the controller name begins with a slash, no defaults are used: <tt>url_for :controller => '/home'</tt>) + comment(# * If the controller changes, the action will default to index unless provided) + comment(#) + comment(# The final rule is applied while the URL is being generated and is best illustrated by an example. Let us consider the) + comment(# route given by <tt>map.connect 'people/:last/:first/:action', :action => 'bio', :controller => 'people'</tt>.) + comment(#) + comment(# Suppose that the current URL is "people/hh/david/contacts". Let's consider a few different cases of URLs which are generated) + comment(# from this page.) + comment(#) + comment(# * <tt>url_for :action => 'bio'</tt> -- During the generation of this URL, default values will be used for the first and) + comment(# last components, and the action shall change. The generated URL will be, "people/hh/david/bio".) + comment(# * <tt>url_for :first => 'davids-little-brother'</tt> This generates the URL 'people/hh/davids-little-brother' -- note) + comment(# that this URL leaves out the assumed action of 'bio'.) + comment(#) + comment(# However, you might ask why the action from the current request, 'contacts', isn't carried over into the new URL. The) + comment(# answer has to do with the order in which the parameters appear in the generated path. In a nutshell, since the) + comment(# value that appears in the slot for <tt>:first</tt> is not equal to default value for <tt>:first</tt> we stop using) + comment(# defaults. On it's own, this rule can account for much of the typical Rails URL behavior.) + comment(#  ) + comment(# Although a convienence, defaults can occasionaly get in your way. In some cases a default persists longer than desired.) + comment(# The default may be cleared by adding <tt>:name => nil</tt> to <tt>url_for</tt>'s options.) + comment(# This is often required when writing form helpers, since the defaults in play may vary greatly depending upon where the) + comment(# helper is used from. The following line will redirect to PostController's default action, regardless of the page it is) + comment(# displayed on:) + comment(#) + comment(# url_for :controller => 'posts', :action => nil) + comment(# ) + comment(# If you explicitly want to create a URL that's almost the same as the current URL, you can do so using the) + comment(# :overwrite_params options. Say for your posts you have different views for showing and printing them.) + comment(# Then, in the show view, you get the URL for the print view like this) + comment(#) + comment(# url_for :overwrite_params => { :action => 'print' }) + comment(#) + comment(# This takes the current URL as is and only exchanges the action. In contrast, <tt>url_for :action => 'print'</tt>) + comment(# would have slashed-off the path components after the changed action.) + reserved(def) method(url_for)operator(()ident(options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) comment(#:doc:) + reserved(case) ident(options) + reserved(when) constant(String) reserved(then) ident(options) + reserved(when) constant(Symbol) reserved(then) ident(send)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + reserved(when) constant(Hash) reserved(then) instance_variable(@url)operator(.)ident(rewrite)operator(()ident(rewrite_options)operator(()ident(options)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".) + reserved(def) method(controller_class_name) + pre_constant(self)operator(.)ident(class)operator(.)ident(controller_class_name) + reserved(end) + + comment(# Converts the class name from something like "OneModule::TwoModule::NeatController" to "neat".) + reserved(def) method(controller_name) + pre_constant(self)operator(.)ident(class)operator(.)ident(controller_name) + reserved(end) + + reserved(def) method(session_enabled?) + ident(request)operator(.)ident(session_options)operator([)symbol(:disabled)operator(]) operator(!=) pre_constant(false) + reserved(end) + + ident(protected) + comment(# Renders the content that will be returned to the browser as the response body.) + comment(#) + comment(# === Rendering an action) + comment(# ) + comment(# Action rendering is the most common form and the type used automatically by Action Controller when nothing else is) + comment(# specified. By default, actions are rendered within the current layout (if one exists\).) + comment(#) + comment(# # Renders the template for the action "goal" within the current controller) + comment(# render :action => "goal") + comment(#) + comment(# # Renders the template for the action "short_goal" within the current controller,) + comment(# # but without the current active layout) + comment(# render :action => "short_goal", :layout => false) + comment(#) + comment(# # Renders the template for the action "long_goal" within the current controller,) + comment(# # but with a custom layout) + comment(# render :action => "long_goal", :layout => "spectacular") + comment(#) + comment(# _Deprecation_ _notice_: This used to have the signatures <tt>render_action("action", status = 200\)</tt>,) + comment(# <tt>render_without_layout("controller/action", status = 200\)</tt>, and ) + comment(# <tt>render_with_layout("controller/action", status = 200, layout\)</tt>.) + comment(#) + comment(# === Rendering partials) + comment(# ) + comment(# Partial rendering is most commonly used together with Ajax calls that only update one or a few elements on a page) + comment(# without reloading. Rendering of partials from the controller makes it possible to use the same partial template in) + comment(# both the full-page rendering (by calling it from within the template\) and when sub-page updates happen (from the) + comment(# controller action responding to Ajax calls\). By default, the current layout is not used.) + comment(#) + comment(# # Renders the partial located at app/views/controller/_win.r(html|xml\)) + comment(# render :partial => "win") + comment(#) + comment(# # Renders the partial with a status code of 500 (internal error\)) + comment(# render :partial => "broken", :status => 500) + comment(#) + comment(# # Renders the same partial but also makes a local variable available to it) + comment(# render :partial => "win", :locals => { :name => "david" }) + comment(#) + comment(# # Renders a collection of the same partial by making each element of @wins available through ) + comment(# # the local variable "win" as it builds the complete response) + comment(# render :partial => "win", :collection => @wins) + comment(#) + comment(# # Renders the same collection of partials, but also renders the win_divider partial in between) + comment(# # each win partial.) + comment(# render :partial => "win", :collection => @wins, :spacer_template => "win_divider") + comment(#) + comment(# _Deprecation_ _notice_: This used to have the signatures ) + comment(# <tt>render_partial(partial_path = default_template_name, object = nil, local_assigns = {}\)</tt> and) + comment(# <tt>render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = {}\)</tt>.) + comment(#) + comment(# === Rendering a template) + comment(# ) + comment(# Template rendering works just like action rendering except that it takes a path relative to the template root. ) + comment(# The current layout is automatically applied.) + comment(#) + comment(# # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml\) (in Rails, app/views/weblog/show.rhtml\)) + comment(# render :template => "weblog/show") + comment(#) + comment(# === Rendering a file) + comment(# ) + comment(# File rendering works just like action rendering except that it takes a filesystem path. By default, the path) + comment(# is assumed to be absolute, and the current layout is not applied.) + comment(#) + comment(# # Renders the template located at the absolute filesystem path) + comment(# render :file => "/path/to/some/template.rhtml") + comment(# render :file => "c:/path/to/some/template.rhtml") + comment(#) + comment(# # Renders a template within the current layout, and with a 404 status code) + comment(# render :file => "/path/to/some/template.rhtml", :layout => true, :status => 404) + comment(# render :file => "c:/path/to/some/template.rhtml", :layout => true, :status => 404) + comment(#) + comment(# # Renders a template relative to the template root and chooses the proper file extension) + comment(# render :file => "some/template", :use_full_path => true) + comment(#) + comment(# _Deprecation_ _notice_: This used to have the signature <tt>render_file(path, status = 200\)</tt>) + comment(#) + comment(# === Rendering text) + comment(# ) + comment(# Rendering of text is usually used for tests or for rendering prepared content, such as a cache. By default, text) + comment(# rendering is not done within the active layout.) + comment(#) + comment(# # Renders the clear text "hello world" with status code 200) + comment(# render :text => "hello world!") + comment(#) + comment(# # Renders the clear text "Explosion!" with status code 500) + comment(# render :text => "Explosion!", :status => 500 ) + comment(#) + comment(# # Renders the clear text "Hi there!" within the current active layout (if one exists\)) + comment(# render :text => "Explosion!", :layout => true) + comment(#) + comment(# # Renders the clear text "Hi there!" within the layout ) + comment(# # placed in "app/views/layouts/special.r(html|xml\)") + comment(# render :text => "Explosion!", :layout => "special") + comment(#) + comment(# _Deprecation_ _notice_: This used to have the signature <tt>render_text("text", status = 200\)</tt>) + comment(#) + comment(# === Rendering an inline template) + comment(#) + comment(# Rendering of an inline template works as a cross between text and action rendering where the source for the template) + comment(# is supplied inline, like text, but its interpreted with ERb or Builder, like action. By default, ERb is used for rendering) + comment(# and the current layout is not used.) + comment(#) + comment(# # Renders "hello, hello, hello, again") + comment(# render :inline => "<%= 'hello, ' * 3 + 'again' %>" ) + comment(#) + comment(# # Renders "<p>Good seeing you!</p>" using Builder) + comment(# render :inline => "xml.p { 'Good seeing you!' }", :type => :rxml) + comment(#) + comment(# # Renders "hello david") + comment(# render :inline => "<%= 'hello ' + name %>", :locals => { :name => "david" }) + comment(#) + comment(# _Deprecation_ _notice_: This used to have the signature <tt>render_template(template, status = 200, type = :rhtml\)</tt>) + comment(#) + comment(# === Rendering inline JavaScriptGenerator page updates) + comment(#) + comment(# In addition to rendering JavaScriptGenerator page updates with Ajax in RJS templates (see ActionView::Base for details\),) + comment(# you can also pass the <tt>:update</tt> parameter to +render+, along with a block, to render page updates inline.) + comment(#) + comment(# render :update do |page|) + comment(# page.replace_html 'user_list', :partial => 'user', :collection => @users) + comment(# page.visual_effect :highlight, 'user_list') + comment(# end) + comment(#) + comment(# === Rendering nothing) + comment(#) + comment(# Rendering nothing is often convenient in combination with Ajax calls that perform their effect client-side or) + comment(# when you just want to communicate a status code. Due to a bug in Safari, nothing actually means a single space.) + comment(#) + comment(# # Renders an empty response with status code 200) + comment(# render :nothing => true) + comment(#) + comment(# # Renders an empty response with status code 401 (access denied\)) + comment(# render :nothing => true, :status => 401) + reserved(def) method(render)operator(()ident(options) operator(=) pre_constant(nil)operator(,) ident(deprecated_status) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) comment(#:doc:) + ident(raise) constant(DoubleRenderError)operator(,) string<delimiter(")content(Can only render or redirect once per action)delimiter(")> reserved(if) ident(performed?) + + comment(# Backwards compatibility) + reserved(unless) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + reserved(if) ident(options) operator(==) symbol(:update) + ident(options) operator(=) operator({)symbol(:update) operator(=)operator(>) pre_constant(true)operator(}) + reserved(else) + reserved(return) ident(render_file)operator(()ident(options) operator(||) ident(default_template_name)operator(,) ident(deprecated_status)operator(,) pre_constant(true)operator(\)) + reserved(end) + reserved(end) + + reserved(if) ident(content_type) operator(=) ident(options)operator([)symbol(:content_type)operator(]) + ident(headers)operator([)string<delimiter(")content(Content-Type)delimiter(")>operator(]) operator(=) ident(content_type) + reserved(end) + + reserved(if) ident(text) operator(=) ident(options)operator([)symbol(:text)operator(]) + ident(render_text)operator(()ident(text)operator(,) ident(options)operator([)symbol(:status)operator(])operator(\)) + + reserved(else) + reserved(if) ident(file) operator(=) ident(options)operator([)symbol(:file)operator(]) + ident(render_file)operator(()ident(file)operator(,) ident(options)operator([)symbol(:status)operator(])operator(,) ident(options)operator([)symbol(:use_full_path)operator(])operator(,) ident(options)operator([)symbol(:locals)operator(]) operator(||) operator({)operator(})operator(\)) + + reserved(elsif) ident(template) operator(=) ident(options)operator([)symbol(:template)operator(]) + ident(render_file)operator(()ident(template)operator(,) ident(options)operator([)symbol(:status)operator(])operator(,) pre_constant(true)operator(\)) + + reserved(elsif) ident(inline) operator(=) ident(options)operator([)symbol(:inline)operator(]) + ident(render_template)operator(()ident(inline)operator(,) ident(options)operator([)symbol(:status)operator(])operator(,) ident(options)operator([)symbol(:type)operator(])operator(,) ident(options)operator([)symbol(:locals)operator(]) operator(||) operator({)operator(})operator(\)) + + reserved(elsif) ident(action_name) operator(=) ident(options)operator([)symbol(:action)operator(]) + ident(render_action)operator(()ident(action_name)operator(,) ident(options)operator([)symbol(:status)operator(])operator(,) ident(options)operator([)symbol(:layout)operator(])operator(\)) + + reserved(elsif) ident(xml) operator(=) ident(options)operator([)symbol(:xml)operator(]) + ident(render_xml)operator(()ident(xml)operator(,) ident(options)operator([)symbol(:status)operator(])operator(\)) + + reserved(elsif) ident(partial) operator(=) ident(options)operator([)symbol(:partial)operator(]) + ident(partial) operator(=) ident(default_template_name) reserved(if) ident(partial) operator(==) pre_constant(true) + reserved(if) ident(collection) operator(=) ident(options)operator([)symbol(:collection)operator(]) + ident(render_partial_collection)operator(()ident(partial)operator(,) ident(collection)operator(,) ident(options)operator([)symbol(:spacer_template)operator(])operator(,) ident(options)operator([)symbol(:locals)operator(])operator(,) ident(options)operator([)symbol(:status)operator(])operator(\)) + reserved(else) + ident(render_partial)operator(()ident(partial)operator(,) constant(ActionView)operator(::)constant(Base)operator(::)constant(ObjectWrapper)operator(.)ident(new)operator(()ident(options)operator([)symbol(:object)operator(])operator(\))operator(,) ident(options)operator([)symbol(:locals)operator(])operator(,) ident(options)operator([)symbol(:status)operator(])operator(\)) + reserved(end) + + reserved(elsif) ident(options)operator([)symbol(:update)operator(]) + ident(add_variables_to_assigns) + instance_variable(@template)operator(.)ident(send) symbol(:evaluate_assigns) + + ident(generator) operator(=) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(PrototypeHelper)operator(::)constant(JavaScriptGenerator)operator(.)ident(new)operator(()instance_variable(@template)operator(,) operator(&)ident(block)operator(\)) + ident(render_javascript)operator(()ident(generator)operator(.)ident(to_s)operator(\)) + + reserved(elsif) ident(options)operator([)symbol(:nothing)operator(]) + comment(# Safari doesn't pass the headers of the return if the response is zero length) + ident(render_text)operator(()string<delimiter(")content( )delimiter(")>operator(,) ident(options)operator([)symbol(:status)operator(])operator(\)) + + reserved(else) + ident(render_file)operator(()ident(default_template_name)operator(,) ident(options)operator([)symbol(:status)operator(])operator(,) pre_constant(true)operator(\)) + + reserved(end) + reserved(end) + reserved(end) + + comment(# Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead) + comment(# of sending it as the response body to the browser.) + reserved(def) method(render_to_string)operator(()ident(options) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) comment(#:doc:) + ident(result) operator(=) ident(render)operator(()ident(options)operator(,) operator(&)ident(block)operator(\)) + + ident(erase_render_results) + ident(forget_variables_added_to_assigns) + ident(reset_variables_added_to_assigns) + + ident(result) + reserved(end) + + reserved(def) method(render_action)operator(()ident(action_name)operator(,) ident(status) operator(=) pre_constant(nil)operator(,) ident(with_layout) operator(=) pre_constant(true)operator(\)) comment(#:nodoc:) + ident(template) operator(=) ident(default_template_name)operator(()ident(action_name)operator(.)ident(to_s)operator(\)) + reserved(if) ident(with_layout) operator(&&) operator(!)ident(template_exempt_from_layout?)operator(()ident(template)operator(\)) + ident(render_with_layout)operator(()ident(template)operator(,) ident(status)operator(\)) + reserved(else) + ident(render_without_layout)operator(()ident(template)operator(,) ident(status)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(render_file)operator(()ident(template_path)operator(,) ident(status) operator(=) pre_constant(nil)operator(,) ident(use_full_path) operator(=) pre_constant(false)operator(,) ident(locals) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(add_variables_to_assigns) + ident(assert_existence_of_template_file)operator(()ident(template_path)operator(\)) reserved(if) ident(use_full_path) + ident(logger)operator(.)ident(info)operator(()string<delimiter(")content(Rendering )inline<inline_delimiter(#{)ident(template_path)inline_delimiter(})>delimiter(")> operator(+) operator(()ident(status) operator(?) string<delimiter(")content( ()inline<inline_delimiter(#{)ident(status)inline_delimiter(})>content(\))delimiter(")> operator(:) string<delimiter(')delimiter(')>operator(\))operator(\)) reserved(if) ident(logger) + ident(render_text)operator(()instance_variable(@template)operator(.)ident(render_file)operator(()ident(template_path)operator(,) ident(use_full_path)operator(,) ident(locals)operator(\))operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_template)operator(()ident(template)operator(,) ident(status) operator(=) pre_constant(nil)operator(,) ident(type) operator(=) symbol(:rhtml)operator(,) ident(local_assigns) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(add_variables_to_assigns) + ident(render_text)operator(()instance_variable(@template)operator(.)ident(render_template)operator(()ident(type)operator(,) ident(template)operator(,) pre_constant(nil)operator(,) ident(local_assigns)operator(\))operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_text)operator(()ident(text) operator(=) pre_constant(nil)operator(,) ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@performed_render) operator(=) pre_constant(true) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(]) operator(=) operator(()ident(status) operator(||) constant(DEFAULT_RENDER_STATUS_CODE)operator(\))operator(.)ident(to_s) + instance_variable(@response)operator(.)ident(body) operator(=) ident(text) + reserved(end) + + reserved(def) method(render_javascript)operator(()ident(javascript)operator(,) ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/javascript; charset=UTF-8)delimiter(')> + ident(render_text)operator(()ident(javascript)operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_xml)operator(()ident(xml)operator(,) ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(]) operator(=) string<delimiter(')content(application/xml)delimiter(')> + ident(render_text)operator(()ident(xml)operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_nothing)operator(()ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(render_text)operator(()string<delimiter(')content( )delimiter(')>operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_partial)operator(()ident(partial_path) operator(=) ident(default_template_name)operator(,) ident(object) operator(=) pre_constant(nil)operator(,) ident(local_assigns) operator(=) pre_constant(nil)operator(,) ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(add_variables_to_assigns) + ident(render_text)operator(()instance_variable(@template)operator(.)ident(render_partial)operator(()ident(partial_path)operator(,) ident(object)operator(,) ident(local_assigns)operator(\))operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_partial_collection)operator(()ident(partial_name)operator(,) ident(collection)operator(,) ident(partial_spacer_template) operator(=) pre_constant(nil)operator(,) ident(local_assigns) operator(=) pre_constant(nil)operator(,) ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(add_variables_to_assigns) + ident(render_text)operator(()instance_variable(@template)operator(.)ident(render_partial_collection)operator(()ident(partial_name)operator(,) ident(collection)operator(,) ident(partial_spacer_template)operator(,) ident(local_assigns)operator(\))operator(,) ident(status)operator(\)) + reserved(end) + + reserved(def) method(render_with_layout)operator(()ident(template_name) operator(=) ident(default_template_name)operator(,) ident(status) operator(=) pre_constant(nil)operator(,) ident(layout) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(render_with_a_layout)operator(()ident(template_name)operator(,) ident(status)operator(,) ident(layout)operator(\)) + reserved(end) + + reserved(def) method(render_without_layout)operator(()ident(template_name) operator(=) ident(default_template_name)operator(,) ident(status) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(render_with_no_layout)operator(()ident(template_name)operator(,) ident(status)operator(\)) + reserved(end) + + + comment(# Clears the rendered results, allowing for another render to be performed.) + reserved(def) method(erase_render_results) comment(#:nodoc:) + instance_variable(@response)operator(.)ident(body) operator(=) pre_constant(nil) + instance_variable(@performed_render) operator(=) pre_constant(false) + reserved(end) + + comment(# Clears the redirected results from the headers, resets the status to 200 and returns ) + comment(# the URL that was used to redirect or nil if there was no redirected URL) + comment(# Note that +redirect_to+ will change the body of the response to indicate a redirection.) + comment(# The response body is not reset here, see +erase_render_results+) + reserved(def) method(erase_redirect_results) comment(#:nodoc:) + instance_variable(@performed_redirect) operator(=) pre_constant(false) + ident(response)operator(.)ident(redirected_to) operator(=) pre_constant(nil) + ident(response)operator(.)ident(redirected_to_method_params) operator(=) pre_constant(nil) + ident(response)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(]) operator(=) constant(DEFAULT_RENDER_STATUS_CODE) + ident(response)operator(.)ident(headers)operator(.)ident(delete)operator(()string<delimiter(')content(location)delimiter(')>operator(\)) + reserved(end) + + comment(# Erase both render and redirect results) + reserved(def) method(erase_results) comment(#:nodoc:) + ident(erase_render_results) + ident(erase_redirect_results) + reserved(end) + + reserved(def) method(rewrite_options)operator(()ident(options)operator(\)) comment(#:nodoc:) + reserved(if) ident(defaults) operator(=) ident(default_url_options)operator(()ident(options)operator(\)) + ident(defaults)operator(.)ident(merge)operator(()ident(options)operator(\)) + reserved(else) + ident(options) + reserved(end) + reserved(end) + + comment(# Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in) + comment(# the form of a hash, just like the one you would use for url_for directly. Example:) + comment(#) + comment(# def default_url_options(options\)) + comment(# { :project => @project.active? ? @project.url_name : "unknown" }) + comment(# end) + comment(#) + comment(# As you can infer from the example, this is mostly useful for situations where you want to centralize dynamic decisions about the) + comment(# urls as they stem from the business domain. Please note that any individual url_for call can always override the defaults set) + comment(# by this method.) + reserved(def) method(default_url_options)operator(()ident(options)operator(\)) comment(#:doc:) + reserved(end) + + comment(# Redirects the browser to the target specified in +options+. This parameter can take one of three forms:) + comment(#) + comment(# * <tt>Hash</tt>: The URL will be generated by calling url_for with the +options+.) + comment(# * <tt>String starting with protocol:// (like http://\)</tt>: Is passed straight through as the target for redirection.) + comment(# * <tt>String not containing a protocol</tt>: The current protocol and host is prepended to the string.) + comment(# * <tt>:back</tt>: Back to the page that issued the request. Useful for forms that are triggered from multiple places.) + comment(# Short-hand for redirect_to(request.env["HTTP_REFERER"]\)) + comment(# ) + comment(# Examples:) + comment(# redirect_to :action => "show", :id => 5) + comment(# redirect_to "http://www.rubyonrails.org") + comment(# redirect_to "/images/screenshot.jpg") + comment(# redirect_to :back) + comment(#) + comment(# The redirection happens as a "302 Moved" header.) + comment(#) + comment(# When using <tt>redirect_to :back</tt>, if there is no referrer,) + comment(# RedirectBackError will be raised. You may specify some fallback) + comment(# behavior for this case by rescueing RedirectBackError.) + reserved(def) method(redirect_to)operator(()ident(options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) comment(#:doc:) + reserved(case) ident(options) + reserved(when) regexp<delimiter(%r{)content(^)char(\\w)content(+://.*)delimiter(})> + ident(raise) constant(DoubleRenderError) reserved(if) ident(performed?) + ident(logger)operator(.)ident(info)operator(()string<delimiter(")content(Redirected to )inline<inline_delimiter(#{)ident(options)inline_delimiter(})>delimiter(")>operator(\)) reserved(if) ident(logger) + ident(response)operator(.)ident(redirect)operator(()ident(options)operator(\)) + ident(response)operator(.)ident(redirected_to) operator(=) ident(options) + instance_variable(@performed_redirect) operator(=) pre_constant(true) + + reserved(when) constant(String) + ident(redirect_to)operator(()ident(request)operator(.)ident(protocol) operator(+) ident(request)operator(.)ident(host_with_port) operator(+) ident(options)operator(\)) + + reserved(when) symbol(:back) + ident(request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_REFERER)delimiter(")>operator(]) operator(?) ident(redirect_to)operator(()ident(request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_REFERER)delimiter(")>operator(])operator(\)) operator(:) ident(raise)operator(()constant(RedirectBackError)operator(\)) + + reserved(else) + reserved(if) ident(parameters_for_method_reference)operator(.)ident(empty?) + ident(redirect_to)operator(()ident(url_for)operator(()ident(options)operator(\))operator(\)) + ident(response)operator(.)ident(redirected_to) operator(=) ident(options) + reserved(else) + ident(redirect_to)operator(()ident(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\))operator(\)) + ident(response)operator(.)ident(redirected_to)operator(,) ident(response)operator(.)ident(redirected_to_method_params) operator(=) ident(options)operator(,) ident(parameters_for_method_reference) + reserved(end) + reserved(end) + reserved(end) + + comment(# Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that) + comment(# intermediate caches shouldn't cache the response.) + comment(#) + comment(# Examples:) + comment(# expires_in 20.minutes) + comment(# expires_in 3.hours, :private => false) + comment(# expires in 3.hours, 'max-stale' => 5.hours, :private => nil, :public => true) + comment(# ) + comment(# This method will overwrite an existing Cache-Control header.) + comment(# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.) + reserved(def) method(expires_in)operator(()ident(seconds)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:doc:) + ident(cache_options) operator(=) operator({) string<delimiter(')content(max-age)delimiter(')> operator(=)operator(>) ident(seconds)operator(,) string<delimiter(')content(private)delimiter(')> operator(=)operator(>) pre_constant(true) operator(})operator(.)ident(symbolize_keys)operator(.)ident(merge!)operator(()ident(options)operator(.)ident(symbolize_keys)operator(\)) + ident(cache_options)operator(.)ident(delete_if) operator({) operator(|)ident(k)operator(,)ident(v)operator(|) ident(v)operator(.)ident(nil?) reserved(or) ident(v) operator(==) pre_constant(false) operator(}) + ident(cache_control) operator(=) ident(cache_options)operator(.)ident(map)operator({) operator(|)ident(k)operator(,)ident(v)operator(|) ident(v) operator(==) pre_constant(true) operator(?) ident(k)operator(.)ident(to_s) operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(k)operator(.)ident(to_s)inline_delimiter(})>content(=)inline<inline_delimiter(#{)ident(v)operator(.)ident(to_s)inline_delimiter(})>delimiter(")>operator(}) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(")content(Cache-Control)delimiter(")>operator(]) operator(=) ident(cache_control)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\)) + reserved(end) + + comment(# Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or) + comment(# intermediate caches (like caching proxy servers\).) + reserved(def) method(expires_now) comment(#:doc:) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(")content(Cache-Control)delimiter(")>operator(]) operator(=) string<delimiter(")content(no-cache)delimiter(")> + reserved(end) + + comment(# Resets the session by clearing out all the objects stored within and initializing a new session object.) + reserved(def) method(reset_session) comment(#:doc:) + instance_variable(@request)operator(.)ident(reset_session) + instance_variable(@session) operator(=) instance_variable(@request)operator(.)ident(session) + instance_variable(@response)operator(.)ident(session) operator(=) instance_variable(@session) + reserved(end) + + ident(private) + reserved(def) pre_constant(self)operator(.)ident(view_class) + instance_variable(@view_class) operator(||=) + comment(# create a new class based on the default template class and include helper methods) + ident(returning) constant(Class)operator(.)ident(new)operator(()constant(ActionView)operator(::)constant(Base)operator(\)) reserved(do) operator(|)ident(view_class)operator(|) + ident(view_class)operator(.)ident(send)operator(()symbol(:include)operator(,) ident(master_helper_module)operator(\)) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(view_root) + instance_variable(@view_root) operator(||=) ident(template_root) + reserved(end) + + reserved(def) method(initialize_template_class)operator(()ident(response)operator(\)) + ident(raise) string<delimiter(")content(You must assign a template class through ActionController.template_class= before processing a request)delimiter(")> reserved(unless) class_variable(@@template_class) + + ident(response)operator(.)ident(template) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(view_class)operator(.)ident(new)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(view_root)operator(,) operator({)operator(})operator(,) pre_constant(self)operator(\)) + ident(response)operator(.)ident(redirected_to) operator(=) pre_constant(nil) + instance_variable(@performed_render) operator(=) instance_variable(@performed_redirect) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(assign_shortcuts)operator(()ident(request)operator(,) ident(response)operator(\)) + instance_variable(@request)operator(,) instance_variable(@params)operator(,) instance_variable(@cookies) operator(=) ident(request)operator(,) ident(request)operator(.)ident(parameters)operator(,) ident(request)operator(.)ident(cookies) + + instance_variable(@response) operator(=) ident(response) + instance_variable(@response)operator(.)ident(session) operator(=) ident(request)operator(.)ident(session) + + instance_variable(@session) operator(=) instance_variable(@response)operator(.)ident(session) + instance_variable(@template) operator(=) instance_variable(@response)operator(.)ident(template) + instance_variable(@assigns) operator(=) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns) + + instance_variable(@headers) operator(=) instance_variable(@response)operator(.)ident(headers) + reserved(end) + + reserved(def) method(initialize_current_url) + instance_variable(@url) operator(=) constant(UrlRewriter)operator(.)ident(new)operator(()instance_variable(@request)operator(,) instance_variable(@params)operator(.)ident(clone)operator(()operator(\))operator(\)) + reserved(end) + + reserved(def) method(log_processing) + reserved(if) ident(logger) + ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)char(\\n)content(Processing )inline<inline_delimiter(#{)ident(controller_class_name)inline_delimiter(})>char(\\#)inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>content( (for )inline<inline_delimiter(#{)ident(request_origin)inline_delimiter(})>content(\) [)inline<inline_delimiter(#{)ident(request)operator(.)ident(method)operator(.)ident(to_s)operator(.)ident(upcase)inline_delimiter(})>content(])delimiter(")> + ident(logger)operator(.)ident(info) string<delimiter(")content( Session ID: )inline<inline_delimiter(#{)instance_variable(@session)operator(.)ident(session_id)inline_delimiter(})>delimiter(")> reserved(if) instance_variable(@session) reserved(and) instance_variable(@session)operator(.)ident(respond_to?)operator(()symbol(:session_id)operator(\)) + ident(logger)operator(.)ident(info) string<delimiter(")content( Parameters: )inline<inline_delimiter(#{)ident(respond_to?)operator(()symbol(:filter_parameters)operator(\)) operator(?) ident(filter_parameters)operator(()instance_variable(@params)operator(\))operator(.)ident(inspect) operator(:) instance_variable(@params)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(perform_action) + reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(action_methods)operator(.)ident(include?)operator(()ident(action_name)operator(\)) operator(||) pre_constant(self)operator(.)ident(class)operator(.)ident(action_methods)operator(.)ident(include?)operator(()string<delimiter(')content(method_missing)delimiter(')>operator(\)) + ident(send)operator(()ident(action_name)operator(\)) + ident(render) reserved(unless) ident(performed?) + reserved(elsif) ident(template_exists?) operator(&&) ident(template_public?) + ident(render) + reserved(else) + ident(raise) constant(UnknownAction)operator(,) string<delimiter(")content(No action responded to )inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>delimiter(")>operator(,) ident(caller) + reserved(end) + reserved(end) + + reserved(def) method(performed?) + instance_variable(@performed_render) operator(||) instance_variable(@performed_redirect) + reserved(end) + + reserved(def) method(assign_names) + instance_variable(@action_name) operator(=) operator(()ident(params)operator([)string<delimiter(')content(action)delimiter(')>operator(]) operator(||) string<delimiter(')content(index)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(action_methods) + pre_constant(self)operator(.)ident(class)operator(.)ident(action_methods) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(action_methods) + instance_variable(@action_methods) operator(||=) constant(Set)operator(.)ident(new)operator(()ident(public_instance_methods) operator(-) ident(hidden_actions)operator(\)) + reserved(end) + + reserved(def) method(add_variables_to_assigns) + reserved(unless) instance_variable(@variables_added) + ident(add_instance_variables_to_assigns) + ident(add_class_variables_to_assigns) reserved(if) ident(view_controller_internals) + instance_variable(@variables_added) operator(=) pre_constant(true) + reserved(end) + reserved(end) + + reserved(def) method(forget_variables_added_to_assigns) + instance_variable(@variables_added) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(reset_variables_added_to_assigns) + instance_variable(@template)operator(.)ident(instance_variable_set)operator(()string<delimiter(")content(@assigns_added)delimiter(")>operator(,) pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(add_instance_variables_to_assigns) + class_variable(@@protected_variables_cache) operator(||=) ident(protected_instance_variables)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(h)operator(,) ident(k)operator(|) ident(h)operator([)ident(k)operator(]) operator(=) pre_constant(true)operator(;) ident(h) operator(}) + ident(instance_variables)operator(.)ident(each) reserved(do) operator(|)ident(var)operator(|) + reserved(next) reserved(if) class_variable(@@protected_variables_cache)operator(.)ident(include?)operator(()ident(var)operator(\)) + instance_variable(@assigns)operator([)ident(var)operator([)integer(1)operator(..)integer(-1)operator(])operator(]) operator(=) ident(instance_variable_get)operator(()ident(var)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(add_class_variables_to_assigns) + string<delimiter(%w()content( template_root logger template_class ignore_missing_templates )delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(cvar)operator(|) + instance_variable(@assigns)operator([)ident(cvar)operator(]) operator(=) pre_constant(self)operator(.)ident(send)operator(()ident(cvar)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(protected_instance_variables) + reserved(if) ident(view_controller_internals) + operator([) string<delimiter(")content(@assigns)delimiter(")>operator(,) string<delimiter(")content(@performed_redirect)delimiter(")>operator(,) string<delimiter(")content(@performed_render)delimiter(")> operator(]) + reserved(else) + operator([) string<delimiter(")content(@assigns)delimiter(")>operator(,) string<delimiter(")content(@performed_redirect)delimiter(")>operator(,) string<delimiter(")content(@performed_render)delimiter(")>operator(,) string<delimiter(")content(@request)delimiter(")>operator(,) string<delimiter(")content(@response)delimiter(")>operator(,) string<delimiter(")content(@session)delimiter(")>operator(,) string<delimiter(")content(@cookies)delimiter(")>operator(,) string<delimiter(")content(@template)delimiter(")>operator(,) string<delimiter(")content(@request_origin)delimiter(")>operator(,) string<delimiter(")content(@parent_controller)delimiter(")> operator(]) + reserved(end) + reserved(end) + + reserved(def) method(request_origin) + comment(# this *needs* to be cached!) + comment(# otherwise you'd get different results if calling it more than once) + instance_variable(@request_origin) operator(||=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(remote_ip)inline_delimiter(})>content( at )inline<inline_delimiter(#{)constant(Time)operator(.)ident(now)operator(.)ident(to_s)operator(()symbol(:db)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(complete_request_uri) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(protocol)inline_delimiter(})>inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(host)inline_delimiter(})>inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(request_uri)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(close_session) + instance_variable(@session)operator(.)ident(close) reserved(unless) instance_variable(@session)operator(.)ident(nil?) operator(||) constant(Hash) operator(===) instance_variable(@session) + reserved(end) + + reserved(def) method(template_exists?)operator(()ident(template_name) operator(=) ident(default_template_name)operator(\)) + instance_variable(@template)operator(.)ident(file_exists?)operator(()ident(template_name)operator(\)) + reserved(end) + + reserved(def) method(template_public?)operator(()ident(template_name) operator(=) ident(default_template_name)operator(\)) + instance_variable(@template)operator(.)ident(file_public?)operator(()ident(template_name)operator(\)) + reserved(end) + + reserved(def) method(template_exempt_from_layout?)operator(()ident(template_name) operator(=) ident(default_template_name)operator(\)) + ident(template_name) operator(=)operator(~) regexp<delimiter(/)char(\\.)content(rjs$)delimiter(/)> operator(||) operator(()instance_variable(@template)operator(.)ident(pick_template_extension)operator(()ident(template_name)operator(\)) operator(==) symbol(:rjs) reserved(rescue) pre_constant(false)operator(\)) + reserved(end) + + reserved(def) method(assert_existence_of_template_file)operator(()ident(template_name)operator(\)) + reserved(unless) ident(template_exists?)operator(()ident(template_name)operator(\)) operator(||) ident(ignore_missing_templates) + ident(full_template_path) operator(=) instance_variable(@template)operator(.)ident(send)operator(()symbol(:full_template_path)operator(,) ident(template_name)operator(,) string<delimiter(')content(rhtml)delimiter(')>operator(\)) + ident(template_type) operator(=) operator(()ident(template_name) operator(=)operator(~) regexp<delimiter(/)content(layouts)delimiter(/)modifier(i)>operator(\)) operator(?) string<delimiter(')content(layout)delimiter(')> operator(:) string<delimiter(')content(template)delimiter(')> + ident(raise)operator(()constant(MissingTemplate)operator(,) string<delimiter(")content(Missing )inline<inline_delimiter(#{)ident(template_type)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(full_template_path)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(default_template_name)operator(()ident(action_name) operator(=) pre_constant(self)operator(.)ident(action_name)operator(\)) + reserved(if) ident(action_name) + ident(action_name) operator(=) ident(action_name)operator(.)ident(to_s) + reserved(if) ident(action_name)operator(.)ident(include?)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) operator(&&) ident(template_path_includes_controller?)operator(()ident(action_name)operator(\)) + ident(action_name) operator(=) ident(strip_out_controller)operator(()ident(action_name)operator(\)) + reserved(end) + reserved(end) + string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(controller_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(strip_out_controller)operator(()ident(path)operator(\)) + ident(path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(,) integer(2)operator(\))operator(.)ident(last) + reserved(end) + + reserved(def) method(template_path_includes_controller?)operator(()ident(path)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(controller_path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator([)integer(-1)operator(]) operator(==) ident(path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(process_cleanup) + ident(close_session) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(benchmark)delimiter(')> + +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# The benchmarking module times the performance of actions and reports to the logger. If the Active Record) + comment(# package has been included, a separate timing section for database calls will be added as well.) + reserved(module) class(Benchmarking) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:perform_action_without_benchmark)operator(,) symbol(:perform_action) + ident(alias_method) symbol(:perform_action)operator(,) symbol(:perform_action_with_benchmark) + + ident(alias_method) symbol(:render_without_benchmark)operator(,) symbol(:render) + ident(alias_method) symbol(:render)operator(,) symbol(:render_with_benchmark) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Log and benchmark the workings of a single block and silence whatever logging that may have happened inside it ) + comment(# (unless <tt>use_silence</tt> is set to false\).) + comment(#) + comment(# The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it) + comment(# easy to include benchmarking statements in production software that will remain inexpensive because the benchmark) + comment(# will only be conducted if the log level is low enough.) + reserved(def) method(benchmark)operator(()ident(title)operator(,) ident(log_level) operator(=) constant(Logger)operator(::)constant(DEBUG)operator(,) ident(use_silence) operator(=) pre_constant(true)operator(\)) + reserved(if) ident(logger) operator(&&) ident(logger)operator(.)ident(level) operator(==) ident(log_level) + ident(result) operator(=) pre_constant(nil) + ident(seconds) operator(=) constant(Benchmark)operator(.)ident(realtime) operator({) ident(result) operator(=) ident(use_silence) operator(?) ident(silence) operator({) reserved(yield) operator(}) operator(:) reserved(yield) operator(}) + ident(logger)operator(.)ident(add)operator(()ident(log_level)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(title)inline_delimiter(})>content( ()inline<inline_delimiter(#{)string<delimiter(')content(%.5f)delimiter(')> operator(%) ident(seconds)inline_delimiter(})>content(\))delimiter(")>operator(\)) + ident(result) + reserved(else) + reserved(yield) + reserved(end) + reserved(end) + + comment(# Silences the logger for the duration of the block.) + reserved(def) method(silence) + ident(old_logger_level)operator(,) ident(logger)operator(.)ident(level) operator(=) ident(logger)operator(.)ident(level)operator(,) constant(Logger)operator(::)constant(ERROR) reserved(if) ident(logger) + reserved(yield) + reserved(ensure) + ident(logger)operator(.)ident(level) operator(=) ident(old_logger_level) reserved(if) ident(logger) + reserved(end) + reserved(end) + + reserved(def) method(render_with_benchmark)operator(()ident(options) operator(=) pre_constant(nil)operator(,) ident(deprecated_status) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + reserved(unless) ident(logger) + ident(render_without_benchmark)operator(()ident(options)operator(,) ident(deprecated_status)operator(,) operator(&)ident(block)operator(\)) + reserved(else) + ident(db_runtime) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(reset_runtime) reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()string<delimiter(")content(ActiveRecord)delimiter(")>operator(\)) operator(&&) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connected?) + + ident(render_output) operator(=) pre_constant(nil) + instance_variable(@rendering_runtime) operator(=) constant(Benchmark)operator(::)ident(measure)operator({) ident(render_output) operator(=) ident(render_without_benchmark)operator(()ident(options)operator(,) ident(deprecated_status)operator(,) operator(&)ident(block)operator(\)) operator(})operator(.)ident(real) + + reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()string<delimiter(")content(ActiveRecord)delimiter(")>operator(\)) operator(&&) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connected?) + instance_variable(@db_rt_before_render) operator(=) ident(db_runtime) + instance_variable(@db_rt_after_render) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(reset_runtime) + instance_variable(@rendering_runtime) operator(-=) instance_variable(@db_rt_after_render) + reserved(end) + + ident(render_output) + reserved(end) + reserved(end) + + reserved(def) method(perform_action_with_benchmark) + reserved(unless) ident(logger) + ident(perform_action_without_benchmark) + reserved(else) + ident(runtime) operator(=) operator([)constant(Benchmark)operator(::)ident(measure)operator({) ident(perform_action_without_benchmark) operator(})operator(.)ident(real)operator(,) float(0.0001)operator(])operator(.)ident(max) + ident(log_message) operator(=) string<delimiter(")content(Completed in )inline<inline_delimiter(#{)ident(sprintf)operator(()string<delimiter(")content(%.5f)delimiter(")>operator(,) ident(runtime)operator(\))inline_delimiter(})>content( ()inline<inline_delimiter(#{)operator(()integer(1) operator(/) ident(runtime)operator(\))operator(.)ident(floor)inline_delimiter(})>content( reqs/sec\))delimiter(")> + ident(log_message) operator(<<) ident(rendering_runtime)operator(()ident(runtime)operator(\)) reserved(if) instance_variable(@rendering_runtime) + ident(log_message) operator(<<) ident(active_record_runtime)operator(()ident(runtime)operator(\)) reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()string<delimiter(")content(ActiveRecord)delimiter(")>operator(\)) operator(&&) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connected?) + ident(log_message) operator(<<) string<delimiter(")content( | )inline<inline_delimiter(#{)ident(headers)operator([)string<delimiter(")content(Status)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + ident(log_message) operator(<<) string<delimiter(")content( [)inline<inline_delimiter(#{)ident(complete_request_uri) reserved(rescue) string<delimiter(")content(unknown)delimiter(")>inline_delimiter(})>content(])delimiter(")> + ident(logger)operator(.)ident(info)operator(()ident(log_message)operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(rendering_runtime)operator(()ident(runtime)operator(\)) + string<delimiter(")content( | Rendering: )inline<inline_delimiter(#{)ident(sprintf)operator(()string<delimiter(")content(%.5f)delimiter(")>operator(,) instance_variable(@rendering_runtime)operator(\))inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(sprintf)operator(()string<delimiter(")content(%d)delimiter(")>operator(,) operator(()instance_variable(@rendering_runtime) operator(*) integer(100)operator(\)) operator(/) ident(runtime)operator(\))inline_delimiter(})>content(%\))delimiter(")> + reserved(end) + + reserved(def) method(active_record_runtime)operator(()ident(runtime)operator(\)) + ident(db_runtime) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(reset_runtime) + ident(db_runtime) operator(+=) instance_variable(@db_rt_before_render) reserved(if) instance_variable(@db_rt_before_render) + ident(db_runtime) operator(+=) instance_variable(@db_rt_after_render) reserved(if) instance_variable(@db_rt_after_render) + ident(db_percentage) operator(=) operator(()ident(db_runtime) operator(*) integer(100)operator(\)) operator(/) ident(runtime) + string<delimiter(")content( | DB: )inline<inline_delimiter(#{)ident(sprintf)operator(()string<delimiter(")content(%.5f)delimiter(")>operator(,) ident(db_runtime)operator(\))inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(sprintf)operator(()string<delimiter(")content(%d)delimiter(")>operator(,) ident(db_percentage)operator(\))inline_delimiter(})>content(%\))delimiter(")> + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(fileutils)delimiter(')> + +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls) + comment(# around for subsequent requests. Action Controller affords you three approaches in varying levels of granularity: Page, Action, Fragment.) + comment(#) + comment(# You can read more about each approach and the sweeping assistance by clicking the modules below.) + comment(#) + comment(# Note: To turn off all caching and sweeping, set Base.perform_caching = false.) + reserved(module) class(Caching) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) comment(#:nodoc:) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(Pages)operator(,) constant(Actions)operator(,) constant(Fragments)operator(,) constant(Sweeping)operator(\)) + + ident(base)operator(.)ident(class_eval) reserved(do) + class_variable(@@perform_caching) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:perform_caching) + reserved(end) + reserved(end) + + comment(# Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server) + comment(# can serve without going through the Action Pack. This can be as much as 100 times faster than going through the process of dynamically) + comment(# generating the content. Unfortunately, this incredible speed-up is only available to stateless pages where all visitors) + comment(# are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are a great fit) + comment(# for this approach, but account-based systems where people log in and manipulate their own data are often less likely candidates.) + comment(#) + comment(# Specifying which actions to cache is done through the <tt>caches</tt> class method:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# caches_page :show, :new) + comment(# end) + comment(#) + comment(# This will generate cache files such as weblog/show/5 and weblog/new, which match the URLs used to trigger the dynamic) + comment(# generation. This is how the web server is able pick up a cache file when it exists and otherwise let the request pass on to) + comment(# the Action Pack to generate it.) + comment(#) + comment(# Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache) + comment(# is not restored before another hit is made against it. The API for doing so mimics the options from url_for and friends:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# def update) + comment(# List.update(params[:list][:id], params[:list]\)) + comment(# expire_page :action => "show", :id => params[:list][:id]) + comment(# redirect_to :action => "show", :id => params[:list][:id]) + comment(# end) + comment(# end) + comment(#) + comment(# Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be) + comment(# expired.) + comment(#) + comment(# == Setting the cache directory) + comment(#) + comment(# The cache directory should be the document root for the web server and is set using Base.page_cache_directory = "/document/root".) + comment(# For Rails, this directory has already been set to RAILS_ROOT + "/public".) + comment(#) + comment(# == Setting the cache extension) + comment(#) + comment(# By default, the cache extension is .html, which makes it easy for the cached files to be picked up by the web server. If you want) + comment(# something else, like .php or .shtml, just set Base.page_cache_extension.) + reserved(module) class(Pages) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) comment(#:nodoc:) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(class_eval) reserved(do) + class_variable(@@page_cache_directory) operator(=) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) operator(?) string<delimiter(")inline<inline_delimiter(#{)constant(RAILS_ROOT)inline_delimiter(})>content(/public)delimiter(")> operator(:) string<delimiter(")delimiter(")> + ident(cattr_accessor) symbol(:page_cache_directory) + + class_variable(@@page_cache_extension) operator(=) string<delimiter(')content(.html)delimiter(')> + ident(cattr_accessor) symbol(:page_cache_extension) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Expires the page that was cached with the +path+ as a key. Example:) + comment(# expire_page "/lists/show") + reserved(def) method(expire_page)operator(()ident(path)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + + ident(benchmark) string<delimiter(")content(Expired page: )inline<inline_delimiter(#{)ident(page_cache_file)operator(()ident(path)operator(\))inline_delimiter(})>delimiter(")> reserved(do) + constant(File)operator(.)ident(delete)operator(()ident(page_cache_path)operator(()ident(path)operator(\))operator(\)) reserved(if) constant(File)operator(.)ident(exists?)operator(()ident(page_cache_path)operator(()ident(path)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Manually cache the +content+ in the key determined by +path+. Example:) + comment(# cache_page "I'm the cached content", "/lists/show") + reserved(def) method(cache_page)operator(()ident(content)operator(,) ident(path)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + + ident(benchmark) string<delimiter(")content(Cached page: )inline<inline_delimiter(#{)ident(page_cache_file)operator(()ident(path)operator(\))inline_delimiter(})>delimiter(")> reserved(do) + constant(FileUtils)operator(.)ident(makedirs)operator(()constant(File)operator(.)ident(dirname)operator(()ident(page_cache_path)operator(()ident(path)operator(\))operator(\))operator(\)) + constant(File)operator(.)ident(open)operator(()ident(page_cache_path)operator(()ident(path)operator(\))operator(,) string<delimiter(")content(wb+)delimiter(")>operator(\)) operator({) operator(|)ident(f)operator(|) ident(f)operator(.)ident(write)operator(()ident(content)operator(\)) operator(}) + reserved(end) + reserved(end) + + comment(# Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that) + comment(# matches the triggering url.) + reserved(def) method(caches_page)operator(()operator(*)ident(actions)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + ident(actions)operator(.)ident(each) reserved(do) operator(|)ident(action)operator(|) + ident(class_eval) string<delimiter(")content(after_filter { |c| c.cache_page if c.action_name == ')inline<inline_delimiter(#{)ident(action)inline_delimiter(})>content(' })delimiter(")> + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(page_cache_file)operator(()ident(path)operator(\)) + ident(name) operator(=) operator(()operator(()ident(path)operator(.)ident(empty?) operator(||) ident(path) operator(==) string<delimiter(")content(/)delimiter(")>operator(\)) operator(?) string<delimiter(")content(/index)delimiter(")> operator(:) constant(URI)operator(.)ident(unescape)operator(()ident(path)operator(\))operator(\)) + ident(name) operator(<<) ident(page_cache_extension) reserved(unless) operator(()ident(name)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator(.)ident(last) operator(||) ident(name)operator(\))operator(.)ident(include?) string<delimiter(')content(.)delimiter(')> + reserved(return) ident(name) + reserved(end) + + reserved(def) method(page_cache_path)operator(()ident(path)operator(\)) + ident(page_cache_directory) operator(+) ident(page_cache_file)operator(()ident(path)operator(\)) + reserved(end) + reserved(end) + + comment(# Expires the page that was cached with the +options+ as a key. Example:) + comment(# expire_page :controller => "lists", :action => "show") + reserved(def) method(expire_page)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + reserved(if) ident(options)operator([)symbol(:action)operator(])operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(options)operator([)symbol(:action)operator(])operator(.)ident(dup)operator(.)ident(each) reserved(do) operator(|)ident(action)operator(|) + pre_constant(self)operator(.)ident(class)operator(.)ident(expire_page)operator(()ident(url_for)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:only_path) operator(=)operator(>) pre_constant(true)operator(,) symbol(:skip_relative_url_root) operator(=)operator(>) pre_constant(true)operator(,) symbol(:action) operator(=)operator(>) ident(action) operator(})operator(\))operator(\))operator(\)) + reserved(end) + reserved(else) + pre_constant(self)operator(.)ident(class)operator(.)ident(expire_page)operator(()ident(url_for)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:only_path) operator(=)operator(>) pre_constant(true)operator(,) symbol(:skip_relative_url_root) operator(=)operator(>) pre_constant(true) operator(})operator(\))operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of @response.body is used) + comment(# If no options are provided, the current +options+ for this action is used. Example:) + comment(# cache_page "I'm the cached content", :controller => "lists", :action => "show") + reserved(def) method(cache_page)operator(()ident(content) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + reserved(return) reserved(unless) ident(perform_caching) operator(&&) ident(caching_allowed) + pre_constant(self)operator(.)ident(class)operator(.)ident(cache_page)operator(()ident(content) operator(||) instance_variable(@response)operator(.)ident(body)operator(,) ident(url_for)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:only_path) operator(=)operator(>) pre_constant(true)operator(,) symbol(:skip_relative_url_root) operator(=)operator(>) pre_constant(true) operator(})operator(\))operator(\))operator(\)) + reserved(end) + + ident(private) + reserved(def) method(caching_allowed) + operator(!)instance_variable(@request)operator(.)ident(post?) operator(&&) instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(]) operator(&&) instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(])operator(.)ident(to_i) operator(<) integer(400) + reserved(end) + reserved(end) + + comment(# Action caching is similar to page caching by the fact that the entire output of the response is cached, but unlike page caching,) + comment(# every request still goes through the Action Pack. The key benefit of this is that filters are run before the cache is served, which) + comment(# allows for authentication and other restrictions on whether someone is allowed to see the cache. Example:) + comment(#) + comment(# class ListsController < ApplicationController) + comment(# before_filter :authenticate, :except => :public) + comment(# caches_page :public) + comment(# caches_action :show, :feed) + comment(# end) + comment(#) + comment(# In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the) + comment(# show and feed action are to be shielded behind the authenticate filter, so we need to implement those as action caches.) + comment(#) + comment(# Action caching internally uses the fragment caching and an around filter to do the job. The fragment cache is named according to both) + comment(# the current host and the path. So a page that is accessed at http://david.somewhere.com/lists/show/1 will result in a fragment named) + comment(# "david.somewhere.com/lists/show/1". This allows the cacher to differentiate between "david.somewhere.com/lists/" and) + comment(# "jamis.somewhere.com/lists/" -- which is a helpful way of assisting the subdomain-as-account-key pattern.) + reserved(module) class(Actions) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:attr_accessor)operator(,) symbol(:rendered_action_cache)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + reserved(def) method(caches_action)operator(()operator(*)ident(actions)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + ident(around_filter)operator(()constant(ActionCacheFilter)operator(.)ident(new)operator(()operator(*)ident(actions)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(expire_action)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + reserved(if) ident(options)operator([)symbol(:action)operator(])operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(options)operator([)symbol(:action)operator(])operator(.)ident(dup)operator(.)ident(each) reserved(do) operator(|)ident(action)operator(|) + ident(expire_fragment)operator(()ident(url_for)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:action) operator(=)operator(>) ident(action) operator(})operator(\))operator(\))operator(.)ident(split)operator(()string<delimiter(")content(://)delimiter(")>operator(\))operator(.)ident(last)operator(\)) + reserved(end) + reserved(else) + ident(expire_fragment)operator(()ident(url_for)operator(()ident(options)operator(\))operator(.)ident(split)operator(()string<delimiter(")content(://)delimiter(")>operator(\))operator(.)ident(last)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(ActionCacheFilter) comment(#:nodoc:) + reserved(def) method(initialize)operator(()operator(*)ident(actions)operator(\)) + instance_variable(@actions) operator(=) ident(actions) + reserved(end) + + reserved(def) method(before)operator(()ident(controller)operator(\)) + reserved(return) reserved(unless) instance_variable(@actions)operator(.)ident(include?)operator(()ident(controller)operator(.)ident(action_name)operator(.)ident(intern)operator(\)) + reserved(if) ident(cache) operator(=) ident(controller)operator(.)ident(read_fragment)operator(()ident(controller)operator(.)ident(url_for)operator(.)ident(split)operator(()string<delimiter(")content(://)delimiter(")>operator(\))operator(.)ident(last)operator(\)) + ident(controller)operator(.)ident(rendered_action_cache) operator(=) pre_constant(true) + ident(controller)operator(.)ident(send)operator(()symbol(:render_text)operator(,) ident(cache)operator(\)) + pre_constant(false) + reserved(end) + reserved(end) + + reserved(def) method(after)operator(()ident(controller)operator(\)) + reserved(return) reserved(if) operator(!)instance_variable(@actions)operator(.)ident(include?)operator(()ident(controller)operator(.)ident(action_name)operator(.)ident(intern)operator(\)) operator(||) ident(controller)operator(.)ident(rendered_action_cache) + ident(controller)operator(.)ident(write_fragment)operator(()ident(controller)operator(.)ident(url_for)operator(.)ident(split)operator(()string<delimiter(")content(://)delimiter(")>operator(\))operator(.)ident(last)operator(,) ident(controller)operator(.)ident(response)operator(.)ident(body)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Fragment caching is used for caching various blocks within templates without caching the entire action as a whole. This is useful when) + comment(# certain elements of an action change frequently or depend on complicated state while other parts rarely change or can be shared amongst multiple) + comment(# parties. The caching is doing using the cache helper available in the Action View. A template with caching might look something like:) + comment(#) + comment(# <b>Hello <%= @name %></b>) + comment(# <% cache do %>) + comment(# All the topics in the system:) + comment(# <%= render_collection_of_partials "topic", Topic.find_all %>) + comment(# <% end %>) + comment(#) + comment(# This cache will bind to the name of action that called it. So you would be able to invalidate it using) + comment(# <tt>expire_fragment(:controller => "topics", :action => "list"\)</tt> -- if that was the controller/action used. This is not too helpful) + comment(# if you need to cache multiple fragments per action or if the action itself is cached using <tt>caches_action</tt>. So instead we should) + comment(# qualify the name of the action used with something like:) + comment(#) + comment(# <% cache(:action => "list", :action_suffix => "all_topics"\) do %>) + comment(#) + comment(# That would result in a name such as "/topics/list/all_topics", which wouldn't conflict with any action cache and neither with another) + comment(# fragment using a different suffix. Note that the URL doesn't have to really exist or be callable. We're just using the url_for system) + comment(# to generate unique cache names that we can refer to later for expirations. The expiration call for this example would be) + comment(# <tt>expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics"\)</tt>.) + comment(#) + comment(# == Fragment stores) + comment(#) + comment(# In order to use the fragment caching, you need to designate where the caches should be stored. This is done by assigning a fragment store) + comment(# of which there are four different kinds:) + comment(#) + comment(# * FileStore: Keeps the fragments on disk in the +cache_path+, which works well for all types of environments and shares the fragments for) + comment(# all the web server processes running off the same application directory.) + comment(# * MemoryStore: Keeps the fragments in memory, which is fine for WEBrick and for FCGI (if you don't care that each FCGI process holds its) + comment(# own fragment store\). It's not suitable for CGI as the process is thrown away at the end of each request. It can potentially also take) + comment(# up a lot of memory since each process keeps all the caches in memory.) + comment(# * DRbStore: Keeps the fragments in the memory of a separate, shared DRb process. This works for all environments and only keeps one cache) + comment(# around for all processes, but requires that you run and manage a separate DRb process.) + comment(# * MemCacheStore: Works like DRbStore, but uses Danga's MemCache instead.) + comment(# Requires the ruby-memcache library: gem install ruby-memcache.) + comment(#) + comment(# Configuration examples (MemoryStore is the default\):) + comment(#) + comment(# ActionController::Base.fragment_cache_store = :memory_store) + comment(# ActionController::Base.fragment_cache_store = :file_store, "/path/to/cache/directory") + comment(# ActionController::Base.fragment_cache_store = :drb_store, "druby://localhost:9192") + comment(# ActionController::Base.fragment_cache_store = :mem_cache_store, "localhost") + comment(# ActionController::Base.fragment_cache_store = MyOwnStore.new("parameter"\)) + reserved(module) class(Fragments) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(class_eval) reserved(do) + class_variable(@@fragment_cache_store) operator(=) constant(MemoryStore)operator(.)ident(new) + ident(cattr_reader) symbol(:fragment_cache_store) + + reserved(def) pre_constant(self)operator(.)ident(fragment_cache_store)operator(=)operator(()ident(store_option)operator(\)) + ident(store)operator(,) operator(*)ident(parameters) operator(=) operator(*)operator(()operator([) ident(store_option) operator(])operator(.)ident(flatten)operator(\)) + class_variable(@@fragment_cache_store) operator(=) reserved(if) ident(store)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + ident(store_class_name) operator(=) operator(()ident(store) operator(==) symbol(:drb_store) operator(?) string<delimiter(")content(DRbStore)delimiter(")> operator(:) ident(store)operator(.)ident(to_s)operator(.)ident(camelize)operator(\)) + ident(store_class) operator(=) constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(.)ident(const_get)operator(()ident(store_class_name)operator(\)) + ident(store_class)operator(.)ident(new)operator(()operator(*)ident(parameters)operator(\)) + reserved(else) + ident(store) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(fragment_cache_key)operator(()ident(name)operator(\)) + ident(name)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(url_for)operator(()ident(name)operator(\))operator(.)ident(split)operator(()string<delimiter(")content(://)delimiter(")>operator(\))operator(.)ident(last) operator(:) ident(name) + reserved(end) + + comment(# Called by CacheHelper#cache) + reserved(def) method(cache_erb_fragment)operator(()ident(block)operator(,) ident(name) operator(=) operator({)operator(})operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + reserved(unless) ident(perform_caching) reserved(then) ident(block)operator(.)ident(call)operator(;) reserved(return) reserved(end) + + ident(buffer) operator(=) ident(eval)operator(()string<delimiter(")content(_erbout)delimiter(")>operator(,) ident(block)operator(.)ident(binding)operator(\)) + + reserved(if) ident(cache) operator(=) ident(read_fragment)operator(()ident(name)operator(,) ident(options)operator(\)) + ident(buffer)operator(.)ident(concat)operator(()ident(cache)operator(\)) + reserved(else) + ident(pos) operator(=) ident(buffer)operator(.)ident(length) + ident(block)operator(.)ident(call) + ident(write_fragment)operator(()ident(name)operator(,) ident(buffer)operator([)ident(pos)operator(..)integer(-1)operator(])operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(write_fragment)operator(()ident(name)operator(,) ident(content)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + + ident(key) operator(=) ident(fragment_cache_key)operator(()ident(name)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(benchmark) string<delimiter(")content(Cached fragment: )inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")> reserved(do) + ident(fragment_cache_store)operator(.)ident(write)operator(()ident(key)operator(,) ident(content)operator(,) ident(options)operator(\)) + reserved(end) + ident(content) + reserved(end) + + reserved(def) method(read_fragment)operator(()ident(name)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + + ident(key) operator(=) ident(fragment_cache_key)operator(()ident(name)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(benchmark) string<delimiter(")content(Fragment read: )inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")> reserved(do) + ident(fragment_cache_store)operator(.)ident(read)operator(()ident(key)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + comment(# Name can take one of three forms:) + comment(# * String: This would normally take the form of a path like "pages/45/notes") + comment(# * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 }) + comment(# * Regexp: Will destroy all the matched fragments, example: %r{pages/\\d*/notes} Ensure you do not specify start and finish in the regex (^$\) because the actual filename matched looks like ./cache/filename/path.cache) + reserved(def) method(expire_fragment)operator(()ident(name)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + + ident(key) operator(=) ident(fragment_cache_key)operator(()ident(name)operator(\)) + + reserved(if) ident(key)operator(.)ident(is_a?)operator(()constant(Regexp)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(benchmark) string<delimiter(")content(Expired fragments matching: )inline<inline_delimiter(#{)ident(key)operator(.)ident(source)inline_delimiter(})>delimiter(")> reserved(do) + ident(fragment_cache_store)operator(.)ident(delete_matched)operator(()ident(key)operator(,) ident(options)operator(\)) + reserved(end) + reserved(else) + pre_constant(self)operator(.)ident(class)operator(.)ident(benchmark) string<delimiter(")content(Expired fragment: )inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")> reserved(do) + ident(fragment_cache_store)operator(.)ident(delete)operator(()ident(key)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Deprecated -- just call expire_fragment with a regular expression) + reserved(def) method(expire_matched_fragments)operator(()ident(matcher) operator(=) regexp<delimiter(/)content(.*)delimiter(/)>operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(expire_fragment)operator(()ident(matcher)operator(,) ident(options)operator(\)) + reserved(end) + + + reserved(class) class(UnthreadedMemoryStore) comment(#:nodoc:) + reserved(def) method(initialize) comment(#:nodoc:) + instance_variable(@data) operator(=) operator({)operator(}) + reserved(end) + + reserved(def) method(read)operator(()ident(name)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@data)operator([)ident(name)operator(]) + reserved(end) + + reserved(def) method(write)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@data)operator([)ident(name)operator(]) operator(=) ident(value) + reserved(end) + + reserved(def) method(delete)operator(()ident(name)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@data)operator(.)ident(delete)operator(()ident(name)operator(\)) + reserved(end) + + reserved(def) method(delete_matched)operator(()ident(matcher)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@data)operator(.)ident(delete_if) operator({) operator(|)ident(k)operator(,)ident(v)operator(|) ident(k) operator(=)operator(~) ident(matcher) operator(}) + reserved(end) + reserved(end) + + reserved(module) class(ThreadSafety) comment(#:nodoc:) + reserved(def) method(read)operator(()ident(name)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@mutex)operator(.)ident(synchronize) operator({) reserved(super) operator(}) + reserved(end) + + reserved(def) method(write)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@mutex)operator(.)ident(synchronize) operator({) reserved(super) operator(}) + reserved(end) + + reserved(def) method(delete)operator(()ident(name)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@mutex)operator(.)ident(synchronize) operator({) reserved(super) operator(}) + reserved(end) + + reserved(def) method(delete_matched)operator(()ident(matcher)operator(,) ident(options)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@mutex)operator(.)ident(synchronize) operator({) reserved(super) operator(}) + reserved(end) + reserved(end) + + reserved(class) class(MemoryStore) operator(<) constant(UnthreadedMemoryStore) comment(#:nodoc:) + reserved(def) method(initialize) comment(#:nodoc:) + reserved(super) + reserved(if) constant(ActionController)operator(::)constant(Base)operator(.)ident(allow_concurrency) + instance_variable(@mutex) operator(=) constant(Mutex)operator(.)ident(new) + constant(MemoryStore)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ThreadSafety)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(DRbStore) operator(<) constant(MemoryStore) comment(#:nodoc:) + ident(attr_reader) symbol(:address) + + reserved(def) method(initialize)operator(()ident(address) operator(=) string<delimiter(')content(druby://localhost:9192)delimiter(')>operator(\)) + reserved(super)operator(()operator(\)) + instance_variable(@address) operator(=) ident(address) + instance_variable(@data) operator(=) constant(DRbObject)operator(.)ident(new)operator(()pre_constant(nil)operator(,) ident(address)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(MemCacheStore) operator(<) constant(MemoryStore) comment(#:nodoc:) + ident(attr_reader) symbol(:addresses) + + reserved(def) method(initialize)operator(()operator(*)ident(addresses)operator(\)) + reserved(super)operator(()operator(\)) + ident(addresses) operator(=) ident(addresses)operator(.)ident(flatten) + ident(addresses) operator(=) operator([)string<delimiter(")content(localhost)delimiter(")>operator(]) reserved(if) ident(addresses)operator(.)ident(empty?) + instance_variable(@addresses) operator(=) ident(addresses) + instance_variable(@data) operator(=) constant(MemCache)operator(.)ident(new)operator(()operator(*)ident(addresses)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(UnthreadedFileStore) comment(#:nodoc:) + ident(attr_reader) symbol(:cache_path) + + reserved(def) method(initialize)operator(()ident(cache_path)operator(\)) + instance_variable(@cache_path) operator(=) ident(cache_path) + reserved(end) + + reserved(def) method(write)operator(()ident(name)operator(,) ident(value)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(ensure_cache_path)operator(()constant(File)operator(.)ident(dirname)operator(()ident(real_file_path)operator(()ident(name)operator(\))operator(\))operator(\)) + constant(File)operator(.)ident(open)operator(()ident(real_file_path)operator(()ident(name)operator(\))operator(,) string<delimiter(")content(wb+)delimiter(")>operator(\)) operator({) operator(|)ident(f)operator(|) ident(f)operator(.)ident(write)operator(()ident(value)operator(\)) operator(}) + reserved(rescue) operator(=)operator(>) ident(e) + constant(Base)operator(.)ident(logger)operator(.)ident(error) string<delimiter(")content(Couldn't create cache directory: )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>content(\))delimiter(")> reserved(if) constant(Base)operator(.)ident(logger) + reserved(end) + + reserved(def) method(read)operator(()ident(name)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + constant(File)operator(.)ident(open)operator(()ident(real_file_path)operator(()ident(name)operator(\))operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) operator({) operator(|)ident(f)operator(|) ident(f)operator(.)ident(read) operator(}) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(delete)operator(()ident(name)operator(,) ident(options)operator(\)) comment(#:nodoc:) + constant(File)operator(.)ident(delete)operator(()ident(real_file_path)operator(()ident(name)operator(\))operator(\)) + reserved(rescue) constant(SystemCallError) operator(=)operator(>) ident(e) + comment(# If there's no cache, then there's nothing to complain about) + reserved(end) + + reserved(def) method(delete_matched)operator(()ident(matcher)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(search_dir)operator(()instance_variable(@cache_path)operator(\)) reserved(do) operator(|)ident(f)operator(|) + reserved(if) ident(f) operator(=)operator(~) ident(matcher) + reserved(begin) + constant(File)operator(.)ident(delete)operator(()ident(f)operator(\)) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + comment(# If there's no cache, then there's nothing to complain about) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(real_file_path)operator(()ident(name)operator(\)) + string<delimiter(')content(%s/%s.cache)delimiter(')> operator(%) operator([)instance_variable(@cache_path)operator(,) ident(name)operator(.)ident(gsub)operator(()string<delimiter(')content(?)delimiter(')>operator(,) string<delimiter(')content(.)delimiter(')>operator(\))operator(.)ident(gsub)operator(()string<delimiter(')content(:)delimiter(')>operator(,) string<delimiter(')content(.)delimiter(')>operator(\))operator(]) + reserved(end) + + reserved(def) method(ensure_cache_path)operator(()ident(path)operator(\)) + constant(FileUtils)operator(.)ident(makedirs)operator(()ident(path)operator(\)) reserved(unless) constant(File)operator(.)ident(exists?)operator(()ident(path)operator(\)) + reserved(end) + + reserved(def) method(search_dir)operator(()ident(dir)operator(,) operator(&)ident(callback)operator(\)) + constant(Dir)operator(.)ident(foreach)operator(()ident(dir)operator(\)) reserved(do) operator(|)ident(d)operator(|) + reserved(next) reserved(if) ident(d) operator(==) string<delimiter(")content(.)delimiter(")> operator(||) ident(d) operator(==) string<delimiter(")content(..)delimiter(")> + ident(name) operator(=) constant(File)operator(.)ident(join)operator(()ident(dir)operator(,) ident(d)operator(\)) + reserved(if) constant(File)operator(.)ident(directory?)operator(()ident(name)operator(\)) + ident(search_dir)operator(()ident(name)operator(,) operator(&)ident(callback)operator(\)) + reserved(else) + ident(callback)operator(.)ident(call) ident(name) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(FileStore) operator(<) constant(UnthreadedFileStore) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(cache_path)operator(\)) + reserved(super)operator(()ident(cache_path)operator(\)) + reserved(if) constant(ActionController)operator(::)constant(Base)operator(.)ident(allow_concurrency) + instance_variable(@mutex) operator(=) constant(Mutex)operator(.)ident(new) + constant(FileStore)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ThreadSafety)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.) + comment(# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:) + comment(#) + comment(# class ListSweeper < ActionController::Caching::Sweeper) + comment(# observe List, Item) + comment(#) + comment(# def after_save(record\)) + comment(# list = record.is_a?(List\) ? record : record.list) + comment(# expire_page(:controller => "lists", :action => %w( show public feed \), :id => list.id\)) + comment(# expire_action(:controller => "lists", :action => "all"\)) + comment(# list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key\) }) + comment(# end) + comment(# end) + comment(#) + comment(# The sweeper is assigned in the controllers that wish to have its job performed using the <tt>cache_sweeper</tt> class method:) + comment(#) + comment(# class ListsController < ApplicationController) + comment(# caches_action :index, :show, :public, :feed) + comment(# cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ]) + comment(# end) + comment(#) + comment(# In the example above, four actions are cached and three actions are responsible for expiring those caches.) + reserved(module) class(Sweeping) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + reserved(def) method(cache_sweeper)operator(()operator(*)ident(sweepers)operator(\)) + reserved(return) reserved(unless) ident(perform_caching) + ident(configuration) operator(=) ident(sweepers)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(sweepers)operator(.)ident(pop) operator(:) operator({)operator(}) + ident(sweepers)operator(.)ident(each) reserved(do) operator(|)ident(sweeper)operator(|) + ident(observer)operator(()ident(sweeper)operator(\)) + + ident(sweeper_instance) operator(=) constant(Object)operator(.)ident(const_get)operator(()constant(Inflector)operator(.)ident(classify)operator(()ident(sweeper)operator(\))operator(\))operator(.)ident(instance) + + reserved(if) ident(sweeper_instance)operator(.)ident(is_a?)operator(()constant(Sweeper)operator(\)) + ident(around_filter)operator(()ident(sweeper_instance)operator(,) symbol(:only) operator(=)operator(>) ident(configuration)operator([)symbol(:only)operator(])operator(\)) + reserved(else) + ident(after_filter)operator(()ident(sweeper_instance)operator(,) symbol(:only) operator(=)operator(>) ident(configuration)operator([)symbol(:only)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(if) reserved(defined?)operator(()constant(ActiveRecord)operator(\)) reserved(and) reserved(defined?)operator(()constant(ActiveRecord)operator(::)constant(Observer)operator(\)) + reserved(class) class(Sweeper) operator(<) constant(ActiveRecord)operator(::)constant(Observer) comment(#:nodoc:) + ident(attr_accessor) symbol(:controller) + + comment(# ActiveRecord::Observer will mark this class as reloadable even though it should not be.) + comment(# However, subclasses of ActionController::Caching::Sweeper should be Reloadable) + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + reserved(def) method(before)operator(()ident(controller)operator(\)) + pre_constant(self)operator(.)ident(controller) operator(=) ident(controller) + ident(callback)operator(()symbol(:before)operator(\)) + reserved(end) + + reserved(def) method(after)operator(()ident(controller)operator(\)) + ident(callback)operator(()symbol(:after)operator(\)) + comment(# Clean up, so that the controller can be collected after this request) + pre_constant(self)operator(.)ident(controller) operator(=) pre_constant(nil) + reserved(end) + + ident(private) + reserved(def) method(callback)operator(()ident(timing)operator(\)) + ident(controller_callback_method_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(timing)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(controller)operator(.)ident(controller_name)operator(.)ident(underscore)inline_delimiter(})>delimiter(")> + ident(action_callback_method_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(controller_callback_method_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(controller)operator(.)ident(action_name)inline_delimiter(})>delimiter(")> + + ident(send)operator(()ident(controller_callback_method_name)operator(\)) reserved(if) ident(respond_to?)operator(()ident(controller_callback_method_name)operator(\)) + ident(send)operator(()ident(action_callback_method_name)operator(\)) reserved(if) ident(respond_to?)operator(()ident(action_callback_method_name)operator(\)) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(\)) + reserved(return) reserved(if) instance_variable(@controller)operator(.)ident(nil?) + instance_variable(@controller)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(cgi/session)delimiter(')> +ident(require) string<delimiter(')content(cgi/session/pstore)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cgi_ext/cgi_methods)delimiter(')> + +comment(# Wrapper around the CGIMethods that have been secluded to allow testing without ) +comment(# an instantiated CGI object) +reserved(class) class(CGI) comment(#:nodoc:) + reserved(class) operator(<<) class(self) + reserved(alias) symbol(:escapeHTML_fail_on_nil) symbol(:escapeHTML) + + reserved(def) method(escapeHTML)operator(()ident(string)operator(\)) + ident(escapeHTML_fail_on_nil)operator(()ident(string)operator(\)) reserved(unless) ident(string)operator(.)ident(nil?) + reserved(end) + reserved(end) + + comment(# Returns a parameter hash including values from both the request (POST/GET\)) + comment(# and the query string with the latter taking precedence.) + reserved(def) method(parameters) + ident(request_parameters)operator(.)ident(update)operator(()ident(query_parameters)operator(\)) + reserved(end) + + reserved(def) method(query_parameters) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()ident(query_string)operator(\)) + reserved(end) + + reserved(def) method(request_parameters) + constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(params)operator(,) ident(env_table)operator(\)) + reserved(end) + + reserved(def) method(redirect)operator(()ident(where)operator(\)) + ident(header)operator(()operator({) + string<delimiter(")content(Status)delimiter(")> operator(=)operator(>) string<delimiter(")content(302 Moved)delimiter(")>operator(,) + string<delimiter(")content(location)delimiter(")> operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(where)inline_delimiter(})>delimiter(")> + operator(})operator(\)) + reserved(end) + + reserved(def) method(session)operator(()ident(parameters) operator(=) pre_constant(nil)operator(\)) + ident(parameters) operator(=) operator({)operator(}) reserved(if) ident(parameters)operator(.)ident(nil?) + ident(parameters)operator([)string<delimiter(')content(database_manager)delimiter(')>operator(]) operator(=) constant(CGI)operator(::)constant(Session)operator(::)constant(PStore) + constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(parameters)operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(action_controller/vendor/xml_simple)delimiter(')> +ident(require) string<delimiter(')content(action_controller/vendor/xml_node)delimiter(')> + +comment(# Static methods for parsing the query and request parameters that can be used in) +comment(# a CGI extension class or testing in isolation.) +reserved(class) class(CGIMethods) comment(#:nodoc:) + ident(public) + comment(# Returns a hash with the pairs from the query string. The implicit hash construction that is done in) + comment(# parse_request_params is not done here.) + reserved(def) constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()ident(query_string)operator(\)) + ident(parsed_params) operator(=) operator({)operator(}) + + ident(query_string)operator(.)ident(split)operator(()regexp<delimiter(/)content([&;])delimiter(/)>operator(\))operator(.)ident(each) operator({) operator(|)ident(p)operator(|) + comment(# Ignore repeated delimiters.) + reserved(next) reserved(if) ident(p)operator(.)ident(empty?) + + ident(k)operator(,) ident(v) operator(=) ident(p)operator(.)ident(split)operator(()string<delimiter(')content(=)delimiter(')>operator(,)integer(2)operator(\)) + ident(v) operator(=) pre_constant(nil) reserved(if) operator(()ident(v) operator(&&) ident(v)operator(.)ident(empty?)operator(\)) + + ident(k) operator(=) constant(CGI)operator(.)ident(unescape)operator(()ident(k)operator(\)) reserved(if) ident(k) + ident(v) operator(=) constant(CGI)operator(.)ident(unescape)operator(()ident(v)operator(\)) reserved(if) ident(v) + + reserved(unless) ident(k)operator(.)ident(include?)operator(()integer(?[)operator(\)) + ident(parsed_params)operator([)ident(k)operator(]) operator(=) ident(v) + reserved(else) + ident(keys) operator(=) ident(split_key)operator(()ident(k)operator(\)) + ident(last_key) operator(=) ident(keys)operator(.)ident(pop) + ident(last_key) operator(=) ident(keys)operator(.)ident(pop) reserved(if) operator(()ident(use_array) operator(=) ident(last_key)operator(.)ident(empty?)operator(\)) + ident(parent) operator(=) ident(keys)operator(.)ident(inject)operator(()ident(parsed_params)operator(\)) operator({)operator(|)ident(h)operator(,) ident(k)operator(|) ident(h)operator([)ident(k)operator(]) operator(||=) operator({)operator(})operator(}) + + reserved(if) ident(use_array) reserved(then) operator(()ident(parent)operator([)ident(last_key)operator(]) operator(||=) operator([)operator(])operator(\)) operator(<<) ident(v) + reserved(else) ident(parent)operator([)ident(last_key)operator(]) operator(=) ident(v) + reserved(end) + reserved(end) + operator(}) + + ident(parsed_params) + reserved(end) + + comment(# Returns the request (POST/GET\) parameters in a parsed form where pairs such as "customer[address][street]" / ) + comment(# "Somewhere cool!" are translated into a full hash hierarchy, like) + comment(# { "customer" => { "address" => { "street" => "Somewhere cool!" } } }) + reserved(def) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(params)operator(\)) + ident(parsed_params) operator(=) operator({)operator(}) + + reserved(for) ident(key)operator(,) ident(value) reserved(in) ident(params) + ident(value) operator(=) operator([)ident(value)operator(]) reserved(if) ident(key) operator(=)operator(~) regexp<delimiter(/)content(.*)char(\\[)char(\\])content($)delimiter(/)> + reserved(unless) ident(key)operator(.)ident(include?)operator(()string<delimiter(')content([)delimiter(')>operator(\)) + comment(# much faster to test for the most common case first (GET\)) + comment(# and avoid the call to build_deep_hash) + ident(parsed_params)operator([)ident(key)operator(]) operator(=) ident(get_typed_value)operator(()ident(value)operator([)integer(0)operator(])operator(\)) + reserved(else) + ident(build_deep_hash)operator(()ident(get_typed_value)operator(()ident(value)operator([)integer(0)operator(])operator(\))operator(,) ident(parsed_params)operator(,) ident(get_levels)operator(()ident(key)operator(\))operator(\)) + reserved(end) + reserved(end) + + ident(parsed_params) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(parse_formatted_request_parameters)operator(()ident(mime_type)operator(,) ident(raw_post_data)operator(\)) + ident(params) operator(=) reserved(case) ident(strategy) operator(=) constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)ident(mime_type)operator(]) + reserved(when) constant(Proc) + ident(strategy)operator(.)ident(call)operator(()ident(raw_post_data)operator(\)) + reserved(when) symbol(:xml_simple) + ident(raw_post_data)operator(.)ident(blank?) operator(?) pre_constant(nil) operator(:) + ident(typecast_xml_value)operator(()constant(XmlSimple)operator(.)ident(xml_in)operator(()ident(raw_post_data)operator(,) + string<delimiter(')content(forcearray)delimiter(')> operator(=)operator(>) pre_constant(false)operator(,) + string<delimiter(')content(forcecontent)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(keeproot)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) + string<delimiter(')content(contentkey)delimiter(')> operator(=)operator(>) string<delimiter(')content(__content__)delimiter(')>operator(\))operator(\)) + reserved(when) symbol(:yaml) + constant(YAML)operator(.)ident(load)operator(()ident(raw_post_data)operator(\)) + reserved(when) symbol(:xml_node) + ident(node) operator(=) constant(XmlNode)operator(.)ident(from_xml)operator(()ident(raw_post_data)operator(\)) + operator({) ident(node)operator(.)ident(node_name) operator(=)operator(>) ident(node) operator(}) + reserved(end) + + ident(dasherize_keys)operator(()ident(params) operator(||) operator({)operator(})operator(\)) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + operator({) string<delimiter(")content(exception)delimiter(")> operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(e)operator(.)ident(class)inline_delimiter(})>content(\))delimiter(")>operator(,) string<delimiter(")content(backtrace)delimiter(")> operator(=)operator(>) ident(e)operator(.)ident(backtrace)operator(,) + string<delimiter(")content(raw_post_data)delimiter(")> operator(=)operator(>) ident(raw_post_data)operator(,) string<delimiter(")content(format)delimiter(")> operator(=)operator(>) ident(mime_type) operator(}) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(typecast_xml_value)operator(()ident(value)operator(\)) + reserved(case) ident(value) + reserved(when) constant(Hash) + reserved(if) ident(value)operator(.)ident(has_key?)operator(()string<delimiter(")content(__content__)delimiter(")>operator(\)) + ident(content) operator(=) ident(translate_xml_entities)operator(()ident(value)operator([)string<delimiter(")content(__content__)delimiter(")>operator(])operator(\)) + reserved(case) ident(value)operator([)string<delimiter(")content(type)delimiter(")>operator(]) + reserved(when) string<delimiter(")content(integer)delimiter(")> reserved(then) ident(content)operator(.)ident(to_i) + reserved(when) string<delimiter(")content(boolean)delimiter(")> reserved(then) ident(content) operator(==) string<delimiter(")content(true)delimiter(")> + reserved(when) string<delimiter(")content(datetime)delimiter(")> reserved(then) constant(Time)operator(.)ident(parse)operator(()ident(content)operator(\)) + reserved(when) string<delimiter(")content(date)delimiter(")> reserved(then) constant(Date)operator(.)ident(parse)operator(()ident(content)operator(\)) + reserved(else) ident(content) + reserved(end) + reserved(else) + ident(value)operator(.)ident(empty?) operator(?) pre_constant(nil) operator(:) ident(value)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(h)operator(,)operator(()ident(k)operator(,)ident(v)operator(\))operator(|) + ident(h)operator([)ident(k)operator(]) operator(=) ident(typecast_xml_value)operator(()ident(v)operator(\)) + ident(h) + reserved(end) + reserved(end) + reserved(when) constant(Array) + ident(value)operator(.)ident(map!) operator({) operator(|)ident(i)operator(|) ident(typecast_xml_value)operator(()ident(i)operator(\)) operator(}) + reserved(case) ident(value)operator(.)ident(length) + reserved(when) integer(0) reserved(then) pre_constant(nil) + reserved(when) integer(1) reserved(then) ident(value)operator(.)ident(first) + reserved(else) ident(value) + reserved(end) + reserved(else) + ident(raise) string<delimiter(")content(can't typecast )inline<inline_delimiter(#{)ident(value)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + ident(private) + + reserved(def) pre_constant(self)operator(.)ident(translate_xml_entities)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(<)delimiter(/)>operator(,) string<delimiter(")content(<)delimiter(")>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(/)content(>)delimiter(/)>operator(,) string<delimiter(")content(>)delimiter(")>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(/)content(")delimiter(/)>operator(,) string<delimiter(')content(")delimiter(')>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(")content(')delimiter(")>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(/)content(&)delimiter(/)>operator(,) string<delimiter(")content(&)delimiter(")>operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(dasherize_keys)operator(()ident(params)operator(\)) + reserved(case) ident(params)operator(.)ident(class)operator(.)ident(to_s) + reserved(when) string<delimiter(")content(Hash)delimiter(")> + ident(params)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(h)operator(,)operator(()ident(k)operator(,)ident(v)operator(\))operator(|) + ident(h)operator([)ident(k)operator(.)ident(to_s)operator(.)ident(tr)operator(()string<delimiter(")content(-)delimiter(")>operator(,) string<delimiter(")content(_)delimiter(")>operator(\))operator(]) operator(=) ident(dasherize_keys)operator(()ident(v)operator(\)) + ident(h) + reserved(end) + reserved(when) string<delimiter(")content(Array)delimiter(")> + ident(params)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) ident(dasherize_keys)operator(()ident(v)operator(\)) operator(}) + reserved(else) + ident(params) + reserved(end) + reserved(end) + + comment(# Splits the given key into several pieces. Example keys are 'name', 'person[name]',) + comment(# 'person[name][first]', and 'people[]'. In each instance, an Array instance is returned.) + comment(# 'person[name][first]' produces ['person', 'name', 'first']; 'people[]' produces ['people', '']) + reserved(def) constant(CGIMethods)operator(.)ident(split_key)operator(()ident(key)operator(\)) + reserved(if) regexp<delimiter(/)content(^([^)char(\\[)content(]+\)((?:)char(\\[)content([^)char(\\])content(]*)char(\\])content(\)+\)$)delimiter(/)> operator(=)operator(~) ident(key) + ident(keys) operator(=) operator([)global_variable($1)operator(]) + + ident(keys)operator(.)ident(concat)operator(()global_variable($2)operator([)integer(1)operator(..)integer(-2)operator(])operator(.)ident(split)operator(()string<delimiter(')content(][)delimiter(')>operator(\))operator(\)) + ident(keys) operator(<<) string<delimiter(')delimiter(')> reserved(if) ident(key)operator([)integer(-2)operator(..)integer(-1)operator(]) operator(==) string<delimiter(')content([])delimiter(')> comment(# Have to add it since split will drop empty strings) + + ident(keys) + reserved(else) + operator([)ident(key)operator(]) + reserved(end) + reserved(end) + + reserved(def) constant(CGIMethods)operator(.)ident(get_typed_value)operator(()ident(value)operator(\)) + comment(# test most frequent case first) + reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(value) + reserved(elsif) ident(value)operator(.)ident(respond_to?)operator(()symbol(:content_type)operator(\)) operator(&&) operator(!) ident(value)operator(.)ident(content_type)operator(.)ident(blank?) + comment(# Uploaded file) + reserved(unless) ident(value)operator(.)ident(respond_to?)operator(()symbol(:full_original_filename)operator(\)) + reserved(class) operator(<<) class(value) + ident(alias_method) symbol(:full_original_filename)operator(,) symbol(:original_filename) + + comment(# Take the basename of the upload's original filename.) + comment(# This handles the full Windows paths given by Internet Explorer) + comment(# (and perhaps other broken user agents\) without affecting) + comment(# those which give the lone filename.) + comment(# The Windows regexp is adapted from Perl's File::Basename.) + reserved(def) method(original_filename) + reserved(if) ident(md) operator(=) regexp<delimiter(/)content(^(?:.*[:)char(\\\\)char(\\/)content(]\)?(.*\))delimiter(/)modifier(m)>operator(.)ident(match)operator(()ident(full_original_filename)operator(\)) + ident(md)operator(.)ident(captures)operator(.)ident(first) + reserved(else) + constant(File)operator(.)ident(basename) ident(full_original_filename) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Return the same value after overriding original_filename.) + ident(value) + + reserved(elsif) ident(value)operator(.)ident(respond_to?)operator(()symbol(:read)operator(\)) + comment(# Value as part of a multipart request) + ident(value)operator(.)ident(read) + reserved(elsif) ident(value)operator(.)ident(class) operator(==) constant(Array) + ident(value)operator(.)ident(collect) operator({) operator(|)ident(v)operator(|) constant(CGIMethods)operator(.)ident(get_typed_value)operator(()ident(v)operator(\)) operator(}) + reserved(else) + comment(# other value (neither string nor a multipart request\)) + ident(value)operator(.)ident(to_s) + reserved(end) + reserved(end) + + constant(PARAMS_HASH_RE) operator(=) regexp<delimiter(/)content(^([^)char(\\[)content(]+\)()char(\\[)content(.*)char(\\])content(\)?(.\)?.*$)delimiter(/)> + reserved(def) constant(CGIMethods)operator(.)ident(get_levels)operator(()ident(key)operator(\)) + ident(all)operator(,) ident(main)operator(,) ident(bracketed)operator(,) ident(trailing) operator(=) constant(PARAMS_HASH_RE)operator(.)ident(match)operator(()ident(key)operator(\))operator(.)ident(to_a) + reserved(if) ident(main)operator(.)ident(nil?) + operator([)operator(]) + reserved(elsif) ident(trailing) + operator([)ident(key)operator(]) + reserved(elsif) ident(bracketed) + operator([)ident(main)operator(]) operator(+) ident(bracketed)operator(.)ident(slice)operator(()integer(1)operator(...)integer(-1)operator(\))operator(.)ident(split)operator(()string<delimiter(')content(][)delimiter(')>operator(\)) + reserved(else) + operator([)ident(main)operator(]) + reserved(end) + reserved(end) + + reserved(def) constant(CGIMethods)operator(.)ident(build_deep_hash)operator(()ident(value)operator(,) ident(hash)operator(,) ident(levels)operator(\)) + reserved(if) ident(levels)operator(.)ident(length) operator(==) integer(0) + ident(value) + reserved(elsif) ident(hash)operator(.)ident(nil?) + operator({) ident(levels)operator(.)ident(first) operator(=)operator(>) constant(CGIMethods)operator(.)ident(build_deep_hash)operator(()ident(value)operator(,) pre_constant(nil)operator(,) ident(levels)operator([)integer(1)operator(..)integer(-1)operator(])operator(\)) operator(}) + reserved(else) + ident(hash)operator(.)ident(update)operator(()operator({) ident(levels)operator(.)ident(first) operator(=)operator(>) constant(CGIMethods)operator(.)ident(build_deep_hash)operator(()ident(value)operator(,) ident(hash)operator([)ident(levels)operator(.)ident(first)operator(])operator(,) ident(levels)operator([)integer(1)operator(..)integer(-1)operator(])operator(\)) operator(})operator(\)) + reserved(end) + reserved(end) +reserved(end) +constant(CGI)operator(.)ident(module_eval) operator({) ident(remove_const) string<delimiter(")content(Cookie)delimiter(")> operator(}) + +reserved(class) class(CGI) comment(#:nodoc:) + comment(# This is a cookie class that fixes the performance problems with the default one that ships with 1.8.1 and below.) + comment(# It replaces the inheritance on SimpleDelegator with DelegateClass(Array\) following the suggestion from Matz on) + comment(# http://groups.google.com/groups?th=e3a4e68ba042f842&seekm=c3sioe%241qvm%241%40news.cybercity.dk#link14) + reserved(class) class(Cookie) operator(<) ident(DelegateClass)operator(()constant(Array)operator(\)) + comment(# Create a new CGI::Cookie object.) + comment(#) + comment(# The contents of the cookie can be specified as a +name+ and one) + comment(# or more +value+ arguments. Alternatively, the contents can) + comment(# be specified as a single hash argument. The possible keywords of) + comment(# this hash are as follows:) + comment(#) + comment(# name:: the name of the cookie. Required.) + comment(# value:: the cookie's value or list of values.) + comment(# path:: the path for which this cookie applies. Defaults to the) + comment(# base directory of the CGI script.) + comment(# domain:: the domain for which this cookie applies.) + comment(# expires:: the time at which this cookie expires, as a +Time+ object.) + comment(# secure:: whether this cookie is a secure cookie or not (default to) + comment(# false\). Secure cookies are only transmitted to HTTPS ) + comment(# servers.) + comment(#) + comment(# These keywords correspond to attributes of the cookie object.) + reserved(def) method(initialize)operator(()ident(name) operator(=) string<delimiter(')delimiter(')>operator(,) operator(*)ident(value)operator(\)) + reserved(if) ident(name)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) + instance_variable(@name) operator(=) ident(name) + instance_variable(@value) operator(=) ident(Array)operator(()ident(value)operator(\)) + instance_variable(@domain) operator(=) pre_constant(nil) + instance_variable(@expires) operator(=) pre_constant(nil) + instance_variable(@secure) operator(=) pre_constant(false) + instance_variable(@path) operator(=) pre_constant(nil) + reserved(else) + instance_variable(@name) operator(=) ident(name)operator([)string<delimiter(')content(name)delimiter(')>operator(]) + instance_variable(@value) operator(=) ident(Array)operator(()ident(name)operator([)string<delimiter(')content(value)delimiter(')>operator(])operator(\)) + instance_variable(@domain) operator(=) ident(name)operator([)string<delimiter(')content(domain)delimiter(')>operator(]) + instance_variable(@expires) operator(=) ident(name)operator([)string<delimiter(')content(expires)delimiter(')>operator(]) + instance_variable(@secure) operator(=) ident(name)operator([)string<delimiter(')content(secure)delimiter(')>operator(]) operator(||) pre_constant(false) + instance_variable(@path) operator(=) ident(name)operator([)string<delimiter(')content(path)delimiter(')>operator(]) + reserved(end) + + reserved(unless) instance_variable(@name) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(`name' required)delimiter(")> + reserved(end) + + comment(# simple support for IE) + reserved(unless) instance_variable(@path) + regexp<delimiter(%r|)content(^(.*/\))delimiter(|)>operator(.)ident(match)operator(()constant(ENV)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(])operator(\)) + instance_variable(@path) operator(=) operator(()global_variable($1) reserved(or) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(super)operator(()instance_variable(@value)operator(\)) + reserved(end) + + reserved(def) method(__setobj__)operator(()ident(obj)operator(\)) + instance_variable(@_dc_obj) operator(=) ident(obj) + reserved(end) + + ident(attr_accessor)operator(()string<delimiter(")content(name)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")>operator(,) string<delimiter(")content(path)delimiter(")>operator(,) string<delimiter(")content(domain)delimiter(")>operator(,) string<delimiter(")content(expires)delimiter(")>operator(\)) + ident(attr_reader)operator(()string<delimiter(")content(secure)delimiter(")>operator(\)) + + comment(# Set whether the Cookie is a secure cookie or not.) + comment(#) + comment(# +val+ must be a boolean.) + reserved(def) method(secure=)operator(()ident(val)operator(\)) + instance_variable(@secure) operator(=) ident(val) reserved(if) ident(val) operator(==) pre_constant(true) reserved(or) ident(val) operator(==) pre_constant(false) + instance_variable(@secure) + reserved(end) + + comment(# Convert the Cookie to its string representation.) + reserved(def) method(to_s) + ident(buf) operator(=) string<delimiter(")delimiter(")> + ident(buf) operator(<<) instance_variable(@name) operator(<<) string<delimiter(')content(=)delimiter(')> + + reserved(if) instance_variable(@value)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) + ident(buf) operator(<<) constant(CGI)operator(::)ident(escape)operator(()instance_variable(@value)operator(\)) + reserved(else) + ident(buf) operator(<<) instance_variable(@value)operator(.)ident(collect)operator({)operator(|)ident(v)operator(|) constant(CGI)operator(::)ident(escape)operator(()ident(v)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(&)delimiter(")>operator(\)) + reserved(end) + + reserved(if) instance_variable(@domain) + ident(buf) operator(<<) string<delimiter(')content(; domain=)delimiter(')> operator(<<) instance_variable(@domain) + reserved(end) + + reserved(if) instance_variable(@path) + ident(buf) operator(<<) string<delimiter(')content(; path=)delimiter(')> operator(<<) instance_variable(@path) + reserved(end) + + reserved(if) instance_variable(@expires) + ident(buf) operator(<<) string<delimiter(')content(; expires=)delimiter(')> operator(<<) constant(CGI)operator(::)ident(rfc1123_date)operator(()instance_variable(@expires)operator(\)) + reserved(end) + + reserved(if) instance_variable(@secure) operator(==) pre_constant(true) + ident(buf) operator(<<) string<delimiter(')content(; secure)delimiter(')> + reserved(end) + + ident(buf) + reserved(end) + + comment(# Parse a raw cookie string into a hash of cookie-name=>Cookie) + comment(# pairs.) + comment(#) + comment(# cookies = CGI::Cookie::parse("raw_cookie_string"\)) + comment(# # { "name1" => cookie1, "name2" => cookie2, ... }) + comment(#) + reserved(def) pre_constant(self)operator(.)ident(parse)operator(()ident(raw_cookie)operator(\)) + ident(cookies) operator(=) constant(Hash)operator(.)ident(new)operator(()operator([)operator(])operator(\)) + + reserved(if) ident(raw_cookie) + ident(raw_cookie)operator(.)ident(split)operator(()regexp<delimiter(/)content(; ?)delimiter(/)>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(pairs)operator(|) + ident(name)operator(,) ident(values) operator(=) ident(pairs)operator(.)ident(split)operator(()string<delimiter(')content(=)delimiter(')>operator(,)integer(2)operator(\)) + reserved(next) reserved(unless) ident(name) reserved(and) ident(values) + ident(name) operator(=) constant(CGI)operator(::)ident(unescape)operator(()ident(name)operator(\)) + ident(values) operator(=) ident(values)operator(.)ident(split)operator(()string<delimiter(')content(&)delimiter(')>operator(\))operator(.)ident(collect!)operator({)operator(|)ident(v)operator(|) constant(CGI)operator(::)ident(unescape)operator(()ident(v)operator(\)) operator(}) + reserved(unless) ident(cookies)operator(.)ident(has_key?)operator(()ident(name)operator(\)) + ident(cookies)operator([)ident(name)operator(]) operator(=) ident(new)operator(()ident(name)operator(,) operator(*)ident(values)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + ident(cookies) + reserved(end) + reserved(end) comment(# class Cookie) +reserved(end) +reserved(class) class(CGI) comment(#:nodoc:) + comment(# Add @request.env['RAW_POST_DATA'] for the vegans.) + reserved(module) class(QueryExtension) + comment(# Initialize the data from the query.) + comment(#) + comment(# Handles multipart forms (in particular, forms that involve file uploads\).) + comment(# Reads query parameters in the @params field, and cookies into @cookies.) + reserved(def) method(initialize_query)operator(()operator(\)) + instance_variable(@cookies) operator(=) constant(CGI)operator(::)constant(Cookie)operator(::)ident(parse)operator(()ident(env_table)operator([)string<delimiter(')content(HTTP_COOKIE)delimiter(')>operator(]) operator(||) ident(env_table)operator([)string<delimiter(')content(COOKIE)delimiter(')>operator(])operator(\)) + + comment(#fix some strange request environments) + reserved(if) ident(method) operator(=) ident(env_table)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) + ident(method) operator(=) ident(method)operator(.)ident(to_s)operator(.)ident(downcase)operator(.)ident(intern) + reserved(else) + ident(method) operator(=) symbol(:get) + reserved(end) + + reserved(if) ident(method) operator(==) symbol(:post) operator(&&) operator(()ident(boundary) operator(=) ident(multipart_form_boundary)operator(\)) + instance_variable(@multipart) operator(=) pre_constant(true) + instance_variable(@params) operator(=) ident(read_multipart)operator(()ident(boundary)operator(,) ident(Integer)operator(()ident(env_table)operator([)string<delimiter(')content(CONTENT_LENGTH)delimiter(')>operator(])operator(\))operator(\)) + reserved(else) + instance_variable(@multipart) operator(=) pre_constant(false) + instance_variable(@params) operator(=) constant(CGI)operator(::)ident(parse)operator(()ident(read_query_params)operator(()ident(method)operator(\)) operator(||) string<delimiter(")delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(unless) reserved(defined?)operator(()constant(MULTIPART_FORM_BOUNDARY_RE)operator(\)) + constant(MULTIPART_FORM_BOUNDARY_RE) operator(=) regexp<delimiter(%r|)char(\\A)content(multipart/form-data.*boundary=)char(\\")content(?([^)char(\\")content(;,]+\))char(\\")content(?)delimiter(|)modifier(n)> comment(#") + reserved(end) + + reserved(def) method(multipart_form_boundary) + constant(MULTIPART_FORM_BOUNDARY_RE)operator(.)ident(match)operator(()ident(env_table)operator([)string<delimiter(')content(CONTENT_TYPE)delimiter(')>operator(])operator(\))operator(.)ident(to_a)operator(.)ident(pop) + reserved(end) + + reserved(if) reserved(defined?) constant(MOD_RUBY) + reserved(def) method(read_params_from_query) + constant(Apache)operator(::)ident(request)operator(.)ident(args) operator(||) string<delimiter(')delimiter(')> + reserved(end) + reserved(else) + reserved(def) method(read_params_from_query) + comment(# fixes CGI querystring parsing for lighttpd) + ident(env_qs) operator(=) ident(env_table)operator([)string<delimiter(')content(QUERY_STRING)delimiter(')>operator(]) + reserved(if) ident(env_qs)operator(.)ident(blank?) operator(&&) operator(!)operator(()ident(uri) operator(=) ident(env_table)operator([)string<delimiter(')content(REQUEST_URI)delimiter(')>operator(])operator(\))operator(.)ident(blank?) + ident(uri)operator(.)ident(split)operator(()string<delimiter(')content(?)delimiter(')>operator(,) integer(2)operator(\))operator([)integer(1)operator(]) operator(||) string<delimiter(')delimiter(')> + reserved(else) + ident(env_qs) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(read_params_from_post) + ident(stdinput)operator(.)ident(binmode) reserved(if) ident(stdinput)operator(.)ident(respond_to?)operator(()symbol(:binmode)operator(\)) + ident(content) operator(=) ident(stdinput)operator(.)ident(read)operator(()ident(Integer)operator(()ident(env_table)operator([)string<delimiter(')content(CONTENT_LENGTH)delimiter(')>operator(])operator(\))operator(\)) operator(||) string<delimiter(')delimiter(')> + comment(# fix for Safari Ajax postings that always append \\000) + ident(content)operator(.)ident(chop!) reserved(if) ident(content)operator([)integer(-1)operator(]) operator(==) integer(0) + ident(content)operator(.)ident(gsub!) regexp<delimiter(/)content(&_=$)delimiter(/)>operator(,) string<delimiter(')delimiter(')> + ident(env_table)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) operator(=) ident(content)operator(.)ident(freeze) + reserved(end) + + reserved(def) method(read_query_params)operator(()ident(method)operator(\)) + reserved(case) ident(method) + reserved(when) symbol(:get) + ident(read_params_from_query) + reserved(when) symbol(:post)operator(,) symbol(:put) + ident(read_params_from_post) + reserved(when) symbol(:cmd) + ident(read_from_cmdline) + reserved(else) comment(# when :head, :delete, :options) + ident(read_params_from_query) + reserved(end) + reserved(end) + reserved(end) comment(# module QueryExtension) +reserved(end) +ident(require) string<delimiter(')content(action_controller/cgi_ext/cgi_ext)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cgi_ext/cookie_performance_fix)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cgi_ext/raw_post_data_fix)delimiter(')> + +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(class) class(Base) + comment(# Process a request extracted from an CGI object and return a response. Pass false as <tt>session_options</tt> to disable) + comment(# sessions (large performance increase if sessions are not needed\). The <tt>session_options</tt> are the same as for CGI::Session:) + comment(#) + comment(# * <tt>:database_manager</tt> - standard options are CGI::Session::FileStore, CGI::Session::MemoryStore, and CGI::Session::PStore) + comment(# (default\). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in ) + comment(# lib/action_controller/session.) + comment(# * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'.) + comment(# * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter) + comment(# of the request, or automatically generated for a new session.) + comment(# * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently) + comment(# exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set, ) + comment(# an ArgumentError is raised.) + comment(# * <tt>:session_expires</tt> - the time the current session expires, as a +Time+ object. If not set, the session will continue) + comment(# indefinitely.) + comment(# * <tt>:session_domain</tt> - the hostname domain for which this session is valid. If not set, defaults to the hostname of the) + comment(# server.) + comment(# * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS.) + comment(# * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script.) + reserved(def) pre_constant(self)operator(.)ident(process_cgi)operator(()ident(cgi) operator(=) constant(CGI)operator(.)ident(new)operator(,) ident(session_options) operator(=) operator({)operator(})operator(\)) + ident(new)operator(.)ident(process_cgi)operator(()ident(cgi)operator(,) ident(session_options)operator(\)) + reserved(end) + + reserved(def) method(process_cgi)operator(()ident(cgi)operator(,) ident(session_options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(process)operator(()constant(CgiRequest)operator(.)ident(new)operator(()ident(cgi)operator(,) ident(session_options)operator(\))operator(,) constant(CgiResponse)operator(.)ident(new)operator(()ident(cgi)operator(\))operator(\))operator(.)ident(out) + reserved(end) + reserved(end) + + reserved(class) class(CgiRequest) operator(<) constant(AbstractRequest) comment(#:nodoc:) + ident(attr_accessor) symbol(:cgi)operator(,) symbol(:session_options) + + constant(DEFAULT_SESSION_OPTIONS) operator(=) operator({) + symbol(:database_manager) operator(=)operator(>) constant(CGI)operator(::)constant(Session)operator(::)constant(PStore)operator(,) + symbol(:prefix) operator(=)operator(>) string<delimiter(")content(ruby_sess.)delimiter(")>operator(,) + symbol(:session_path) operator(=)operator(>) string<delimiter(")content(/)delimiter(")> + operator(}) reserved(unless) ident(const_defined?)operator(()symbol(:DEFAULT_SESSION_OPTIONS)operator(\)) + + reserved(def) method(initialize)operator(()ident(cgi)operator(,) ident(session_options) operator(=) operator({)operator(})operator(\)) + instance_variable(@cgi) operator(=) ident(cgi) + instance_variable(@session_options) operator(=) ident(session_options) + instance_variable(@env) operator(=) instance_variable(@cgi)operator(.)ident(send)operator(()symbol(:env_table)operator(\)) + reserved(super)operator(()operator(\)) + reserved(end) + + reserved(def) method(query_string) + reserved(if) operator(()ident(qs) operator(=) instance_variable(@cgi)operator(.)ident(query_string)operator(\)) operator(&&) operator(!)ident(qs)operator(.)ident(empty?) + ident(qs) + reserved(elsif) ident(uri) operator(=) instance_variable(@env)operator([)string<delimiter(')content(REQUEST_URI)delimiter(')>operator(]) + ident(parts) operator(=) ident(uri)operator(.)ident(split)operator(()string<delimiter(')content(?)delimiter(')>operator(\)) + ident(parts)operator(.)ident(shift) + ident(parts)operator(.)ident(join)operator(()string<delimiter(')content(?)delimiter(')>operator(\)) + reserved(else) + instance_variable(@env)operator([)string<delimiter(')content(QUERY_STRING)delimiter(')>operator(]) operator(||) string<delimiter(')delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(query_parameters) + operator(()ident(qs) operator(=) pre_constant(self)operator(.)ident(query_string)operator(\))operator(.)ident(empty?) operator(?) operator({)operator(}) operator(:) constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()ident(qs)operator(\)) + reserved(end) + + reserved(def) method(request_parameters) + instance_variable(@request_parameters) operator(||=) + reserved(if) constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator(.)ident(has_key?)operator(()ident(content_type)operator(\)) + constant(CGIMethods)operator(.)ident(parse_formatted_request_parameters)operator(()ident(content_type)operator(,) instance_variable(@env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(])operator(\)) + reserved(else) + constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()instance_variable(@cgi)operator(.)ident(params)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(cookies) + instance_variable(@cgi)operator(.)ident(cookies)operator(.)ident(freeze) + reserved(end) + + reserved(def) method(host_with_port) + reserved(if) ident(forwarded) operator(=) ident(env)operator([)string<delimiter(")content(HTTP_X_FORWARDED_HOST)delimiter(")>operator(]) + ident(forwarded)operator(.)ident(split)operator(()regexp<delimiter(/)content(,)char(\\s)content(?)delimiter(/)>operator(\))operator(.)ident(last) + reserved(elsif) ident(http_host) operator(=) ident(env)operator([)string<delimiter(')content(HTTP_HOST)delimiter(')>operator(]) + ident(http_host) + reserved(elsif) ident(server_name) operator(=) ident(env)operator([)string<delimiter(')content(SERVER_NAME)delimiter(')>operator(]) + ident(server_name) + reserved(else) + string<delimiter(")inline<inline_delimiter(#{)ident(env)operator([)string<delimiter(')content(SERVER_ADDR)delimiter(')>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(env)operator([)string<delimiter(')content(SERVER_PORT)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(host) + ident(host_with_port)operator([)regexp<delimiter(/)content(^[^:]+)delimiter(/)>operator(]) + reserved(end) + + reserved(def) method(port) + reserved(if) ident(host_with_port) operator(=)operator(~) regexp<delimiter(/)content(:()char(\\d)content(+\)$)delimiter(/)> + global_variable($1)operator(.)ident(to_i) + reserved(else) + ident(standard_port) + reserved(end) + reserved(end) + + reserved(def) method(session) + reserved(unless) instance_variable(@session) + reserved(if) instance_variable(@session_options) operator(==) pre_constant(false) + instance_variable(@session) operator(=) constant(Hash)operator(.)ident(new) + reserved(else) + ident(stale_session_check!) reserved(do) + reserved(if) ident(session_options_with_string_keys)operator([)string<delimiter(')content(new_session)delimiter(')>operator(]) operator(==) pre_constant(true) + instance_variable(@session) operator(=) ident(new_session) + reserved(else) + instance_variable(@session) operator(=) constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()instance_variable(@cgi)operator(,) ident(session_options_with_string_keys)operator(\)) + reserved(end) + instance_variable(@session)operator([)string<delimiter(')content(__valid_session)delimiter(')>operator(]) + reserved(end) + reserved(end) + reserved(end) + instance_variable(@session) + reserved(end) + + reserved(def) method(reset_session) + instance_variable(@session)operator(.)ident(delete) reserved(if) constant(CGI)operator(::)constant(Session) operator(===) instance_variable(@session) + instance_variable(@session) operator(=) ident(new_session) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(method_id)operator(,) operator(*)ident(arguments)operator(\)) + instance_variable(@cgi)operator(.)ident(send)operator(()ident(method_id)operator(,) operator(*)ident(arguments)operator(\)) reserved(rescue) reserved(super) + reserved(end) + + ident(private) + comment(# Delete an old session if it exists then create a new one.) + reserved(def) method(new_session) + reserved(if) instance_variable(@session_options) operator(==) pre_constant(false) + constant(Hash)operator(.)ident(new) + reserved(else) + constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()instance_variable(@cgi)operator(,) ident(session_options_with_string_keys)operator(.)ident(merge)operator(()string<delimiter(")content(new_session)delimiter(")> operator(=)operator(>) pre_constant(false)operator(\))operator(\))operator(.)ident(delete) reserved(rescue) pre_constant(nil) + constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()instance_variable(@cgi)operator(,) ident(session_options_with_string_keys)operator(.)ident(merge)operator(()string<delimiter(")content(new_session)delimiter(")> operator(=)operator(>) pre_constant(true)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(stale_session_check!) + reserved(yield) + reserved(rescue) constant(ArgumentError) operator(=)operator(>) ident(argument_error) + reserved(if) ident(argument_error)operator(.)ident(message) operator(=)operator(~) regexp<delimiter(%r{)content(undefined class/module ()char(\\w)content(+\))delimiter(})> + reserved(begin) + constant(Module)operator(.)ident(const_missing)operator(()global_variable($1)operator(\)) + reserved(rescue) constant(LoadError)operator(,) constant(NameError) operator(=)operator(>) ident(const_error) + ident(raise) constant(ActionController)operator(::)constant(SessionRestoreError)operator(,) string<delimiter(<<end_msg)>string<content( +Session contains objects whose class definition isn)char(\\')content(t available. +Remember to require the classes for all objects kept in the session. +(Original exception: )inline<inline_delimiter(#{)ident(const_error)operator(.)ident(message)inline_delimiter(})>content( [)inline<inline_delimiter(#{)ident(const_error)operator(.)ident(class)inline_delimiter(})>content(]\))delimiter( +end_msg)> + reserved(end) + + reserved(retry) + reserved(else) + ident(raise) + reserved(end) + reserved(end) + + reserved(def) method(session_options_with_string_keys) + instance_variable(@session_options_with_string_keys) operator(||=) constant(DEFAULT_SESSION_OPTIONS)operator(.)ident(merge)operator(()instance_variable(@session_options)operator(\))operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(options)operator(,) operator(()ident(k)operator(,)ident(v)operator(\))operator(|) ident(options)operator([)ident(k)operator(.)ident(to_s)operator(]) operator(=) ident(v)operator(;) ident(options) operator(}) + reserved(end) + reserved(end) + + reserved(class) class(CgiResponse) operator(<) constant(AbstractResponse) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(cgi)operator(\)) + instance_variable(@cgi) operator(=) ident(cgi) + reserved(super)operator(()operator(\)) + reserved(end) + + reserved(def) method(out)operator(()ident(output) operator(=) global_variable($stdout)operator(\)) + ident(convert_content_type!)operator(()instance_variable(@headers)operator(\)) + ident(output)operator(.)ident(binmode) reserved(if) ident(output)operator(.)ident(respond_to?)operator(()symbol(:binmode)operator(\)) + ident(output)operator(.)ident(sync) operator(=) pre_constant(false) reserved(if) ident(output)operator(.)ident(respond_to?)operator(()symbol(:sync=)operator(\)) + + reserved(begin) + ident(output)operator(.)ident(write)operator(()instance_variable(@cgi)operator(.)ident(header)operator(()instance_variable(@headers)operator(\))operator(\)) + + reserved(if) instance_variable(@cgi)operator(.)ident(send)operator(()symbol(:env_table)operator(\))operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(==) string<delimiter(')content(HEAD)delimiter(')> + reserved(return) + reserved(elsif) instance_variable(@body)operator(.)ident(respond_to?)operator(()symbol(:call)operator(\)) + instance_variable(@body)operator(.)ident(call)operator(()pre_constant(self)operator(,) ident(output)operator(\)) + reserved(else) + ident(output)operator(.)ident(write)operator(()instance_variable(@body)operator(\)) + reserved(end) + + ident(output)operator(.)ident(flush) reserved(if) ident(output)operator(.)ident(respond_to?)operator(()symbol(:flush)operator(\)) + reserved(rescue) constant(Errno)operator(::)constant(EPIPE) operator(=)operator(>) ident(e) + comment(# lost connection to the FCGI process -- ignore the output, then) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(convert_content_type!)operator(()ident(headers)operator(\)) + reserved(if) ident(header) operator(=) ident(headers)operator(.)ident(delete)operator(()string<delimiter(")content(Content-Type)delimiter(")>operator(\)) + ident(headers)operator([)string<delimiter(")content(type)delimiter(")>operator(]) operator(=) ident(header) + reserved(end) + reserved(if) ident(header) operator(=) ident(headers)operator(.)ident(delete)operator(()string<delimiter(")content(Content-type)delimiter(")>operator(\)) + ident(headers)operator([)string<delimiter(")content(type)delimiter(")>operator(]) operator(=) ident(header) + reserved(end) + reserved(if) ident(header) operator(=) ident(headers)operator(.)ident(delete)operator(()string<delimiter(")content(content-type)delimiter(")>operator(\)) + ident(headers)operator([)string<delimiter(")content(type)delimiter(")>operator(]) operator(=) ident(header) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) + reserved(module) class(CodeGeneration) comment(#:nodoc:) + reserved(class) class(GenerationError) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + + reserved(class) class(Source) comment(#:nodoc:) + ident(attr_reader) symbol(:lines)operator(,) symbol(:indentation_level) + constant(IndentationString) operator(=) string<delimiter(')content( )delimiter(')> + reserved(def) method(initialize) + instance_variable(@lines)operator(,) instance_variable(@indentation_level) operator(=) operator([)operator(])operator(,) integer(0) + reserved(end) + reserved(def) method(line)operator(()ident(line)operator(\)) + instance_variable(@lines) operator(<<) operator(()constant(IndentationString) operator(*) instance_variable(@indentation_level) operator(+) ident(line)operator(\)) + reserved(end) + reserved(alias) symbol(:<<) symbol(:line) + + reserved(def) method(indent) + instance_variable(@indentation_level) operator(+=) integer(1) + reserved(yield) + reserved(ensure) + instance_variable(@indentation_level) operator(-=) integer(1) + reserved(end) + + reserved(def) method(to_s)operator(()operator(\)) ident(lines)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) reserved(end) + reserved(end) + + reserved(class) class(CodeGenerator) comment(#:nodoc:) + ident(attr_accessor) symbol(:source)operator(,) symbol(:locals) + reserved(def) method(initialize)operator(()ident(source) operator(=) pre_constant(nil)operator(\)) + instance_variable(@locals) operator(=) operator([)operator(]) + instance_variable(@source) operator(=) ident(source) operator(||) constant(Source)operator(.)ident(new) + reserved(end) + + constant(BeginKeywords) operator(=) string<delimiter(%w()content(if unless begin until while def)delimiter(\))>operator(.)ident(collect) operator({)operator(|)ident(kw)operator(|) ident(kw)operator(.)ident(to_sym)operator(}) + constant(ResumeKeywords) operator(=) string<delimiter(%w()content(elsif else rescue)delimiter(\))>operator(.)ident(collect) operator({)operator(|)ident(kw)operator(|) ident(kw)operator(.)ident(to_sym)operator(}) + constant(Keywords) operator(=) constant(BeginKeywords) operator(+) constant(ResumeKeywords) + + reserved(def) method(method_missing)operator(()ident(keyword)operator(,) operator(*)ident(text)operator(\)) + reserved(if) constant(Keywords)operator(.)ident(include?) ident(keyword) + reserved(if) constant(ResumeKeywords)operator(.)ident(include?) ident(keyword) + ident(raise) constant(GenerationError)operator(,) string<delimiter(")content(Can only resume with )inline<inline_delimiter(#{)ident(keyword)inline_delimiter(})>content( immediately after an end)delimiter(")> reserved(unless) ident(source)operator(.)ident(lines)operator(.)ident(last) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*end)char(\\s)content(*$)delimiter(/)> + ident(source)operator(.)ident(lines)operator(.)ident(pop) comment(# Remove the 'end') + reserved(end) + + ident(line) string<delimiter(")inline<inline_delimiter(#{)ident(keyword)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(text)operator(.)ident(join) string<delimiter(')content( )delimiter(')>inline_delimiter(})>delimiter(")> + reserved(begin) ident(source)operator(.)ident(indent) operator({) reserved(yield)operator(()pre_constant(self)operator(.)ident(dup)operator(\)) operator(}) + reserved(ensure) ident(line) string<delimiter(')content(end)delimiter(')> + reserved(end) + reserved(else) + reserved(super)operator(()ident(keyword)operator(,) operator(*)ident(text)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(line)operator(()operator(*)ident(args)operator(\)) pre_constant(self)operator(.)ident(source)operator(.)ident(line)operator(()operator(*)ident(args)operator(\)) reserved(end) + reserved(alias) symbol(:<<) symbol(:line) + reserved(def) method(indent)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) ident(source)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) reserved(end) + reserved(def) method(to_s)operator(()operator(\)) ident(source)operator(.)ident(to_s) reserved(end) + + reserved(def) method(share_locals_with)operator(()ident(other)operator(\)) + ident(other)operator(.)ident(locals) operator(=) pre_constant(self)operator(.)ident(locals) operator(=) operator(()ident(other)operator(.)ident(locals) operator(|) ident(locals)operator(\)) + reserved(end) + + constant(FieldsToDuplicate) operator(=) operator([)symbol(:locals)operator(]) + reserved(def) method(dup) + ident(copy) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(new)operator(()ident(source)operator(\)) + pre_constant(self)operator(.)ident(class)operator(::)constant(FieldsToDuplicate)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(value) operator(=) pre_constant(self)operator(.)ident(send)operator(()ident(sym)operator(\)) + ident(value) operator(=) ident(value)operator(.)ident(dup) reserved(unless) ident(value)operator(.)ident(nil?) operator(||) ident(value)operator(.)ident(is_a?)operator(()constant(Numeric)operator(\)) + ident(copy)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=)delimiter(")>operator(,) ident(value)operator(\)) + reserved(end) + reserved(return) ident(copy) + reserved(end) + reserved(end) + + reserved(class) class(RecognitionGenerator) operator(<) constant(CodeGenerator) comment(#:nodoc:) + constant(Attributes) operator(=) operator([)symbol(:after)operator(,) symbol(:before)operator(,) symbol(:current)operator(,) symbol(:results)operator(,) symbol(:constants)operator(,) symbol(:depth)operator(,) symbol(:move_ahead)operator(,) symbol(:finish_statement)operator(]) + ident(attr_accessor)operator(()operator(*)constant(Attributes)operator(\)) + constant(FieldsToDuplicate) operator(=) constant(CodeGenerator)operator(::)constant(FieldsToDuplicate) operator(+) constant(Attributes) + + reserved(def) method(initialize)operator(()operator(*)ident(args)operator(\)) + reserved(super)operator(()operator(*)ident(args)operator(\)) + instance_variable(@after)operator(,) instance_variable(@before) operator(=) operator([)operator(])operator(,) operator([)operator(]) + instance_variable(@current) operator(=) pre_constant(nil) + instance_variable(@results)operator(,) instance_variable(@constants) operator(=) operator({)operator(})operator(,) operator({)operator(}) + instance_variable(@depth) operator(=) integer(0) + instance_variable(@move_ahead) operator(=) pre_constant(nil) + instance_variable(@finish_statement) operator(=) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(hash_expr)operator(|) ident(hash_expr)operator(}) + reserved(end) + + reserved(def) method(if_next_matches)operator(()ident(string)operator(,) operator(&)ident(block)operator(\)) + ident(test) operator(=) constant(Routing)operator(.)ident(test_condition)operator(()ident(next_segment)operator(()pre_constant(true)operator(\))operator(,) ident(string)operator(\)) + pre_constant(self)operator(.)ident(if)operator(()ident(test)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(move_forward)operator(()ident(places) operator(=) integer(1)operator(\)) + ident(dup) operator(=) pre_constant(self)operator(.)ident(dup) + ident(dup)operator(.)ident(depth) operator(+=) integer(1) + ident(dup)operator(.)ident(move_ahead) operator(=) ident(places) + reserved(yield) ident(dup) + reserved(end) + + reserved(def) method(next_segment)operator(()ident(assign_inline) operator(=) pre_constant(false)operator(,) ident(default) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(locals)operator(.)ident(include?)operator(()ident(segment_name)operator(\)) + ident(code) operator(=) ident(segment_name) + reserved(else) + ident(code) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(segment_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(path_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(index_name)inline_delimiter(})>content(])delimiter(")> + reserved(if) ident(assign_inline) + ident(code) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content(\))delimiter(")> + reserved(else) + ident(line)operator(()ident(code)operator(\)) + ident(code) operator(=) ident(segment_name) + reserved(end) + + ident(locals) operator(<<) ident(segment_name) + reserved(end) + ident(code) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content( || )inline<inline_delimiter(#{)ident(default)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(default) + + reserved(return) ident(code)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(segment_name)operator(()operator(\)) string<delimiter(")content(segment)inline<inline_delimiter(#{)ident(depth)inline_delimiter(})>delimiter(")>operator(.)ident(to_sym) reserved(end) + reserved(def) method(path_name)operator(()operator(\)) symbol(:path) reserved(end) + reserved(def) method(index_name) + ident(move_ahead)operator(,) instance_variable(@move_ahead) operator(=) instance_variable(@move_ahead)operator(,) pre_constant(nil) + ident(move_ahead) operator(?) string<delimiter(")content(index += )inline<inline_delimiter(#{)ident(move_ahead)inline_delimiter(})>delimiter(")> operator(:) string<delimiter(')content(index)delimiter(')> + reserved(end) + + reserved(def) method(continue) + ident(dup) operator(=) pre_constant(self)operator(.)ident(dup) + ident(dup)operator(.)ident(before) operator(<<) ident(dup)operator(.)ident(current) + ident(dup)operator(.)ident(current) operator(=) ident(dup)operator(.)ident(after)operator(.)ident(shift) + ident(dup)operator(.)ident(go) + reserved(end) + + reserved(def) method(go) + reserved(if) ident(current) reserved(then) ident(current)operator(.)ident(write_recognition)operator(()pre_constant(self)operator(\)) + reserved(else) pre_constant(self)operator(.)ident(finish) + reserved(end) + reserved(end) + + reserved(def) method(result)operator(()ident(key)operator(,) ident(expression)operator(,) ident(delay) operator(=) pre_constant(false)operator(\)) + reserved(unless) ident(delay) + ident(line) string<delimiter(")inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(_value = )inline<inline_delimiter(#{)ident(expression)inline_delimiter(})>delimiter(")> + ident(expression) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(_value)delimiter(")> + reserved(end) + ident(results)operator([)ident(key)operator(]) operator(=) ident(expression) + reserved(end) + reserved(def) method(constant_result)operator(()ident(key)operator(,) ident(object)operator(\)) + ident(constants)operator([)ident(key)operator(]) operator(=) ident(object) + reserved(end) + + reserved(def) method(finish)operator(()ident(ensure_traversal_finished) operator(=) pre_constant(true)operator(\)) + ident(pairs) operator(=) operator([)operator(]) + operator(()ident(results)operator(.)ident(keys) operator(+) ident(constants)operator(.)ident(keys)operator(\))operator(.)ident(uniq)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + ident(pairs) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(key)operator(.)ident(to_s)operator(.)ident(inspect)inline_delimiter(})>content( => )inline<inline_delimiter(#{)ident(results)operator([)ident(key)operator(]) operator(?) ident(results)operator([)ident(key)operator(]) operator(:) ident(constants)operator([)ident(key)operator(])operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + ident(hash_expr) operator(=) string<delimiter(")content({)inline<inline_delimiter(#{)ident(pairs)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>content(})delimiter(")> + + ident(statement) operator(=) ident(finish_statement)operator(.)ident(call)operator(()ident(hash_expr)operator(\)) + reserved(if) ident(ensure_traversal_finished) reserved(then) pre_constant(self)operator(.)ident(if)operator(()string<delimiter(")content(! )inline<inline_delimiter(#{)ident(next_segment)operator(()pre_constant(true)operator(\))inline_delimiter(})>delimiter(")>operator(\)) operator({)operator(|)ident(gp)operator(|) ident(gp) operator(<<) ident(statement)operator(}) + reserved(else) pre_constant(self) operator(<<) ident(statement) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(GenerationGenerator) operator(<) constant(CodeGenerator) comment(#:nodoc:) + constant(Attributes) operator(=) operator([)symbol(:after)operator(,) symbol(:before)operator(,) symbol(:current)operator(,) symbol(:segments)operator(]) + ident(attr_accessor)operator(()operator(*)constant(Attributes)operator(\)) + constant(FieldsToDuplicate) operator(=) constant(CodeGenerator)operator(::)constant(FieldsToDuplicate) operator(+) constant(Attributes) + + reserved(def) method(initialize)operator(()operator(*)ident(args)operator(\)) + reserved(super)operator(()operator(*)ident(args)operator(\)) + instance_variable(@after)operator(,) instance_variable(@before) operator(=) operator([)operator(])operator(,) operator([)operator(]) + instance_variable(@current) operator(=) pre_constant(nil) + instance_variable(@segments) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(hash_name)operator(()operator(\)) string<delimiter(')content(hash)delimiter(')> reserved(end) + reserved(def) method(local_name)operator(()ident(key)operator(\)) string<delimiter(")inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(_value)delimiter(")> reserved(end) + + reserved(def) method(hash_value)operator(()ident(key)operator(,) ident(assign) operator(=) pre_constant(true)operator(,) ident(default) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(locals)operator(.)ident(include?)operator(()ident(local_name)operator(()ident(key)operator(\))operator(\)) reserved(then) ident(code) operator(=) ident(local_name)operator(()ident(key)operator(\)) + reserved(else) + ident(code) operator(=) string<delimiter(")content(hash[)inline<inline_delimiter(#{)ident(key)operator(.)ident(to_sym)operator(.)ident(inspect)inline_delimiter(})>content(])delimiter(")> + reserved(if) ident(assign) + ident(code) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(local_name)operator(()ident(key)operator(\))inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content(\))delimiter(")> + ident(locals) operator(<<) ident(local_name)operator(()ident(key)operator(\)) + reserved(end) + reserved(end) + ident(code) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content( || ()inline<inline_delimiter(#{)ident(default)operator(.)ident(inspect)inline_delimiter(})>content(\)\))delimiter(")> reserved(if) ident(default) + reserved(return) ident(code) + reserved(end) + + reserved(def) method(expire_for_keys)operator(()operator(*)ident(keys)operator(\)) + reserved(return) reserved(if) ident(keys)operator(.)ident(empty?) + ident(conds) operator(=) ident(keys)operator(.)ident(collect) operator({)operator(|)ident(key)operator(|) string<delimiter(")content(expire_on[)inline<inline_delimiter(#{)ident(key)operator(.)ident(to_sym)operator(.)ident(inspect)inline_delimiter(})>content(])delimiter(")>operator(}) + ident(line) string<delimiter(")content(not_expired, )inline<inline_delimiter(#{)ident(hash_name)inline_delimiter(})>content( = false, options if not_expired && )inline<inline_delimiter(#{)ident(conds)operator(.)ident(join)operator(()string<delimiter(')content( && )delimiter(')>operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(add_segment)operator(()operator(*)ident(segments)operator(\)) + ident(d) operator(=) ident(dup) + ident(d)operator(.)ident(segments)operator(.)ident(concat) ident(segments) + reserved(yield) ident(d) + reserved(end) + + reserved(def) method(go) + reserved(if) ident(current) reserved(then) ident(current)operator(.)ident(write_generation)operator(()pre_constant(self)operator(\)) + reserved(else) pre_constant(self)operator(.)ident(finish) + reserved(end) + reserved(end) + + reserved(def) method(continue) + ident(d) operator(=) ident(dup) + ident(d)operator(.)ident(before) operator(<<) ident(d)operator(.)ident(current) + ident(d)operator(.)ident(current) operator(=) ident(d)operator(.)ident(after)operator(.)ident(shift) + ident(d)operator(.)ident(go) + reserved(end) + + reserved(def) method(finish) + ident(line) string<delimiter(%()content("/)inline<inline_delimiter(#{)ident(segments)operator(.)ident(join)operator(()string<delimiter(')content(/)delimiter(')>operator(\))inline_delimiter(})>content(")delimiter(\))> + reserved(end) + + reserved(def) method(check_conditions)operator(()ident(conditions)operator(\)) + ident(tests) operator(=) operator([)operator(]) + ident(generator) operator(=) pre_constant(nil) + ident(conditions)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(condition)operator(|) + ident(tests) operator(<<) operator(()ident(generator) operator(||) pre_constant(self)operator(\))operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\)) reserved(if) ident(condition)operator(.)ident(is_a?) constant(Regexp) + ident(tests) operator(<<) constant(Routing)operator(.)ident(test_condition)operator(()operator(()ident(generator) operator(||) pre_constant(self)operator(\))operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(false)operator(\))operator(,) ident(condition)operator(\)) + ident(generator) operator(=) pre_constant(self)operator(.)ident(dup) reserved(unless) ident(generator) + reserved(end) + reserved(return) ident(tests)operator(.)ident(join)operator(()string<delimiter(')content( && )delimiter(')>operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# Components allow you to call other actions for their rendered response while executing another action. You can either delegate) + comment(# the entire response rendering or you can mix a partial response in with your other content.) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# # Performs a method and then lets hello_world output its render) + comment(# def delegate_action) + comment(# do_other_stuff_before_hello_world) + comment(# render_component :controller => "greeter", :action => "hello_world", :params => { :person => "david" }) + comment(# end) + comment(# end) + comment(#) + comment(# class GreeterController < ActionController::Base) + comment(# def hello_world) + comment(# render :text => "#{params[:person]} says, Hello World!") + comment(# end) + comment(# end) + comment(#) + comment(# The same can be done in a view to do a partial rendering:) + comment(# ) + comment(# Let's see a greeting: ) + comment(# <%= render_component :controller => "greeter", :action => "hello_world" %>) + comment(#) + comment(# It is also possible to specify the controller as a class constant, bypassing the inflector) + comment(# code to compute the controller class at runtime:) + comment(# ) + comment(# <%= render_component :controller => GreeterController, :action => "hello_world" %>) + comment(#) + comment(# == When to use components) + comment(#) + comment(# Components should be used with care. They're significantly slower than simply splitting reusable parts into partials and) + comment(# conceptually more complicated. Don't use components as a way of separating concerns inside a single application. Instead,) + comment(# reserve components to those rare cases where you truly have reusable view and controller elements that can be employed ) + comment(# across many applications at once.) + comment(#) + comment(# So to repeat: Components are a special-purpose approach that can often be replaced with better use of partials and filters.) + reserved(module) class(Components) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) comment(#:nodoc:) + ident(base)operator(.)ident(send) symbol(:include)operator(,) constant(InstanceMethods) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + + ident(base)operator(.)ident(helper) reserved(do) + reserved(def) method(render_component)operator(()ident(options)operator(\)) + instance_variable(@controller)operator(.)ident(send)operator(()symbol(:render_component_as_string)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + comment(# If this controller was instantiated to process a component request,) + comment(# +parent_controller+ points to the instantiator of this controller.) + ident(base)operator(.)ident(send) symbol(:attr_accessor)operator(,) symbol(:parent_controller) + + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:process_cleanup_without_components)operator(,) symbol(:process_cleanup) + ident(alias_method) symbol(:process_cleanup)operator(,) symbol(:process_cleanup_with_components) + + ident(alias_method) symbol(:set_session_options_without_components)operator(,) symbol(:set_session_options) + ident(alias_method) symbol(:set_session_options)operator(,) symbol(:set_session_options_with_components) + + ident(alias_method) symbol(:flash_without_components)operator(,) symbol(:flash) + ident(alias_method) symbol(:flash)operator(,) symbol(:flash_with_components) + + ident(alias_method) symbol(:component_request?)operator(,) symbol(:parent_controller) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Track parent controller to identify component requests) + reserved(def) method(process_with_components)operator(()ident(request)operator(,) ident(response)operator(,) ident(parent_controller) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(controller) operator(=) ident(new) + ident(controller)operator(.)ident(parent_controller) operator(=) ident(parent_controller) + ident(controller)operator(.)ident(process)operator(()ident(request)operator(,) ident(response)operator(\)) + reserved(end) + + comment(# Set the template root to be one directory behind the root dir of the controller. Examples:) + comment(# /code/weblog/components/admin/users_controller.rb with Admin::UsersController ) + comment(# will use /code/weblog/components as template root ) + comment(# and find templates in /code/weblog/components/admin/users/) + comment(#) + comment(# /code/weblog/components/admin/parties/users_controller.rb with Admin::Parties::UsersController ) + comment(# will also use /code/weblog/components as template root ) + comment(# and find templates in /code/weblog/components/admin/parties/users/) + reserved(def) method(uses_component_template_root) + ident(path_of_calling_controller) operator(=) constant(File)operator(.)ident(dirname)operator(()ident(caller)operator([)integer(0)operator(])operator(.)ident(split)operator(()regexp<delimiter(/)content(:)char(\\d)content(+:)delimiter(/)>operator(\))operator(.)ident(first)operator(\)) + ident(path_of_controller_root) operator(=) ident(path_of_calling_controller)operator(.)ident(sub)operator(()regexp<delimiter(/)inline<inline_delimiter(#{)ident(controller_path)operator(.)ident(split)operator(()string<delimiter(")content(/)delimiter(")>operator(\))operator([)integer(0)operator(..)integer(-2)operator(])inline_delimiter(})>content($)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\)) comment(# " (for ruby-mode\)) + + pre_constant(self)operator(.)ident(template_root) operator(=) ident(path_of_controller_root) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) + comment(# Extracts the action_name from the request parameters and performs that action.) + reserved(def) method(process_with_components)operator(()ident(request)operator(,) ident(response)operator(,) ident(method) operator(=) symbol(:perform_action)operator(,) operator(*)ident(arguments)operator(\)) comment(#:nodoc:) + ident(flash)operator(.)ident(discard) reserved(if) ident(component_request?) + ident(process_without_components)operator(()ident(request)operator(,) ident(response)operator(,) ident(method)operator(,) operator(*)ident(arguments)operator(\)) + reserved(end) + + ident(protected) + comment(# Renders the component specified as the response for the current method) + reserved(def) method(render_component)operator(()ident(options)operator(\)) comment(#:doc:) + ident(component_logging)operator(()ident(options)operator(\)) reserved(do) + ident(render_text)operator(()ident(component_response)operator(()ident(options)operator(,) pre_constant(true)operator(\))operator(.)ident(body)operator(,) ident(response)operator(.)ident(headers)operator([)string<delimiter(")content(Status)delimiter(")>operator(])operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the component response as a string) + reserved(def) method(render_component_as_string)operator(()ident(options)operator(\)) comment(#:doc:) + ident(component_logging)operator(()ident(options)operator(\)) reserved(do) + ident(response) operator(=) ident(component_response)operator(()ident(options)operator(,) pre_constant(false)operator(\)) + + reserved(if) ident(redirected) operator(=) ident(response)operator(.)ident(redirected_to) + ident(render_component_as_string)operator(()ident(redirected)operator(\)) + reserved(else) + ident(response)operator(.)ident(body) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(flash_with_components)operator(()ident(refresh) operator(=) pre_constant(false)operator(\)) comment(#:nodoc:) + reserved(if) instance_variable(@flash)operator(.)ident(nil?) operator(||) ident(refresh) + instance_variable(@flash) operator(=) + reserved(if) instance_variable(@parent_controller) + instance_variable(@parent_controller)operator(.)ident(flash) + reserved(else) + ident(flash_without_components) + reserved(end) + reserved(end) + + instance_variable(@flash) + reserved(end) + + ident(private) + reserved(def) method(component_response)operator(()ident(options)operator(,) ident(reuse_response)operator(\)) + ident(klass) operator(=) ident(component_class)operator(()ident(options)operator(\)) + ident(request) operator(=) ident(request_for_component)operator(()ident(klass)operator(.)ident(controller_name)operator(,) ident(options)operator(\)) + ident(response) operator(=) ident(reuse_response) operator(?) instance_variable(@response) operator(:) instance_variable(@response)operator(.)ident(dup) + + ident(klass)operator(.)ident(process_with_components)operator(()ident(request)operator(,) ident(response)operator(,) pre_constant(self)operator(\)) + reserved(end) + + comment(# determine the controller class for the component request) + reserved(def) method(component_class)operator(()ident(options)operator(\)) + reserved(if) ident(controller) operator(=) ident(options)operator([)symbol(:controller)operator(]) + ident(controller)operator(.)ident(is_a?)operator(()constant(Class)operator(\)) operator(?) ident(controller) operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(controller)operator(.)ident(camelize)inline_delimiter(})>content(Controller)delimiter(")>operator(.)ident(constantize) + reserved(else) + pre_constant(self)operator(.)ident(class) + reserved(end) + reserved(end) + + comment(# Create a new request object based on the current request.) + comment(# The new request inherits the session from the current request,) + comment(# bypassing any session options set for the component controller's class) + reserved(def) method(request_for_component)operator(()ident(controller_name)operator(,) ident(options)operator(\)) + ident(request) operator(=) instance_variable(@request)operator(.)ident(dup) + ident(request)operator(.)ident(session) operator(=) instance_variable(@request)operator(.)ident(session) + + ident(request)operator(.)ident(instance_variable_set)operator(() + symbol(:@parameters)operator(,) + operator(()ident(options)operator([)symbol(:params)operator(]) operator(||) operator({)operator(})operator(\))operator(.)ident(with_indifferent_access)operator(.)ident(update)operator(() + string<delimiter(")content(controller)delimiter(")> operator(=)operator(>) ident(controller_name)operator(,) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) ident(options)operator([)symbol(:action)operator(])operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(options)operator([)symbol(:id)operator(]) + operator(\)) + operator(\)) + + ident(request) + reserved(end) + + reserved(def) method(component_logging)operator(()ident(options)operator(\)) + reserved(if) ident(logger) + ident(logger)operator(.)ident(info) string<delimiter(")content(Start rendering component ()inline<inline_delimiter(#{)ident(options)operator(.)ident(inspect)inline_delimiter(})>content(\): )delimiter(")> + ident(result) operator(=) reserved(yield) + ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)char(\\n)content(End of component rendering)delimiter(")> + ident(result) + reserved(else) + reserved(yield) + reserved(end) + reserved(end) + + reserved(def) method(set_session_options_with_components)operator(()ident(request)operator(\)) + ident(set_session_options_without_components)operator(()ident(request)operator(\)) reserved(unless) ident(component_request?) + reserved(end) + + reserved(def) method(process_cleanup_with_components) + ident(process_cleanup_without_components) reserved(unless) ident(component_request?) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# Cookies are read and written through ActionController#cookies. The cookies being read are what were received along with the request,) + comment(# the cookies being written are what will be sent out with the response. Cookies are read by value (so you won't get the cookie object) + comment(# itself back -- just the value it holds\). Examples for writing:) + comment(#) + comment(# cookies[:user_name] = "david" # => Will set a simple session cookie) + comment(# cookies[:login] = { :value => "XJ-122", :expires => Time.now + 360} # => Will set a cookie that expires in 1 hour) + comment(# ) + comment(# Examples for reading:) + comment(#) + comment(# cookies[:user_name] # => "david") + comment(# cookies.size # => 2) + comment(# ) + comment(# Example for deleting:) + comment(#) + comment(# cookies.delete :user_name) + comment(#) + comment(# All the option symbols for setting cookies are:) + comment(#) + comment(# * <tt>value</tt> - the cookie's value or list of values (as an array\).) + comment(# * <tt>path</tt> - the path for which this cookie applies. Defaults to the root of the application.) + comment(# * <tt>domain</tt> - the domain for which this cookie applies.) + comment(# * <tt>expires</tt> - the time at which this cookie expires, as a +Time+ object.) + comment(# * <tt>secure</tt> - whether this cookie is a secure cookie or not (default to false\).) + comment(# Secure cookies are only transmitted to HTTPS servers.) + reserved(module) class(Cookies) + ident(protected) + comment(# Returns the cookie container, which operates as described above.) + reserved(def) method(cookies) + constant(CookieJar)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Deprecated cookie writer method) + reserved(def) method(cookie)operator(()operator(*)ident(options)operator(\)) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(]) operator(<<) constant(CGI)operator(::)constant(Cookie)operator(.)ident(new)operator(()operator(*)ident(options)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(CookieJar) operator(<) constant(Hash) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(controller)operator(\)) + instance_variable(@controller)operator(,) instance_variable(@cookies) operator(=) ident(controller)operator(,) ident(controller)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@cookies)delimiter(")>operator(\)) + reserved(super)operator(()operator(\)) + ident(update)operator(()instance_variable(@cookies)operator(\)) + reserved(end) + + comment(# Returns the value of the cookie by +name+ -- or nil if no such cookie exists. You set new cookies using either the cookie method) + comment(# or cookies[]= (for simple name/value cookies without options\).) + reserved(def) method([])operator(()ident(name)operator(\)) + instance_variable(@cookies)operator([)ident(name)operator(.)ident(to_s)operator(])operator(.)ident(value)operator(.)ident(first) reserved(if) instance_variable(@cookies)operator([)ident(name)operator(.)ident(to_s)operator(]) operator(&&) instance_variable(@cookies)operator([)ident(name)operator(.)ident(to_s)operator(])operator(.)ident(respond_to?)operator(()symbol(:value)operator(\)) + reserved(end) + + reserved(def) method([]=)operator(()ident(name)operator(,) ident(options)operator(\)) + reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(options)operator(,) ident(pair)operator(|) ident(options)operator([)ident(pair)operator(.)ident(first)operator(.)ident(to_s)operator(]) operator(=) ident(pair)operator(.)ident(last)operator(;) ident(options) operator(}) + ident(options)operator([)string<delimiter(")content(name)delimiter(")>operator(]) operator(=) ident(name)operator(.)ident(to_s) + reserved(else) + ident(options) operator(=) operator({) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(.)ident(to_s)operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(options) operator(}) + reserved(end) + + ident(set_cookie)operator(()ident(options)operator(\)) + reserved(end) + + comment(# Removes the cookie on the client machine by setting the value to an empty string) + comment(# and setting its expiration date into the past) + reserved(def) method(delete)operator(()ident(name)operator(\)) + ident(set_cookie)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(.)ident(to_s)operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(expires)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(at)operator(()integer(0)operator(\))operator(\)) + reserved(end) + + ident(private) + reserved(def) method(set_cookie)operator(()ident(options)operator(\)) comment(#:doc:) + ident(options)operator([)string<delimiter(")content(path)delimiter(")>operator(]) operator(=) string<delimiter(")content(/)delimiter(")> reserved(unless) ident(options)operator([)string<delimiter(")content(path)delimiter(")>operator(]) + ident(cookie) operator(=) constant(CGI)operator(::)constant(Cookie)operator(.)ident(new)operator(()ident(options)operator(\)) + instance_variable(@controller)operator(.)ident(logger)operator(.)ident(info) string<delimiter(")content(Cookie set: )inline<inline_delimiter(#{)ident(cookie)inline_delimiter(})>delimiter(")> reserved(unless) instance_variable(@controller)operator(.)ident(logger)operator(.)ident(nil?) + instance_variable(@controller)operator(.)ident(response)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(]) operator(<<) ident(cookie) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(module) class(Dependencies) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Dependencies control what classes are needed for the controller to run its course. This is an alternative to doing explicit) + comment(# +require+ statements that bring a number of benefits. It's more succinct, communicates what type of dependency we're talking about,) + comment(# can trigger special behavior (as in the case of +observer+\), and enables Rails to be clever about reloading in cached environments) + comment(# like FCGI. Example:) + comment(#) + comment(# class ApplicationController < ActionController::Base) + comment(# model :account, :company, :person, :project, :category) + comment(# helper :access_control) + comment(# service :notifications, :billings) + comment(# observer :project_change_observer) + comment(# end) + comment(#) + comment(# Please note that a controller like ApplicationController will automatically attempt to require_dependency on a model of its ) + comment(# singuralized name and a helper of its name. If nothing is found, no error is raised. This is especially useful for concrete ) + comment(# controllers like PostController:) + comment(#) + comment(# class PostController < ApplicationController) + comment(# # model :post (already required\)) + comment(# # helper :post (already required\)) + comment(# end) + comment(#) + comment(# Also note, that if the models follow the pattern of just 1 class per file in the form of MyClass => my_class.rb, then these) + comment(# classes don't have to be required as Active Support will auto-require them.) + reserved(module) class(ClassMethods) comment(#:nodoc:) + comment(# Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar) + comment(# backend for modelling entity classes.) + reserved(def) method(model)operator(()operator(*)ident(models)operator(\)) + ident(require_dependencies)operator(()symbol(:model)operator(,) ident(models)operator(\)) + ident(depend_on)operator(()symbol(:model)operator(,) ident(models)operator(\)) + reserved(end) + + comment(# Specifies a variable number of services that this controller depends on. Services are normally singletons or factories, like) + comment(# Action Mailer service or a Payment Gateway service.) + reserved(def) method(service)operator(()operator(*)ident(services)operator(\)) + ident(require_dependencies)operator(()symbol(:service)operator(,) ident(services)operator(\)) + ident(depend_on)operator(()symbol(:service)operator(,) ident(services)operator(\)) + reserved(end) + + comment(# Specifies a variable number of observers that are to govern when this controller is handling actions. The observers will) + comment(# automatically have .instance called on them to make them active on assignment.) + reserved(def) method(observer)operator(()operator(*)ident(observers)operator(\)) + ident(require_dependencies)operator(()symbol(:observer)operator(,) ident(observers)operator(\)) + ident(depend_on)operator(()symbol(:observer)operator(,) ident(observers)operator(\)) + ident(instantiate_observers)operator(()ident(observers)operator(\)) + reserved(end) + + comment(# Returns an array of symbols that specify the dependencies on a given layer. For the example at the top, calling) + comment(# <tt>ApplicationController.dependencies_on(:model\)</tt> would return <tt>[:account, :company, :person, :project, :category]</tt>) + reserved(def) method(dependencies_on)operator(()ident(layer)operator(\)) + ident(read_inheritable_attribute)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(layer)inline_delimiter(})>content(_dependencies)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(depend_on)operator(()ident(layer)operator(,) ident(dependencies)operator(\)) comment(#:nodoc:) + ident(write_inheritable_array)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(layer)inline_delimiter(})>content(_dependencies)delimiter(")>operator(,) ident(dependencies)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(instantiate_observers)operator(()ident(observers)operator(\)) + ident(observers)operator(.)ident(flatten)operator(.)ident(each) operator({) operator(|)ident(observer)operator(|) constant(Object)operator(.)ident(const_get)operator(()constant(Inflector)operator(.)ident(classify)operator(()ident(observer)operator(.)ident(to_s)operator(\))operator(\))operator(.)ident(instance) operator(}) + reserved(end) + + reserved(def) method(require_dependencies)operator(()ident(layer)operator(,) ident(dependencies)operator(\)) + ident(dependencies)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(dependency)operator(|) + reserved(begin) + ident(require_dependency)operator(()ident(dependency)operator(.)ident(to_s)operator(\)) + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(e) + ident(raise) constant(LoadError)operator(.)ident(new)operator(()string<delimiter(")content(Missing )inline<inline_delimiter(#{)ident(layer)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(dependency)inline_delimiter(})>content(.rb)delimiter(")>operator(\))operator(.)ident(copy_blame!)operator(()ident(e)operator(\)) + reserved(rescue) constant(Object) operator(=)operator(>) ident(exception) + ident(exception)operator(.)ident(blame_file!) string<delimiter(")content(=> )inline<inline_delimiter(#{)ident(layer)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(dependency)inline_delimiter(})>content(.rb)delimiter(")> + ident(raise) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(test/unit/assertions)delimiter(')> +ident(require) string<delimiter(')content(rexml/document)delimiter(')> + +reserved(module) class(Test) comment(#:nodoc:) + reserved(module) class(Unit) comment(#:nodoc:) + reserved(module) class(Assertions) + reserved(def) method(assert_success)operator(()ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(assert_response)operator(()symbol(:success)operator(,) ident(message)operator(\)) + reserved(end) + + reserved(def) method(assert_redirect)operator(()ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(assert_response)operator(()symbol(:redirect)operator(,) ident(message)operator(\)) + reserved(end) + + reserved(def) method(assert_rendered_file)operator(()ident(expected)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(assert_template)operator(()ident(expected)operator(,) ident(message)operator(\)) + reserved(end) + + comment(# ensure that the session has an object with the specified name) + reserved(def) method(assert_session_has)operator(()ident(key)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is not in the session <?>)delimiter(")>operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(session)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(has_session_object?)operator(()ident(key)operator(\)) operator(}) + reserved(end) + + comment(# ensure that the session has no object with the specified name) + reserved(def) method(assert_session_has_no)operator(()ident(key)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is in the session <?>)delimiter(")>operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(session)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) operator(!)instance_variable(@response)operator(.)ident(has_session_object?)operator(()ident(key)operator(\)) operator(}) + reserved(end) + + reserved(def) method(assert_session_equal)operator(()ident(expected) operator(=) pre_constant(nil)operator(,) ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> expected in session['?'] but was <?>)delimiter(")>operator(,) ident(expected)operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(session)operator([)ident(key)operator(])operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(expected) operator(==) instance_variable(@response)operator(.)ident(session)operator([)ident(key)operator(]) operator(}) + reserved(end) + + comment(# -- cookie assertions ---------------------------------------------------) + + reserved(def) method(assert_no_cookie)operator(()ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(actual) operator(=) instance_variable(@response)operator(.)ident(cookies)operator([)ident(key)operator(]) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> not expected in cookies['?'])delimiter(")>operator(,) ident(actual)operator(,) ident(key)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(actual)operator(.)ident(nil?) reserved(or) ident(actual)operator(.)ident(empty?) operator(}) + reserved(end) + + reserved(def) method(assert_cookie_equal)operator(()ident(expected) operator(=) pre_constant(nil)operator(,) ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(actual) operator(=) instance_variable(@response)operator(.)ident(cookies)operator([)ident(key)operator(]) + ident(actual) operator(=) ident(actual)operator(.)ident(first) reserved(if) ident(actual) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> expected in cookies['?'] but was <?>)delimiter(")>operator(,) ident(expected)operator(,) ident(key)operator(,) ident(actual)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(expected) operator(==) ident(actual) operator(}) + reserved(end) + + comment(# -- flash assertions ---------------------------------------------------) + + comment(# ensure that the flash has an object with the specified name) + reserved(def) method(assert_flash_has)operator(()ident(key)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is not in the flash <?>)delimiter(")>operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(flash)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(has_flash_object?)operator(()ident(key)operator(\)) operator(}) + reserved(end) + + comment(# ensure that the flash has no object with the specified name) + reserved(def) method(assert_flash_has_no)operator(()ident(key)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is in the flash <?>)delimiter(")>operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(flash)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) operator(!)instance_variable(@response)operator(.)ident(has_flash_object?)operator(()ident(key)operator(\)) operator(}) + reserved(end) + + comment(# ensure the flash exists) + reserved(def) method(assert_flash_exists)operator(()ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(the flash does not exist <?>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(session)operator([)string<delimiter(')content(flash)delimiter(')>operator(]) operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(has_flash?) operator(}) + reserved(end) + + comment(# ensure the flash does not exist) + reserved(def) method(assert_flash_not_exists)operator(()ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(the flash exists <?>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(flash)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) operator(!)instance_variable(@response)operator(.)ident(has_flash?) operator(}) + reserved(end) + + comment(# ensure the flash is empty but existent) + reserved(def) method(assert_flash_empty)operator(()ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(the flash is not empty <?>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(flash)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) operator(!)instance_variable(@response)operator(.)ident(has_flash_with_contents?) operator(}) + reserved(end) + + comment(# ensure the flash is not empty) + reserved(def) method(assert_flash_not_empty)operator(()ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(the flash is empty)delimiter(")>operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(has_flash_with_contents?) operator(}) + reserved(end) + + reserved(def) method(assert_flash_equal)operator(()ident(expected) operator(=) pre_constant(nil)operator(,) ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> expected in flash['?'] but was <?>)delimiter(")>operator(,) ident(expected)operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(flash)operator([)ident(key)operator(])operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(expected) operator(==) instance_variable(@response)operator(.)ident(flash)operator([)ident(key)operator(]) operator(}) + reserved(end) + + + comment(# ensure our redirection url is an exact match) + reserved(def) method(assert_redirect_url)operator(()ident(url)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(assert_redirect)operator(()ident(message)operator(\)) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is not the redirected location <?>)delimiter(")>operator(,) ident(url)operator(,) instance_variable(@response)operator(.)ident(redirect_url)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(redirect_url) operator(==) ident(url) operator(}) + reserved(end) + + comment(# ensure our redirection url matches a pattern) + reserved(def) method(assert_redirect_url_match)operator(()ident(pattern)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(assert_redirect)operator(()ident(message)operator(\)) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> was not found in the location: <?>)delimiter(")>operator(,) ident(pattern)operator(,) instance_variable(@response)operator(.)ident(redirect_url)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(redirect_url_match?)operator(()ident(pattern)operator(\)) operator(}) + reserved(end) + + + comment(# -- template assertions ------------------------------------------------) + + comment(# ensure that a template object with the given name exists) + reserved(def) method(assert_template_has)operator(()ident(key)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is not a template object)delimiter(")>operator(,) ident(key) operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) instance_variable(@response)operator(.)ident(has_template_object?)operator(()ident(key)operator(\)) operator(}) + reserved(end) + + comment(# ensure that a template object with the given name does not exist) + reserved(def) method(assert_template_has_no)operator(()ident(key)operator(=)pre_constant(nil)operator(,)ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> is a template object <?>)delimiter(")>operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(template_objects)operator([)ident(key)operator(])operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) operator(!)instance_variable(@response)operator(.)ident(has_template_object?)operator(()ident(key)operator(\)) operator(}) + reserved(end) + + comment(# ensures that the object assigned to the template on +key+ is equal to +expected+ object.) + reserved(def) method(assert_template_equal)operator(()ident(expected) operator(=) pre_constant(nil)operator(,) ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> expected in assigns['?'] but was <?>)delimiter(")>operator(,) ident(expected)operator(,) ident(key)operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)ident(key)operator(.)ident(to_s)operator(])operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(expected) operator(==) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)ident(key)operator(.)ident(to_s)operator(]) operator(}) + reserved(end) + ident(alias_method) symbol(:assert_assigned_equal)operator(,) symbol(:assert_template_equal) + + comment(# Asserts that the template returns the +expected+ string or array based on the XPath +expression+.) + comment(# This will only work if the template rendered a valid XML document.) + reserved(def) method(assert_template_xpath_match)operator(()ident(expression)operator(=)pre_constant(nil)operator(,) ident(expected)operator(=)pre_constant(nil)operator(,) ident(message)operator(=)pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(xml)operator(,) ident(matches) operator(=) constant(REXML)operator(::)constant(Document)operator(.)ident(new)operator(()instance_variable(@response)operator(.)ident(body)operator(\))operator(,) operator([)operator(]) + ident(xml)operator(.)ident(elements)operator(.)ident(each)operator(()ident(expression)operator(\)) operator({) operator(|)ident(e)operator(|) ident(matches) operator(<<) ident(e)operator(.)ident(text) operator(}) + reserved(if) ident(matches)operator(.)ident(empty?) reserved(then) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> not found in document)delimiter(")>operator(,) ident(expression)operator(\)) + ident(flunk)operator(()ident(msg)operator(\)) + reserved(return) + reserved(elsif) ident(matches)operator(.)ident(length) operator(<) integer(2) reserved(then) + ident(matches) operator(=) ident(matches)operator(.)ident(first) + reserved(end) + + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(<?> found <?>, not <?>)delimiter(")>operator(,) ident(expression)operator(,) ident(matches)operator(,) ident(expected)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(matches) operator(==) ident(expected) operator(}) + reserved(end) + + comment(# Assert the template object with the given name is an Active Record descendant and is valid.) + reserved(def) method(assert_valid_record)operator(()ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(record) operator(=) ident(find_record_in_template)operator(()ident(key)operator(\)) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(Active Record is invalid <?>\))delimiter(")>operator(,) ident(record)operator(.)ident(errors)operator(.)ident(full_messages)operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(record)operator(.)ident(valid?) operator(}) + reserved(end) + + comment(# Assert the template object with the given name is an Active Record descendant and is invalid.) + reserved(def) method(assert_invalid_record)operator(()ident(key) operator(=) pre_constant(nil)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(record) operator(=) ident(find_record_in_template)operator(()ident(key)operator(\)) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(Active Record is valid\))delimiter(")>operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) operator(!)ident(record)operator(.)ident(valid?) operator(}) + reserved(end) + + comment(# Assert the template object with the given name is an Active Record descendant and the specified column(s\) are valid.) + reserved(def) method(assert_valid_column_on_record)operator(()ident(key) operator(=) pre_constant(nil)operator(,) ident(columns) operator(=) string<delimiter(")delimiter(")>operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(record) operator(=) ident(find_record_in_template)operator(()ident(key)operator(\)) + ident(record)operator(.)ident(send)operator(()symbol(:validate)operator(\)) + + ident(cols) operator(=) ident(glue_columns)operator(()ident(columns)operator(\)) + ident(cols)operator(.)ident(delete_if) operator({) operator(|)ident(col)operator(|) operator(!)ident(record)operator(.)ident(errors)operator(.)ident(invalid?)operator(()ident(col)operator(\)) operator(}) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(Active Record has invalid columns <?>\))delimiter(")>operator(,) ident(cols)operator(.)ident(join)operator(()string<delimiter(")content(,)delimiter(")>operator(\)) operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(cols)operator(.)ident(empty?) operator(}) + reserved(end) + + comment(# Assert the template object with the given name is an Active Record descendant and the specified column(s\) are invalid.) + reserved(def) method(assert_invalid_column_on_record)operator(()ident(key) operator(=) pre_constant(nil)operator(,) ident(columns) operator(=) string<delimiter(")delimiter(")>operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(record) operator(=) ident(find_record_in_template)operator(()ident(key)operator(\)) + ident(record)operator(.)ident(send)operator(()symbol(:validate)operator(\)) + + ident(cols) operator(=) ident(glue_columns)operator(()ident(columns)operator(\)) + ident(cols)operator(.)ident(delete_if) operator({) operator(|)ident(col)operator(|) ident(record)operator(.)ident(errors)operator(.)ident(invalid?)operator(()ident(col)operator(\)) operator(}) + ident(msg) operator(=) ident(build_message)operator(()ident(message)operator(,) string<delimiter(")content(Active Record has valid columns <?>\))delimiter(")>operator(,) ident(cols)operator(.)ident(join)operator(()string<delimiter(")content(,)delimiter(")>operator(\)) operator(\)) + ident(assert_block)operator(()ident(msg)operator(\)) operator({) ident(cols)operator(.)ident(empty?) operator(}) + reserved(end) + + ident(private) + reserved(def) method(glue_columns)operator(()ident(columns)operator(\)) + ident(cols) operator(=) operator([)operator(]) + ident(cols) operator(<<) ident(columns) reserved(if) ident(columns)operator(.)ident(class) operator(==) constant(String) + ident(cols) operator(+=) ident(columns) reserved(if) ident(columns)operator(.)ident(class) operator(==) constant(Array) + ident(cols) + reserved(end) + + reserved(def) method(find_record_in_template)operator(()ident(key) operator(=) pre_constant(nil)operator(\)) + ident(assert_template_has)operator(()ident(key)operator(\)) + ident(record) operator(=) instance_variable(@response)operator(.)ident(template_objects)operator([)ident(key)operator(]) + + ident(assert_not_nil)operator(()ident(record)operator(\)) + ident(assert_kind_of) constant(ActiveRecord)operator(::)constant(Base)operator(,) ident(record) + + reserved(return) ident(record) + reserved(end) + reserved(end) + reserved(end) +ident(endmodule) constant(ActionController) + reserved(class) class(Base) + ident(protected) + comment(# Deprecated in favor of calling redirect_to directly with the path.) + reserved(def) method(redirect_to_path)operator(()ident(path)operator(\)) comment(#:nodoc:) + ident(redirect_to)operator(()ident(path)operator(\)) + reserved(end) + + comment(# Deprecated in favor of calling redirect_to directly with the url. If the resource has moved permanently, it's possible to pass) + comment(# true as the second parameter and the browser will get "301 Moved Permanently" instead of "302 Found". This can also be done through) + comment(# just setting the headers["Status"] to "301 Moved Permanently" before using the redirect_to.) + reserved(def) method(redirect_to_url)operator(()ident(url)operator(,) ident(permanently) operator(=) pre_constant(false)operator(\)) comment(#:nodoc:) + ident(headers)operator([)string<delimiter(")content(Status)delimiter(")>operator(]) operator(=) string<delimiter(")content(301 Moved Permanently)delimiter(")> reserved(if) ident(permanently) + ident(redirect_to)operator(()ident(url)operator(\)) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) + reserved(class) class(AbstractRequest) + comment(# Determine whether the body of a HTTP call is URL-encoded (default\)) + comment(# or matches one of the registered param_parsers. ) + comment(#) + comment(# For backward compatibility, the post format is extracted from the) + comment(# X-Post-Data-Format HTTP header if present.) + reserved(def) method(post_format) + reserved(case) ident(content_type)operator(.)ident(to_s) + reserved(when) string<delimiter(')content(application/xml)delimiter(')> + symbol(:xml) + reserved(when) string<delimiter(')content(application/x-yaml)delimiter(')> + symbol(:yaml) + reserved(else) + symbol(:url_encoded) + reserved(end) + reserved(end) + + comment(# Is this a POST request formatted as XML or YAML?) + reserved(def) method(formatted_post?) + ident(post?) operator(&&) operator(()ident(post_format) operator(==) symbol(:yaml) operator(||) ident(post_format) operator(==) symbol(:xml)operator(\)) + reserved(end) + + comment(# Is this a POST request formatted as XML?) + reserved(def) method(xml_post?) + ident(post?) operator(&&) ident(post_format) operator(==) symbol(:xml) + reserved(end) + + comment(# Is this a POST request formatted as YAML?) + reserved(def) method(yaml_post?) + ident(post?) operator(&&) ident(post_format) operator(==) symbol(:yaml) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(module) class(Filters) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionController)operator(::)constant(Filters)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + comment(# Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do ) + comment(# authentication, caching, or auditing before the intended action is performed. Or to do localization or output ) + comment(# compression after the action has been performed.) + comment(#) + comment(# Filters have access to the request, response, and all the instance variables set by other filters in the chain) + comment(# or by the action (in the case of after filters\). Additionally, it's possible for a pre-processing <tt>before_filter</tt>) + comment(# to halt the processing before the intended action is processed by returning false or performing a redirect or render. ) + comment(# This is especially useful for filters like authentication where you're not interested in allowing the action to be ) + comment(# performed if the proper credentials are not in order.) + comment(#) + comment(# == Filter inheritance) + comment(#) + comment(# Controller inheritance hierarchies share filters downwards, but subclasses can also add new filters without) + comment(# affecting the superclass. For example:) + comment(#) + comment(# class BankController < ActionController::Base) + comment(# before_filter :audit) + comment(#) + comment(# private) + comment(# def audit) + comment(# # record the action and parameters in an audit log) + comment(# end) + comment(# end) + comment(#) + comment(# class VaultController < BankController) + comment(# before_filter :verify_credentials) + comment(#) + comment(# private) + comment(# def verify_credentials) + comment(# # make sure the user is allowed into the vault) + comment(# end) + comment(# end) + comment(#) + comment(# Now any actions performed on the BankController will have the audit method called before. On the VaultController,) + comment(# first the audit method is called, then the verify_credentials method. If the audit method returns false, then ) + comment(# verify_credentials and the intended action are never called.) + comment(#) + comment(# == Filter types) + comment(#) + comment(# A filter can take one of three forms: method reference (symbol\), external class, or inline method (proc\). The first) + comment(# is the most common and works by referencing a protected or private method somewhere in the inheritance hierarchy of) + comment(# the controller by use of a symbol. In the bank example above, both BankController and VaultController use this form.) + comment(#) + comment(# Using an external class makes for more easily reused generic filters, such as output compression. External filter classes) + comment(# are implemented by having a static +filter+ method on any class and then passing this class to the filter method. Example:) + comment(#) + comment(# class OutputCompressionFilter) + comment(# def self.filter(controller\)) + comment(# controller.response.body = compress(controller.response.body\)) + comment(# end) + comment(# end) + comment(#) + comment(# class NewspaperController < ActionController::Base) + comment(# after_filter OutputCompressionFilter) + comment(# end) + comment(#) + comment(# The filter method is passed the controller instance and is hence granted access to all aspects of the controller and can) + comment(# manipulate them as it sees fit.) + comment(#) + comment(# The inline method (using a proc\) can be used to quickly do something small that doesn't require a lot of explanation. ) + comment(# Or just as a quick test. It works like this:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# before_filter { |controller| false if controller.params["stop_action"] }) + comment(# end) + comment(#) + comment(# As you can see, the block expects to be passed the controller after it has assigned the request to the internal variables.) + comment(# This means that the block has access to both the request and response objects complete with convenience methods for params,) + comment(# session, template, and assigns. Note: The inline method doesn't strictly have to be a block; any object that responds to call) + comment(# and returns 1 or -1 on arity will do (such as a Proc or an Method object\).) + comment(#) + comment(# == Filter chain ordering) + comment(#) + comment(# Using <tt>before_filter</tt> and <tt>after_filter</tt> appends the specified filters to the existing chain. That's usually) + comment(# just fine, but some times you care more about the order in which the filters are executed. When that's the case, you) + comment(# can use <tt>prepend_before_filter</tt> and <tt>prepend_after_filter</tt>. Filters added by these methods will be put at the) + comment(# beginning of their respective chain and executed before the rest. For example:) + comment(#) + comment(# class ShoppingController) + comment(# before_filter :verify_open_shop) + comment(#) + comment(# class CheckoutController) + comment(# prepend_before_filter :ensure_items_in_cart, :ensure_items_in_stock) + comment(#) + comment(# The filter chain for the CheckoutController is now <tt>:ensure_items_in_cart, :ensure_items_in_stock,</tt>) + comment(# <tt>:verify_open_shop</tt>. So if either of the ensure filters return false, we'll never get around to see if the shop ) + comment(# is open or not.) + comment(#) + comment(# You may pass multiple filter arguments of each type as well as a filter block.) + comment(# If a block is given, it is treated as the last argument.) + comment(#) + comment(# == Around filters) + comment(#) + comment(# In addition to the individual before and after filters, it's also possible to specify that a single object should handle) + comment(# both the before and after call. That's especially useful when you need to keep state active between the before and after,) + comment(# such as the example of a benchmark filter below:) + comment(# ) + comment(# class WeblogController < ActionController::Base) + comment(# around_filter BenchmarkingFilter.new) + comment(# ) + comment(# # Before this action is performed, BenchmarkingFilter#before(controller\) is executed) + comment(# def index) + comment(# end) + comment(# # After this action has been performed, BenchmarkingFilter#after(controller\) is executed) + comment(# end) + comment(#) + comment(# class BenchmarkingFilter) + comment(# def initialize) + comment(# @runtime) + comment(# end) + comment(# ) + comment(# def before) + comment(# start_timer) + comment(# end) + comment(# ) + comment(# def after) + comment(# stop_timer) + comment(# report_result) + comment(# end) + comment(# end) + comment(#) + comment(# == Filter chain skipping) + comment(#) + comment(# Some times its convenient to specify a filter chain in a superclass that'll hold true for the majority of the ) + comment(# subclasses, but not necessarily all of them. The subclasses that behave in exception can then specify which filters) + comment(# they would like to be relieved of. Examples) + comment(#) + comment(# class ApplicationController < ActionController::Base) + comment(# before_filter :authenticate) + comment(# end) + comment(#) + comment(# class WeblogController < ApplicationController) + comment(# # will run the :authenticate filter) + comment(# end) + comment(#) + comment(# class SignupController < ApplicationController) + comment(# # will not run the :authenticate filter) + comment(# skip_before_filter :authenticate) + comment(# end) + comment(#) + comment(# == Filter conditions) + comment(#) + comment(# Filters can be limited to run for only specific actions. This can be expressed either by listing the actions to) + comment(# exclude or the actions to include when executing the filter. Available conditions are +:only+ or +:except+, both ) + comment(# of which accept an arbitrary number of method references. For example:) + comment(#) + comment(# class Journal < ActionController::Base) + comment(# # only require authentication if the current action is edit or delete) + comment(# before_filter :authorize, :only => [ :edit, :delete ]) + comment(# ) + comment(# private) + comment(# def authorize) + comment(# # redirect to login unless authenticated) + comment(# end) + comment(# end) + comment(# ) + comment(# When setting conditions on inline method (proc\) filters the condition must come first and be placed in parentheses.) + comment(#) + comment(# class UserPreferences < ActionController::Base) + comment(# before_filter(:except => :new\) { # some proc ... }) + comment(# # ...) + comment(# end) + comment(#) + reserved(module) class(ClassMethods) + comment(# The passed <tt>filters</tt> will be appended to the array of filters that's run _before_ actions) + comment(# on this controller are performed.) + reserved(def) method(append_before_filter)operator(()operator(*)ident(filters)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + ident(filters) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + ident(append_filter_to_chain)operator(()string<delimiter(')content(before)delimiter(')>operator(,) ident(filters)operator(\)) + reserved(end) + + comment(# The passed <tt>filters</tt> will be prepended to the array of filters that's run _before_ actions) + comment(# on this controller are performed.) + reserved(def) method(prepend_before_filter)operator(()operator(*)ident(filters)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + ident(filters) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + ident(prepend_filter_to_chain)operator(()string<delimiter(')content(before)delimiter(')>operator(,) ident(filters)operator(\)) + reserved(end) + + comment(# Short-hand for append_before_filter since that's the most common of the two.) + reserved(alias) symbol(:before_filter) symbol(:append_before_filter) + + comment(# The passed <tt>filters</tt> will be appended to the array of filters that's run _after_ actions) + comment(# on this controller are performed.) + reserved(def) method(append_after_filter)operator(()operator(*)ident(filters)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + ident(filters) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + ident(append_filter_to_chain)operator(()string<delimiter(')content(after)delimiter(')>operator(,) ident(filters)operator(\)) + reserved(end) + + comment(# The passed <tt>filters</tt> will be prepended to the array of filters that's run _after_ actions) + comment(# on this controller are performed.) + reserved(def) method(prepend_after_filter)operator(()operator(*)ident(filters)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + ident(filters) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + ident(prepend_filter_to_chain)operator(()string<delimiter(")content(after)delimiter(")>operator(,) ident(filters)operator(\)) + reserved(end) + + comment(# Short-hand for append_after_filter since that's the most common of the two.) + reserved(alias) symbol(:after_filter) symbol(:append_after_filter) + + comment(# The passed <tt>filters</tt> will have their +before+ method appended to the array of filters that's run both before actions) + comment(# on this controller are performed and have their +after+ method prepended to the after actions. The filter objects must all ) + comment(# respond to both +before+ and +after+. So if you do append_around_filter A.new, B.new, the callstack will look like:) + comment(#) + comment(# B#before) + comment(# A#before) + comment(# A#after) + comment(# B#after) + reserved(def) method(append_around_filter)operator(()operator(*)ident(filters)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + reserved(for) ident(filter) reserved(in) ident(filters)operator(.)ident(flatten) + ident(ensure_filter_responds_to_before_and_after)operator(()ident(filter)operator(\)) + ident(append_before_filter)operator(()ident(conditions) operator(||) operator({)operator(})operator(\)) operator({) operator(|)ident(c)operator(|) ident(filter)operator(.)ident(before)operator(()ident(c)operator(\)) operator(}) + ident(prepend_after_filter)operator(()ident(conditions) operator(||) operator({)operator(})operator(\)) operator({) operator(|)ident(c)operator(|) ident(filter)operator(.)ident(after)operator(()ident(c)operator(\)) operator(}) + reserved(end) + reserved(end) + + comment(# The passed <tt>filters</tt> will have their +before+ method prepended to the array of filters that's run both before actions) + comment(# on this controller are performed and have their +after+ method appended to the after actions. The filter objects must all ) + comment(# respond to both +before+ and +after+. So if you do prepend_around_filter A.new, B.new, the callstack will look like:) + comment(#) + comment(# A#before) + comment(# B#before) + comment(# B#after) + comment(# A#after) + reserved(def) method(prepend_around_filter)operator(()operator(*)ident(filters)operator(\)) + reserved(for) ident(filter) reserved(in) ident(filters)operator(.)ident(flatten) + ident(ensure_filter_responds_to_before_and_after)operator(()ident(filter)operator(\)) + ident(prepend_before_filter) operator({) operator(|)ident(c)operator(|) ident(filter)operator(.)ident(before)operator(()ident(c)operator(\)) operator(}) + ident(append_after_filter) operator({) operator(|)ident(c)operator(|) ident(filter)operator(.)ident(after)operator(()ident(c)operator(\)) operator(}) + reserved(end) + reserved(end) + + comment(# Short-hand for append_around_filter since that's the most common of the two.) + reserved(alias) symbol(:around_filter) symbol(:append_around_filter) + + comment(# Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference ) + comment(# filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out) + comment(# of many sub-controllers need a different hierarchy.) + comment(#) + comment(# You can control the actions to skip the filter for with the <tt>:only</tt> and <tt>:except</tt> options, ) + comment(# just like when you apply the filters.) + reserved(def) method(skip_before_filter)operator(()operator(*)ident(filters)operator(\)) + reserved(if) ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + ident(remove_contradicting_conditions!)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + ident(conditions)operator([)symbol(:only)operator(])operator(,) ident(conditions)operator([)symbol(:except)operator(]) operator(=) ident(conditions)operator([)symbol(:except)operator(])operator(,) ident(conditions)operator([)symbol(:only)operator(]) + ident(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + reserved(else) + reserved(for) ident(filter) reserved(in) ident(filters)operator(.)ident(flatten) + ident(write_inheritable_attribute)operator(()string<delimiter(")content(before_filters)delimiter(")>operator(,) ident(read_inheritable_attribute)operator(()string<delimiter(")content(before_filters)delimiter(")>operator(\)) operator(-) operator([) ident(filter) operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Removes the specified filters from the +after+ filter chain. Note that this only works for skipping method-reference ) + comment(# filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out) + comment(# of many sub-controllers need a different hierarchy.) + comment(#) + comment(# You can control the actions to skip the filter for with the <tt>:only</tt> and <tt>:except</tt> options, ) + comment(# just like when you apply the filters.) + reserved(def) method(skip_after_filter)operator(()operator(*)ident(filters)operator(\)) + reserved(if) ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(filters)operator(\)) + ident(remove_contradicting_conditions!)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + ident(conditions)operator([)symbol(:only)operator(])operator(,) ident(conditions)operator([)symbol(:except)operator(]) operator(=) ident(conditions)operator([)symbol(:except)operator(])operator(,) ident(conditions)operator([)symbol(:only)operator(]) + ident(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + reserved(else) + reserved(for) ident(filter) reserved(in) ident(filters)operator(.)ident(flatten) + ident(write_inheritable_attribute)operator(()string<delimiter(")content(after_filters)delimiter(")>operator(,) ident(read_inheritable_attribute)operator(()string<delimiter(")content(after_filters)delimiter(")>operator(\)) operator(-) operator([) ident(filter) operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns all the before filters for this class and all its ancestors.) + reserved(def) method(before_filters) comment(#:nodoc:) + instance_variable(@before_filters) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(before_filters)delimiter(")>operator(\)) operator(||) operator([)operator(]) + reserved(end) + + comment(# Returns all the after filters for this class and all its ancestors.) + reserved(def) method(after_filters) comment(#:nodoc:) + instance_variable(@after_filters) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(after_filters)delimiter(")>operator(\)) operator(||) operator([)operator(]) + reserved(end) + + comment(# Returns a mapping between filters and the actions that may run them.) + reserved(def) method(included_actions) comment(#:nodoc:) + instance_variable(@included_actions) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(included_actions)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + comment(# Returns a mapping between filters and actions that may not run them.) + reserved(def) method(excluded_actions) comment(#:nodoc:) + instance_variable(@excluded_actions) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(excluded_actions)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + ident(private) + reserved(def) method(append_filter_to_chain)operator(()ident(condition)operator(,) ident(filters)operator(\)) + ident(write_inheritable_array)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(_filters)delimiter(")>operator(,) ident(filters)operator(\)) + reserved(end) + + reserved(def) method(prepend_filter_to_chain)operator(()ident(condition)operator(,) ident(filters)operator(\)) + ident(old_filters) operator(=) ident(read_inheritable_attribute)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(_filters)delimiter(")>operator(\)) operator(||) operator([)operator(]) + ident(write_inheritable_attribute)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(_filters)delimiter(")>operator(,) ident(filters) operator(+) ident(old_filters)operator(\)) + reserved(end) + + reserved(def) method(ensure_filter_responds_to_before_and_after)operator(()ident(filter)operator(\)) + reserved(unless) ident(filter)operator(.)ident(respond_to?)operator(()symbol(:before)operator(\)) operator(&&) ident(filter)operator(.)ident(respond_to?)operator(()symbol(:after)operator(\)) + ident(raise) constant(ActionControllerError)operator(,) string<delimiter(")content(Filter object must respond to both before and after)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(extract_conditions!)operator(()ident(filters)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(filters)operator(.)ident(last)operator(.)ident(is_a?) constant(Hash) + ident(filters)operator(.)ident(pop) + reserved(end) + + reserved(def) method(add_action_conditions)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + reserved(return) reserved(unless) ident(conditions) + ident(included)operator(,) ident(excluded) operator(=) ident(conditions)operator([)symbol(:only)operator(])operator(,) ident(conditions)operator([)symbol(:except)operator(]) + ident(write_inheritable_hash)operator(()string<delimiter(')content(included_actions)delimiter(')>operator(,) ident(condition_hash)operator(()ident(filters)operator(,) ident(included)operator(\))operator(\)) operator(&&) reserved(return) reserved(if) ident(included) + ident(write_inheritable_hash)operator(()string<delimiter(')content(excluded_actions)delimiter(')>operator(,) ident(condition_hash)operator(()ident(filters)operator(,) ident(excluded)operator(\))operator(\)) reserved(if) ident(excluded) + reserved(end) + + reserved(def) method(condition_hash)operator(()ident(filters)operator(,) operator(*)ident(actions)operator(\)) + ident(filters)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({)operator(|)ident(hash)operator(,) ident(filter)operator(|) ident(hash)operator(.)ident(merge)operator(()ident(filter) operator(=)operator(>) ident(actions)operator(.)ident(flatten)operator(.)ident(map) operator({)operator(|)ident(action)operator(|) ident(action)operator(.)ident(to_s)operator(})operator(\))operator(}) + reserved(end) + + reserved(def) method(remove_contradicting_conditions!)operator(()ident(filters)operator(,) ident(conditions)operator(\)) + reserved(return) reserved(unless) ident(conditions)operator([)symbol(:only)operator(]) + ident(filters)operator(.)ident(each) reserved(do) operator(|)ident(filter)operator(|) + reserved(next) reserved(unless) ident(included_actions_for_filter) operator(=) operator(()ident(read_inheritable_attribute)operator(()string<delimiter(')content(included_actions)delimiter(')>operator(\)) operator(||) operator({)operator(})operator(\))operator([)ident(filter)operator(]) + operator([)operator(*)ident(conditions)operator([)symbol(:only)operator(])operator(])operator(.)ident(each) reserved(do) operator(|)ident(conditional_action)operator(|) + ident(conditional_action) operator(=) ident(conditional_action)operator(.)ident(to_s) + ident(included_actions_for_filter)operator(.)ident(delete)operator(()ident(conditional_action)operator(\)) reserved(if) ident(included_actions_for_filter)operator(.)ident(include?)operator(()ident(conditional_action)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:perform_action_without_filters)operator(,) symbol(:perform_action) + ident(alias_method) symbol(:perform_action)operator(,) symbol(:perform_action_with_filters) + + ident(alias_method) symbol(:process_without_filters)operator(,) symbol(:process) + ident(alias_method) symbol(:process)operator(,) symbol(:process_with_filters) + + ident(alias_method) symbol(:process_cleanup_without_filters)operator(,) symbol(:process_cleanup) + ident(alias_method) symbol(:process_cleanup)operator(,) symbol(:process_cleanup_with_filters) + reserved(end) + reserved(end) + + reserved(def) method(perform_action_with_filters) + ident(before_action_result) operator(=) ident(before_action) + + reserved(unless) ident(before_action_result) operator(==) pre_constant(false) operator(||) ident(performed?) + ident(perform_action_without_filters) + ident(after_action) + reserved(end) + + instance_variable(@before_filter_chain_aborted) operator(=) operator(()ident(before_action_result) operator(==) pre_constant(false)operator(\)) + reserved(end) + + reserved(def) method(process_with_filters)operator(()ident(request)operator(,) ident(response)operator(,) ident(method) operator(=) symbol(:perform_action)operator(,) operator(*)ident(arguments)operator(\)) comment(#:nodoc:) + instance_variable(@before_filter_chain_aborted) operator(=) pre_constant(false) + ident(process_without_filters)operator(()ident(request)operator(,) ident(response)operator(,) ident(method)operator(,) operator(*)ident(arguments)operator(\)) + reserved(end) + + comment(# Calls all the defined before-filter filters, which are added by using "before_filter :method".) + comment(# If any of the filters return false, no more filters will be executed and the action is aborted.) + reserved(def) method(before_action) comment(#:doc:) + ident(call_filters)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(before_filters)operator(\)) + reserved(end) + + comment(# Calls all the defined after-filter filters, which are added by using "after_filter :method".) + comment(# If any of the filters return false, no more filters will be executed.) + reserved(def) method(after_action) comment(#:doc:) + ident(call_filters)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(after_filters)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(call_filters)operator(()ident(filters)operator(\)) + ident(filters)operator(.)ident(each) reserved(do) operator(|)ident(filter)operator(|) + reserved(next) reserved(if) ident(action_exempted?)operator(()ident(filter)operator(\)) + + ident(filter_result) operator(=) reserved(case) + reserved(when) ident(filter)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + pre_constant(self)operator(.)ident(send)operator(()ident(filter)operator(\)) + reserved(when) ident(filter_block?)operator(()ident(filter)operator(\)) + ident(filter)operator(.)ident(call)operator(()pre_constant(self)operator(\)) + reserved(when) ident(filter_class?)operator(()ident(filter)operator(\)) + ident(filter)operator(.)ident(filter)operator(()pre_constant(self)operator(\)) + reserved(else) + ident(raise)operator(() + constant(ActionControllerError)operator(,) + string<delimiter(')content(Filters need to be either a symbol, proc/method, or class implementing a static filter method)delimiter(')> + operator(\)) + reserved(end) + + reserved(if) ident(filter_result) operator(==) pre_constant(false) + ident(logger)operator(.)ident(info) string<delimiter(")content(Filter chain halted as [)inline<inline_delimiter(#{)ident(filter)inline_delimiter(})>content(] returned false)delimiter(")> reserved(if) ident(logger) + reserved(return) pre_constant(false) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(filter_block?)operator(()ident(filter)operator(\)) + ident(filter)operator(.)ident(respond_to?)operator(()string<delimiter(')content(call)delimiter(')>operator(\)) operator(&&) operator(()ident(filter)operator(.)ident(arity) operator(==) integer(1) operator(||) ident(filter)operator(.)ident(arity) operator(==) integer(-1)operator(\)) + reserved(end) + + reserved(def) method(filter_class?)operator(()ident(filter)operator(\)) + ident(filter)operator(.)ident(respond_to?)operator(()string<delimiter(')content(filter)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(action_exempted?)operator(()ident(filter)operator(\)) + reserved(case) + reserved(when) ident(ia) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(included_actions)operator([)ident(filter)operator(]) + operator(!)ident(ia)operator(.)ident(include?)operator(()ident(action_name)operator(\)) + reserved(when) ident(ea) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(excluded_actions)operator([)ident(filter)operator(]) + ident(ea)operator(.)ident(include?)operator(()ident(action_name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(process_cleanup_with_filters) + reserved(if) instance_variable(@before_filter_chain_aborted) + ident(close_session) + reserved(else) + ident(process_cleanup_without_filters) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed) + comment(# to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create action) + comment(# that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can then expose ) + comment(# the flash to its template. Actually, that exposure is automatically done. Example:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# def create) + comment(# # save post) + comment(# flash[:notice] = "Successfully created post") + comment(# redirect_to :action => "display", :params => { :id => post.id }) + comment(# end) + comment(#) + comment(# def display) + comment(# # doesn't need to assign the flash notice to the template, that's done automatically) + comment(# end) + comment(# end) + comment(#) + comment(# display.rhtml) + comment(# <% if @flash[:notice] %><div class="notice"><%= @flash[:notice] %></div><% end %>) + comment(#) + comment(# This example just places a string in the flash, but you can put any object in there. And of course, you can put as many) + comment(# as you like at a time too. Just remember: They'll be gone by the time the next action has been performed.) + comment(#) + comment(# See docs on the FlashHash class for more details about the flash.) + reserved(module) class(Flash) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(send) symbol(:include)operator(,) constant(InstanceMethods) + + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:assign_shortcuts_without_flash)operator(,) symbol(:assign_shortcuts) + ident(alias_method) symbol(:assign_shortcuts)operator(,) symbol(:assign_shortcuts_with_flash) + + ident(alias_method) symbol(:process_cleanup_without_flash)operator(,) symbol(:process_cleanup) + ident(alias_method) symbol(:process_cleanup)operator(,) symbol(:process_cleanup_with_flash) + reserved(end) + reserved(end) + + + reserved(class) class(FlashNow) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(flash)operator(\)) + instance_variable(@flash) operator(=) ident(flash) + reserved(end) + + reserved(def) method([]=)operator(()ident(k)operator(,) ident(v)operator(\)) + instance_variable(@flash)operator([)ident(k)operator(]) operator(=) ident(v) + instance_variable(@flash)operator(.)ident(discard)operator(()ident(k)operator(\)) + ident(v) + reserved(end) + + reserved(def) method([])operator(()ident(k)operator(\)) + instance_variable(@flash)operator([)ident(k)operator(]) + reserved(end) + reserved(end) + + reserved(class) class(FlashHash) operator(<) constant(Hash) + reserved(def) method(initialize) comment(#:nodoc:) + reserved(super) + instance_variable(@used) operator(=) operator({)operator(}) + reserved(end) + + reserved(def) method([]=)operator(()ident(k)operator(,) ident(v)operator(\)) comment(#:nodoc:) + ident(keep)operator(()ident(k)operator(\)) + reserved(super) + reserved(end) + + reserved(def) method(update)operator(()ident(h)operator(\)) comment(#:nodoc:) + ident(h)operator(.)ident(keys)operator(.)ident(each)operator({) operator(|)ident(k)operator(|) ident(discard)operator(()ident(k)operator(\)) operator(}) + reserved(super) + reserved(end) + + reserved(alias) symbol(:merge!) symbol(:update) + + reserved(def) method(replace)operator(()ident(h)operator(\)) comment(#:nodoc:) + instance_variable(@used) operator(=) operator({)operator(}) + reserved(super) + reserved(end) + + comment(# Sets a flash that will not be available to the next action, only to the current.) + comment(#) + comment(# flash.now[:message] = "Hello current action") + comment(# ) + comment(# This method enables you to use the flash as a central messaging system in your app.) + comment(# When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>\).) + comment(# When you need to pass an object to the current action, you use <tt>now</tt>, and your object will) + comment(# vanish when the current action is done.) + comment(#) + comment(# Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.) + reserved(def) method(now) + constant(FlashNow)operator(.)ident(new) pre_constant(self) + reserved(end) + + comment(# Keeps either the entire current flash or a specific flash entry available for the next action:) + comment(#) + comment(# flash.keep # keeps the entire flash) + comment(# flash.keep(:notice\) # keeps only the "notice" entry, the rest of the flash is discarded) + reserved(def) method(keep)operator(()ident(k)operator(=)pre_constant(nil)operator(\)) + ident(use)operator(()ident(k)operator(,) pre_constant(false)operator(\)) + reserved(end) + + comment(# Marks the entire flash or a single flash entry to be discarded by the end of the current action) + comment(#) + comment(# flash.keep # keep entire flash available for the next action) + comment(# flash.discard(:warning\) # discard the "warning" entry (it'll still be available for the current action\)) + reserved(def) method(discard)operator(()ident(k)operator(=)pre_constant(nil)operator(\)) + ident(use)operator(()ident(k)operator(\)) + reserved(end) + + comment(# Mark for removal entries that were kept, and delete unkept ones.) + comment(#) + comment(# This method is called automatically by filters, so you generally don't need to care about it.) + reserved(def) method(sweep) comment(#:nodoc:) + ident(keys)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(|) + reserved(unless) instance_variable(@used)operator([)ident(k)operator(]) + ident(use)operator(()ident(k)operator(\)) + reserved(else) + ident(delete)operator(()ident(k)operator(\)) + instance_variable(@used)operator(.)ident(delete)operator(()ident(k)operator(\)) + reserved(end) + reserved(end) + operator(()instance_variable(@used)operator(.)ident(keys) operator(-) ident(keys)operator(\))operator(.)ident(each)operator({)operator(|)ident(k)operator(|) instance_variable(@used)operator(.)ident(delete) ident(k) operator(}) comment(# clean up after keys that could have been left over by calling reject! or shift on the flash) + reserved(end) + + ident(private) + comment(# Used internally by the <tt>keep</tt> and <tt>discard</tt> methods) + comment(# use(\) # marks the entire flash as used) + comment(# use('msg'\) # marks the "msg" entry as used) + comment(# use(nil, false\) # marks the entire flash as unused (keeps it around for one more action\)) + comment(# use('msg', false\) # marks the "msg" entry as unused (keeps it around for one more action\)) + reserved(def) method(use)operator(()ident(k)operator(=)pre_constant(nil)operator(,) ident(v)operator(=)pre_constant(true)operator(\)) + reserved(unless) ident(k)operator(.)ident(nil?) + instance_variable(@used)operator([)ident(k)operator(]) operator(=) ident(v) + reserved(else) + ident(keys)operator(.)ident(each)operator({)operator(|)ident(key)operator(|) ident(use) ident(key)operator(,) ident(v) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) comment(#:nodoc:) + reserved(def) method(assign_shortcuts_with_flash)operator(()ident(request)operator(,) ident(response)operator(\)) comment(#:nodoc:) + ident(assign_shortcuts_without_flash)operator(()ident(request)operator(,) ident(response)operator(\)) + ident(flash)operator(()symbol(:refresh)operator(\)) + reserved(end) + + reserved(def) method(process_cleanup_with_flash) + ident(flash)operator(.)ident(sweep) reserved(if) instance_variable(@session) + ident(process_cleanup_without_flash) + reserved(end) + + ident(protected) + comment(# Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or ) + comment(# <tt>flash["notice"] = "hello"</tt> to put a new one.) + comment(# Note that if sessions are disabled only flash.now will work.) + reserved(def) method(flash)operator(()ident(refresh) operator(=) pre_constant(false)operator(\)) comment(#:doc:) + reserved(if) instance_variable(@flash)operator(.)ident(nil?) operator(||) ident(refresh) + instance_variable(@flash) operator(=) + reserved(if) instance_variable(@session)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + comment(# @session is a Hash, if sessions are disabled) + comment(# we don't put the flash in the session in this case) + constant(FlashHash)operator(.)ident(new) + reserved(else) + comment(# otherwise, @session is a CGI::Session or a TestSession) + comment(# so make sure it gets retrieved from/saved to session storage after request processing) + instance_variable(@session)operator([)string<delimiter(")content(flash)delimiter(")>operator(]) operator(||=) constant(FlashHash)operator(.)ident(new) + reserved(end) + reserved(end) + + instance_variable(@flash) + reserved(end) + + comment(# deprecated. use <tt>flash.keep</tt> instead) + reserved(def) method(keep_flash) comment(#:doc:) + ident(warn) string<delimiter(')content(keep_flash is deprecated; use flash.keep instead.)delimiter(')> + ident(flash)operator(.)ident(keep) + reserved(end) + reserved(end) + reserved(end) +ident(endmodule) constant(ActionController) comment(#:nodoc:) + reserved(module) class(Helpers) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + + comment(# Initialize the base module to aggregate its helpers.) + ident(base)operator(.)ident(class_inheritable_accessor) symbol(:master_helper_module) + ident(base)operator(.)ident(master_helper_module) operator(=) constant(Module)operator(.)ident(new) + + comment(# Extend base with class methods to declare helpers.) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + + ident(base)operator(.)ident(class_eval) reserved(do) + comment(# Wrap inherited to create a new master helper module for subclasses.) + reserved(class) operator(<<) class(self) + ident(alias_method) symbol(:inherited_without_helper)operator(,) symbol(:inherited) + ident(alias_method) symbol(:inherited)operator(,) symbol(:inherited_with_helper) + reserved(end) + reserved(end) + reserved(end) + + comment(# The template helpers serve to relieve the templates from including the same inline code again and again. It's a) + comment(# set of standardized methods for working with forms (FormHelper\), dates (DateHelper\), texts (TextHelper\), and ) + comment(# Active Records (ActiveRecordHelper\) that's available to all templates by default.) + comment(#) + comment(# It's also really easy to make your own helpers and it's much encouraged to keep the template files free) + comment(# from complicated logic. It's even encouraged to bundle common compositions of methods from other helpers ) + comment(# (often the common helpers\) as they're used by the specific application.) + comment(# ) + comment(# module MyHelper) + comment(# def hello_world(\) "hello world" end) + comment(# end) + comment(# ) + comment(# MyHelper can now be included in a controller, like this:) + comment(# ) + comment(# class MyController < ActionController::Base) + comment(# helper :my_helper) + comment(# end) + comment(# ) + comment(# ...and, same as above, used in any template rendered from MyController, like this:) + comment(# ) + comment(# Let's hear what the helper has to say: <tt><%= hello_world %></tt>) + reserved(module) class(ClassMethods) + comment(# Makes all the (instance\) methods in the helper module available to templates rendered through this controller.) + comment(# See ActionView::Helpers (link:classes/ActionView/Helpers.html\) for more about making your own helper modules ) + comment(# available to the templates.) + reserved(def) method(add_template_helper)operator(()ident(helper_module)operator(\)) comment(#:nodoc:) + ident(master_helper_module)operator(.)ident(send)operator(()symbol(:include)operator(,) ident(helper_module)operator(\)) + reserved(end) + + comment(# Declare a helper:) + comment(# helper :foo) + comment(# requires 'foo_helper' and includes FooHelper in the template class.) + comment(# helper FooHelper) + comment(# includes FooHelper in the template class.) + comment(# helper { def foo(\) "#{bar} is the very best" end }) + comment(# evaluates the block in the template class, adding method #foo.) + comment(# helper(:three, BlindHelper\) { def mice(\) 'mice' end }) + comment(# does all three.) + reserved(def) method(helper)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(args)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(arg)operator(|) + reserved(case) ident(arg) + reserved(when) constant(Module) + ident(add_template_helper)operator(()ident(arg)operator(\)) + reserved(when) constant(String)operator(,) constant(Symbol) + ident(file_name) operator(=) ident(arg)operator(.)ident(to_s)operator(.)ident(underscore) operator(+) string<delimiter(')content(_helper)delimiter(')> + ident(class_name) operator(=) ident(file_name)operator(.)ident(camelize) + + reserved(begin) + ident(require_dependency)operator(()ident(file_name)operator(\)) + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(load_error) + ident(requiree) operator(=) regexp<delimiter(/)content( -- (.*?\)()char(\\.)content(rb\)?$)delimiter(/)>operator(.)ident(match)operator(()ident(load_error)operator(\))operator(.)ident(to_a)operator([)integer(1)operator(]) + ident(msg) operator(=) operator(()ident(requiree) operator(==) ident(file_name)operator(\)) operator(?) string<delimiter(")content(Missing helper file helpers/)inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>content(.rb)delimiter(")> operator(:) string<delimiter(")content(Can't load file: )inline<inline_delimiter(#{)ident(requiree)inline_delimiter(})>delimiter(")> + ident(raise) constant(LoadError)operator(.)ident(new)operator(()ident(msg)operator(\))operator(.)ident(copy_blame!)operator(()ident(load_error)operator(\)) + reserved(end) + + ident(add_template_helper)operator(()ident(class_name)operator(.)ident(constantize)operator(\)) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(helper expects String, Symbol, or Module argument)delimiter(')> + reserved(end) + reserved(end) + + comment(# Evaluate block in template class if given.) + ident(master_helper_module)operator(.)ident(module_eval)operator(()operator(&)ident(block)operator(\)) reserved(if) ident(block_given?) + reserved(end) + + comment(# Declare a controller method as a helper. For example,) + comment(# helper_method :link_to) + comment(# def link_to(name, options\) ... end) + comment(# makes the link_to controller method available in the view.) + reserved(def) method(helper_method)operator(()operator(*)ident(methods)operator(\)) + ident(methods)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(master_helper_module)operator(.)ident(module_eval) string<delimiter(<<-end_eval)>string<content( + def )inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content((*args, &block\) + controller.send(%()inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(\), *args, &block\) + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + + comment(# Declare a controller attribute as a helper. For example,) + comment(# helper_attr :name) + comment(# attr_accessor :name) + comment(# makes the name and name= controller methods available in the view.) + comment(# The is a convenience wrapper for helper_method.) + reserved(def) method(helper_attr)operator(()operator(*)ident(attrs)operator(\)) + ident(attrs)operator(.)ident(flatten)operator(.)ident(each) operator({) operator(|)ident(attr)operator(|) ident(helper_method)operator(()ident(attr)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(attr)inline_delimiter(})>content(=)delimiter(")>operator(\)) operator(}) + reserved(end) + + ident(private) + reserved(def) method(default_helper_module!) + ident(module_name) operator(=) ident(name)operator(.)ident(sub)operator(()regexp<delimiter(/)content(Controller$|$)delimiter(/)>operator(,) string<delimiter(')content(Helper)delimiter(')>operator(\)) + ident(module_path) operator(=) ident(module_name)operator(.)ident(split)operator(()string<delimiter(')content(::)delimiter(')>operator(\))operator(.)ident(map) operator({) operator(|)ident(m)operator(|) ident(m)operator(.)ident(underscore) operator(})operator(.)ident(join)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) + ident(require_dependency) ident(module_path) + ident(helper) ident(module_name)operator(.)ident(constantize) + reserved(rescue) constant(LoadError) + ident(logger)operator(.)ident(debug)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(: missing default helper path )inline<inline_delimiter(#{)ident(module_path)inline_delimiter(})>delimiter(")>operator(\)) reserved(if) ident(logger) + reserved(rescue) constant(NameError) + ident(logger)operator(.)ident(debug)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(: missing default helper module )inline<inline_delimiter(#{)ident(module_name)inline_delimiter(})>delimiter(")>operator(\)) reserved(if) ident(logger) + reserved(end) + + reserved(def) method(inherited_with_helper)operator(()ident(child)operator(\)) + ident(inherited_without_helper)operator(()ident(child)operator(\)) + reserved(begin) + ident(child)operator(.)ident(master_helper_module) operator(=) constant(Module)operator(.)ident(new) + ident(child)operator(.)ident(master_helper_module)operator(.)ident(send) symbol(:include)operator(,) ident(master_helper_module) + ident(child)operator(.)ident(send) symbol(:default_helper_module!) + reserved(rescue) constant(MissingSourceFile) operator(=)operator(>) ident(e) + ident(raise) reserved(unless) ident(e)operator(.)ident(is_missing?)operator(()string<delimiter(")content(helpers/)inline<inline_delimiter(#{)ident(child)operator(.)ident(controller_path)inline_delimiter(})>content(_helper)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(dispatcher)delimiter(')> +ident(require) string<delimiter(')content(stringio)delimiter(')> +ident(require) string<delimiter(')content(uri)delimiter(')> + +reserved(module) class(ActionController) + reserved(module) class(Integration) comment(#:nodoc:) + comment(# An integration Session instance represents a set of requests and responses) + comment(# performed sequentially by some virtual user. Becase you can instantiate) + comment(# multiple sessions and run them side-by-side, you can also mimic (to some) + comment(# limited extent\) multiple simultaneous users interacting with your system.) + comment(#) + comment(# Typically, you will instantiate a new session using IntegrationTest#open_session,) + comment(# rather than instantiating Integration::Session directly.) + reserved(class) class(Session) + ident(include) constant(Test)operator(::)constant(Unit)operator(::)constant(Assertions) + ident(include) constant(ActionController)operator(::)constant(TestProcess) + + comment(# The integer HTTP status code of the last request.) + ident(attr_reader) symbol(:status) + + comment(# The status message that accompanied the status code of the last request.) + ident(attr_reader) symbol(:status_message) + + comment(# The URI of the last request.) + ident(attr_reader) symbol(:path) + + comment(# The hostname used in the last request.) + ident(attr_accessor) symbol(:host) + + comment(# The remote_addr used in the last request.) + ident(attr_accessor) symbol(:remote_addr) + + comment(# The Accept header to send.) + ident(attr_accessor) symbol(:accept) + + comment(# A map of the cookies returned by the last response, and which will be) + comment(# sent with the next request.) + ident(attr_reader) symbol(:cookies) + + comment(# A map of the headers returned by the last response.) + ident(attr_reader) symbol(:headers) + + comment(# A reference to the controller instance used by the last request.) + ident(attr_reader) symbol(:controller) + + comment(# A reference to the request instance used by the last request.) + ident(attr_reader) symbol(:request) + + comment(# A reference to the response instance used by the last request.) + ident(attr_reader) symbol(:response) + + comment(# Create an initialize a new Session instance.) + reserved(def) method(initialize) + ident(reset!) + reserved(end) + + comment(# Resets the instance. This can be used to reset the state information) + comment(# in an existing session instance, so it can be used from a clean-slate) + comment(# condition.) + comment(#) + comment(# session.reset!) + reserved(def) method(reset!) + instance_variable(@status) operator(=) instance_variable(@path) operator(=) instance_variable(@headers) operator(=) pre_constant(nil) + instance_variable(@result) operator(=) instance_variable(@status_message) operator(=) pre_constant(nil) + instance_variable(@https) operator(=) pre_constant(false) + instance_variable(@cookies) operator(=) operator({)operator(}) + instance_variable(@controller) operator(=) instance_variable(@request) operator(=) instance_variable(@response) operator(=) pre_constant(nil) + + pre_constant(self)operator(.)ident(host) operator(=) string<delimiter(")content(www.example.com)delimiter(")> + pre_constant(self)operator(.)ident(remote_addr) operator(=) string<delimiter(")content(127.0.0.1)delimiter(")> + pre_constant(self)operator(.)ident(accept) operator(=) string<delimiter(")content(text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5)delimiter(")> + + reserved(unless) instance_variable(@named_routes_configured) + comment(# install the named routes in this session instance.) + ident(klass) operator(=) reserved(class)operator(<<)class(self)operator(;) pre_constant(self)operator(;) reserved(end) + constant(Routing)operator(::)constant(NamedRoutes)operator(.)ident(install)operator(()ident(klass)operator(\)) + + comment(# the helpers are made protected by default--we make them public for) + comment(# easier access during testing and troubleshooting.) + ident(klass)operator(.)ident(send)operator(()symbol(:public)operator(,) operator(*)constant(Routing)operator(::)constant(NamedRoutes)operator(::)constant(Helpers)operator(\)) + instance_variable(@named_routes_configured) operator(=) pre_constant(true) + reserved(end) + reserved(end) + + comment(# Specify whether or not the session should mimic a secure HTTPS request.) + comment(#) + comment(# session.https!) + comment(# session.https!(false\)) + reserved(def) method(https!)operator(()ident(flag)operator(=)pre_constant(true)operator(\)) + instance_variable(@https) operator(=) ident(flag) + reserved(end) + + comment(# Return +true+ if the session is mimicing a secure HTTPS request.) + comment(#) + comment(# if session.https?) + comment(# ...) + comment(# end) + reserved(def) method(https?) + instance_variable(@https) + reserved(end) + + comment(# Set the host name to use in the next request.) + comment(#) + comment(# session.host! "www.example.com") + reserved(def) method(host!)operator(()ident(name)operator(\)) + instance_variable(@host) operator(=) ident(name) + reserved(end) + + comment(# Follow a single redirect response. If the last response was not a) + comment(# redirect, an exception will be raised. Otherwise, the redirect is) + comment(# performed on the location header.) + reserved(def) method(follow_redirect!) + ident(raise) string<delimiter(")content(not a redirect! )inline<inline_delimiter(#{)instance_variable(@status)inline_delimiter(})>content( )inline<inline_delimiter(#{)instance_variable(@status_message)inline_delimiter(})>delimiter(")> reserved(unless) ident(redirect?) + ident(get)operator(()ident(interpret_uri)operator(()ident(headers)operator([)string<delimiter(")content(location)delimiter(")>operator(])operator(.)ident(first)operator(\))operator(\)) + ident(status) + reserved(end) + + comment(# Performs a GET request, following any subsequent redirect. Note that) + comment(# the redirects are followed until the response is not a redirect--this) + comment(# means you may run into an infinite loop if your redirect loops back to) + comment(# itself.) + reserved(def) method(get_via_redirect)operator(()ident(path)operator(,) ident(args)operator(=)operator({)operator(})operator(\)) + ident(get) ident(path)operator(,) ident(args) + ident(follow_redirect!) reserved(while) ident(redirect?) + ident(status) + reserved(end) + + comment(# Performs a POST request, following any subsequent redirect. This is) + comment(# vulnerable to infinite loops, the same as #get_via_redirect.) + reserved(def) method(post_via_redirect)operator(()ident(path)operator(,) ident(args)operator(=)operator({)operator(})operator(\)) + ident(post) ident(path)operator(,) ident(args) + ident(follow_redirect!) reserved(while) ident(redirect?) + ident(status) + reserved(end) + + comment(# Returns +true+ if the last response was a redirect.) + reserved(def) method(redirect?) + ident(status)operator(/)integer(100) operator(==) integer(3) + reserved(end) + + comment(# Performs a GET request with the given parameters. The parameters may) + comment(# be +nil+, a Hash, or a string that is appropriately encoded) + comment(# (application/x-www-form-urlencoded or multipart/form-data\). The headers) + comment(# should be a hash. The keys will automatically be upcased, with the ) + comment(# prefix 'HTTP_' added if needed.) + reserved(def) method(get)operator(()ident(path)operator(,) ident(parameters)operator(=)pre_constant(nil)operator(,) ident(headers)operator(=)pre_constant(nil)operator(\)) + ident(process) symbol(:get)operator(,) ident(path)operator(,) ident(parameters)operator(,) ident(headers) + reserved(end) + + comment(# Performs a POST request with the given parameters. The parameters may) + comment(# be +nil+, a Hash, or a string that is appropriately encoded) + comment(# (application/x-www-form-urlencoded or multipart/form-data\). The headers) + comment(# should be a hash. The keys will automatically be upcased, with the ) + comment(# prefix 'HTTP_' added if needed.) + reserved(def) method(post)operator(()ident(path)operator(,) ident(parameters)operator(=)pre_constant(nil)operator(,) ident(headers)operator(=)pre_constant(nil)operator(\)) + ident(process) symbol(:post)operator(,) ident(path)operator(,) ident(parameters)operator(,) ident(headers) + reserved(end) + + comment(# Performs an XMLHttpRequest request with the given parameters, mimicing) + comment(# the request environment created by the Prototype library. The parameters) + comment(# may be +nil+, a Hash, or a string that is appropriately encoded) + comment(# (application/x-www-form-urlencoded or multipart/form-data\). The headers) + comment(# should be a hash. The keys will automatically be upcased, with the ) + comment(# prefix 'HTTP_' added if needed.) + reserved(def) method(xml_http_request)operator(()ident(path)operator(,) ident(parameters)operator(=)pre_constant(nil)operator(,) ident(headers)operator(=)pre_constant(nil)operator(\)) + ident(headers) operator(=) operator(()ident(headers) operator(||) operator({)operator(})operator(\))operator(.)ident(merge)operator(()string<delimiter(")content(X-Requested-With)delimiter(")> operator(=)operator(>) string<delimiter(")content(XMLHttpRequest)delimiter(")>operator(\)) + ident(post)operator(()ident(path)operator(,) ident(parameters)operator(,) ident(headers)operator(\)) + reserved(end) + + comment(# Returns the URL for the given options, according to the rules specified) + comment(# in the application's routes.) + reserved(def) method(url_for)operator(()ident(options)operator(\)) + ident(controller) operator(?) ident(controller)operator(.)ident(url_for)operator(()ident(options)operator(\)) operator(:) ident(generic_url_rewriter)operator(.)ident(rewrite)operator(()ident(options)operator(\)) + reserved(end) + + ident(private) + + reserved(class) class(MockCGI) operator(<) constant(CGI) comment(#:nodoc:) + ident(attr_accessor) symbol(:stdinput)operator(,) symbol(:stdoutput)operator(,) symbol(:env_table) + + reserved(def) method(initialize)operator(()ident(env)operator(,) ident(input)operator(=)pre_constant(nil)operator(\)) + pre_constant(self)operator(.)ident(env_table) operator(=) ident(env) + pre_constant(self)operator(.)ident(stdinput) operator(=) constant(StringIO)operator(.)ident(new)operator(()ident(input) operator(||) string<delimiter(")delimiter(")>operator(\)) + pre_constant(self)operator(.)ident(stdoutput) operator(=) constant(StringIO)operator(.)ident(new) + + reserved(super)operator(()operator(\)) + reserved(end) + reserved(end) + + comment(# Tailors the session based on the given URI, setting the HTTPS value) + comment(# and the hostname.) + reserved(def) method(interpret_uri)operator(()ident(path)operator(\)) + ident(location) operator(=) constant(URI)operator(.)ident(parse)operator(()ident(path)operator(\)) + ident(https!) constant(URI)operator(::)constant(HTTPS) operator(===) ident(location) reserved(if) ident(location)operator(.)ident(scheme) + ident(host!) ident(location)operator(.)ident(host) reserved(if) ident(location)operator(.)ident(host) + ident(location)operator(.)ident(query) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(location)operator(.)ident(path)inline_delimiter(})>content(?)inline<inline_delimiter(#{)ident(location)operator(.)ident(query)inline_delimiter(})>delimiter(")> operator(:) ident(location)operator(.)ident(path) + reserved(end) + + comment(# Performs the actual request.) + reserved(def) method(process)operator(()ident(method)operator(,) ident(path)operator(,) ident(parameters)operator(=)pre_constant(nil)operator(,) ident(headers)operator(=)pre_constant(nil)operator(\)) + ident(data) operator(=) ident(requestify)operator(()ident(parameters)operator(\)) + ident(path) operator(=) ident(interpret_uri)operator(()ident(path)operator(\)) reserved(if) ident(path) operator(=)operator(~) regexp<delimiter(%r{)content(://)delimiter(})> + ident(path) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")> reserved(unless) ident(path)operator([)integer(0)operator(]) operator(==) integer(?/) + instance_variable(@path) operator(=) ident(path) + ident(env) operator(=) operator({)operator(}) + + reserved(if) ident(method) operator(==) symbol(:get) + ident(env)operator([)string<delimiter(")content(QUERY_STRING)delimiter(")>operator(]) operator(=) ident(data) + ident(data) operator(=) pre_constant(nil) + reserved(end) + + ident(env)operator(.)ident(update)operator(() + string<delimiter(")content(REQUEST_METHOD)delimiter(")> operator(=)operator(>) ident(method)operator(.)ident(to_s)operator(.)ident(upcase)operator(,) + string<delimiter(")content(REQUEST_URI)delimiter(")> operator(=)operator(>) ident(path)operator(,) + string<delimiter(")content(HTTP_HOST)delimiter(")> operator(=)operator(>) ident(host)operator(,) + string<delimiter(")content(REMOTE_ADDR)delimiter(")> operator(=)operator(>) ident(remote_addr)operator(,) + string<delimiter(")content(SERVER_PORT)delimiter(")> operator(=)operator(>) operator(()ident(https?) operator(?) string<delimiter(")content(443)delimiter(")> operator(:) string<delimiter(")content(80)delimiter(")>operator(\))operator(,) + string<delimiter(")content(CONTENT_TYPE)delimiter(")> operator(=)operator(>) string<delimiter(")content(application/x-www-form-urlencoded)delimiter(")>operator(,) + string<delimiter(")content(CONTENT_LENGTH)delimiter(")> operator(=)operator(>) ident(data) operator(?) ident(data)operator(.)ident(length)operator(.)ident(to_s) operator(:) pre_constant(nil)operator(,) + string<delimiter(")content(HTTP_COOKIE)delimiter(")> operator(=)operator(>) ident(encode_cookies)operator(,) + string<delimiter(")content(HTTPS)delimiter(")> operator(=)operator(>) ident(https?) operator(?) string<delimiter(")content(on)delimiter(")> operator(:) string<delimiter(")content(off)delimiter(")>operator(,) + string<delimiter(")content(HTTP_ACCEPT)delimiter(")> operator(=)operator(>) ident(accept) + operator(\)) + + operator(()ident(headers) operator(||) operator({)operator(})operator(\))operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + ident(key) operator(=) ident(key)operator(.)ident(to_s)operator(.)ident(upcase)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(-)delimiter(/)>operator(,) string<delimiter(")content(_)delimiter(")>operator(\)) + ident(key) operator(=) string<delimiter(")content(HTTP_)inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")> reserved(unless) ident(env)operator(.)ident(has_key?)operator(()ident(key)operator(\)) operator(||) ident(env) operator(=)operator(~) regexp<delimiter(/)content(^X|HTTP)delimiter(/)> + ident(env)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(end) + + reserved(unless) constant(ActionController)operator(::)constant(Base)operator(.)ident(respond_to?)operator(()symbol(:clear_last_instantiation!)operator(\)) + constant(ActionController)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ControllerCapture)operator(\)) + reserved(end) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(clear_last_instantiation!) + + ident(cgi) operator(=) constant(MockCGI)operator(.)ident(new)operator(()ident(env)operator(,) ident(data)operator(\)) + constant(Dispatcher)operator(.)ident(dispatch)operator(()ident(cgi)operator(,) constant(ActionController)operator(::)constant(CgiRequest)operator(::)constant(DEFAULT_SESSION_OPTIONS)operator(,) ident(cgi)operator(.)ident(stdoutput)operator(\)) + instance_variable(@result) operator(=) ident(cgi)operator(.)ident(stdoutput)operator(.)ident(string) + + instance_variable(@controller) operator(=) constant(ActionController)operator(::)constant(Base)operator(.)ident(last_instantiation) + instance_variable(@request) operator(=) instance_variable(@controller)operator(.)ident(request) + instance_variable(@response) operator(=) instance_variable(@controller)operator(.)ident(response) + + comment(# Decorate the response with the standard behavior of the TestResponse) + comment(# so that things like assert_response can be used in integration) + comment(# tests.) + instance_variable(@response)operator(.)ident(extend)operator(()constant(TestResponseBehavior)operator(\)) + + ident(parse_result) + reserved(return) ident(status) + reserved(end) + + comment(# Parses the result of the response and extracts the various values,) + comment(# like cookies, status, headers, etc.) + reserved(def) method(parse_result) + ident(headers)operator(,) ident(result_body) operator(=) instance_variable(@result)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\r)char(\\n)char(\\r)char(\\n)delimiter(/)>operator(,) integer(2)operator(\)) + + instance_variable(@headers) operator(=) constant(Hash)operator(.)ident(new) operator({) operator(|)ident(h)operator(,)ident(k)operator(|) ident(h)operator([)ident(k)operator(]) operator(=) operator([)operator(]) operator(}) + ident(headers)operator(.)ident(each_line) reserved(do) operator(|)ident(line)operator(|) + ident(key)operator(,) ident(value) operator(=) ident(line)operator(.)ident(strip)operator(.)ident(split)operator(()regexp<delimiter(/)content(:)char(\\s)content(*)delimiter(/)>operator(,) integer(2)operator(\)) + instance_variable(@headers)operator([)ident(key)operator(.)ident(downcase)operator(]) operator(<<) ident(value) + reserved(end) + + operator(()instance_variable(@headers)operator([)string<delimiter(')content(set-cookie)delimiter(')>operator(]) operator(||) operator([)operator(]) operator(\))operator(.)ident(each) reserved(do) operator(|)ident(string)operator(|) + ident(name)operator(,) ident(value) operator(=) ident(string)operator(.)ident(match)operator(()regexp<delimiter(/)content(^(.*?\)=(.*?\);)delimiter(/)>operator(\))operator([)integer(1)operator(,)integer(2)operator(]) + instance_variable(@cookies)operator([)ident(name)operator(]) operator(=) ident(value) + reserved(end) + + instance_variable(@status)operator(,) instance_variable(@status_message) operator(=) instance_variable(@headers)operator([)string<delimiter(")content(status)delimiter(")>operator(])operator(.)ident(first)operator(.)ident(split)operator(()regexp<delimiter(/)content( )delimiter(/)>operator(\)) + instance_variable(@status) operator(=) instance_variable(@status)operator(.)ident(to_i) + reserved(end) + + comment(# Encode the cookies hash in a format suitable for passing to a ) + comment(# request.) + reserved(def) method(encode_cookies) + ident(cookies)operator(.)ident(inject)operator(()string<delimiter(")delimiter(")>operator(\)) reserved(do) operator(|)ident(string)operator(,) operator(()ident(name)operator(,) ident(value)operator(\))operator(|) + ident(string) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(=)inline<inline_delimiter(#{)ident(value)inline_delimiter(})>content(; )delimiter(")> + reserved(end) + reserved(end) + + comment(# Get a temporarly URL writer object) + reserved(def) method(generic_url_rewriter) + ident(cgi) operator(=) constant(MockCGI)operator(.)ident(new)operator(()string<delimiter(')content(REQUEST_METHOD)delimiter(')> operator(=)operator(>) string<delimiter(")content(GET)delimiter(")>operator(,) + string<delimiter(')content(QUERY_STRING)delimiter(')> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + string<delimiter(")content(REQUEST_URI)delimiter(")> operator(=)operator(>) string<delimiter(")content(/)delimiter(")>operator(,) + string<delimiter(")content(HTTP_HOST)delimiter(")> operator(=)operator(>) ident(host)operator(,) + string<delimiter(")content(SERVER_PORT)delimiter(")> operator(=)operator(>) ident(https?) operator(?) string<delimiter(")content(443)delimiter(")> operator(:) string<delimiter(")content(80)delimiter(")>operator(,) + string<delimiter(")content(HTTPS)delimiter(")> operator(=)operator(>) ident(https?) operator(?) string<delimiter(")content(on)delimiter(")> operator(:) string<delimiter(")content(off)delimiter(")>operator(\)) + constant(ActionController)operator(::)constant(UrlRewriter)operator(.)ident(new)operator(()constant(ActionController)operator(::)constant(CgiRequest)operator(.)ident(new)operator(()ident(cgi)operator(\))operator(,) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(name_with_prefix)operator(()ident(prefix)operator(,) ident(name)operator(\)) + ident(prefix) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(prefix)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(])delimiter(")> operator(:) ident(name)operator(.)ident(to_s) + reserved(end) + + comment(# Convert the given parameters to a request string. The parameters may) + comment(# be a string, +nil+, or a Hash.) + reserved(def) method(requestify)operator(()ident(parameters)operator(,) ident(prefix)operator(=)pre_constant(nil)operator(\)) + reserved(if) constant(Hash) operator(===) ident(parameters) + reserved(return) pre_constant(nil) reserved(if) ident(parameters)operator(.)ident(empty?) + ident(parameters)operator(.)ident(map) operator({) operator(|)ident(k)operator(,)ident(v)operator(|) ident(requestify)operator(()ident(v)operator(,) ident(name_with_prefix)operator(()ident(prefix)operator(,) ident(k)operator(\))operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(&)delimiter(")>operator(\)) + reserved(elsif) constant(Array) operator(===) ident(parameters) + ident(parameters)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) ident(requestify)operator(()ident(v)operator(,) ident(name_with_prefix)operator(()ident(prefix)operator(,) string<delimiter(")delimiter(")>operator(\))operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(&)delimiter(")>operator(\)) + reserved(elsif) ident(prefix)operator(.)ident(nil?) + ident(parameters) + reserved(else) + string<delimiter(")inline<inline_delimiter(#{)constant(CGI)operator(.)ident(escape)operator(()ident(prefix)operator(\))inline_delimiter(})>content(=)inline<inline_delimiter(#{)constant(CGI)operator(.)ident(escape)operator(()ident(parameters)operator(.)ident(to_s)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(end) + + comment(# A module used to extend ActionController::Base, so that integration tests) + comment(# can capture the controller used to satisfy a request.) + reserved(module) class(ControllerCapture) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(class_eval) reserved(do) + reserved(class) operator(<<)class(self) + ident(alias_method) symbol(:new_without_capture)operator(,) symbol(:new) + ident(alias_method) symbol(:new)operator(,) symbol(:new_with_capture) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + ident(mattr_accessor) symbol(:last_instantiation) + + reserved(def) method(clear_last_instantiation!) + pre_constant(self)operator(.)ident(last_instantiation) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(new_with_capture)operator(()operator(*)ident(args)operator(\)) + pre_constant(self)operator(.)ident(last_instantiation) operator(||=) ident(new_without_capture)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# An IntegrationTest is one that spans multiple controllers and actions,) + comment(# tying them all together to ensure they work together as expected. It tests) + comment(# more completely than either unit or functional tests do, exercising the) + comment(# entire stack, from the dispatcher to the database.) + comment(#) + comment(# At its simplest, you simply extend IntegrationTest and write your tests) + comment(# using the get/post methods:) + comment(#) + comment(# require "#{File.dirname(__FILE__\)}/test_helper") + comment(#) + comment(# class ExampleTest < ActionController::IntegrationTest) + comment(# fixtures :people) + comment(#) + comment(# def test_login) + comment(# # get the login page) + comment(# get "/login") + comment(# assert_equal 200, status) + comment(#) + comment(# # post the login and follow through to the home page) + comment(# post "/login", :username => people(:jamis\).username,) + comment(# :password => people(:jamis\).password) + comment(# follow_redirect!) + comment(# assert_equal 200, status) + comment(# assert_equal "/home", path) + comment(# end) + comment(# end) + comment(#) + comment(# However, you can also have multiple session instances open per test, and) + comment(# even extend those instances with assertions and methods to create a very) + comment(# powerful testing DSL that is specific for your application. You can even) + comment(# reference any named routes you happen to have defined!) + comment(#) + comment(# require "#{File.dirname(__FILE__\)}/test_helper") + comment(#) + comment(# class AdvancedTest < ActionController::IntegrationTest) + comment(# fixtures :people, :rooms) + comment(#) + comment(# def test_login_and_speak) + comment(# jamis, david = login(:jamis\), login(:david\)) + comment(# room = rooms(:office\)) + comment(#) + comment(# jamis.enter(room\)) + comment(# jamis.speak(room, "anybody home?"\)) + comment(#) + comment(# david.enter(room\)) + comment(# david.speak(room, "hello!"\)) + comment(# end) + comment(#) + comment(# private) + comment(#) + comment(# module CustomAssertions) + comment(# def enter(room\)) + comment(# # reference a named route, for maximum internal consistency!) + comment(# get(room_url(:id => room.id\)\)) + comment(# assert(...\)) + comment(# ...) + comment(# end) + comment(#) + comment(# def speak(room, message\)) + comment(# xml_http_request "/say/#{room.id}", :message => message) + comment(# assert(...\)) + comment(# ...) + comment(# end) + comment(# end) + comment(#) + comment(# def login(who\)) + comment(# open_session do |sess|) + comment(# sess.extend(CustomAssertions\)) + comment(# who = people(who\)) + comment(# sess.post "/login", :username => who.username,) + comment(# :password => who.password) + comment(# assert(...\)) + comment(# end) + comment(# end) + comment(# end) + reserved(class) class(IntegrationTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + comment(# Work around a bug in test/unit caused by the default test being named) + comment(# as a symbol (:default_test\), which causes regex test filters) + comment(# (like "ruby test.rb -n /foo/"\) to fail because =~ doesn't work on) + comment(# symbols.) + reserved(def) method(initialize)operator(()ident(name)operator(\)) comment(#:nodoc:) + reserved(super)operator(()ident(name)operator(.)ident(to_s)operator(\)) + reserved(end) + + comment(# Work around test/unit's requirement that every subclass of TestCase have) + comment(# at least one test method. Note that this implementation extends to all) + comment(# subclasses, as well, so subclasses of IntegrationTest may also exist) + comment(# without any test methods.) + reserved(def) method(run)operator(()operator(*)ident(args)operator(\)) comment(#:nodoc:) + reserved(return) reserved(if) instance_variable(@method_name) operator(==) string<delimiter(")content(default_test)delimiter(")> + reserved(super) + reserved(end) + + comment(# Because of how use_instantiated_fixtures and use_transactional_fixtures) + comment(# are defined, we need to treat them as special cases. Otherwise, users) + comment(# would potentially have to set their values for both Test::Unit::TestCase) + comment(# ActionController::IntegrationTest, since by the time the value is set on) + comment(# TestCase, IntegrationTest has already been defined and cannot inherit) + comment(# changes to those variables. So, we make those two attributes copy-on-write.) + + reserved(class) operator(<<) class(self) + reserved(def) method(use_transactional_fixtures=)operator(()ident(flag)operator(\)) comment(#:nodoc:) + instance_variable(@_use_transactional_fixtures) operator(=) pre_constant(true) + instance_variable(@use_transactional_fixtures) operator(=) ident(flag) + reserved(end) + + reserved(def) method(use_instantiated_fixtures=)operator(()ident(flag)operator(\)) comment(#:nodoc:) + instance_variable(@_use_instantiated_fixtures) operator(=) pre_constant(true) + instance_variable(@use_instantiated_fixtures) operator(=) ident(flag) + reserved(end) + + reserved(def) method(use_transactional_fixtures) comment(#:nodoc:) + instance_variable(@_use_transactional_fixtures) operator(?) + instance_variable(@use_transactional_fixtures) operator(:) + ident(superclass)operator(.)ident(use_transactional_fixtures) + reserved(end) + + reserved(def) method(use_instantiated_fixtures) comment(#:nodoc:) + instance_variable(@_use_instantiated_fixtures) operator(?) + instance_variable(@use_instantiated_fixtures) operator(:) + ident(superclass)operator(.)ident(use_instantiated_fixtures) + reserved(end) + reserved(end) + + comment(# Reset the current session. This is useful for testing multiple sessions) + comment(# in a single test case.) + reserved(def) method(reset!) + instance_variable(@integration_session) operator(=) ident(open_session) + reserved(end) + + string<delimiter(%w()content(get post cookies assigns xml_http_request)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(define_method)operator(()ident(method)operator(\)) reserved(do) operator(|*)ident(args)operator(|) + ident(reset!) reserved(unless) instance_variable(@integration_session) + ident(returning) instance_variable(@integration_session)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(args)operator(\)) reserved(do) + ident(copy_session_variables!) + reserved(end) + reserved(end) + reserved(end) + + comment(# Open a new session instance. If a block is given, the new session is) + comment(# yielded to the block before being returned.) + comment(#) + comment(# session = open_session do |sess|) + comment(# sess.extend(CustomAssertions\)) + comment(# end) + comment(#) + comment(# By default, a single session is automatically created for you, but you) + comment(# can use this method to open multiple sessions that ought to be tested) + comment(# simultaneously.) + reserved(def) method(open_session) + ident(session) operator(=) constant(Integration)operator(::)constant(Session)operator(.)ident(new) + + comment(# delegate the fixture accessors back to the test instance) + ident(extras) operator(=) constant(Module)operator(.)ident(new) operator({) ident(attr_accessor) symbol(:delegate)operator(,) symbol(:test_result) operator(}) + pre_constant(self)operator(.)ident(class)operator(.)ident(fixture_table_names)operator(.)ident(each) reserved(do) operator(|)ident(table_name)operator(|) + ident(name) operator(=) ident(table_name)operator(.)ident(tr)operator(()string<delimiter(")content(.)delimiter(")>operator(,) string<delimiter(")content(_)delimiter(")>operator(\)) + reserved(next) reserved(unless) ident(respond_to?)operator(()ident(name)operator(\)) + ident(extras)operator(.)ident(send)operator(()symbol(:define_method)operator(,) ident(name)operator(\)) operator({) operator(|*)ident(args)operator(|) ident(delegate)operator(.)ident(send)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) operator(}) + reserved(end) + + comment(# delegate add_assertion to the test case) + ident(extras)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:add_assertion)operator(\)) operator({) ident(test_result)operator(.)ident(add_assertion) operator(}) + ident(session)operator(.)ident(extend)operator(()ident(extras)operator(\)) + ident(session)operator(.)ident(delegate) operator(=) pre_constant(self) + ident(session)operator(.)ident(test_result) operator(=) instance_variable(@_result) + + reserved(yield) ident(session) reserved(if) ident(block_given?) + ident(session) + reserved(end) + + comment(# Copy the instance variables from the current session instance into the) + comment(# test instance.) + reserved(def) method(copy_session_variables!) comment(#:nodoc:) + reserved(return) reserved(unless) instance_variable(@integration_session) + string<delimiter(%w()content(controller response request)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(var)operator(|) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(var)inline_delimiter(})>delimiter(")>operator(,) instance_variable(@integration_session)operator(.)ident(send)operator(()ident(var)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Delegate unhandled messages to the current session instance.) + reserved(def) method(method_missing)operator(()ident(sym)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(reset!) reserved(unless) instance_variable(@integration_session) + ident(returning) instance_variable(@integration_session)operator(.)ident(send)operator(()ident(sym)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) reserved(do) + ident(copy_session_variables!) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(module) class(Layout) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:render_with_no_layout)operator(,) symbol(:render) + ident(alias_method) symbol(:render)operator(,) symbol(:render_with_a_layout) + + reserved(class) operator(<<) class(self) + ident(alias_method) symbol(:inherited_without_layout)operator(,) symbol(:inherited) + ident(alias_method) symbol(:inherited)operator(,) symbol(:inherited_with_layout) + reserved(end) + reserved(end) + reserved(end) + + comment(# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in) + comment(# repeated setups. The inclusion pattern has pages that look like this:) + comment(#) + comment(# <%= render "shared/header" %>) + comment(# Hello World) + comment(# <%= render "shared/footer" %>) + comment(#) + comment(# This approach is a decent way of keeping common structures isolated from the changing content, but it's verbose) + comment(# and if you ever want to change the structure of these two includes, you'll have to change all the templates.) + comment(#) + comment(# With layouts, you can flip it around and have the common structure know where to insert changing content. This means) + comment(# that the header and footer are only mentioned in one place, like this:) + comment(#) + comment(# <!-- The header part of this layout -->) + comment(# <%= yield %>) + comment(# <!-- The footer part of this layout -->) + comment(#) + comment(# And then you have content pages that look like this:) + comment(#) + comment(# hello world) + comment(#) + comment(# Not a word about common structures. At rendering time, the content page is computed and then inserted in the layout, ) + comment(# like this:) + comment(#) + comment(# <!-- The header part of this layout -->) + comment(# hello world) + comment(# <!-- The footer part of this layout -->) + comment(#) + comment(# == Accessing shared variables) + comment(#) + comment(# Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with) + comment(# references that won't materialize before rendering time:) + comment(#) + comment(# <h1><%= @page_title %></h1>) + comment(# <%= yield %>) + comment(#) + comment(# ...and content pages that fulfill these references _at_ rendering time:) + comment(#) + comment(# <% @page_title = "Welcome" %>) + comment(# Off-world colonies offers you a chance to start a new life) + comment(#) + comment(# The result after rendering is:) + comment(#) + comment(# <h1>Welcome</h1>) + comment(# Off-world colonies offers you a chance to start a new life) + comment(#) + comment(# == Automatic layout assignment) + comment(#) + comment(# If there is a template in <tt>app/views/layouts/</tt> with the same name as the current controller then it will be automatically) + comment(# set as that controller's layout unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named ) + comment(# <tt>app/views/layouts/weblog.rhtml</tt> or <tt>app/views/layouts/weblog.rxml</tt> exists then it will be automatically set as) + comment(# the layout for your WeblogController. You can create a layout with the name <tt>application.rhtml</tt> or <tt>application.rxml</tt>) + comment(# and this will be set as the default controller if there is no layout with the same name as the current controller and there is ) + comment(# no layout explicitly assigned with the +layout+ method. Nested controllers use the same folder structure for automatic layout.) + comment(# assignment. So an Admin::WeblogController will look for a template named <tt>app/views/layouts/admin/weblog.rhtml</tt>.) + comment(# Setting a layout explicitly will always override the automatic behaviour for the controller where the layout is set.) + comment(# Explicitly setting the layout in a parent class, though, will not override the child class's layout assignement if the child) + comment(# class has a layout with the same name. ) + comment(#) + comment(# == Inheritance for layouts) + comment(#) + comment(# Layouts are shared downwards in the inheritance hierarchy, but not upwards. Examples:) + comment(#) + comment(# class BankController < ActionController::Base) + comment(# layout "bank_standard") + comment(#) + comment(# class InformationController < BankController) + comment(#) + comment(# class VaultController < BankController) + comment(# layout :access_level_layout) + comment(#) + comment(# class EmployeeController < BankController) + comment(# layout nil) + comment(#) + comment(# The InformationController uses "bank_standard" inherited from the BankController, the VaultController overwrites) + comment(# and picks the layout dynamically, and the EmployeeController doesn't want to use a layout at all.) + comment(#) + comment(# == Types of layouts) + comment(#) + comment(# Layouts are basically just regular templates, but the name of this template needs not be specified statically. Sometimes) + comment(# you want to alternate layouts depending on runtime information, such as whether someone is logged in or not. This can) + comment(# be done either by specifying a method reference as a symbol or using an inline method (as a proc\).) + comment(#) + comment(# The method reference is the preferred approach to variable layouts and is used like this:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# layout :writers_and_readers) + comment(#) + comment(# def index) + comment(# # fetching posts) + comment(# end) + comment(#) + comment(# private) + comment(# def writers_and_readers) + comment(# logged_in? ? "writer_layout" : "reader_layout") + comment(# end) + comment(#) + comment(# Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing ) + comment(# is logged in or not.) + comment(#) + comment(# If you want to use an inline method, such as a proc, do something like this:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" }) + comment(#) + comment(# Of course, the most common way of specifying a layout is still just as a plain template name:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# layout "weblog_standard") + comment(#) + comment(# If no directory is specified for the template name, the template will by default by looked for in +app/views/layouts/+.) + comment(#) + comment(# == Conditional layouts) + comment(#) + comment(# If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering) + comment(# a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The ) + comment(# <tt>:only</tt> and <tt>:except</tt> options can be passed to the layout call. For example:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# layout "weblog_standard", :except => :rss) + comment(# ) + comment(# # ...) + comment(#) + comment(# end) + comment(#) + comment(# This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout ) + comment(# around the rendered view.) + comment(#) + comment(# Both the <tt>:only</tt> and <tt>:except</tt> condition can accept an arbitrary number of method references, so ) + comment(# #<tt>:except => [ :rss, :text_only ]</tt> is valid, as is <tt>:except => :rss</tt>.) + comment(#) + comment(# == Using a different layout in the action render call) + comment(# ) + comment(# If most of your actions use the same layout, it makes perfect sense to define a controller-wide layout as described above.) + comment(# Some times you'll have exceptions, though, where one action wants to use a different layout than the rest of the controller.) + comment(# This is possible using the <tt>render</tt> method. It's just a bit more manual work as you'll have to supply fully) + comment(# qualified template and layout names as this example shows:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# def help) + comment(# render :action => "help/index", :layout => "help") + comment(# end) + comment(# end) + comment(#) + comment(# As you can see, you pass the template as the first parameter, the status code as the second ("200" is OK\), and the layout) + comment(# as the third.) + comment(#) + comment(# NOTE: The old notation for rendering the view from a layout was to expose the magic <tt>@content_for_layout</tt> instance ) + comment(# variable. The preferred notation now is to use <tt>yield</tt>, as documented above.) + reserved(module) class(ClassMethods) + comment(# If a layout is specified, all rendered actions will have their result rendered ) + comment(# when the layout<tt>yield</tt>'s. This layout can itself depend on instance variables assigned during action) + comment(# performance and have access to them as any normal template would.) + reserved(def) method(layout)operator(()ident(template_name)operator(,) ident(conditions) operator(=) operator({)operator(})operator(\)) + ident(add_layout_conditions)operator(()ident(conditions)operator(\)) + ident(write_inheritable_attribute) string<delimiter(")content(layout)delimiter(")>operator(,) ident(template_name) + reserved(end) + + reserved(def) method(layout_conditions) comment(#:nodoc:) + instance_variable(@layout_conditions) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(layout_conditions)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(default_layout) comment(#:nodoc:) + instance_variable(@default_layout) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(layout)delimiter(")>operator(\)) + reserved(end) + + ident(private) + reserved(def) method(inherited_with_layout)operator(()ident(child)operator(\)) + ident(inherited_without_layout)operator(()ident(child)operator(\)) + ident(child)operator(.)ident(send) symbol(:include)operator(,) constant(Reloadable) + ident(layout_match) operator(=) ident(child)operator(.)ident(name)operator(.)ident(underscore)operator(.)ident(sub)operator(()regexp<delimiter(/)content(_controller$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(sub)operator(()regexp<delimiter(/)content(^controllers)char(\\/)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(child)operator(.)ident(layout)operator(()ident(layout_match)operator(\)) reserved(unless) ident(layout_list)operator(.)ident(grep)operator(()regexp<delimiter(%r{)content(layouts/)inline<inline_delimiter(#{)ident(layout_match)inline_delimiter(})>char(\\.)content([a-z][0-9a-z]*$)delimiter(})>operator(\))operator(.)ident(empty?) + reserved(end) + + reserved(def) method(layout_list) + constant(Dir)operator(.)ident(glob)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(template_root)inline_delimiter(})>content(/layouts/**/*)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(add_layout_conditions)operator(()ident(conditions)operator(\)) + ident(write_inheritable_hash) string<delimiter(")content(layout_conditions)delimiter(")>operator(,) ident(normalize_conditions)operator(()ident(conditions)operator(\)) + reserved(end) + + reserved(def) method(normalize_conditions)operator(()ident(conditions)operator(\)) + ident(conditions)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({)operator(|)ident(hash)operator(,) operator(()ident(key)operator(,) ident(value)operator(\))operator(|) ident(hash)operator(.)ident(merge)operator(()ident(key) operator(=)operator(>) operator([)ident(value)operator(])operator(.)ident(flatten)operator(.)ident(map) operator({)operator(|)ident(action)operator(|) ident(action)operator(.)ident(to_s)operator(})operator(\))operator(}) + reserved(end) + + reserved(def) method(layout_directory_exists_cache) + class_variable(@@layout_directory_exists_cache) operator(||=) constant(Hash)operator(.)ident(new) reserved(do) operator(|)ident(h)operator(,) ident(dirname)operator(|) + ident(h)operator([)ident(dirname)operator(]) operator(=) constant(File)operator(.)ident(directory?) ident(dirname) + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns the name of the active layout. If the layout was specified as a method reference (through a symbol\), this method) + comment(# is called and the return value is used. Likewise if the layout was specified as an inline method (through a proc or method) + comment(# object\). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return) + comment(# weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.) + reserved(def) method(active_layout)operator(()ident(passed_layout) operator(=) pre_constant(nil)operator(\)) + ident(layout) operator(=) ident(passed_layout) operator(||) pre_constant(self)operator(.)ident(class)operator(.)ident(default_layout) + + ident(active_layout) operator(=) reserved(case) ident(layout) + reserved(when) constant(String) reserved(then) ident(layout) + reserved(when) constant(Symbol) reserved(then) ident(send)operator(()ident(layout)operator(\)) + reserved(when) constant(Proc) reserved(then) ident(layout)operator(.)ident(call)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Explicitly passed layout names with slashes are looked up relative to the template root,) + comment(# but auto-discovered layouts derived from a nested controller will contain a slash, though be relative) + comment(# to the 'layouts' directory so we have to check the file system to infer which case the layout name came from.) + reserved(if) ident(active_layout) + reserved(if) ident(active_layout)operator(.)ident(include?)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) operator(&&) operator(!) ident(layout_directory?)operator(()ident(active_layout)operator(\)) + ident(active_layout) + reserved(else) + string<delimiter(")content(layouts/)inline<inline_delimiter(#{)ident(active_layout)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(render_with_a_layout)operator(()ident(options) operator(=) pre_constant(nil)operator(,) ident(deprecated_status) operator(=) pre_constant(nil)operator(,) ident(deprecated_layout) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) comment(#:nodoc:) + ident(template_with_options) operator(=) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + reserved(if) ident(apply_layout?)operator(()ident(template_with_options)operator(,) ident(options)operator(\)) operator(&&) operator(()ident(layout) operator(=) ident(pick_layout)operator(()ident(template_with_options)operator(,) ident(options)operator(,) ident(deprecated_layout)operator(\))operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(merge) symbol(:layout) operator(=)operator(>) pre_constant(false) reserved(if) ident(template_with_options) + ident(logger)operator(.)ident(info)operator(()string<delimiter(")content(Rendering )inline<inline_delimiter(#{)ident(options)inline_delimiter(})>content( within )inline<inline_delimiter(#{)ident(layout)inline_delimiter(})>delimiter(")>operator(\)) reserved(if) ident(logger) + + reserved(if) ident(template_with_options) + ident(content_for_layout) operator(=) ident(render_with_no_layout)operator(()ident(options)operator(,) operator(&)ident(block)operator(\)) + ident(deprecated_status) operator(=) ident(options)operator([)symbol(:status)operator(]) operator(||) ident(deprecated_status) + reserved(else) + ident(content_for_layout) operator(=) ident(render_with_no_layout)operator(()ident(options)operator(,) ident(deprecated_status)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + ident(erase_render_results) + ident(add_variables_to_assigns) + instance_variable(@template)operator(.)ident(instance_variable_set)operator(()string<delimiter(")content(@content_for_layout)delimiter(")>operator(,) ident(content_for_layout)operator(\)) + ident(render_text)operator(()instance_variable(@template)operator(.)ident(render_file)operator(()ident(layout)operator(,) pre_constant(true)operator(\))operator(,) ident(deprecated_status)operator(\)) + reserved(else) + ident(render_with_no_layout)operator(()ident(options)operator(,) ident(deprecated_status)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + ident(private) + + reserved(def) method(apply_layout?)operator(()ident(template_with_options)operator(,) ident(options)operator(\)) + reserved(return) pre_constant(false) reserved(if) ident(options) operator(==) symbol(:update) + ident(template_with_options) operator(?) ident(candidate_for_layout?)operator(()ident(options)operator(\)) operator(:) operator(!)ident(template_exempt_from_layout?) + reserved(end) + + reserved(def) method(candidate_for_layout?)operator(()ident(options)operator(\)) + operator(()ident(options)operator(.)ident(has_key?)operator(()symbol(:layout)operator(\)) operator(&&) ident(options)operator([)symbol(:layout)operator(]) operator(!=) pre_constant(false)operator(\)) operator(||) + ident(options)operator(.)ident(values_at)operator(()symbol(:text)operator(,) symbol(:xml)operator(,) symbol(:file)operator(,) symbol(:inline)operator(,) symbol(:partial)operator(,) symbol(:nothing)operator(\))operator(.)ident(compact)operator(.)ident(empty?) operator(&&) + operator(!)ident(template_exempt_from_layout?)operator(()ident(default_template_name)operator(()ident(options)operator([)symbol(:action)operator(]) operator(||) ident(options)operator([)symbol(:template)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(pick_layout)operator(()ident(template_with_options)operator(,) ident(options)operator(,) ident(deprecated_layout)operator(\)) + reserved(if) ident(deprecated_layout) + ident(deprecated_layout) + reserved(elsif) ident(template_with_options) + reserved(case) ident(layout) operator(=) ident(options)operator([)symbol(:layout)operator(]) + reserved(when) constant(FalseClass) + pre_constant(nil) + reserved(when) constant(NilClass)operator(,) constant(TrueClass) + ident(active_layout) reserved(if) ident(action_has_layout?) + reserved(else) + ident(active_layout)operator(()ident(layout)operator(\)) + reserved(end) + reserved(else) + ident(active_layout) reserved(if) ident(action_has_layout?) + reserved(end) + reserved(end) + + reserved(def) method(action_has_layout?) + reserved(if) ident(conditions) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(layout_conditions) + reserved(case) + reserved(when) ident(only) operator(=) ident(conditions)operator([)symbol(:only)operator(]) + ident(only)operator(.)ident(include?)operator(()ident(action_name)operator(\)) + reserved(when) ident(except) operator(=) ident(conditions)operator([)symbol(:except)operator(]) + operator(!)ident(except)operator(.)ident(include?)operator(()ident(action_name)operator(\)) + reserved(else) + pre_constant(true) + reserved(end) + reserved(else) + pre_constant(true) + reserved(end) + reserved(end) + + comment(# Does a layout directory for this class exist?) + comment(# we cache this info in a class level hash) + reserved(def) method(layout_directory?)operator(()ident(layout_name)operator(\)) + ident(template_path) operator(=) constant(File)operator(.)ident(join)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(view_root)operator(,) string<delimiter(')content(layouts)delimiter(')>operator(,) ident(layout_name)operator(\)) + ident(dirname) operator(=) constant(File)operator(.)ident(dirname)operator(()ident(template_path)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(send)operator(()symbol(:layout_directory_exists_cache)operator(\))operator([)ident(dirname)operator(]) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) + comment(# Macros are class-level calls that add pre-defined actions to the controller based on the parameters passed in.) + comment(# Currently, they're used to bridge the JavaScript macros, like autocompletion and in-place editing, with the controller) + comment(# backing.) + reserved(module) class(Macros) + reserved(module) class(AutoComplete) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Example:) + comment(#) + comment(# # Controller) + comment(# class BlogController < ApplicationController) + comment(# auto_complete_for :post, :title) + comment(# end) + comment(#) + comment(# # View) + comment(# <%= text_field_with_auto_complete :post, title %>) + comment(#) + comment(# By default, auto_complete_for limits the results to 10 entries,) + comment(# and sorts by the given field.) + comment(# ) + comment(# auto_complete_for takes a third parameter, an options hash to) + comment(# the find method used to search for the records:) + comment(#) + comment(# auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC') + comment(#) + comment(# For help on defining text input fields with autocompletion, ) + comment(# see ActionView::Helpers::JavaScriptHelper.) + comment(#) + comment(# For more examples, see script.aculo.us:) + comment(# * http://script.aculo.us/demos/ajax/autocompleter) + comment(# * http://script.aculo.us/demos/ajax/autocompleter_customized) + reserved(module) class(ClassMethods) + reserved(def) method(auto_complete_for)operator(()ident(object)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(define_method)operator(()string<delimiter(")content(auto_complete_for_)inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>delimiter(")>operator(\)) reserved(do) + ident(find_options) operator(=) operator({) + symbol(:conditions) operator(=)operator(>) operator([) string<delimiter(")content(LOWER()inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(\) LIKE ?)delimiter(")>operator(,) string<delimiter(')content(%)delimiter(')> operator(+) ident(params)operator([)ident(object)operator(])operator([)ident(method)operator(])operator(.)ident(downcase) operator(+) string<delimiter(')content(%)delimiter(')> operator(])operator(,) + symbol(:order) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content( ASC)delimiter(")>operator(,) + symbol(:limit) operator(=)operator(>) integer(10) operator(})operator(.)ident(merge!)operator(()ident(options)operator(\)) + + instance_variable(@items) operator(=) ident(object)operator(.)ident(to_s)operator(.)ident(camelize)operator(.)ident(constantize)operator(.)ident(find)operator(()symbol(:all)operator(,) ident(find_options)operator(\)) + + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(<%= auto_complete_result @items, ')inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(' %>)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +ident(endmodule) constant(ActionController) + reserved(module) class(Macros) + reserved(module) class(InPlaceEditing) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Example:) + comment(#) + comment(# # Controller) + comment(# class BlogController < ApplicationController) + comment(# in_place_edit_for :post, :title) + comment(# end) + comment(#) + comment(# # View) + comment(# <%= in_place_editor_field :post, 'title' %>) + comment(#) + comment(# For help on defining an in place editor in the browser,) + comment(# see ActionView::Helpers::JavaScriptHelper.) + reserved(module) class(ClassMethods) + reserved(def) method(in_place_edit_for)operator(()ident(object)operator(,) ident(attribute)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(define_method)operator(()string<delimiter(")content(set_)inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(attribute)inline_delimiter(})>delimiter(")>operator(\)) reserved(do) + instance_variable(@item) operator(=) ident(object)operator(.)ident(to_s)operator(.)ident(camelize)operator(.)ident(constantize)operator(.)ident(find)operator(()ident(params)operator([)symbol(:id)operator(])operator(\)) + instance_variable(@item)operator(.)ident(update_attribute)operator(()ident(attribute)operator(,) ident(params)operator([)symbol(:value)operator(])operator(\)) + ident(render) symbol(:text) operator(=)operator(>) instance_variable(@item)operator(.)ident(send)operator(()ident(attribute)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(module) class(MimeResponds) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionController)operator(::)constant(MimeResponds)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + reserved(module) class(InstanceMethods) + comment(# Without web-service support, an action which collects the data for displaying a list of people) + comment(# might look something like this:) + comment(#) + comment(# def list) + comment(# @people = Person.find(:all\)) + comment(# end) + comment(# ) + comment(# Here's the same action, with web-service support baked in:) + comment(# ) + comment(# def list) + comment(# @people = Person.find(:all\)) + comment(# ) + comment(# respond_to do |wants|) + comment(# wants.html) + comment(# wants.xml { render :xml => @people.to_xml }) + comment(# end) + comment(# end) + comment(# ) + comment(# What that says is, "if the client wants HTML in response to this action, just respond as we ) + comment(# would have before, but if the client wants XML, return them the list of people in XML format." ) + comment(# (Rails determines the desired response format from the HTTP Accept header submitted by the client.\)) + comment(# ) + comment(# Supposing you have an action that adds a new person, optionally creating their company ) + comment(# (by name\) if it does not already exist, without web-services, it might look like this:) + comment(# ) + comment(# def add) + comment(# @company = Company.find_or_create_by_name(params[:company][:name]\)) + comment(# @person = @company.people.create(params[:person]\)) + comment(# ) + comment(# redirect_to(person_list_url\)) + comment(# end) + comment(# ) + comment(# Here's the same action, with web-service support baked in:) + comment(# ) + comment(# def add) + comment(# company = params[:person].delete(:company\)) + comment(# @company = Company.find_or_create_by_name(company[:name]\)) + comment(# @person = @company.people.create(params[:person]\)) + comment(# ) + comment(# respond_to do |wants|) + comment(# wants.html { redirect_to(person_list_url\) }) + comment(# wants.js) + comment(# wants.xml { render :xml => @person.to_xml(:include => @company\) }) + comment(# end) + comment(# end) + comment(# ) + comment(# If the client wants HTML, we just redirect them back to the person list. If they want Javascript ) + comment(# (wants.js\), then it is an RJS request and we render the RJS template associated with this action. ) + comment(# Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also ) + comment(# include the person’s company in the rendered XML, so you get something like this:) + comment(# ) + comment(# <person>) + comment(# <id>...</id>) + comment(# ...) + comment(# <company>) + comment(# <id>...</id>) + comment(# <name>...</name>) + comment(# ...) + comment(# </company>) + comment(# </person>) + comment(# ) + comment(# Note, however, the extra bit at the top of that action:) + comment(# ) + comment(# company = params[:person].delete(:company\)) + comment(# @company = Company.find_or_create_by_name(company[:name]\)) + comment(# ) + comment(# This is because the incoming XML document (if a web-service request is in process\) can only contain a ) + comment(# single root-node. So, we have to rearrange things so that the request looks like this (url-encoded\):) + comment(# ) + comment(# person[name]=...&person[company][name]=...&...) + comment(# ) + comment(# And, like this (xml-encoded\):) + comment(# ) + comment(# <person>) + comment(# <name>...</name>) + comment(# <company>) + comment(# <name>...</name>) + comment(# </company>) + comment(# </person>) + comment(# ) + comment(# In other words, we make the request so that it operates on a single entity—a person. Then, in the action, ) + comment(# we extract the company data from the request, find or create the company, and then create the new person ) + comment(# with the remaining data.) + comment(# ) + comment(# Note that you can define your own XML parameter parser which would allow you to describe multiple entities ) + comment(# in a single request (i.e., by wrapping them all in a single root note\), but if you just go with the flow ) + comment(# and accept Rails' defaults, life will be much easier.) + comment(# ) + comment(# If you need to use a MIME type which isn't supported by default, you can register your own handlers in) + comment(# environment.rb as follows.) + comment(# ) + comment(# Mime::Type.register "image/jpg", :jpg) + comment(# ) + reserved(def) method(respond_to)operator(()operator(*)ident(types)operator(,) operator(&)ident(block)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(respond_to takes either types or a block, never bot)delimiter(")> reserved(unless) ident(types)operator(.)ident(any?) operator(^) ident(block) + ident(block) operator(||=) ident(lambda) operator({) operator(|)ident(responder)operator(|) ident(types)operator(.)ident(each) operator({) operator(|)ident(type)operator(|) ident(responder)operator(.)ident(send)operator(()ident(type)operator(\)) operator(}) operator(}) + ident(responder) operator(=) constant(Responder)operator(.)ident(new)operator(()ident(block)operator(.)ident(binding)operator(\)) + ident(block)operator(.)ident(call)operator(()ident(responder)operator(\)) + ident(responder)operator(.)ident(respond) + reserved(end) + reserved(end) + + reserved(class) class(Responder) comment(#:nodoc:) + constant(DEFAULT_BLOCKS) operator(=) operator({) + symbol(:html) operator(=)operator(>) string<delimiter(')content(Proc.new { render })delimiter(')>operator(,) + symbol(:js) operator(=)operator(>) string<delimiter(')content(Proc.new { render :action => "#{action_name}.rjs" })delimiter(')>operator(,) + symbol(:xml) operator(=)operator(>) string<delimiter(')content(Proc.new { render :action => "#{action_name}.rxml" })delimiter(')> + operator(}) + + reserved(def) method(initialize)operator(()ident(block_binding)operator(\)) + instance_variable(@block_binding) operator(=) ident(block_binding) + instance_variable(@mime_type_priority) operator(=) ident(eval)operator(()string<delimiter(")content(request.accepts)delimiter(")>operator(,) ident(block_binding)operator(\)) + instance_variable(@order) operator(=) operator([)operator(]) + instance_variable(@responses) operator(=) operator({)operator(}) + reserved(end) + + reserved(def) method(custom)operator(()ident(mime_type)operator(,) operator(&)ident(block)operator(\)) + ident(mime_type) operator(=) ident(mime_type)operator(.)ident(is_a?)operator(()constant(Mime)operator(::)constant(Type)operator(\)) operator(?) ident(mime_type) operator(:) constant(Mime)operator(::)constant(Type)operator(.)ident(lookup)operator(()ident(mime_type)operator(.)ident(to_s)operator(\)) + + instance_variable(@order) operator(<<) ident(mime_type) + + reserved(if) ident(block_given?) + instance_variable(@responses)operator([)ident(mime_type)operator(]) operator(=) ident(block) + reserved(else) + instance_variable(@responses)operator([)ident(mime_type)operator(]) operator(=) ident(eval)operator(()constant(DEFAULT_BLOCKS)operator([)ident(mime_type)operator(.)ident(to_sym)operator(])operator(,) instance_variable(@block_binding)operator(\)) + reserved(end) + reserved(end) + + reserved(for) ident(mime_type) reserved(in) string<delimiter(%w()content( all html js xml rss atom yaml )delimiter(\))> + ident(eval) string<delimiter(<<-EOT)>string<content( + def )inline<inline_delimiter(#{)ident(mime_type)inline_delimiter(})>content((&block\) + custom(Mime::)inline<inline_delimiter(#{)ident(mime_type)operator(.)ident(upcase)inline_delimiter(})>content(, &block\) + end)delimiter( + EOT)> + reserved(end) + + reserved(def) method(any)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(args)operator(.)ident(each) operator({) operator(|)ident(type)operator(|) ident(send)operator(()ident(type)operator(,) operator(&)ident(block)operator(\)) operator(}) + reserved(end) + + reserved(def) method(respond) + reserved(for) ident(priority) reserved(in) instance_variable(@mime_type_priority) + reserved(if) ident(priority) operator(==) constant(Mime)operator(::)constant(ALL) + instance_variable(@responses)operator([)instance_variable(@order)operator(.)ident(first)operator(])operator(.)ident(call) + reserved(return) + reserved(else) + reserved(if) ident(priority) operator(===) instance_variable(@order) + instance_variable(@responses)operator([)ident(priority)operator(])operator(.)ident(call) + reserved(return) comment(# mime type match found, be happy and return) + reserved(end) + reserved(end) + reserved(end) + + reserved(if) instance_variable(@order)operator(.)ident(include?)operator(()constant(Mime)operator(::)constant(ALL)operator(\)) + instance_variable(@responses)operator([)constant(Mime)operator(::)constant(ALL)operator(])operator(.)ident(call) + reserved(else) + ident(eval) string<delimiter(')content(render(:nothing => true, :status => "406 Not Acceptable"\))delimiter(')>operator(,) instance_variable(@block_binding) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(Mime) + reserved(class) class(Type) comment(#:nodoc:) + comment(# A simple helper class used in parsing the accept header) + reserved(class) class(AcceptItem) comment(#:nodoc:) + ident(attr_accessor) symbol(:order)operator(,) symbol(:name)operator(,) symbol(:q) + + reserved(def) method(initialize)operator(()ident(order)operator(,) ident(name)operator(,) ident(q)operator(=)pre_constant(nil)operator(\)) + instance_variable(@order) operator(=) ident(order) + instance_variable(@name) operator(=) ident(name)operator(.)ident(strip) + ident(q) operator(||=) float(0.0) reserved(if) instance_variable(@name) operator(==) string<delimiter(")content(*/*)delimiter(")> comment(# default "*/*" to end of list) + instance_variable(@q) operator(=) operator(()operator(()ident(q) operator(||) float(1.0)operator(\))operator(.)ident(to_f) operator(*) integer(100)operator(\))operator(.)ident(to_i) + reserved(end) + + reserved(def) method(to_s) + instance_variable(@name) + reserved(end) + + reserved(def) method(<=>)operator(()ident(item)operator(\)) + ident(result) operator(=) ident(item)operator(.)ident(q) operator(<=>) ident(q) + ident(result) operator(=) ident(order) operator(<=>) ident(item)operator(.)ident(order) reserved(if) ident(result) operator(==) integer(0) + ident(result) + reserved(end) + + reserved(def) method(==)operator(()ident(item)operator(\)) + ident(name) operator(==) operator(()ident(item)operator(.)ident(respond_to?)operator(()symbol(:name)operator(\)) operator(?) ident(item)operator(.)ident(name) operator(:) ident(item)operator(\)) + reserved(end) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(def) method(lookup)operator(()ident(string)operator(\)) + constant(LOOKUP)operator([)ident(string)operator(]) + reserved(end) + + reserved(def) method(parse)operator(()ident(accept_header)operator(\)) + comment(# keep track of creation order to keep the subsequent sort stable) + ident(index) operator(=) integer(0) + ident(list) operator(=) ident(accept_header)operator(.)ident(split)operator(()regexp<delimiter(/)content(,)delimiter(/)>operator(\))operator(.) + ident(map!) operator({) operator(|)ident(i)operator(|) constant(AcceptItem)operator(.)ident(new)operator(()ident(index) operator(+=) integer(1)operator(,) operator(*)ident(i)operator(.)ident(split)operator(()regexp<delimiter(/)content(;)char(\\s)content(*q=)delimiter(/)>operator(\))operator(\)) operator(})operator(.)ident(sort!) + + comment(# Take care of the broken text/xml entry by renaming or deleting it) + + ident(text_xml) operator(=) ident(list)operator(.)ident(index)operator(()string<delimiter(")content(text/xml)delimiter(")>operator(\)) + ident(app_xml) operator(=) ident(list)operator(.)ident(index)operator(()string<delimiter(")content(application/xml)delimiter(")>operator(\)) + + reserved(if) ident(text_xml) operator(&&) ident(app_xml) + comment(# set the q value to the max of the two) + ident(list)operator([)ident(app_xml)operator(])operator(.)ident(q) operator(=) operator([)ident(list)operator([)ident(text_xml)operator(])operator(.)ident(q)operator(,) ident(list)operator([)ident(app_xml)operator(])operator(.)ident(q)operator(])operator(.)ident(max) + + comment(# make sure app_xml is ahead of text_xml in the list) + reserved(if) ident(app_xml) operator(>) ident(text_xml) + ident(list)operator([)ident(app_xml)operator(])operator(,) ident(list)operator([)ident(text_xml)operator(]) operator(=) ident(list)operator([)ident(text_xml)operator(])operator(,) ident(list)operator([)ident(app_xml)operator(]) + ident(app_xml)operator(,) ident(text_xml) operator(=) ident(text_xml)operator(,) ident(app_xml) + reserved(end) + + comment(# delete text_xml from the list) + ident(list)operator(.)ident(delete_at)operator(()ident(text_xml)operator(\)) + + reserved(elsif) ident(text_xml) + ident(list)operator([)ident(text_xml)operator(])operator(.)ident(name) operator(=) string<delimiter(")content(application/xml)delimiter(")> + reserved(end) + + comment(# Look for more specific xml-based types and sort them ahead of app/xml) + + reserved(if) ident(app_xml) + ident(idx) operator(=) ident(app_xml) + ident(app_xml_type) operator(=) ident(list)operator([)ident(app_xml)operator(]) + + reserved(while)operator(()ident(idx) operator(<) ident(list)operator(.)ident(length)operator(\)) + ident(type) operator(=) ident(list)operator([)ident(idx)operator(]) + reserved(break) reserved(if) ident(type)operator(.)ident(q) operator(<) ident(app_xml_type)operator(.)ident(q) + reserved(if) ident(type)operator(.)ident(name) operator(=)operator(~) regexp<delimiter(/)char(\\+)content(xml$)delimiter(/)> + ident(list)operator([)ident(app_xml)operator(])operator(,) ident(list)operator([)ident(idx)operator(]) operator(=) ident(list)operator([)ident(idx)operator(])operator(,) ident(list)operator([)ident(app_xml)operator(]) + ident(app_xml) operator(=) ident(idx) + reserved(end) + ident(idx) operator(+=) integer(1) + reserved(end) + reserved(end) + + ident(list)operator(.)ident(map!) operator({) operator(|)ident(i)operator(|) constant(Mime)operator(::)constant(Type)operator(.)ident(lookup)operator(()ident(i)operator(.)ident(name)operator(\)) operator(})operator(.)ident(uniq!) + ident(list) + reserved(end) + reserved(end) + + reserved(def) method(initialize)operator(()ident(string)operator(,) ident(symbol) operator(=) pre_constant(nil)operator(,) ident(synonyms) operator(=) operator([)operator(])operator(\)) + instance_variable(@symbol)operator(,) instance_variable(@synonyms) operator(=) ident(symbol)operator(,) ident(synonyms) + instance_variable(@string) operator(=) ident(string) + reserved(end) + + reserved(def) method(to_s) + instance_variable(@string) + reserved(end) + + reserved(def) method(to_str) + ident(to_s) + reserved(end) + + reserved(def) method(to_sym) + instance_variable(@symbol) operator(||) instance_variable(@string)operator(.)ident(to_sym) + reserved(end) + + reserved(def) method(===)operator(()ident(list)operator(\)) + reserved(if) ident(list)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + operator(()instance_variable(@synonyms) operator(+) operator([) pre_constant(self) operator(])operator(\))operator(.)ident(any?) operator({) operator(|)ident(synonym)operator(|) ident(list)operator(.)ident(include?)operator(()ident(synonym)operator(\)) operator(}) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(def) method(==)operator(()ident(mime_type)operator(\)) + operator(()instance_variable(@synonyms) operator(+) operator([) pre_constant(self) operator(])operator(\))operator(.)ident(any?) operator({) operator(|)ident(synonym)operator(|) ident(synonym)operator(.)ident(to_s) operator(==) ident(mime_type)operator(.)ident(to_s) operator(}) reserved(if) ident(mime_type) + reserved(end) + reserved(end) + + constant(ALL) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(*/*)delimiter(")>operator(,) symbol(:all) + constant(HTML) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(text/html)delimiter(")>operator(,) symbol(:html)operator(,) string<delimiter(%w()content( application/xhtml+xml )delimiter(\))> + constant(JS) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(text/javascript)delimiter(")>operator(,) symbol(:js)operator(,) string<delimiter(%w()content( application/javascript application/x-javascript )delimiter(\))> + constant(XML) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(application/xml)delimiter(")>operator(,) symbol(:xml)operator(,) string<delimiter(%w()content( text/xml application/x-xml )delimiter(\))> + constant(RSS) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(application/rss+xml)delimiter(")>operator(,) symbol(:rss) + constant(ATOM) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(application/atom+xml)delimiter(")>operator(,) symbol(:atom) + constant(YAML) operator(=) constant(Type)operator(.)ident(new) string<delimiter(")content(application/x-yaml)delimiter(")>operator(,) symbol(:yaml)operator(,) string<delimiter(%w()content( text/yaml )delimiter(\))> + + constant(LOOKUP) operator(=) constant(Hash)operator(.)ident(new) operator({) operator(|)ident(h)operator(,) ident(k)operator(|) ident(h)operator([)ident(k)operator(]) operator(=) constant(Type)operator(.)ident(new)operator(()ident(k)operator(\)) operator(}) + + constant(LOOKUP)operator([)string<delimiter(")content(*/*)delimiter(")>operator(]) operator(=) constant(ALL) + + constant(LOOKUP)operator([)string<delimiter(")content(text/html)delimiter(")>operator(]) operator(=) constant(HTML) + constant(LOOKUP)operator([)string<delimiter(")content(application/xhtml+xml)delimiter(")>operator(]) operator(=) constant(HTML) + + constant(LOOKUP)operator([)string<delimiter(")content(application/xml)delimiter(")>operator(]) operator(=) constant(XML) + constant(LOOKUP)operator([)string<delimiter(")content(text/xml)delimiter(")>operator(]) operator(=) constant(XML) + constant(LOOKUP)operator([)string<delimiter(")content(application/x-xml)delimiter(")>operator(]) operator(=) constant(XML) + + constant(LOOKUP)operator([)string<delimiter(")content(text/javascript)delimiter(")>operator(]) operator(=) constant(JS) + constant(LOOKUP)operator([)string<delimiter(")content(application/javascript)delimiter(")>operator(]) operator(=) constant(JS) + constant(LOOKUP)operator([)string<delimiter(")content(application/x-javascript)delimiter(")>operator(]) operator(=) constant(JS) + + constant(LOOKUP)operator([)string<delimiter(")content(text/yaml)delimiter(")>operator(]) operator(=) constant(YAML) + constant(LOOKUP)operator([)string<delimiter(")content(application/x-yaml)delimiter(")>operator(]) operator(=) constant(YAML) + + constant(LOOKUP)operator([)string<delimiter(")content(application/rss+xml)delimiter(")>operator(]) operator(=) constant(RSS) + constant(LOOKUP)operator([)string<delimiter(")content(application/atom+xml)delimiter(")>operator(]) operator(=) constant(ATOM) +ident(endmodule) constant(ActionController) + comment(# === Action Pack pagination for Active Record collections) + comment(#) + comment(# The Pagination module aids in the process of paging large collections of) + comment(# Active Record objects. It offers macro-style automatic fetching of your) + comment(# model for multiple views, or explicit fetching for single actions. And if) + comment(# the magic isn't flexible enough for your needs, you can create your own) + comment(# paginators with a minimal amount of code.) + comment(#) + comment(# The Pagination module can handle as much or as little as you wish. In the) + comment(# controller, have it automatically query your model for pagination; or,) + comment(# if you prefer, create Paginator objects yourself.) + comment(#) + comment(# Pagination is included automatically for all controllers.) + comment(#) + comment(# For help rendering pagination links, see ) + comment(# ActionView::Helpers::PaginationHelper.) + comment(#) + comment(# ==== Automatic pagination for every action in a controller) + comment(#) + comment(# class PersonController < ApplicationController ) + comment(# model :person) + comment(#) + comment(# paginate :people, :order => 'last_name, first_name',) + comment(# :per_page => 20) + comment(# ) + comment(# # ...) + comment(# end) + comment(#) + comment(# Each action in this controller now has access to a <tt>@people</tt>) + comment(# instance variable, which is an ordered collection of model objects for the) + comment(# current page (at most 20, sorted by last name and first name\), and a ) + comment(# <tt>@person_pages</tt> Paginator instance. The current page is determined) + comment(# by the <tt>params[:page]</tt> variable.) + comment(#) + comment(# ==== Pagination for a single action) + comment(#) + comment(# def list) + comment(# @person_pages, @people =) + comment(# paginate :people, :order => 'last_name, first_name') + comment(# end) + comment(#) + comment(# Like the previous example, but explicitly creates <tt>@person_pages</tt>) + comment(# and <tt>@people</tt> for a single action, and uses the default of 10 items) + comment(# per page.) + comment(#) + comment(# ==== Custom/"classic" pagination ) + comment(#) + comment(# def list) + comment(# @person_pages = Paginator.new self, Person.count, 10, params[:page]) + comment(# @people = Person.find :all, :order => 'last_name, first_name', ) + comment(# :limit => @person_pages.items_per_page,) + comment(# :offset => @person_pages.current.offset) + comment(# end) + comment(# ) + comment(# Explicitly creates the paginator from the previous example and uses ) + comment(# Paginator#to_sql to retrieve <tt>@people</tt> from the model.) + comment(#) + reserved(module) class(Pagination) + reserved(unless) ident(const_defined?)operator(()symbol(:OPTIONS)operator(\)) + comment(# A hash holding options for controllers using macro-style pagination) + constant(OPTIONS) operator(=) constant(Hash)operator(.)ident(new) + + comment(# The default options for pagination) + constant(DEFAULT_OPTIONS) operator(=) operator({) + symbol(:class_name) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:singular_name) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:per_page) operator(=)operator(>) integer(10)operator(,) + symbol(:conditions) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:order_by) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:order) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:join) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:joins) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:count) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:include) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:select) operator(=)operator(>) pre_constant(nil)operator(,) + symbol(:parameter) operator(=)operator(>) string<delimiter(')content(page)delimiter(')> + operator(}) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(validate_options!)operator(()ident(collection_id)operator(,) ident(options)operator(,) ident(in_action)operator(\)) comment(#:nodoc:) + ident(options)operator(.)ident(merge!)operator(()constant(DEFAULT_OPTIONS)operator(\)) operator({)operator(|)ident(key)operator(,) ident(old)operator(,) ident(new)operator(|) ident(old)operator(}) + + ident(valid_options) operator(=) constant(DEFAULT_OPTIONS)operator(.)ident(keys) + ident(valid_options) operator(<<) symbol(:actions) reserved(unless) ident(in_action) + + ident(unknown_option_keys) operator(=) ident(options)operator(.)ident(keys) operator(-) ident(valid_options) + ident(raise) constant(ActionController)operator(::)constant(ActionControllerError)operator(,) + string<delimiter(")content(Unknown options: )inline<inline_delimiter(#{)ident(unknown_option_keys)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>delimiter(")> reserved(unless) + ident(unknown_option_keys)operator(.)ident(empty?) + + ident(options)operator([)symbol(:singular_name)operator(]) operator(||=) constant(Inflector)operator(.)ident(singularize)operator(()ident(collection_id)operator(.)ident(to_s)operator(\)) + ident(options)operator([)symbol(:class_name)operator(]) operator(||=) constant(Inflector)operator(.)ident(camelize)operator(()ident(options)operator([)symbol(:singular_name)operator(])operator(\)) + reserved(end) + + comment(# Returns a paginator and a collection of Active Record model instances) + comment(# for the paginator's current page. This is designed to be used in a) + comment(# single action; to automatically paginate multiple actions, consider) + comment(# ClassMethods#paginate.) + comment(#) + comment(# +options+ are:) + comment(# <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by) + comment(# singularizing the collection name) + comment(# <tt>:class_name</tt>:: the class name to use, if it can't be inferred by) + comment(# camelizing the singular name) + comment(# <tt>:per_page</tt>:: the maximum number of items to include in a ) + comment(# single page. Defaults to 10) + comment(# <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params\) and) + comment(# Model.count) + comment(# <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params\)) + comment(# <tt>:order_by</tt>:: (deprecated, used :order\) optional order parameter passed to Model.find(:all, *params\)) + comment(# <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params\)) + comment(# and Model.count) + comment(# <tt>:join</tt>:: (deprecated, used :joins or :include\) optional join parameter passed to Model.find(:all, *params\)) + comment(# and Model.count) + comment(# <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params\)) + comment(# and Model.count) + comment(# <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params\)) + comment(#) + comment(# <tt>:count</tt>:: parameter passed as :select option to Model.count(*params\)) + comment(#) + reserved(def) method(paginate)operator(()ident(collection_id)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + constant(Pagination)operator(.)ident(validate_options!)operator(()ident(collection_id)operator(,) ident(options)operator(,) pre_constant(true)operator(\)) + ident(paginator_and_collection_for)operator(()ident(collection_id)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# These methods become class methods on any controller ) + reserved(module) class(ClassMethods) + comment(# Creates a +before_filter+ which automatically paginates an Active) + comment(# Record model for all actions in a controller (or certain actions if) + comment(# specified with the <tt>:actions</tt> option\).) + comment(#) + comment(# +options+ are the same as PaginationHelper#paginate, with the addition ) + comment(# of:) + comment(# <tt>:actions</tt>:: an array of actions for which the pagination is) + comment(# active. Defaults to +nil+ (i.e., every action\)) + reserved(def) method(paginate)operator(()ident(collection_id)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + constant(Pagination)operator(.)ident(validate_options!)operator(()ident(collection_id)operator(,) ident(options)operator(,) pre_constant(false)operator(\)) + ident(module_eval) reserved(do) + ident(before_filter) symbol(:create_paginators_and_retrieve_collections) + constant(OPTIONS)operator([)pre_constant(self)operator(]) operator(||=) constant(Hash)operator(.)ident(new) + constant(OPTIONS)operator([)pre_constant(self)operator(])operator([)ident(collection_id)operator(]) operator(=) ident(options) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(create_paginators_and_retrieve_collections) comment(#:nodoc:) + constant(Pagination)operator(::)constant(OPTIONS)operator([)pre_constant(self)operator(.)ident(class)operator(])operator(.)ident(each) reserved(do) operator(|)ident(collection_id)operator(,) ident(options)operator(|) + reserved(next) reserved(unless) ident(options)operator([)symbol(:actions)operator(])operator(.)ident(include?) ident(action_name) reserved(if) + ident(options)operator([)symbol(:actions)operator(]) + + ident(paginator)operator(,) ident(collection) operator(=) + ident(paginator_and_collection_for)operator(()ident(collection_id)operator(,) ident(options)operator(\)) + + ident(paginator_name) operator(=) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(options)operator([)symbol(:singular_name)operator(])inline_delimiter(})>content(_pages)delimiter(")> + pre_constant(self)operator(.)ident(instance_variable_set)operator(()ident(paginator_name)operator(,) ident(paginator)operator(\)) + + ident(collection_name) operator(=) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(collection_id)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + pre_constant(self)operator(.)ident(instance_variable_set)operator(()ident(collection_name)operator(,) ident(collection)operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the total number of items in the collection to be paginated for) + comment(# the +model+ and given +conditions+. Override this method to implement a) + comment(# custom counter.) + reserved(def) method(count_collection_for_pagination)operator(()ident(model)operator(,) ident(options)operator(\)) + ident(model)operator(.)ident(count)operator(()symbol(:conditions) operator(=)operator(>) ident(options)operator([)symbol(:conditions)operator(])operator(,) + symbol(:joins) operator(=)operator(>) ident(options)operator([)symbol(:join)operator(]) operator(||) ident(options)operator([)symbol(:joins)operator(])operator(,) + symbol(:include) operator(=)operator(>) ident(options)operator([)symbol(:include)operator(])operator(,) + symbol(:select) operator(=)operator(>) ident(options)operator([)symbol(:count)operator(])operator(\)) + reserved(end) + + comment(# Returns a collection of items for the given +model+ and +options[conditions]+,) + comment(# ordered by +options[order]+, for the current page in the given +paginator+.) + comment(# Override this method to implement a custom finder.) + reserved(def) method(find_collection_for_pagination)operator(()ident(model)operator(,) ident(options)operator(,) ident(paginator)operator(\)) + ident(model)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) ident(options)operator([)symbol(:conditions)operator(])operator(,) + symbol(:order) operator(=)operator(>) ident(options)operator([)symbol(:order_by)operator(]) operator(||) ident(options)operator([)symbol(:order)operator(])operator(,) + symbol(:joins) operator(=)operator(>) ident(options)operator([)symbol(:join)operator(]) operator(||) ident(options)operator([)symbol(:joins)operator(])operator(,) symbol(:include) operator(=)operator(>) ident(options)operator([)symbol(:include)operator(])operator(,) + symbol(:select) operator(=)operator(>) ident(options)operator([)symbol(:select)operator(])operator(,) symbol(:limit) operator(=)operator(>) ident(options)operator([)symbol(:per_page)operator(])operator(,) + symbol(:offset) operator(=)operator(>) ident(paginator)operator(.)ident(current)operator(.)ident(offset)operator(\)) + reserved(end) + + ident(protected) symbol(:create_paginators_and_retrieve_collections)operator(,) + symbol(:count_collection_for_pagination)operator(,) + symbol(:find_collection_for_pagination) + + reserved(def) method(paginator_and_collection_for)operator(()ident(collection_id)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(klass) operator(=) ident(options)operator([)symbol(:class_name)operator(])operator(.)ident(constantize) + ident(page) operator(=) instance_variable(@params)operator([)ident(options)operator([)symbol(:parameter)operator(])operator(]) + ident(count) operator(=) ident(count_collection_for_pagination)operator(()ident(klass)operator(,) ident(options)operator(\)) + ident(paginator) operator(=) constant(Paginator)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(count)operator(,) ident(options)operator([)symbol(:per_page)operator(])operator(,) ident(page)operator(\)) + ident(collection) operator(=) ident(find_collection_for_pagination)operator(()ident(klass)operator(,) ident(options)operator(,) ident(paginator)operator(\)) + + reserved(return) ident(paginator)operator(,) ident(collection) + reserved(end) + + ident(private) symbol(:paginator_and_collection_for) + + comment(# A class representing a paginator for an Active Record collection.) + reserved(class) class(Paginator) + ident(include) constant(Enumerable) + + comment(# Creates a new Paginator on the given +controller+ for a set of items) + comment(# of size +item_count+ and having +items_per_page+ items per page.) + comment(# Raises ArgumentError if items_per_page is out of bounds (i.e., less) + comment(# than or equal to zero\). The page CGI parameter for links defaults to) + comment(# "page" and can be overridden with +page_parameter+.) + reserved(def) method(initialize)operator(()ident(controller)operator(,) ident(item_count)operator(,) ident(items_per_page)operator(,) ident(current_page)operator(=)integer(1)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(must have at least one item per page)delimiter(')> reserved(if) + ident(items_per_page) operator(<=) integer(0) + + instance_variable(@controller) operator(=) ident(controller) + instance_variable(@item_count) operator(=) ident(item_count) operator(||) integer(0) + instance_variable(@items_per_page) operator(=) ident(items_per_page) + instance_variable(@pages) operator(=) operator({)operator(}) + + pre_constant(self)operator(.)ident(current_page) operator(=) ident(current_page) + reserved(end) + ident(attr_reader) symbol(:controller)operator(,) symbol(:item_count)operator(,) symbol(:items_per_page) + + comment(# Sets the current page number of this paginator. If +page+ is a Page) + comment(# object, its +number+ attribute is used as the value; if the page does ) + comment(# not belong to this Paginator, an ArgumentError is raised.) + reserved(def) method(current_page=)operator(()ident(page)operator(\)) + reserved(if) ident(page)operator(.)ident(is_a?) constant(Page) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(Page/Paginator mismatch)delimiter(')> reserved(unless) + ident(page)operator(.)ident(paginator) operator(==) pre_constant(self) + reserved(end) + ident(page) operator(=) ident(page)operator(.)ident(to_i) + instance_variable(@current_page_number) operator(=) ident(has_page_number?)operator(()ident(page)operator(\)) operator(?) ident(page) operator(:) integer(1) + reserved(end) + + comment(# Returns a Page object representing this paginator's current page.) + reserved(def) method(current_page) + instance_variable(@current_page) operator(||=) pre_constant(self)operator([)instance_variable(@current_page_number)operator(]) + reserved(end) + reserved(alias) method(current) symbol(:current_page) + + comment(# Returns a new Page representing the first page in this paginator.) + reserved(def) method(first_page) + instance_variable(@first_page) operator(||=) pre_constant(self)operator([)integer(1)operator(]) + reserved(end) + reserved(alias) method(first) symbol(:first_page) + + comment(# Returns a new Page representing the last page in this paginator.) + reserved(def) method(last_page) + instance_variable(@last_page) operator(||=) pre_constant(self)operator([)ident(page_count)operator(]) + reserved(end) + reserved(alias) method(last) symbol(:last_page) + + comment(# Returns the number of pages in this paginator.) + reserved(def) method(page_count) + instance_variable(@page_count) operator(||=) instance_variable(@item_count)operator(.)ident(zero?) operator(?) integer(1) operator(:) + operator(()ident(q)operator(,)ident(r)operator(=)instance_variable(@item_count)operator(.)ident(divmod)operator(()instance_variable(@items_per_page)operator(\))operator(;) ident(r)operator(==)integer(0)operator(?) ident(q) operator(:) ident(q)operator(+)integer(1)operator(\)) + reserved(end) + + reserved(alias) method(length) symbol(:page_count) + + comment(# Returns true if this paginator contains the page of index +number+.) + reserved(def) method(has_page_number?)operator(()ident(number)operator(\)) + ident(number) operator(>)operator(=) integer(1) reserved(and) ident(number) operator(<=) ident(page_count) + reserved(end) + + comment(# Returns a new Page representing the page with the given index) + comment(# +number+.) + reserved(def) method([])operator(()ident(number)operator(\)) + instance_variable(@pages)operator([)ident(number)operator(]) operator(||=) constant(Page)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(number)operator(\)) + reserved(end) + + comment(# Successively yields all the paginator's pages to the given block.) + reserved(def) method(each)operator(()operator(&)ident(block)operator(\)) + ident(page_count)operator(.)ident(times) reserved(do) operator(|)ident(n)operator(|) + reserved(yield) pre_constant(self)operator([)ident(n)operator(+)integer(1)operator(]) + reserved(end) + reserved(end) + + comment(# A class representing a single page in a paginator.) + reserved(class) class(Page) + ident(include) constant(Comparable) + + comment(# Creates a new Page for the given +paginator+ with the index) + comment(# +number+. If +number+ is not in the range of valid page numbers or) + comment(# is not a number at all, it defaults to 1.) + reserved(def) method(initialize)operator(()ident(paginator)operator(,) ident(number)operator(\)) + instance_variable(@paginator) operator(=) ident(paginator) + instance_variable(@number) operator(=) ident(number)operator(.)ident(to_i) + instance_variable(@number) operator(=) integer(1) reserved(unless) instance_variable(@paginator)operator(.)ident(has_page_number?) instance_variable(@number) + reserved(end) + ident(attr_reader) symbol(:paginator)operator(,) symbol(:number) + reserved(alias) method(to_i) symbol(:number) + + comment(# Compares two Page objects and returns true when they represent the ) + comment(# same page (i.e., their paginators are the same and they have the) + comment(# same page number\).) + reserved(def) method(==)operator(()ident(page)operator(\)) + reserved(return) pre_constant(false) reserved(if) ident(page)operator(.)ident(nil?) + instance_variable(@paginator) operator(==) ident(page)operator(.)ident(paginator) reserved(and) + instance_variable(@number) operator(==) ident(page)operator(.)ident(number) + reserved(end) + + comment(# Compares two Page objects and returns -1 if the left-hand page comes) + comment(# before the right-hand page, 0 if the pages are equal, and 1 if the) + comment(# left-hand page comes after the right-hand page. Raises ArgumentError) + comment(# if the pages do not belong to the same Paginator object.) + reserved(def) method(<=>)operator(()ident(page)operator(\)) + ident(raise) constant(ArgumentError) reserved(unless) instance_variable(@paginator) operator(==) ident(page)operator(.)ident(paginator) + instance_variable(@number) operator(<=>) ident(page)operator(.)ident(number) + reserved(end) + + comment(# Returns the item offset for the first item in this page.) + reserved(def) method(offset) + instance_variable(@paginator)operator(.)ident(items_per_page) operator(*) operator(()instance_variable(@number) operator(-) integer(1)operator(\)) + reserved(end) + + comment(# Returns the number of the first item displayed.) + reserved(def) method(first_item) + ident(offset) operator(+) integer(1) + reserved(end) + + comment(# Returns the number of the last item displayed.) + reserved(def) method(last_item) + operator([)instance_variable(@paginator)operator(.)ident(items_per_page) operator(*) instance_variable(@number)operator(,) instance_variable(@paginator)operator(.)ident(item_count)operator(])operator(.)ident(min) + reserved(end) + + comment(# Returns true if this page is the first page in the paginator.) + reserved(def) method(first?) + pre_constant(self) operator(==) instance_variable(@paginator)operator(.)ident(first) + reserved(end) + + comment(# Returns true if this page is the last page in the paginator.) + reserved(def) method(last?) + pre_constant(self) operator(==) instance_variable(@paginator)operator(.)ident(last) + reserved(end) + + comment(# Returns a new Page object representing the page just before this) + comment(# page, or nil if this is the first page.) + reserved(def) method(previous) + reserved(if) ident(first?) reserved(then) pre_constant(nil) reserved(else) instance_variable(@paginator)operator([)instance_variable(@number) operator(-) integer(1)operator(]) reserved(end) + reserved(end) + + comment(# Returns a new Page object representing the page just after this) + comment(# page, or nil if this is the last page.) + reserved(def) method(next) + reserved(if) ident(last?) reserved(then) pre_constant(nil) reserved(else) instance_variable(@paginator)operator([)instance_variable(@number) operator(+) integer(1)operator(]) reserved(end) + reserved(end) + + comment(# Returns a new Window object for this page with the specified ) + comment(# +padding+.) + reserved(def) method(window)operator(()ident(padding)operator(=)integer(2)operator(\)) + constant(Window)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(padding)operator(\)) + reserved(end) + + comment(# Returns the limit/offset array for this page.) + reserved(def) method(to_sql) + operator([)instance_variable(@paginator)operator(.)ident(items_per_page)operator(,) ident(offset)operator(]) + reserved(end) + + reserved(def) method(to_param) comment(#:nodoc:) + instance_variable(@number)operator(.)ident(to_s) + reserved(end) + reserved(end) + + comment(# A class for representing ranges around a given page.) + reserved(class) class(Window) + comment(# Creates a new Window object for the given +page+ with the specified) + comment(# +padding+.) + reserved(def) method(initialize)operator(()ident(page)operator(,) ident(padding)operator(=)integer(2)operator(\)) + instance_variable(@paginator) operator(=) ident(page)operator(.)ident(paginator) + instance_variable(@page) operator(=) ident(page) + pre_constant(self)operator(.)ident(padding) operator(=) ident(padding) + reserved(end) + ident(attr_reader) symbol(:paginator)operator(,) symbol(:page) + + comment(# Sets the window's padding (the number of pages on either side of the) + comment(# window page\).) + reserved(def) method(padding=)operator(()ident(padding)operator(\)) + instance_variable(@padding) operator(=) ident(padding) operator(<) integer(0) operator(?) integer(0) operator(:) ident(padding) + comment(# Find the beginning and end pages of the window) + instance_variable(@first) operator(=) instance_variable(@paginator)operator(.)ident(has_page_number?)operator(()instance_variable(@page)operator(.)ident(number) operator(-) instance_variable(@padding)operator(\)) operator(?) + instance_variable(@paginator)operator([)instance_variable(@page)operator(.)ident(number) operator(-) instance_variable(@padding)operator(]) operator(:) instance_variable(@paginator)operator(.)ident(first) + instance_variable(@last) operator(=) instance_variable(@paginator)operator(.)ident(has_page_number?)operator(()instance_variable(@page)operator(.)ident(number) operator(+) instance_variable(@padding)operator(\)) operator(?) + instance_variable(@paginator)operator([)instance_variable(@page)operator(.)ident(number) operator(+) instance_variable(@padding)operator(]) operator(:) instance_variable(@paginator)operator(.)ident(last) + reserved(end) + ident(attr_reader) symbol(:padding)operator(,) symbol(:first)operator(,) symbol(:last) + + comment(# Returns an array of Page objects in the current window.) + reserved(def) method(pages) + operator(()instance_variable(@first)operator(.)ident(number)operator(..)instance_variable(@last)operator(.)ident(number)operator(\))operator(.)ident(to_a)operator(.)ident(collect!) operator({)operator(|)ident(n)operator(|) instance_variable(@paginator)operator([)ident(n)operator(])operator(}) + reserved(end) + reserved(alias) method(to_a) symbol(:pages) + reserved(end) + reserved(end) + + reserved(end) +reserved(end) +reserved(module) class(ActionController) + comment(# Subclassing AbstractRequest makes these methods available to the request objects used in production and testing,) + comment(# CgiRequest and TestRequest) + reserved(class) class(AbstractRequest) + ident(cattr_accessor) symbol(:relative_url_root) + + comment(# Returns the hash of environment variables for this request,) + comment(# such as { 'RAILS_ENV' => 'production' }.) + ident(attr_reader) symbol(:env) + + comment(# Returns both GET and POST parameters in a single hash.) + reserved(def) method(parameters) + instance_variable(@parameters) operator(||=) ident(request_parameters)operator(.)ident(update)operator(()ident(query_parameters)operator(\))operator(.)ident(update)operator(()ident(path_parameters)operator(\))operator(.)ident(with_indifferent_access) + reserved(end) + + comment(# Returns the HTTP request method as a lowercase symbol (:get, for example\)) + reserved(def) method(method) + instance_variable(@request_method) operator(||=) instance_variable(@env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(])operator(.)ident(downcase)operator(.)ident(to_sym) + reserved(end) + + comment(# Is this a GET request? Equivalent to request.method == :get) + reserved(def) method(get?) + ident(method) operator(==) symbol(:get) + reserved(end) + + comment(# Is this a POST request? Equivalent to request.method == :post) + reserved(def) method(post?) + ident(method) operator(==) symbol(:post) + reserved(end) + + comment(# Is this a PUT request? Equivalent to request.method == :put) + reserved(def) method(put?) + ident(method) operator(==) symbol(:put) + reserved(end) + + comment(# Is this a DELETE request? Equivalent to request.method == :delete) + reserved(def) method(delete?) + ident(method) operator(==) symbol(:delete) + reserved(end) + + comment(# Is this a HEAD request? Equivalent to request.method == :head) + reserved(def) method(head?) + ident(method) operator(==) symbol(:head) + reserved(end) + + comment(# Determine whether the body of a HTTP call is URL-encoded (default\)) + comment(# or matches one of the registered param_parsers. ) + comment(#) + comment(# For backward compatibility, the post format is extracted from the) + comment(# X-Post-Data-Format HTTP header if present.) + reserved(def) method(content_type) + instance_variable(@content_type) operator(||=) + reserved(begin) + ident(content_type) operator(=) instance_variable(@env)operator([)string<delimiter(')content(CONTENT_TYPE)delimiter(')>operator(])operator(.)ident(to_s)operator(.)ident(downcase) + + reserved(if) ident(x_post_format) operator(=) instance_variable(@env)operator([)string<delimiter(')content(HTTP_X_POST_DATA_FORMAT)delimiter(')>operator(]) + reserved(case) ident(x_post_format)operator(.)ident(to_s)operator(.)ident(downcase) + reserved(when) string<delimiter(')content(yaml)delimiter(')> + ident(content_type) operator(=) string<delimiter(')content(application/x-yaml)delimiter(')> + reserved(when) string<delimiter(')content(xml)delimiter(')> + ident(content_type) operator(=) string<delimiter(')content(application/xml)delimiter(')> + reserved(end) + reserved(end) + + constant(Mime)operator(::)constant(Type)operator(.)ident(lookup)operator(()ident(content_type)operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the accepted MIME type for the request) + reserved(def) method(accepts) + instance_variable(@accepts) operator(||=) + reserved(if) instance_variable(@env)operator([)string<delimiter(')content(HTTP_ACCEPT)delimiter(')>operator(])operator(.)ident(to_s)operator(.)ident(strip)operator(.)ident(empty?) + operator([) ident(content_type)operator(,) constant(Mime)operator(::)constant(ALL) operator(]) + reserved(else) + constant(Mime)operator(::)constant(Type)operator(.)ident(parse)operator(()instance_variable(@env)operator([)string<delimiter(')content(HTTP_ACCEPT)delimiter(')>operator(])operator(\)) + reserved(end) + reserved(end) + + comment(# Returns true if the request's "X-Requested-With" header contains) + comment(# "XMLHttpRequest". (The Prototype Javascript library sends this header with) + comment(# every Ajax request.\)) + reserved(def) method(xml_http_request?) + reserved(not) regexp<delimiter(/)content(XMLHttpRequest)delimiter(/)modifier(i)>operator(.)ident(match)operator(()instance_variable(@env)operator([)string<delimiter(')content(HTTP_X_REQUESTED_WITH)delimiter(')>operator(])operator(\))operator(.)ident(nil?) + reserved(end) + reserved(alias) method(xhr?) symbol(:xml_http_request?) + + comment(# Determine originating IP address. REMOTE_ADDR is the standard) + comment(# but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or) + comment(# HTTP_X_FORWARDED_FOR are set by proxies so check for these before) + comment(# falling back to REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma-) + comment(# delimited list in the case of multiple chained proxies; the first is) + comment(# the originating IP.) + reserved(def) method(remote_ip) + reserved(return) instance_variable(@env)operator([)string<delimiter(')content(HTTP_CLIENT_IP)delimiter(')>operator(]) reserved(if) instance_variable(@env)operator(.)ident(include?) string<delimiter(')content(HTTP_CLIENT_IP)delimiter(')> + + reserved(if) instance_variable(@env)operator(.)ident(include?) string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')> reserved(then) + ident(remote_ips) operator(=) instance_variable(@env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(])operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\))operator(.)ident(reject) reserved(do) operator(|)ident(ip)operator(|) + ident(ip) operator(=)operator(~) regexp<delimiter(/)content(^unknown$|^(10|172)char(\\.)content((1[6-9]|2[0-9]|30|31\)|192)char(\\.)content(168\))char(\\.)delimiter(/)modifier(i)> + reserved(end) + + reserved(return) ident(remote_ips)operator(.)ident(first)operator(.)ident(strip) reserved(unless) ident(remote_ips)operator(.)ident(empty?) + reserved(end) + + instance_variable(@env)operator([)string<delimiter(')content(REMOTE_ADDR)delimiter(')>operator(]) + reserved(end) + + comment(# Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify) + comment(# a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".) + reserved(def) method(domain)operator(()ident(tld_length) operator(=) integer(1)operator(\)) + reserved(return) pre_constant(nil) reserved(if) operator(!)regexp<delimiter(/)char(\\d)content({1,3})char(\\.)char(\\d)content({1,3})char(\\.)char(\\d)content({1,3})char(\\.)char(\\d)content({1,3})delimiter(/)>operator(.)ident(match)operator(()ident(host)operator(\))operator(.)ident(nil?) reserved(or) ident(host)operator(.)ident(nil?) + + ident(host)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(.)ident(last)operator(()integer(1) operator(+) ident(tld_length)operator(\))operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) + + comment(# Returns all the subdomains as an array, so ["dev", "www"] would be returned for "dev.www.rubyonrails.org".) + comment(# You can specify a different <tt>tld_length</tt>, such as 2 to catch ["www"] instead of ["www", "rubyonrails"]) + comment(# in "www.rubyonrails.co.uk".) + reserved(def) method(subdomains)operator(()ident(tld_length) operator(=) integer(1)operator(\)) + reserved(return) operator([)operator(]) reserved(unless) ident(host) + ident(parts) operator(=) ident(host)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + ident(parts)operator([)integer(0)operator(..)operator(-)operator(()ident(tld_length)operator(+)integer(2)operator(\))operator(]) + reserved(end) + + comment(# Receive the raw post data.) + comment(# This is useful for services such as REST, XMLRPC and SOAP) + comment(# which communicate over HTTP POST but don't use the traditional parameter format.) + reserved(def) method(raw_post) + instance_variable(@env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) + reserved(end) + + comment(# Returns the request URI correctly, taking into account the idiosyncracies) + comment(# of the various servers.) + reserved(def) method(request_uri) + reserved(if) ident(uri) operator(=) instance_variable(@env)operator([)string<delimiter(')content(REQUEST_URI)delimiter(')>operator(]) + operator(()regexp<delimiter(%r{)content(^)char(\\w)content(+)char(\\:)content(//[^/]+(/.*|$\)$)delimiter(})> operator(=)operator(~) ident(uri)operator(\)) operator(?) global_variable($1) operator(:) ident(uri) comment(# Remove domain, which webrick puts into the request_uri.) + reserved(else) comment(# REQUEST_URI is blank under IIS - get this from PATH_INFO and SCRIPT_NAME) + ident(script_filename) operator(=) instance_variable(@env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(])operator(.)ident(to_s)operator(.)ident(match)operator(()regexp<delimiter(%r{)content([^/]+$)delimiter(})>operator(\)) + ident(uri) operator(=) instance_variable(@env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) + ident(uri) operator(=) ident(uri)operator(.)ident(sub)operator(()regexp<delimiter(/)inline<inline_delimiter(#{)ident(script_filename)inline_delimiter(})>char(\\/)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) reserved(unless) ident(script_filename)operator(.)ident(nil?) + reserved(unless) operator(()ident(env_qs) operator(=) instance_variable(@env)operator([)string<delimiter(')content(QUERY_STRING)delimiter(')>operator(])operator(\))operator(.)ident(nil?) operator(||) ident(env_qs)operator(.)ident(empty?) + ident(uri) operator(<<) string<delimiter(')content(?)delimiter(')> operator(<<) ident(env_qs) + reserved(end) + ident(uri) + reserved(end) + reserved(end) + + comment(# Return 'https://' if this is an SSL request and 'http://' otherwise.) + reserved(def) method(protocol) + ident(ssl?) operator(?) string<delimiter(')content(https://)delimiter(')> operator(:) string<delimiter(')content(http://)delimiter(')> + reserved(end) + + comment(# Is this an SSL request?) + reserved(def) method(ssl?) + instance_variable(@env)operator([)string<delimiter(')content(HTTPS)delimiter(')>operator(]) operator(==) string<delimiter(')content(on)delimiter(')> operator(||) instance_variable(@env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_PROTO)delimiter(')>operator(]) operator(==) string<delimiter(')content(https)delimiter(')> + reserved(end) + + comment(# Returns the interpreted path to requested resource after all the installation directory of this application was taken into account) + reserved(def) method(path) + ident(path) operator(=) operator(()ident(uri) operator(=) ident(request_uri)operator(\)) operator(?) ident(uri)operator(.)ident(split)operator(()string<delimiter(')content(?)delimiter(')>operator(\))operator(.)ident(first) operator(:) string<delimiter(')delimiter(')> + + comment(# Cut off the path to the installation directory if given) + ident(root) operator(=) ident(relative_url_root) + ident(path)operator([)integer(0)operator(,) ident(root)operator(.)ident(length)operator(]) operator(=) string<delimiter(')delimiter(')> reserved(if) ident(root) + ident(path) operator(||) string<delimiter(')delimiter(')> + reserved(end) + + comment(# Returns the path minus the web server relative installation directory.) + comment(# This can be set with the environment variable RAILS_RELATIVE_URL_ROOT.) + comment(# It can be automatically extracted for Apache setups. If the server is not) + comment(# Apache, this method returns an empty string.) + reserved(def) method(relative_url_root) + class_variable(@@relative_url_root) operator(||=) reserved(case) + reserved(when) instance_variable(@env)operator([)string<delimiter(")content(RAILS_RELATIVE_URL_ROOT)delimiter(")>operator(]) + instance_variable(@env)operator([)string<delimiter(")content(RAILS_RELATIVE_URL_ROOT)delimiter(")>operator(]) + reserved(when) ident(server_software) operator(==) string<delimiter(')content(apache)delimiter(')> + instance_variable(@env)operator([)string<delimiter(")content(SCRIPT_NAME)delimiter(")>operator(])operator(.)ident(to_s)operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\/)content(dispatch)char(\\.)content((fcgi|rb|cgi\)$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(else) + string<delimiter(')delimiter(')> + reserved(end) + reserved(end) + + comment(# Returns the port number of this request as an integer.) + reserved(def) method(port) + instance_variable(@port_as_int) operator(||=) instance_variable(@env)operator([)string<delimiter(')content(SERVER_PORT)delimiter(')>operator(])operator(.)ident(to_i) + reserved(end) + + comment(# Returns the standard port number for this request's protocol) + reserved(def) method(standard_port) + reserved(case) ident(protocol) + reserved(when) string<delimiter(')content(https://)delimiter(')> reserved(then) integer(443) + reserved(else) integer(80) + reserved(end) + reserved(end) + + comment(# Returns a port suffix like ":8080" if the port number of this request) + comment(# is not the default HTTP port 80 or HTTPS port 443.) + reserved(def) method(port_string) + operator(()ident(port) operator(==) ident(standard_port)operator(\)) operator(?) string<delimiter(')delimiter(')> operator(:) string<delimiter(")content(:)inline<inline_delimiter(#{)ident(port)inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Returns a host:port string for this request, such as example.com or) + comment(# example.com:8080.) + reserved(def) method(host_with_port) + ident(host) operator(+) ident(port_string) + reserved(end) + + reserved(def) method(path_parameters=)operator(()ident(parameters)operator(\)) comment(#:nodoc:) + instance_variable(@path_parameters) operator(=) ident(parameters) + instance_variable(@symbolized_path_parameters) operator(=) instance_variable(@parameters) operator(=) pre_constant(nil) + reserved(end) + + comment(# The same as <tt>path_parameters</tt> with explicitly symbolized keys ) + reserved(def) method(symbolized_path_parameters) + instance_variable(@symbolized_path_parameters) operator(||=) ident(path_parameters)operator(.)ident(symbolize_keys) + reserved(end) + + comment(# Returns a hash with the parameters used to form the path of the request ) + comment(#) + comment(# Example: ) + comment(#) + comment(# {:action => 'my_action', :controller => 'my_controller'}) + reserved(def) method(path_parameters) + instance_variable(@path_parameters) operator(||=) operator({)operator(}) + reserved(end) + + comment(# Returns the lowercase name of the HTTP server software.) + reserved(def) method(server_software) + operator(()instance_variable(@env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(&&) regexp<delimiter(/)content(^([a-zA-Z]+\))delimiter(/)> operator(=)operator(~) instance_variable(@env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(])operator(\)) operator(?) global_variable($1)operator(.)ident(downcase) operator(:) pre_constant(nil) + reserved(end) + + comment(#--) + comment(# Must be implemented in the concrete request) + comment(#++) + reserved(def) method(query_parameters) comment(#:nodoc:) + reserved(end) + + reserved(def) method(request_parameters) comment(#:nodoc:) + reserved(end) + + comment(# Returns the host for this request, such as example.com.) + reserved(def) method(host) + reserved(end) + + reserved(def) method(cookies) comment(#:nodoc:) + reserved(end) + + reserved(def) method(session) comment(#:nodoc:) + reserved(end) + + reserved(def) method(session=)operator(()ident(session)operator(\)) comment(#:nodoc:) + instance_variable(@session) operator(=) ident(session) + reserved(end) + + reserved(def) method(reset_session) comment(#:nodoc:) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# Actions that fail to perform as expected throw exceptions. These exceptions can either be rescued for the public view ) + comment(# (with a nice user-friendly explanation\) or for the developers view (with tons of debugging information\). The developers view) + comment(# is already implemented by the Action Controller, but the public view should be tailored to your specific application. So too) + comment(# could the decision on whether something is a public or a developer request.) + comment(#) + comment(# You can tailor the rescuing behavior and appearance by overwriting the following two stub methods.) + reserved(module) class(Rescue) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:perform_action_without_rescue)operator(,) symbol(:perform_action) + ident(alias_method) symbol(:perform_action)operator(,) symbol(:perform_action_with_rescue) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + reserved(def) method(process_with_exception)operator(()ident(request)operator(,) ident(response)operator(,) ident(exception)operator(\)) + ident(new)operator(.)ident(process)operator(()ident(request)operator(,) ident(response)operator(,) symbol(:rescue_action)operator(,) ident(exception)operator(\)) + reserved(end) + reserved(end) + + ident(protected) + comment(# Exception handler called when the performance of an action raises an exception.) + reserved(def) method(rescue_action)operator(()ident(exception)operator(\)) + ident(log_error)operator(()ident(exception)operator(\)) reserved(if) ident(logger) + ident(erase_results) reserved(if) ident(performed?) + + reserved(if) ident(consider_all_requests_local) operator(||) ident(local_request?) + ident(rescue_action_locally)operator(()ident(exception)operator(\)) + reserved(else) + ident(rescue_action_in_public)operator(()ident(exception)operator(\)) + reserved(end) + reserved(end) + + comment(# Overwrite to implement custom logging of errors. By default logs as fatal.) + reserved(def) method(log_error)operator(()ident(exception)operator(\)) comment(#:doc:) + reserved(if) constant(ActionView)operator(::)constant(TemplateError) operator(===) ident(exception) + ident(logger)operator(.)ident(fatal)operator(()ident(exception)operator(.)ident(to_s)operator(\)) + reserved(else) + ident(logger)operator(.)ident(fatal)operator(() + string<delimiter(")char(\\n)char(\\n)inline<inline_delimiter(#{)ident(exception)operator(.)ident(class)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(exception)operator(.)ident(message)inline_delimiter(})>content(\):)char(\\n)content( )delimiter(")> operator(+) + ident(clean_backtrace)operator(()ident(exception)operator(\))operator(.)ident(join)operator(()string<delimiter(")char(\\n)content( )delimiter(")>operator(\)) operator(+) + string<delimiter(")char(\\n)char(\\n)delimiter(")> + operator(\)) + reserved(end) + reserved(end) + + comment(# Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>\).) + reserved(def) method(rescue_action_in_public)operator(()ident(exception)operator(\)) comment(#:doc:) + reserved(case) ident(exception) + reserved(when) constant(RoutingError)operator(,) constant(UnknownAction) reserved(then) + ident(render_text)operator(()constant(IO)operator(.)ident(read)operator(()constant(File)operator(.)ident(join)operator(()constant(RAILS_ROOT)operator(,) string<delimiter(')content(public)delimiter(')>operator(,) string<delimiter(')content(404.html)delimiter(')>operator(\))operator(\))operator(,) string<delimiter(")content(404 Not Found)delimiter(")>operator(\)) + reserved(else) ident(render_text) string<delimiter(")content(<html><body><h1>Application error (Rails\)</h1></body></html>)delimiter(")> + reserved(end) + reserved(end) + + comment(# Overwrite to expand the meaning of a local request in order to show local rescues on other occurrences than) + comment(# the remote IP being 127.0.0.1. For example, this could include the IP of the developer machine when debugging) + comment(# remotely.) + reserved(def) method(local_request?) comment(#:doc:) + operator([)instance_variable(@request)operator(.)ident(remote_addr)operator(,) instance_variable(@request)operator(.)ident(remote_ip)operator(]) operator(==) operator([)string<delimiter(")content(127.0.0.1)delimiter(")>operator(]) operator(*) integer(2) + reserved(end) + + comment(# Renders a detailed diagnostics screen on action exceptions. ) + reserved(def) method(rescue_action_locally)operator(()ident(exception)operator(\)) + ident(add_variables_to_assigns) + instance_variable(@template)operator(.)ident(instance_variable_set)operator(()string<delimiter(")content(@exception)delimiter(")>operator(,) ident(exception)operator(\)) + instance_variable(@template)operator(.)ident(instance_variable_set)operator(()string<delimiter(")content(@rescues_path)delimiter(")>operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/templates/rescues/)delimiter(")>operator(\)) + instance_variable(@template)operator(.)ident(send)operator(()symbol(:assign_variables_from_controller)operator(\)) + + instance_variable(@template)operator(.)ident(instance_variable_set)operator(()string<delimiter(")content(@contents)delimiter(")>operator(,) instance_variable(@template)operator(.)ident(render_file)operator(()ident(template_path_for_local_rescue)operator(()ident(exception)operator(\))operator(,) pre_constant(false)operator(\))operator(\)) + + instance_variable(@headers)operator([)string<delimiter(")content(Content-Type)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/html)delimiter(")> + ident(render_file)operator(()ident(rescues_path)operator(()string<delimiter(")content(layout)delimiter(")>operator(\))operator(,) ident(response_code_for_rescue)operator(()ident(exception)operator(\))operator(\)) + reserved(end) + + ident(private) + reserved(def) method(perform_action_with_rescue) comment(#:nodoc:) + reserved(begin) + ident(perform_action_without_rescue) + reserved(rescue) constant(Object) operator(=)operator(>) ident(exception) + reserved(if) reserved(defined?)operator(()constant(Breakpoint)operator(\)) operator(&&) instance_variable(@params)operator([)string<delimiter(")content(BP-RETRY)delimiter(")>operator(]) + ident(msg) operator(=) ident(exception)operator(.)ident(backtrace)operator(.)ident(first) + reserved(if) ident(md) operator(=) regexp<delimiter(/)content(^(.+?\):()char(\\d)content(+\)(?::in `(.+\)'\)?$)delimiter(/)>operator(.)ident(match)operator(()ident(msg)operator(\)) reserved(then) + ident(origin_file)operator(,) ident(origin_line) operator(=) ident(md)operator([)integer(1)operator(])operator(,) ident(md)operator([)integer(2)operator(])operator(.)ident(to_i) + + ident(set_trace_func)operator(()ident(lambda) reserved(do) operator(|)ident(type)operator(,) ident(file)operator(,) ident(line)operator(,) ident(method)operator(,) ident(context)operator(,) ident(klass)operator(|) + reserved(if) ident(file) operator(==) ident(origin_file) reserved(and) ident(line) operator(==) ident(origin_line) reserved(then) + ident(set_trace_func)operator(()pre_constant(nil)operator(\)) + instance_variable(@params)operator([)string<delimiter(")content(BP-RETRY)delimiter(")>operator(]) operator(=) pre_constant(false) + + ident(callstack) operator(=) ident(caller) + ident(callstack)operator(.)ident(slice!)operator(()integer(0)operator(\)) reserved(if) ident(callstack)operator(.)ident(first)operator([)string<delimiter(")content(rescue.rb)delimiter(")>operator(]) + ident(file)operator(,) ident(line)operator(,) ident(method) operator(=) operator(*)ident(callstack)operator(.)ident(first)operator(.)ident(match)operator(()regexp<delimiter(/)content(^(.+?\):()char(\\d)content(+\)(?::in `(.*?\)'\)?)delimiter(/)>operator(\))operator(.)ident(captures) + + ident(message) operator(=) string<delimiter(")content(Exception at )inline<inline_delimiter(#{)ident(file)inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(line)inline_delimiter(})>inline<inline_delimiter(#{)string<delimiter(")content( in `)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(')delimiter(")> reserved(if) ident(method)inline_delimiter(})>content(.)delimiter(")> comment(# `´ ( for ruby-mode\)) + + constant(Breakpoint)operator(.)ident(handle_breakpoint)operator(()ident(context)operator(,) ident(message)operator(,) ident(file)operator(,) ident(line)operator(\)) + reserved(end) + reserved(end)operator(\)) + + reserved(retry) + reserved(end) + reserved(end) + + ident(rescue_action)operator(()ident(exception)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(rescues_path)operator(()ident(template_name)operator(\)) + constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/templates/rescues/)inline<inline_delimiter(#{)ident(template_name)inline_delimiter(})>content(.rhtml)delimiter(")> + reserved(end) + + reserved(def) method(template_path_for_local_rescue)operator(()ident(exception)operator(\)) + ident(rescues_path)operator(() + reserved(case) ident(exception) + reserved(when) constant(MissingTemplate) reserved(then) string<delimiter(")content(missing_template)delimiter(")> + reserved(when) constant(RoutingError) reserved(then) string<delimiter(")content(routing_error)delimiter(")> + reserved(when) constant(UnknownAction) reserved(then) string<delimiter(")content(unknown_action)delimiter(")> + reserved(when) constant(ActionView)operator(::)constant(TemplateError) reserved(then) string<delimiter(")content(template_error)delimiter(")> + reserved(else) string<delimiter(")content(diagnostics)delimiter(")> + reserved(end) + operator(\)) + reserved(end) + + reserved(def) method(response_code_for_rescue)operator(()ident(exception)operator(\)) + reserved(case) ident(exception) + reserved(when) constant(UnknownAction)operator(,) constant(RoutingError) reserved(then) string<delimiter(")content(404 Page Not Found)delimiter(")> + reserved(else) string<delimiter(")content(500 Internal Error)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(clean_backtrace)operator(()ident(exception)operator(\)) + ident(exception)operator(.)ident(backtrace)operator(.)ident(collect) operator({) operator(|)ident(line)operator(|) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:RAILS_ROOT)operator(\)) operator(?) ident(line)operator(.)ident(gsub)operator(()constant(RAILS_ROOT)operator(,) string<delimiter(")delimiter(")>operator(\)) operator(:) ident(line) operator(}) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) + reserved(class) class(AbstractResponse) comment(#:nodoc:) + constant(DEFAULT_HEADERS) operator(=) operator({) string<delimiter(")content(Cache-Control)delimiter(")> operator(=)operator(>) string<delimiter(")content(no-cache)delimiter(")> operator(}) + ident(attr_accessor) symbol(:body)operator(,) symbol(:headers)operator(,) symbol(:session)operator(,) symbol(:cookies)operator(,) symbol(:assigns)operator(,) symbol(:template)operator(,) symbol(:redirected_to)operator(,) symbol(:redirected_to_method_params) + + reserved(def) method(initialize) + instance_variable(@body)operator(,) instance_variable(@headers)operator(,) instance_variable(@session)operator(,) instance_variable(@assigns) operator(=) string<delimiter(")delimiter(")>operator(,) constant(DEFAULT_HEADERS)operator(.)ident(merge)operator(()string<delimiter(")content(cookie)delimiter(")> operator(=)operator(>) operator([)operator(])operator(\))operator(,) operator([)operator(])operator(,) operator([)operator(]) + reserved(end) + + reserved(def) method(redirect)operator(()ident(to_url)operator(,) ident(permanently) operator(=) pre_constant(false)operator(\)) + instance_variable(@headers)operator([)string<delimiter(")content(Status)delimiter(")>operator(]) operator(=) string<delimiter(")content(302 Found)delimiter(")> reserved(unless) instance_variable(@headers)operator([)string<delimiter(")content(Status)delimiter(")>operator(]) operator(==) string<delimiter(")content(301 Moved Permanently)delimiter(")> + instance_variable(@headers)operator([)string<delimiter(")content(location)delimiter(")>operator(]) operator(=) ident(to_url) + + instance_variable(@body) operator(=) string<delimiter(")content(<html><body>You are being <a href=)char(\\")inline<inline_delimiter(#{)ident(to_url)inline_delimiter(})>char(\\")content(>redirected</a>.</body></html>)delimiter(")> + reserved(end) + reserved(end) +ident(endmodule) constant(ActionController) + reserved(module) class(Routing) comment(#:nodoc:) + reserved(class) operator(<<) class(self) + reserved(def) method(expiry_hash)operator(()ident(options)operator(,) ident(recall)operator(\)) + ident(k) operator(=) ident(v) operator(=) pre_constant(nil) + ident(expire_on) operator(=) operator({)operator(}) + ident(options)operator(.)ident(each) operator({)operator(|)ident(k)operator(,) ident(v)operator(|) ident(expire_on)operator([)ident(k)operator(]) operator(=) operator(()operator(()ident(rcv) operator(=) ident(recall)operator([)ident(k)operator(])operator(\)) operator(&&) operator(()ident(rcv) operator(!=) ident(v)operator(\))operator(\))operator(}) + ident(expire_on) + reserved(end) + + reserved(def) method(extract_parameter_value)operator(()ident(parameter)operator(\)) comment(#:nodoc:) + constant(CGI)operator(.)ident(escape)operator(()operator(()ident(parameter)operator(.)ident(respond_to?)operator(()symbol(:to_param)operator(\)) operator(?) ident(parameter)operator(.)ident(to_param) operator(:) ident(parameter)operator(\))operator(.)ident(to_s)operator(\)) + reserved(end) + reserved(def) method(controller_relative_to)operator(()ident(controller)operator(,) ident(previous)operator(\)) + reserved(if) ident(controller)operator(.)ident(nil?) reserved(then) ident(previous) + reserved(elsif) ident(controller)operator([)integer(0)operator(]) operator(==) integer(?/) reserved(then) ident(controller)operator([)integer(1)operator(..)integer(-1)operator(]) + reserved(elsif) regexp<delimiter(%r{)content(^(.*\)/)delimiter(})> operator(=)operator(~) ident(previous) reserved(then) string<delimiter(")inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(controller)inline_delimiter(})>delimiter(")> + reserved(else) ident(controller) + reserved(end) + reserved(end) + + reserved(def) method(treat_hash)operator(()ident(hash)operator(,) ident(keys_to_delete) operator(=) operator([)operator(])operator(\)) + ident(k) operator(=) ident(v) operator(=) pre_constant(nil) + ident(hash)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,) ident(v)operator(|) + reserved(if) ident(v) reserved(then) ident(hash)operator([)ident(k)operator(]) operator(=) operator(()ident(v)operator(.)ident(respond_to?) symbol(:to_param)operator(\)) operator(?) ident(v)operator(.)ident(to_param)operator(.)ident(to_s) operator(:) ident(v)operator(.)ident(to_s) + reserved(else) + ident(hash)operator(.)ident(delete) ident(k) + ident(keys_to_delete) operator(<<) ident(k) + reserved(end) + reserved(end) + ident(hash) + reserved(end) + + reserved(def) method(test_condition)operator(()ident(expression)operator(,) ident(condition)operator(\)) + reserved(case) ident(condition) + reserved(when) constant(String) reserved(then) string<delimiter(")content(()inline<inline_delimiter(#{)ident(expression)inline_delimiter(})>content( == )inline<inline_delimiter(#{)ident(condition)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> + reserved(when) constant(Regexp) reserved(then) + ident(condition) operator(=) constant(Regexp)operator(.)ident(new)operator(()string<delimiter(")content(^)inline<inline_delimiter(#{)ident(condition)operator(.)ident(source)inline_delimiter(})>content($)delimiter(")>operator(\)) reserved(unless) regexp<delimiter(/)content(^)char(\\^)content(.*)char(\\$)content($)delimiter(/)> operator(=)operator(~) ident(condition)operator(.)ident(source) + string<delimiter(")content(()inline<inline_delimiter(#{)ident(condition)operator(.)ident(inspect)inline_delimiter(})>content( =~ )inline<inline_delimiter(#{)ident(expression)inline_delimiter(})>content(\))delimiter(")> + reserved(when) constant(Array) reserved(then) + ident(conds) operator(=) ident(condition)operator(.)ident(collect) reserved(do) operator(|)ident(condition)operator(|) + ident(cond) operator(=) ident(test_condition)operator(()ident(expression)operator(,) ident(condition)operator(\)) + operator(()ident(cond)operator([)integer(0)operator(,) integer(1)operator(]) operator(==) string<delimiter(')content(()delimiter(')> operator(&&) ident(cond)operator([)integer(-1)operator(,) integer(1)operator(]) operator(==) string<delimiter(')content(\))delimiter(')>operator(\)) operator(?) ident(cond) operator(:) string<delimiter(")content(()inline<inline_delimiter(#{)ident(cond)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + string<delimiter(")content(()inline<inline_delimiter(#{)ident(conds)operator(.)ident(join)operator(()string<delimiter(')content( || )delimiter(')>operator(\))inline_delimiter(})>content(\))delimiter(")> + reserved(when) pre_constant(true) reserved(then) ident(expression) + reserved(when) pre_constant(nil) reserved(then) string<delimiter(")content(! )inline<inline_delimiter(#{)ident(expression)inline_delimiter(})>delimiter(")> + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Valid criteria are strings, regular expressions, true, or nil)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Component) comment(#:nodoc:) + reserved(def) method(dynamic?)operator(()operator(\)) pre_constant(false) reserved(end) + reserved(def) method(optional?)operator(()operator(\)) pre_constant(false) reserved(end) + + reserved(def) method(key)operator(()operator(\)) pre_constant(nil) reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(new)operator(()ident(string)operator(,) operator(*)ident(args)operator(\)) + reserved(return) reserved(super)operator(()ident(string)operator(,) operator(*)ident(args)operator(\)) reserved(unless) pre_constant(self) operator(==) constant(Component) + reserved(case) ident(string) + reserved(when) string<delimiter(')content(:controller)delimiter(')> reserved(then) constant(ControllerComponent)operator(.)ident(new)operator(()symbol(:controller)operator(,) operator(*)ident(args)operator(\)) + reserved(when) regexp<delimiter(/)content(^:()char(\\w)content(+\)$)delimiter(/)> reserved(then) constant(DynamicComponent)operator(.)ident(new)operator(()global_variable($1)operator(,) operator(*)ident(args)operator(\)) + reserved(when) regexp<delimiter(/)content(^)char(\\*)content(()char(\\w)content(+\)$)delimiter(/)> reserved(then) constant(PathComponent)operator(.)ident(new)operator(()global_variable($1)operator(,) operator(*)ident(args)operator(\)) + reserved(else) constant(StaticComponent)operator(.)ident(new)operator(()ident(string)operator(,) operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(StaticComponent) operator(<) constant(Component) comment(#:nodoc:) + ident(attr_reader) symbol(:value) + + reserved(def) method(initialize)operator(()ident(value)operator(\)) + instance_variable(@value) operator(=) ident(value) + reserved(end) + + reserved(def) method(write_recognition)operator(()ident(g)operator(\)) + ident(g)operator(.)ident(if_next_matches)operator(()ident(value)operator(\)) reserved(do) operator(|)ident(gp)operator(|) + ident(gp)operator(.)ident(move_forward) operator({)operator(|)ident(gpp)operator(|) ident(gpp)operator(.)ident(continue)operator(}) + reserved(end) + reserved(end) + + reserved(def) method(write_generation)operator(()ident(g)operator(\)) + ident(g)operator(.)ident(add_segment)operator(()ident(value)operator(\)) operator({)operator(|)ident(gp)operator(|) ident(gp)operator(.)ident(continue) operator(}) + reserved(end) + reserved(end) + + reserved(class) class(DynamicComponent) operator(<) constant(Component) comment(#:nodoc:) + ident(attr_reader) symbol(:key)operator(,) symbol(:default) + ident(attr_accessor) symbol(:condition) + + reserved(def) method(dynamic?)operator(()operator(\)) pre_constant(true) reserved(end) + reserved(def) method(optional?)operator(()operator(\)) instance_variable(@optional) reserved(end) + + reserved(def) method(default=)operator(()ident(default)operator(\)) + instance_variable(@optional) operator(=) pre_constant(true) + instance_variable(@default) operator(=) ident(default) + reserved(end) + + reserved(def) method(initialize)operator(()ident(key)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@key) operator(=) ident(key)operator(.)ident(to_sym) + instance_variable(@optional) operator(=) pre_constant(false) + ident(default)operator(,) instance_variable(@condition) operator(=) ident(options)operator([)symbol(:default)operator(])operator(,) ident(options)operator([)symbol(:condition)operator(]) + pre_constant(self)operator(.)ident(default) operator(=) ident(default) reserved(if) ident(options)operator(.)ident(key?)operator(()symbol(:default)operator(\)) + reserved(end) + + reserved(def) method(default_check)operator(()ident(g)operator(\)) + ident(presence) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) operator(!)operator(!) ident(default)operator(\))inline_delimiter(})>delimiter(")> + reserved(if) ident(default) + string<delimiter(")content(!()inline<inline_delimiter(#{)ident(presence)inline_delimiter(})>content( && )inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(false)operator(\))inline_delimiter(})>content( != )inline<inline_delimiter(#{)ident(default)operator(.)ident(to_s)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> + reserved(else) + string<delimiter(")content(! )inline<inline_delimiter(#{)ident(presence)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(write_generation)operator(()ident(g)operator(\)) + ident(wrote_dropout) operator(=) ident(write_dropout_generation)operator(()ident(g)operator(\)) + ident(write_continue_generation)operator(()ident(g)operator(,) ident(wrote_dropout)operator(\)) + reserved(end) + + reserved(def) method(write_dropout_generation)operator(()ident(g)operator(\)) + reserved(return) pre_constant(false) reserved(unless) ident(optional?) operator(&&) ident(g)operator(.)ident(after)operator(.)ident(all?) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(optional?)operator(}) + + ident(check) operator(=) operator([)ident(default_check)operator(()ident(g)operator(\))operator(]) + ident(gp) operator(=) ident(g)operator(.)ident(dup) comment(# Use another generator to write the conditions after the first &&) + comment(# We do this to ensure that the generator will not assume x_value is set. It will) + comment(# not be set if it follows a false condition -- for example, false && (x = 2\)) + + ident(check) operator(+=) ident(gp)operator(.)ident(after)operator(.)ident(map) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(default_check) ident(gp)operator(}) + ident(gp)operator(.)ident(if)operator(()ident(check)operator(.)ident(join)operator(()string<delimiter(')content( && )delimiter(')>operator(\))operator(\)) operator({) ident(gp)operator(.)ident(finish) operator(}) comment(# If this condition is met, we stop here) + pre_constant(true) + reserved(end) + + reserved(def) method(write_continue_generation)operator(()ident(g)operator(,) ident(use_else)operator(\)) + ident(test) operator(=) constant(Routing)operator(.)ident(test_condition)operator(()ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(,) ident(default)operator(\))operator(,) ident(condition) operator(||) pre_constant(true)operator(\)) + ident(check) operator(=) operator(()ident(use_else) operator(&&) ident(condition)operator(.)ident(nil?) operator(&&) ident(default)operator(\)) operator(?) operator([)symbol(:else)operator(]) operator(:) operator([)ident(use_else) operator(?) symbol(:elsif) operator(:) symbol(:if)operator(,) ident(test)operator(]) + + ident(g)operator(.)ident(send)operator(()operator(*)ident(check)operator(\)) reserved(do) operator(|)ident(gp)operator(|) + ident(gp)operator(.)ident(expire_for_keys)operator(()ident(key)operator(\)) reserved(unless) ident(gp)operator(.)ident(after)operator(.)ident(empty?) + ident(add_segments_to)operator(()ident(gp)operator(\)) operator({)operator(|)ident(gpp)operator(|) ident(gpp)operator(.)ident(continue)operator(}) + reserved(end) + reserved(end) + + reserved(def) method(add_segments_to)operator(()ident(g)operator(\)) + ident(g)operator(.)ident(add_segment)operator(()string<delimiter(%()char(\\#)content({CGI.escape)nesting_delimiter(()inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(,) ident(default)operator(\))inline_delimiter(})>nesting_delimiter(\))content(})delimiter(\))>operator(\)) operator({)operator(|)ident(gp)operator(|) reserved(yield) ident(gp)operator(}) + reserved(end) + + reserved(def) method(recognition_check)operator(()ident(g)operator(\)) + ident(test_type) operator(=) operator([)pre_constant(true)operator(,) pre_constant(nil)operator(])operator(.)ident(include?)operator(()ident(condition)operator(\)) operator(?) symbol(:presence) operator(:) symbol(:constraint) + + ident(prefix) operator(=) ident(condition)operator(.)ident(is_a?)operator(()constant(Regexp)operator(\)) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(g)operator(.)ident(next_segment)operator(()pre_constant(true)operator(\))inline_delimiter(})>content( && )delimiter(")> operator(:) string<delimiter(')delimiter(')> + ident(check) operator(=) ident(prefix) operator(+) constant(Routing)operator(.)ident(test_condition)operator(()ident(g)operator(.)ident(next_segment)operator(()pre_constant(true)operator(\))operator(,) ident(condition) operator(||) pre_constant(true)operator(\)) + + ident(g)operator(.)ident(if)operator(()ident(check)operator(\)) operator({)operator(|)ident(gp)operator(|) reserved(yield) ident(gp)operator(,) ident(test_type)operator(}) + reserved(end) + + reserved(def) method(write_recognition)operator(()ident(g)operator(\)) + ident(test_type) operator(=) pre_constant(nil) + ident(recognition_check)operator(()ident(g)operator(\)) reserved(do) operator(|)ident(gp)operator(,) ident(test_type)operator(|) + ident(assign_result)operator(()ident(gp)operator(\)) operator({)operator(|)ident(gpp)operator(|) ident(gpp)operator(.)ident(continue)operator(}) + reserved(end) + + reserved(if) ident(optional?) operator(&&) ident(g)operator(.)ident(after)operator(.)ident(all?) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(optional?)operator(}) + ident(call) operator(=) operator(()ident(test_type) operator(==) symbol(:presence)operator(\)) operator(?) operator([)symbol(:else)operator(]) operator(:) operator([)symbol(:elsif)operator(,) string<delimiter(")content(! )inline<inline_delimiter(#{)ident(g)operator(.)ident(next_segment)operator(()pre_constant(true)operator(\))inline_delimiter(})>delimiter(")>operator(]) + + ident(g)operator(.)ident(send)operator(()operator(*)ident(call)operator(\)) reserved(do) operator(|)ident(gp)operator(|) + ident(assign_default)operator(()ident(gp)operator(\)) + ident(gp)operator(.)ident(after)operator(.)ident(each) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(assign_default)operator(()ident(gp)operator(\))operator(}) + ident(gp)operator(.)ident(finish)operator(()pre_constant(false)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(assign_result)operator(()ident(g)operator(,) ident(with_default) operator(=) pre_constant(false)operator(\)) + ident(g)operator(.)ident(result) ident(key)operator(,) string<delimiter(")content(CGI.unescape()inline<inline_delimiter(#{)ident(g)operator(.)ident(next_segment)operator(()pre_constant(true)operator(,) ident(with_default) operator(?) ident(default) operator(:) pre_constant(nil)operator(\))inline_delimiter(})>content(\))delimiter(")> + ident(g)operator(.)ident(move_forward) operator({)operator(|)ident(gp)operator(|) reserved(yield) ident(gp)operator(}) + reserved(end) + + reserved(def) method(assign_default)operator(()ident(g)operator(\)) + ident(g)operator(.)ident(constant_result) ident(key)operator(,) ident(default) reserved(unless) ident(default)operator(.)ident(nil?) + reserved(end) + reserved(end) + + reserved(class) class(ControllerComponent) operator(<) constant(DynamicComponent) comment(#:nodoc:) + reserved(def) method(key)operator(()operator(\)) symbol(:controller) reserved(end) + + reserved(def) method(add_segments_to)operator(()ident(g)operator(\)) + ident(g)operator(.)ident(add_segment)operator(()string<delimiter(%()char(\\#)content({)inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(,) ident(default)operator(\))inline_delimiter(})>content(})delimiter(\))>operator(\)) operator({)operator(|)ident(gp)operator(|) reserved(yield) ident(gp)operator(}) + reserved(end) + + reserved(def) method(recognition_check)operator(()ident(g)operator(\)) + ident(g) operator(<<) string<delimiter(")content(controller_result = ::ActionController::Routing::ControllerComponent.traverse_to_controller()inline<inline_delimiter(#{)ident(g)operator(.)ident(path_name)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(g)operator(.)ident(index_name)inline_delimiter(})>content(\))delimiter(")> + ident(g)operator(.)ident(if)operator(()string<delimiter(')content(controller_result)delimiter(')>operator(\)) reserved(do) operator(|)ident(gp)operator(|) + ident(gp) operator(<<) string<delimiter(')content(controller_value, segments_to_controller = controller_result)delimiter(')> + reserved(if) ident(condition) + ident(gp) operator(<<) string<delimiter(")content(controller_path = )inline<inline_delimiter(#{)ident(gp)operator(.)ident(path_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(gp)operator(.)ident(index_name)inline_delimiter(})>content(,segments_to_controller].join('/'\))delimiter(")> + ident(gp)operator(.)ident(if)operator(()constant(Routing)operator(.)ident(test_condition)operator(()string<delimiter(")content(controller_path)delimiter(")>operator(,) ident(condition)operator(\))operator(\)) reserved(do) operator(|)ident(gpp)operator(|) + ident(gpp)operator(.)ident(move_forward)operator(()string<delimiter(')content(segments_to_controller)delimiter(')>operator(\)) operator({)operator(|)ident(gppp)operator(|) reserved(yield) ident(gppp)operator(,) symbol(:constraint)operator(}) + reserved(end) + reserved(else) + ident(gp)operator(.)ident(move_forward)operator(()string<delimiter(')content(segments_to_controller)delimiter(')>operator(\)) operator({)operator(|)ident(gpp)operator(|) reserved(yield) ident(gpp)operator(,) symbol(:constraint)operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(assign_result)operator(()ident(g)operator(\)) + ident(g)operator(.)ident(result) ident(key)operator(,) string<delimiter(')content(controller_value)delimiter(')> + reserved(yield) ident(g) + reserved(end) + + reserved(def) method(assign_default)operator(()ident(g)operator(\)) + constant(ControllerComponent)operator(.)ident(assign_controller)operator(()ident(g)operator(,) ident(default)operator(\)) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(def) method(assign_controller)operator(()ident(g)operator(,) ident(controller)operator(\)) + ident(expr) operator(=) string<delimiter(")content(::)inline<inline_delimiter(#{)ident(controller)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator(.)ident(collect) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(camelize)operator(})operator(.)ident(join)operator(()string<delimiter(')content(::)delimiter(')>operator(\))inline_delimiter(})>content(Controller)delimiter(")> + ident(g)operator(.)ident(result) symbol(:controller)operator(,) ident(expr)operator(,) pre_constant(true) + reserved(end) + + reserved(def) method(traverse_to_controller)operator(()ident(segments)operator(,) ident(start_at) operator(=) integer(0)operator(\)) + ident(mod) operator(=) operator(::)constant(Object) + ident(length) operator(=) ident(segments)operator(.)ident(length) + ident(index) operator(=) ident(start_at) + ident(mod_name) operator(=) ident(controller_name) operator(=) ident(segment) operator(=) pre_constant(nil) + reserved(while) ident(index) operator(<) ident(length) + reserved(return) pre_constant(nil) reserved(unless) regexp<delimiter(/)char(\\A)content([A-Za-z][A-Za-z)char(\\d)content(_]*)char(\\Z)delimiter(/)> operator(=)operator(~) operator(()ident(segment) operator(=) ident(segments)operator([)ident(index)operator(])operator(\)) + ident(index) operator(+=) integer(1) + + ident(mod_name) operator(=) ident(segment)operator(.)ident(camelize) + ident(controller_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(mod_name)inline_delimiter(})>content(Controller)delimiter(")> + ident(path_suffix) operator(=) constant(File)operator(.)ident(join)operator(()ident(segments)operator([)ident(start_at)operator(..)operator(()ident(index) operator(-) integer(1)operator(\))operator(])operator(\)) + ident(next_mod) operator(=) pre_constant(nil) + + comment(# If the controller is already present, or if we load it, return it.) + reserved(if) ident(mod)operator(.)ident(const_defined?)operator(()ident(controller_name)operator(\)) operator(||) ident(attempt_load)operator(()ident(mod)operator(,) ident(controller_name)operator(,) ident(path_suffix) operator(+) string<delimiter(")content(_controller)delimiter(")>operator(\)) operator(==) symbol(:defined) + ident(controller) operator(=) ident(mod)operator(.)ident(const_get)operator(()ident(controller_name)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(controller)operator(.)ident(is_a?)operator(()constant(Class)operator(\)) operator(&&) ident(controller)operator(.)ident(ancestors)operator(.)ident(include?)operator(()constant(ActionController)operator(::)constant(Base)operator(\)) comment(# it's not really a controller?) + reserved(return) operator([)ident(controller)operator(,) operator(()ident(index) operator(-) ident(start_at)operator(\))operator(]) + reserved(end) + + comment(# No controller? Look for the module) + reserved(if) ident(mod)operator(.)ident(const_defined?) ident(mod_name) + ident(next_mod) operator(=) ident(mod)operator(.)ident(send)operator(()symbol(:const_get)operator(,) ident(mod_name)operator(\)) + ident(next_mod) operator(=) pre_constant(nil) reserved(unless) ident(next_mod)operator(.)ident(is_a?)operator(()constant(Module)operator(\)) + reserved(else) + comment(# Try to load a file that defines the module we want.) + reserved(case) ident(attempt_load)operator(()ident(mod)operator(,) ident(mod_name)operator(,) ident(path_suffix)operator(\)) + reserved(when) symbol(:defined) reserved(then) ident(next_mod) operator(=) ident(mod)operator(.)ident(const_get) ident(mod_name) + reserved(when) symbol(:dir) reserved(then) comment(# We didn't find a file, but there's a dir.) + ident(next_mod) operator(=) constant(Module)operator(.)ident(new) comment(# So create a module for the directory) + ident(mod)operator(.)ident(send) symbol(:const_set)operator(,) ident(mod_name)operator(,) ident(next_mod) + reserved(else) + reserved(return) pre_constant(nil) + reserved(end) + reserved(end) + ident(mod) operator(=) ident(next_mod) + + reserved(return) pre_constant(nil) reserved(unless) ident(mod) operator(&&) ident(mod)operator(.)ident(is_a?)operator(()constant(Module)operator(\)) + reserved(end) + pre_constant(nil) + reserved(end) + + ident(protected) + reserved(def) method(safe_load_paths) comment(#:nodoc:) + reserved(if) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) + global_variable($LOAD_PATH)operator(.)ident(select) reserved(do) operator(|)ident(base)operator(|) + ident(base) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(base)operator(\)) + ident(extended_root) operator(=) constant(File)operator(.)ident(expand_path)operator(()constant(RAILS_ROOT)operator(\)) + comment(# Exclude all paths that are not nested within app, lib, or components.) + ident(base)operator(.)ident(match)operator(()regexp<delimiter(/)char(\\A)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(escape)operator(()ident(extended_root)operator(\))inline_delimiter(})>char(\\/)content(*(app|lib|components\))char(\\/)content([a-z])delimiter(/)>operator(\)) operator(||) ident(base) operator(=)operator(~) regexp<delimiter(%r{)content(rails-[)char(\\d)content(.]+/builtin)delimiter(})> + reserved(end) + reserved(else) + global_variable($LOAD_PATH) + reserved(end) + reserved(end) + + reserved(def) method(attempt_load)operator(()ident(mod)operator(,) ident(const_name)operator(,) ident(path)operator(\)) + ident(has_dir) operator(=) pre_constant(false) + ident(safe_load_paths)operator(.)ident(each) reserved(do) operator(|)ident(load_path)operator(|) + ident(full_path) operator(=) constant(File)operator(.)ident(join)operator(()ident(load_path)operator(,) ident(path)operator(\)) + ident(file_path) operator(=) ident(full_path) operator(+) string<delimiter(')content(.rb)delimiter(')> + reserved(if) constant(File)operator(.)ident(file?)operator(()ident(file_path)operator(\)) comment(# Found a .rb file? Load it up) + ident(require_dependency)operator(()ident(file_path)operator(\)) + reserved(return) symbol(:defined) reserved(if) ident(mod)operator(.)ident(const_defined?) ident(const_name) + reserved(else) + ident(has_dir) operator(||=) constant(File)operator(.)ident(directory?)operator(()ident(full_path)operator(\)) + reserved(end) + reserved(end) + reserved(return) operator(()ident(has_dir) operator(?) symbol(:dir) operator(:) pre_constant(nil)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(PathComponent) operator(<) constant(DynamicComponent) comment(#:nodoc:) + reserved(def) method(optional?)operator(()operator(\)) pre_constant(true) reserved(end) + reserved(def) method(default)operator(()operator(\)) operator([)operator(]) reserved(end) + reserved(def) method(condition)operator(()operator(\)) pre_constant(nil) reserved(end) + + reserved(def) method(default=)operator(()ident(value)operator(\)) + ident(raise) constant(RoutingError)operator(,) string<delimiter(")content(All path components have an implicit default of [])delimiter(")> reserved(unless) ident(value) operator(==) operator([)operator(]) + reserved(end) + + reserved(def) method(write_generation)operator(()ident(g)operator(\)) + ident(raise) constant(RoutingError)operator(,) string<delimiter(')content(Path components must occur last)delimiter(')> reserved(unless) ident(g)operator(.)ident(after)operator(.)ident(empty?) + ident(g)operator(.)ident(if)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\))inline_delimiter(})>content( && ! )inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\))inline_delimiter(})>content(.empty?)delimiter(")>operator(\)) reserved(do) + ident(g) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\))inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\))inline_delimiter(})>content(.join('/'\) unless )inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\))inline_delimiter(})>content(.is_a?(String\))delimiter(")> + ident(g)operator(.)ident(add_segment)operator(()string<delimiter(")char(\\#)content({CGI.escape_skipping_slashes()inline<inline_delimiter(#{)ident(g)operator(.)ident(hash_value)operator(()ident(key)operator(,) pre_constant(true)operator(\))inline_delimiter(})>content(\)})delimiter(")>operator(\)) operator({)operator(|)ident(gp)operator(|) ident(gp)operator(.)ident(finish) operator(}) + reserved(end) + ident(g)operator(.)ident(else) operator({) ident(g)operator(.)ident(finish) operator(}) + reserved(end) + + reserved(def) method(write_recognition)operator(()ident(g)operator(\)) + ident(raise) constant(RoutingError)operator(,) string<delimiter(")content(Path components must occur last)delimiter(")> reserved(unless) ident(g)operator(.)ident(after)operator(.)ident(empty?) + + ident(start) operator(=) ident(g)operator(.)ident(index_name) + ident(start) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(start)inline_delimiter(})>content(\))delimiter(")> reserved(unless) regexp<delimiter(/)content(^)char(\\w)content(+$)delimiter(/)> operator(=)operator(~) ident(start) + + ident(value_expr) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(g)operator(.)ident(path_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(start)inline_delimiter(})>content(..-1] || [])delimiter(")> + ident(g)operator(.)ident(result) ident(key)operator(,) string<delimiter(")content(ActionController::Routing::PathComponent::Result.new_escaped()inline<inline_delimiter(#{)ident(value_expr)inline_delimiter(})>content(\))delimiter(")> + ident(g)operator(.)ident(finish)operator(()pre_constant(false)operator(\)) + reserved(end) + + reserved(class) class(Result) operator(<) operator(::)constant(Array) comment(#:nodoc:) + reserved(def) method(to_s)operator(()operator(\)) ident(join) string<delimiter(')content(/)delimiter(')> reserved(end) + reserved(def) pre_constant(self)operator(.)ident(new_escaped)operator(()ident(strings)operator(\)) + ident(new) ident(strings)operator(.)ident(collect) operator({)operator(|)ident(str)operator(|) constant(CGI)operator(.)ident(unescape) ident(str)operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Route) comment(#:nodoc:) + ident(attr_accessor) symbol(:components)operator(,) symbol(:known) + ident(attr_reader) symbol(:path)operator(,) symbol(:options)operator(,) symbol(:keys)operator(,) symbol(:defaults) + + reserved(def) method(initialize)operator(()ident(path)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@path)operator(,) instance_variable(@options) operator(=) ident(path)operator(,) ident(options) + + ident(initialize_components) ident(path) + ident(defaults)operator(,) ident(conditions) operator(=) ident(initialize_hashes) ident(options)operator(.)ident(dup) + instance_variable(@defaults) operator(=) ident(defaults)operator(.)ident(dup) + ident(configure_components)operator(()ident(defaults)operator(,) ident(conditions)operator(\)) + ident(add_default_requirements) + ident(initialize_keys) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(path)operator(.)ident(inspect)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(options)operator(.)ident(inspect)operator([)integer(1)operator(..)integer(-1)operator(])inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(write_generation)operator(()ident(generator) operator(=) constant(CodeGeneration)operator(::)constant(GenerationGenerator)operator(.)ident(new)operator(\)) + ident(generator)operator(.)ident(before)operator(,) ident(generator)operator(.)ident(current)operator(,) ident(generator)operator(.)ident(after) operator(=) operator([)operator(])operator(,) ident(components)operator(.)ident(first)operator(,) operator(()ident(components)operator([)integer(1)operator(..)integer(-1)operator(]) operator(||) operator([)operator(])operator(\)) + + reserved(if) ident(known)operator(.)ident(empty?) reserved(then) ident(generator)operator(.)ident(go) + reserved(else) + comment(# Alter the conditions to allow :action => 'index' to also catch :action => nil) + ident(altered_known) operator(=) ident(known)operator(.)ident(collect) reserved(do) operator(|)ident(k)operator(,) ident(v)operator(|) + reserved(if) ident(k) operator(==) symbol(:action) operator(&&) ident(v)operator(==) string<delimiter(')content(index)delimiter(')> reserved(then) operator([)ident(k)operator(,) operator([)pre_constant(nil)operator(,) string<delimiter(')content(index)delimiter(')>operator(])operator(]) + reserved(else) operator([)ident(k)operator(,) ident(v)operator(]) + reserved(end) + reserved(end) + ident(generator)operator(.)ident(if)operator(()ident(generator)operator(.)ident(check_conditions)operator(()ident(altered_known)operator(\))operator(\)) operator({)operator(|)ident(gp)operator(|) ident(gp)operator(.)ident(go) operator(}) + reserved(end) + + ident(generator) + reserved(end) + + reserved(def) method(write_recognition)operator(()ident(generator) operator(=) constant(CodeGeneration)operator(::)constant(RecognitionGenerator)operator(.)ident(new)operator(\)) + ident(g) operator(=) ident(generator)operator(.)ident(dup) + ident(g)operator(.)ident(share_locals_with) ident(generator) + ident(g)operator(.)ident(before)operator(,) ident(g)operator(.)ident(current)operator(,) ident(g)operator(.)ident(after) operator(=) operator([)operator(])operator(,) ident(components)operator(.)ident(first)operator(,) operator(()ident(components)operator([)integer(1)operator(..)integer(-1)operator(]) operator(||) operator([)operator(])operator(\)) + + ident(known)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) ident(key) operator(==) symbol(:controller) reserved(then) constant(ControllerComponent)operator(.)ident(assign_controller)operator(()ident(g)operator(,) ident(value)operator(\)) + reserved(else) ident(g)operator(.)ident(constant_result)operator(()ident(key)operator(,) ident(value)operator(\)) + reserved(end) + reserved(end) + + ident(g)operator(.)ident(go) + + ident(generator) + reserved(end) + + reserved(def) method(initialize_keys) + instance_variable(@keys) operator(=) operator(()ident(components)operator(.)ident(collect) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(key)operator(}) operator(+) ident(known)operator(.)ident(keys)operator(\))operator(.)ident(compact) + instance_variable(@keys)operator(.)ident(freeze) + reserved(end) + + reserved(def) method(extra_keys)operator(()ident(options)operator(\)) + ident(options)operator(.)ident(keys) operator(-) instance_variable(@keys) + reserved(end) + + reserved(def) method(matches_controller?)operator(()ident(controller)operator(\)) + reserved(if) ident(known)operator([)symbol(:controller)operator(]) reserved(then) ident(known)operator([)symbol(:controller)operator(]) operator(==) ident(controller) + reserved(else) + ident(c) operator(=) ident(components)operator(.)ident(find) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(key) operator(==) symbol(:controller)operator(}) + reserved(return) pre_constant(false) reserved(unless) ident(c) + reserved(return) ident(c)operator(.)ident(condition)operator(.)ident(nil?) operator(||) ident(eval)operator(()constant(Routing)operator(.)ident(test_condition)operator(()string<delimiter(')content(controller)delimiter(')>operator(,) ident(c)operator(.)ident(condition)operator(\))operator(\)) + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(initialize_components)operator(()ident(path)operator(\)) + ident(path) operator(=) ident(path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) reserved(if) ident(path)operator(.)ident(is_a?) constant(String) + ident(path)operator(.)ident(shift) reserved(if) ident(path)operator(.)ident(first)operator(.)ident(blank?) + pre_constant(self)operator(.)ident(components) operator(=) ident(path)operator(.)ident(collect) operator({)operator(|)ident(str)operator(|) constant(Component)operator(.)ident(new) ident(str)operator(}) + reserved(end) + + reserved(def) method(initialize_hashes)operator(()ident(options)operator(\)) + ident(path_keys) operator(=) ident(components)operator(.)ident(collect) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(key) operator(})operator(.)ident(compact) + pre_constant(self)operator(.)ident(known) operator(=) operator({)operator(}) + ident(defaults) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:defaults)operator(\)) operator(||) operator({)operator(}) + ident(conditions) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:require)operator(\)) operator(||) operator({)operator(}) + ident(conditions)operator(.)ident(update)operator(()ident(options)operator(.)ident(delete)operator(()symbol(:requirements)operator(\)) operator(||) operator({)operator(})operator(\)) + + ident(options)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,) ident(v)operator(|) + reserved(if) ident(path_keys)operator(.)ident(include?)operator(()ident(k)operator(\)) reserved(then) operator(()ident(v)operator(.)ident(is_a?)operator(()constant(Regexp)operator(\)) operator(?) ident(conditions) operator(:) ident(defaults)operator(\))operator([)ident(k)operator(]) operator(=) ident(v) + reserved(else) ident(known)operator([)ident(k)operator(]) operator(=) ident(v) + reserved(end) + reserved(end) + operator([)ident(defaults)operator(,) ident(conditions)operator(]) + reserved(end) + + reserved(def) method(configure_components)operator(()ident(defaults)operator(,) ident(conditions)operator(\)) + ident(components)operator(.)ident(each) reserved(do) operator(|)ident(component)operator(|) + reserved(if) ident(defaults)operator(.)ident(key?)operator(()ident(component)operator(.)ident(key)operator(\)) reserved(then) ident(component)operator(.)ident(default) operator(=) ident(defaults)operator([)ident(component)operator(.)ident(key)operator(]) + reserved(elsif) ident(component)operator(.)ident(key) operator(==) symbol(:action) reserved(then) ident(component)operator(.)ident(default) operator(=) string<delimiter(')content(index)delimiter(')> + reserved(elsif) ident(component)operator(.)ident(key) operator(==) symbol(:id) reserved(then) ident(component)operator(.)ident(default) operator(=) pre_constant(nil) + reserved(end) + + ident(component)operator(.)ident(condition) operator(=) ident(conditions)operator([)ident(component)operator(.)ident(key)operator(]) reserved(if) ident(conditions)operator(.)ident(key?)operator(()ident(component)operator(.)ident(key)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(add_default_requirements) + ident(component_keys) operator(=) ident(components)operator(.)ident(collect) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(key)operator(}) + ident(known)operator([)symbol(:action)operator(]) operator(||=) string<delimiter(')content(index)delimiter(')> reserved(unless) ident(component_keys)operator(.)ident(include?) symbol(:action) + reserved(end) + reserved(end) + + reserved(class) class(RouteSet) comment(#:nodoc:) + ident(attr_reader) symbol(:routes)operator(,) symbol(:categories)operator(,) symbol(:controller_to_selector) + reserved(def) method(initialize) + instance_variable(@routes) operator(=) operator([)operator(]) + instance_variable(@generation_methods) operator(=) constant(Hash)operator(.)ident(new)operator(()symbol(:generate_default_path)operator(\)) + reserved(end) + + reserved(def) method(generate)operator(()ident(options)operator(,) ident(request_or_recall_hash) operator(=) operator({)operator(})operator(\)) + ident(recall) operator(=) ident(request_or_recall_hash)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(request_or_recall_hash) operator(:) ident(request_or_recall_hash)operator(.)ident(symbolized_path_parameters) + ident(use_recall) operator(=) pre_constant(true) + + ident(controller) operator(=) ident(options)operator([)symbol(:controller)operator(]) + ident(options)operator([)symbol(:action)operator(]) operator(||=) string<delimiter(')content(index)delimiter(')> reserved(if) ident(controller) + ident(recall_controller) operator(=) ident(recall)operator([)symbol(:controller)operator(]) + reserved(if) operator(()ident(recall_controller) operator(&&) ident(recall_controller)operator(.)ident(include?)operator(()integer(?/)operator(\))operator(\)) operator(||) operator(()ident(controller) operator(&&) ident(controller)operator(.)ident(include?)operator(()integer(?/)operator(\))operator(\)) + ident(recall) operator(=) operator({)operator(}) reserved(if) ident(controller) operator(&&) ident(controller)operator([)integer(0)operator(]) operator(==) integer(?/) + ident(options)operator([)symbol(:controller)operator(]) operator(=) constant(Routing)operator(.)ident(controller_relative_to)operator(()ident(controller)operator(,) ident(recall_controller)operator(\)) + reserved(end) + ident(options) operator(=) ident(recall)operator(.)ident(dup) reserved(if) ident(options)operator(.)ident(empty?) comment(# XXX move to url_rewriter?) + + ident(keys_to_delete) operator(=) operator([)operator(]) + constant(Routing)operator(.)ident(treat_hash)operator(()ident(options)operator(,) ident(keys_to_delete)operator(\)) + + ident(merged) operator(=) ident(recall)operator(.)ident(merge)operator(()ident(options)operator(\)) + ident(keys_to_delete)operator(.)ident(each) operator({)operator(|)ident(key)operator(|) ident(merged)operator(.)ident(delete) ident(key)operator(}) + ident(expire_on) operator(=) constant(Routing)operator(.)ident(expiry_hash)operator(()ident(options)operator(,) ident(recall)operator(\)) + + ident(generate_path)operator(()ident(merged)operator(,) ident(options)operator(,) ident(expire_on)operator(\)) + reserved(end) + + reserved(def) method(generate_path)operator(()ident(merged)operator(,) ident(options)operator(,) ident(expire_on)operator(\)) + ident(send) instance_variable(@generation_methods)operator([)ident(merged)operator([)symbol(:controller)operator(])operator(])operator(,) ident(merged)operator(,) ident(options)operator(,) ident(expire_on) + reserved(end) + reserved(def) method(generate_default_path)operator(()operator(*)ident(args)operator(\)) + ident(write_generation) + ident(generate_default_path)operator(()operator(*)ident(args)operator(\)) + reserved(end) + + reserved(def) method(write_generation) + ident(method_sources) operator(=) operator([)operator(]) + instance_variable(@generation_methods) operator(=) constant(Hash)operator(.)ident(new)operator(()symbol(:generate_default_path)operator(\)) + ident(categorize_routes)operator(.)ident(each) reserved(do) operator(|)ident(controller)operator(,) ident(routes)operator(|) + reserved(next) reserved(unless) ident(routes)operator(.)ident(length) operator(<) instance_variable(@routes)operator(.)ident(length) + + ident(ivar) operator(=) ident(controller)operator(.)ident(gsub)operator(()string<delimiter(')content(/)delimiter(')>operator(,) string<delimiter(')content(__)delimiter(')>operator(\)) + ident(method_name) operator(=) string<delimiter(")content(generate_path_for_)inline<inline_delimiter(#{)ident(ivar)inline_delimiter(})>delimiter(")>operator(.)ident(to_sym) + ident(instance_variable_set) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(ivar)inline_delimiter(})>delimiter(")>operator(,) ident(routes) + ident(code) operator(=) ident(generation_code_for)operator(()ident(ivar)operator(,) ident(method_name)operator(\))operator(.)ident(to_s) + ident(method_sources) operator(<<) ident(code) + + ident(filename) operator(=) string<delimiter(")content(generated_code/routing/generation_for_controller_)inline<inline_delimiter(#{)ident(controller)inline_delimiter(})>content(.rb)delimiter(")> + ident(eval)operator(()ident(code)operator(,) pre_constant(nil)operator(,) ident(filename)operator(\)) + + instance_variable(@generation_methods)operator([)ident(controller)operator(.)ident(to_s)operator(]) operator(=) ident(method_name) + instance_variable(@generation_methods)operator([)ident(controller)operator(.)ident(to_sym)operator(]) operator(=) ident(method_name) + reserved(end) + + ident(code) operator(=) ident(generation_code_for)operator(()string<delimiter(')content(routes)delimiter(')>operator(,) string<delimiter(')content(generate_default_path)delimiter(')>operator(\))operator(.)ident(to_s) + ident(eval)operator(()ident(code)operator(,) pre_constant(nil)operator(,) string<delimiter(')content(generated_code/routing/generation.rb)delimiter(')>operator(\)) + + reserved(return) operator(()ident(method_sources) operator(<<) ident(code)operator(\)) + reserved(end) + + reserved(def) method(recognize)operator(()ident(request)operator(\)) + ident(string_path) operator(=) ident(request)operator(.)ident(path) + ident(string_path)operator(.)ident(chomp!) reserved(if) ident(string_path)operator([)integer(0)operator(]) operator(==) integer(?/) + ident(path) operator(=) ident(string_path)operator(.)ident(split) string<delimiter(')content(/)delimiter(')> + ident(path)operator(.)ident(shift) + + ident(hash) operator(=) ident(recognize_path)operator(()ident(path)operator(\)) + reserved(return) ident(recognition_failed)operator(()ident(request)operator(\)) reserved(unless) ident(hash) operator(&&) ident(hash)operator([)string<delimiter(')content(controller)delimiter(')>operator(]) + + ident(controller) operator(=) ident(hash)operator([)string<delimiter(')content(controller)delimiter(')>operator(]) + ident(hash)operator([)string<delimiter(')content(controller)delimiter(')>operator(]) operator(=) ident(controller)operator(.)ident(controller_path) + ident(request)operator(.)ident(path_parameters) operator(=) ident(hash) + ident(controller)operator(.)ident(new) + reserved(end) + reserved(alias) symbol(:recognize!) symbol(:recognize) + + reserved(def) method(recognition_failed)operator(()ident(request)operator(\)) + ident(raise) constant(ActionController)operator(::)constant(RoutingError)operator(,) string<delimiter(")content(Recognition failed for )inline<inline_delimiter(#{)ident(request)operator(.)ident(path)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(write_recognition) + ident(g) operator(=) ident(generator) operator(=) constant(CodeGeneration)operator(::)constant(RecognitionGenerator)operator(.)ident(new) + ident(g)operator(.)ident(finish_statement) operator(=) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(hash_expr)operator(|) string<delimiter(")content(return )inline<inline_delimiter(#{)ident(hash_expr)inline_delimiter(})>delimiter(")>operator(}) + + ident(g)operator(.)ident(def) string<delimiter(")content(self.recognize_path(path\))delimiter(")> reserved(do) + ident(each) reserved(do) operator(|)ident(route)operator(|) + ident(g) operator(<<) string<delimiter(')content(index = 0)delimiter(')> + ident(route)operator(.)ident(write_recognition)operator(()ident(g)operator(\)) + reserved(end) + reserved(end) + + ident(eval) ident(g)operator(.)ident(to_s)operator(,) pre_constant(nil)operator(,) string<delimiter(')content(generated/routing/recognition.rb)delimiter(')> + reserved(return) ident(g)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(generation_code_for)operator(()ident(ivar) operator(=) string<delimiter(')content(routes)delimiter(')>operator(,) ident(method_name) operator(=) pre_constant(nil)operator(\)) + ident(routes) operator(=) ident(instance_variable_get)operator(()string<delimiter(')content(@)delimiter(')> operator(+) ident(ivar)operator(\)) + ident(key_ivar) operator(=) string<delimiter(")content(@keys_for_)inline<inline_delimiter(#{)ident(ivar)inline_delimiter(})>delimiter(")> + ident(instance_variable_set)operator(()ident(key_ivar)operator(,) ident(routes)operator(.)ident(collect) operator({)operator(|)ident(route)operator(|) ident(route)operator(.)ident(keys)operator(})operator(\)) + + ident(g) operator(=) ident(generator) operator(=) constant(CodeGeneration)operator(::)constant(GenerationGenerator)operator(.)ident(new) + ident(g)operator(.)ident(def) string<delimiter(")content(self.)inline<inline_delimiter(#{)ident(method_name)inline_delimiter(})>content((merged, options, expire_on\))delimiter(")> reserved(do) + ident(g) operator(<<) string<delimiter(')content(unused_count = options.length + 1)delimiter(')> + ident(g) operator(<<) string<delimiter(")content(unused_keys = keys = options.keys)delimiter(")> + ident(g) operator(<<) string<delimiter(')content(path = nil)delimiter(')> + + ident(routes)operator(.)ident(each_with_index) reserved(do) operator(|)ident(route)operator(,) ident(index)operator(|) + ident(g) operator(<<) string<delimiter(")content(new_unused_keys = keys - )inline<inline_delimiter(#{)ident(key_ivar)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(index)inline_delimiter(})>content(])delimiter(")> + ident(g) operator(<<) string<delimiter(')content(new_path = ()delimiter(')> + ident(g)operator(.)ident(source)operator(.)ident(indent) reserved(do) + reserved(if) ident(index)operator(.)ident(zero?) + ident(g) operator(<<) string<delimiter(")content(new_unused_count = new_unused_keys.length)delimiter(")> + ident(g) operator(<<) string<delimiter(")content(hash = merged; not_expired = true)delimiter(")> + ident(route)operator(.)ident(write_generation)operator(()ident(g)operator(.)ident(dup)operator(\)) + reserved(else) + ident(g)operator(.)ident(if) string<delimiter(")content((new_unused_count = new_unused_keys.length\) < unused_count)delimiter(")> reserved(do) operator(|)ident(gp)operator(|) + ident(gp) operator(<<) string<delimiter(")content(hash = merged; not_expired = true)delimiter(")> + ident(route)operator(.)ident(write_generation)operator(()ident(gp)operator(\)) + reserved(end) + reserved(end) + reserved(end) + ident(g)operator(.)ident(source)operator(.)ident(lines)operator(.)ident(last) operator(<<) string<delimiter(')content( \))delimiter(')> comment(# Add the closing brace to the end line) + ident(g)operator(.)ident(if) string<delimiter(')content(new_path)delimiter(')> reserved(do) + ident(g) operator(<<) string<delimiter(')content(return new_path, [] if new_unused_count.zero?)delimiter(')> + ident(g) operator(<<) string<delimiter(')content(path = new_path; unused_keys = new_unused_keys; unused_count = new_unused_count)delimiter(')> + reserved(end) + reserved(end) + + ident(g) operator(<<) string<delimiter(")content(raise RoutingError, )char(\\")content(No url can be generated for the hash )char(\\#)content({options.inspect})char(\\")content( unless path)delimiter(")> + ident(g) operator(<<) string<delimiter(")content(return path, unused_keys)delimiter(")> + reserved(end) + + reserved(return) ident(g) + reserved(end) + + reserved(def) method(categorize_routes) + instance_variable(@categorized_routes) operator(=) ident(by_controller) operator(=) constant(Hash)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + + ident(known_controllers)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(set) operator(=) ident(by_controller)operator([)ident(name)operator(]) operator(=) operator([)operator(]) + ident(each) reserved(do) operator(|)ident(route)operator(|) + ident(set) operator(<<) ident(route) reserved(if) ident(route)operator(.)ident(matches_controller?) ident(name) + reserved(end) + reserved(end) + + instance_variable(@categorized_routes) + reserved(end) + + reserved(def) method(known_controllers) + instance_variable(@routes)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(known)operator(,) ident(route)operator(|) + reserved(if) operator(()ident(controller) operator(=) ident(route)operator(.)ident(known)operator([)symbol(:controller)operator(])operator(\)) + reserved(if) ident(controller)operator(.)ident(is_a?)operator(()constant(Regexp)operator(\)) + ident(known) operator(<<) ident(controller)operator(.)ident(source)operator(.)ident(scan)operator(()regexp<delimiter(%r{)content([)char(\\w)char(\\d)content(/]+)delimiter(})>operator(\))operator(.)ident(select) operator({)operator(|)ident(word)operator(|) ident(controller) operator(=)operator(~) ident(word)operator(}) + reserved(else) ident(known) operator(<<) ident(controller) + reserved(end) + reserved(end) + ident(known) + reserved(end)operator(.)ident(uniq) + reserved(end) + + reserved(def) method(reload) + constant(NamedRoutes)operator(.)ident(clear) + + reserved(if) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) reserved(then) ident(load)operator(()constant(File)operator(.)ident(join)operator(()constant(RAILS_ROOT)operator(,) string<delimiter(')content(config)delimiter(')>operator(,) string<delimiter(')content(routes.rb)delimiter(')>operator(\))operator(\)) + reserved(else) ident(connect)operator(()string<delimiter(')content(:controller/:action/:id)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) pre_constant(nil)operator(\)) + reserved(end) + + constant(NamedRoutes)operator(.)ident(install) + reserved(end) + + reserved(def) method(connect)operator(()operator(*)ident(args)operator(\)) + ident(new_route) operator(=) constant(Route)operator(.)ident(new)operator(()operator(*)ident(args)operator(\)) + instance_variable(@routes) operator(<<) ident(new_route) + reserved(return) ident(new_route) + reserved(end) + + reserved(def) method(draw) + ident(old_routes) operator(=) instance_variable(@routes) + instance_variable(@routes) operator(=) operator([)operator(]) + + reserved(begin) reserved(yield) pre_constant(self) + reserved(rescue) + instance_variable(@routes) operator(=) ident(old_routes) + ident(raise) + reserved(end) + ident(write_generation) + ident(write_recognition) + reserved(end) + + reserved(def) method(empty?)operator(()operator(\)) instance_variable(@routes)operator(.)ident(empty?) reserved(end) + + reserved(def) method(each)operator(()operator(&)ident(block)operator(\)) instance_variable(@routes)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) reserved(end) + + comment(# Defines a new named route with the provided name and arguments.) + comment(# This method need only be used when you wish to use a name that a RouteSet instance) + comment(# method exists for, such as categories.) + comment(#) + comment(# For example, map.categories '/categories', :controller => 'categories' will not work) + comment(# due to RouteSet#categories.) + reserved(def) method(named_route)operator(()ident(name)operator(,) ident(path)operator(,) ident(hash) operator(=) operator({)operator(})operator(\)) + ident(route) operator(=) ident(connect)operator(()ident(path)operator(,) ident(hash)operator(\)) + constant(NamedRoutes)operator(.)ident(name_route)operator(()ident(route)operator(,) ident(name)operator(\)) + ident(route) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) + operator(()integer(1)operator(..)integer(2)operator(\))operator(.)ident(include?)operator(()ident(args)operator(.)ident(length)operator(\)) operator(?) ident(named_route)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) operator(:) reserved(super)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) + reserved(end) + + reserved(def) method(extra_keys)operator(()ident(options)operator(,) ident(recall) operator(=) operator({)operator(})operator(\)) + ident(generate)operator(()ident(options)operator(.)ident(dup)operator(,) ident(recall)operator(\))operator(.)ident(last) + reserved(end) + reserved(end) + + reserved(module) class(NamedRoutes) comment(#:nodoc:) + constant(Helpers) operator(=) operator([)operator(]) + reserved(class) operator(<<) class(self) + reserved(def) method(clear)operator(()operator(\)) constant(Helpers)operator(.)ident(clear) reserved(end) + + reserved(def) method(hash_access_name)operator(()ident(name)operator(\)) + string<delimiter(")content(hash_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(_url)delimiter(")> + reserved(end) + + reserved(def) method(url_helper_name)operator(()ident(name)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(_url)delimiter(")> + reserved(end) + + reserved(def) method(known_hash_for_route)operator(()ident(route)operator(\)) + ident(hash) operator(=) ident(route)operator(.)ident(known)operator(.)ident(symbolize_keys) + ident(route)operator(.)ident(defaults)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + ident(hash)operator([)ident(key)operator(.)ident(to_sym)operator(]) operator(||=) ident(value) reserved(if) ident(value) + reserved(end) + ident(hash)operator([)symbol(:controller)operator(]) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(hash)operator([)symbol(:controller)operator(])inline_delimiter(})>delimiter(")> + + ident(hash) + reserved(end) + + reserved(def) method(define_hash_access_method)operator(()ident(route)operator(,) ident(name)operator(\)) + ident(hash) operator(=) ident(known_hash_for_route)operator(()ident(route)operator(\)) + ident(define_method)operator(()ident(hash_access_name)operator(()ident(name)operator(\))operator(\)) reserved(do) operator(|*)ident(args)operator(|) + ident(args)operator(.)ident(first) operator(?) ident(hash)operator(.)ident(merge)operator(()ident(args)operator(.)ident(first)operator(\)) operator(:) ident(hash) + reserved(end) + reserved(end) + + reserved(def) method(name_route)operator(()ident(route)operator(,) ident(name)operator(\)) + ident(define_hash_access_method)operator(()ident(route)operator(,) ident(name)operator(\)) + + ident(module_eval)operator(()string<delimiter(%{)content(def )inline<inline_delimiter(#{)ident(url_helper_name) ident(name)inline_delimiter(})>content((options = )nesting_delimiter({)nesting_delimiter(})content(\) + url_for()inline<inline_delimiter(#{)ident(hash_access_name)operator(()ident(name)operator(\))inline_delimiter(})>content(.merge(options\)\) + end)delimiter(})>operator(,) string<delimiter(")content(generated/routing/named_routes/)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(.rb)delimiter(")>operator(\)) + + ident(protected) ident(url_helper_name)operator(()ident(name)operator(\))operator(,) ident(hash_access_name)operator(()ident(name)operator(\)) + + constant(Helpers) operator(<<) ident(url_helper_name)operator(()ident(name)operator(\))operator(.)ident(to_sym) + constant(Helpers) operator(<<) ident(hash_access_name)operator(()ident(name)operator(\))operator(.)ident(to_sym) + constant(Helpers)operator(.)ident(uniq!) + reserved(end) + + reserved(def) method(install)operator(()ident(cls) operator(=) constant(ActionController)operator(::)constant(Base)operator(\)) + ident(cls)operator(.)ident(send) symbol(:include)operator(,) pre_constant(self) + reserved(if) ident(cls)operator(.)ident(respond_to?) symbol(:helper_method) + constant(Helpers)operator(.)ident(each) reserved(do) operator(|)ident(helper_name)operator(|) + ident(cls)operator(.)ident(send) symbol(:helper_method)operator(,) ident(helper_name) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + constant(Routes) operator(=) constant(RouteSet)operator(.)ident(new) + reserved(end) +reserved(end) +reserved(module) class(ActionController) + reserved(module) class(Scaffolding) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Scaffolding is a way to quickly put an Active Record class online by providing a series of standardized actions) + comment(# for listing, showing, creating, updating, and destroying objects of the class. These standardized actions come) + comment(# with both controller logic and default templates that through introspection already know which fields to display) + comment(# and which input types to use. Example:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# scaffold :entry) + comment(# end) + comment(#) + comment(# This tiny piece of code will add all of the following methods to the controller:) + comment(#) + comment(# class WeblogController < ActionController::Base) + comment(# verify :method => :post, :only => [ :destroy, :create, :update ],) + comment(# :redirect_to => { :action => :list }) + comment(#) + comment(# def index) + comment(# list) + comment(# end) + comment(#) + comment(# def list) + comment(# @entries = Entry.find_all) + comment(# render_scaffold "list") + comment(# end) + comment(# ) + comment(# def show) + comment(# @entry = Entry.find(params[:id]\)) + comment(# render_scaffold) + comment(# end) + comment(# ) + comment(# def destroy) + comment(# Entry.find(params[:id]\).destroy) + comment(# redirect_to :action => "list") + comment(# end) + comment(# ) + comment(# def new) + comment(# @entry = Entry.new) + comment(# render_scaffold) + comment(# end) + comment(# ) + comment(# def create) + comment(# @entry = Entry.new(params[:entry]\)) + comment(# if @entry.save) + comment(# flash[:notice] = "Entry was successfully created") + comment(# redirect_to :action => "list") + comment(# else) + comment(# render_scaffold('new'\)) + comment(# end) + comment(# end) + comment(# ) + comment(# def edit) + comment(# @entry = Entry.find(params[:id]\)) + comment(# render_scaffold) + comment(# end) + comment(# ) + comment(# def update) + comment(# @entry = Entry.find(params[:id]\)) + comment(# @entry.attributes = params[:entry]) + comment(# ) + comment(# if @entry.save) + comment(# flash[:notice] = "Entry was successfully updated") + comment(# redirect_to :action => "show", :id => @entry) + comment(# else) + comment(# render_scaffold('edit'\)) + comment(# end) + comment(# end) + comment(# end) + comment(#) + comment(# The <tt>render_scaffold</tt> method will first check to see if you've made your own template (like "weblog/show.rhtml" for ) + comment(# the show action\) and if not, then render the generic template for that action. This gives you the possibility of using the ) + comment(# scaffold while you're building your specific application. Start out with a totally generic setup, then replace one template ) + comment(# and one action at a time while relying on the rest of the scaffolded templates and actions.) + reserved(module) class(ClassMethods) + comment(# Adds a swath of generic CRUD actions to the controller. The +model_id+ is automatically converted into a class name unless) + comment(# one is specifically provide through <tt>options[:class_name]</tt>. So <tt>scaffold :post</tt> would use Post as the class) + comment(# and @post/@posts for the instance variables.) + comment(# ) + comment(# It's possible to use more than one scaffold in a single controller by specifying <tt>options[:suffix] = true</tt>. This will) + comment(# make <tt>scaffold :post, :suffix => true</tt> use method names like list_post, show_post, and create_post ) + comment(# instead of just list, show, and post. If suffix is used, then no index method is added.) + reserved(def) method(scaffold)operator(()ident(model_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(()symbol(:class_name)operator(,) symbol(:suffix)operator(\)) + + ident(singular_name) operator(=) ident(model_id)operator(.)ident(to_s) + ident(class_name) operator(=) ident(options)operator([)symbol(:class_name)operator(]) operator(||) ident(singular_name)operator(.)ident(camelize) + ident(plural_name) operator(=) ident(singular_name)operator(.)ident(pluralize) + ident(suffix) operator(=) ident(options)operator([)symbol(:suffix)operator(]) operator(?) string<delimiter(")content(_)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>delimiter(")> operator(:) string<delimiter(")delimiter(")> + + reserved(unless) ident(options)operator([)symbol(:suffix)operator(]) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def index + list + end)delimiter( + end_eval)> + reserved(end) + + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + + verify :method => :post, :only => [ :destroy)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(, :create)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(, :update)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( ], + :redirect_to => { :action => :list)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( } + + + def list)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(_pages, @)inline<inline_delimiter(#{)ident(plural_name)inline_delimiter(})>content( = paginate :)inline<inline_delimiter(#{)ident(plural_name)inline_delimiter(})>content(, :per_page => 10 + render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold "list)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(" + end + + def show)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.find(params[:id]\) + render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold + end + + def destroy)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.find(params[:id]\).destroy + redirect_to :action => "list)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(" + end + + def new)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.new + render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold + end + + def create)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.new(params[:)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(]\) + if @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(.save + flash[:notice] = ")inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content( was successfully created" + redirect_to :action => "list)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(" + else + render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold('new'\) + end + end + + def edit)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.find(params[:id]\) + render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold + end + + def update)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content( + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.find(params[:id]\) + @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(.attributes = params[:)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(] + + if @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(.save + flash[:notice] = ")inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content( was successfully updated" + redirect_to :action => "show)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(", :id => @)inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content( + else + render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold('edit'\) + end + end + + private + def render)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(_scaffold(action=nil\) + action ||= caller_method_name(caller\) + # logger.info ("testing template:" + ")char(\\#)content({self.class.controller_path}/)char(\\#)content({action}"\) if logger + + if template_exists?(")char(\\#)content({self.class.controller_path}/)char(\\#)content({action}"\) + render_action(action\) + else + @scaffold_class = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content( + @scaffold_singular_name, @scaffold_plural_name = ")inline<inline_delimiter(#{)ident(singular_name)inline_delimiter(})>content(", ")inline<inline_delimiter(#{)ident(plural_name)inline_delimiter(})>content(" + @scaffold_suffix = ")inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content(" + add_instance_variables_to_assigns + + @template.instance_variable_set("@content_for_layout", @template.render_file(scaffold_path(action.sub(/)inline<inline_delimiter(#{)ident(suffix)inline_delimiter(})>content($/, ""\)\), false\)\) + + if !active_layout.nil? + render_file(active_layout, nil, true\) + else + render_file(scaffold_path("layout"\)\) + end + end + end + + def scaffold_path(template_name\) + File.dirname(__FILE__\) + "/templates/scaffolds/" + template_name + ".rhtml" + end + + def caller_method_name(caller\) + caller.first.scan(/`(.*\)'/\).first.first # ' ruby-mode + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(cgi/session)delimiter(')> +ident(require) string<delimiter(')content(digest/md5)delimiter(')> +ident(require) string<delimiter(')content(base64)delimiter(')> + +reserved(class) class(CGI) + reserved(class) class(Session) + comment(# Return this session's underlying Session instance. Useful for the DB-backed session stores.) + reserved(def) method(model) + instance_variable(@dbman)operator(.)ident(model) reserved(if) instance_variable(@dbman) + reserved(end) + + + comment(# A session store backed by an Active Record class. A default class is) + comment(# provided, but any object duck-typing to an Active Record +Session+ class) + comment(# with text +session_id+ and +data+ attributes is sufficient.) + comment(#) + comment(# The default assumes a +sessions+ tables with columns:) + comment(# +id+ (numeric primary key\),) + comment(# +session_id+ (text, or longtext if your session data exceeds 65K\), and) + comment(# +data+ (text or longtext; careful if your session data exceeds 65KB\).) + comment(# The +session_id+ column should always be indexed for speedy lookups.) + comment(# Session data is marshaled to the +data+ column in Base64 format.) + comment(# If the data you write is larger than the column's size limit,) + comment(# ActionController::SessionOverflowError will be raised.) + comment(#) + comment(# You may configure the table name, primary key, and data column.) + comment(# For example, at the end of config/environment.rb:) + comment(# CGI::Session::ActiveRecordStore::Session.table_name = 'legacy_session_table') + comment(# CGI::Session::ActiveRecordStore::Session.primary_key = 'session_id') + comment(# CGI::Session::ActiveRecordStore::Session.data_column_name = 'legacy_session_data') + comment(# Note that setting the primary key to the session_id frees you from) + comment(# having a separate id column if you don't want it. However, you must) + comment(# set session.model.id = session.session_id by hand! A before_filter) + comment(# on ApplicationController is a good place.) + comment(#) + comment(# Since the default class is a simple Active Record, you get timestamps) + comment(# for free if you add +created_at+ and +updated_at+ datetime columns to) + comment(# the +sessions+ table, making periodic session expiration a snap.) + comment(#) + comment(# You may provide your own session class implementation, whether a) + comment(# feature-packed Active Record or a bare-metal high-performance SQL) + comment(# store, by setting) + comment(# +CGI::Session::ActiveRecordStore.session_class = MySessionClass+) + comment(# You must implement these methods:) + comment(# self.find_by_session_id(session_id\)) + comment(# initialize(hash_of_session_id_and_data\)) + comment(# attr_reader :session_id) + comment(# attr_accessor :data) + comment(# save) + comment(# destroy) + comment(#) + comment(# The example SqlBypass class is a generic SQL session store. You may) + comment(# use it as a basis for high-performance database-specific stores.) + reserved(class) class(ActiveRecordStore) + comment(# The default Active Record class.) + reserved(class) class(Session) operator(<) constant(ActiveRecord)operator(::)constant(Base) + comment(# Customizable data column name. Defaults to 'data'.) + ident(cattr_accessor) symbol(:data_column_name) + pre_constant(self)operator(.)ident(data_column_name) operator(=) string<delimiter(')content(data)delimiter(')> + + ident(before_save) symbol(:marshal_data!) + ident(before_save) symbol(:raise_on_session_data_overflow!) + + reserved(class) operator(<<) class(self) + comment(# Don't try to reload ARStore::Session in dev mode.) + reserved(def) method(reloadable?) comment(#:nodoc:) + pre_constant(false) + reserved(end) + + reserved(def) method(data_column_size_limit) + instance_variable(@data_column_size_limit) operator(||=) ident(columns_hash)operator([)class_variable(@@data_column_name)operator(])operator(.)ident(limit) + reserved(end) + + comment(# Hook to set up sessid compatibility.) + reserved(def) method(find_by_session_id)operator(()ident(session_id)operator(\)) + ident(setup_sessid_compatibility!) + ident(find_by_session_id)operator(()ident(session_id)operator(\)) + reserved(end) + + reserved(def) method(marshal)operator(()ident(data)operator(\)) constant(Base64)operator(.)ident(encode64)operator(()constant(Marshal)operator(.)ident(dump)operator(()ident(data)operator(\))operator(\)) reserved(if) ident(data) reserved(end) + reserved(def) method(unmarshal)operator(()ident(data)operator(\)) constant(Marshal)operator(.)ident(load)operator(()constant(Base64)operator(.)ident(decode64)operator(()ident(data)operator(\))operator(\)) reserved(if) ident(data) reserved(end) + + reserved(def) method(create_table!) + ident(connection)operator(.)ident(execute) string<delimiter(<<-end_sql)>string<content( + CREATE TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ( + id INTEGER PRIMARY KEY, + )inline<inline_delimiter(#{)ident(connection)operator(.)ident(quote_column_name)operator(()string<delimiter(')content(session_id)delimiter(')>operator(\))inline_delimiter(})>content( TEXT UNIQUE, + )inline<inline_delimiter(#{)ident(connection)operator(.)ident(quote_column_name)operator(()class_variable(@@data_column_name)operator(\))inline_delimiter(})>content( TEXT(255\) + \))delimiter( + end_sql)> + reserved(end) + + reserved(def) method(drop_table!) + ident(connection)operator(.)ident(execute) string<delimiter(")content(DROP TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(private) + comment(# Compatibility with tables using sessid instead of session_id.) + reserved(def) method(setup_sessid_compatibility!) + comment(# Reset column info since it may be stale.) + ident(reset_column_information) + reserved(if) ident(columns_hash)operator([)string<delimiter(')content(sessid)delimiter(')>operator(]) + reserved(def) pre_constant(self)operator(.)ident(find_by_session_id)operator(()operator(*)ident(args)operator(\)) + ident(find_by_sessid)operator(()operator(*)ident(args)operator(\)) + reserved(end) + + ident(define_method)operator(()symbol(:session_id)operator(\)) operator({) ident(sessid) operator(}) + ident(define_method)operator(()symbol(:session_id=)operator(\)) operator({) operator(|)ident(session_id)operator(|) pre_constant(self)operator(.)ident(sessid) operator(=) ident(session_id) operator(}) + reserved(else) + reserved(def) pre_constant(self)operator(.)ident(find_by_session_id)operator(()ident(session_id)operator(\)) + ident(find) symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(session_id )inline<inline_delimiter(#{)ident(attribute_condition)operator(()ident(session_id)operator(\))inline_delimiter(})>delimiter(")>operator(,) ident(session_id)operator(]) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Lazy-unmarshal session state.) + reserved(def) method(data) + instance_variable(@data) operator(||=) pre_constant(self)operator(.)ident(class)operator(.)ident(unmarshal)operator(()ident(read_attribute)operator(()class_variable(@@data_column_name)operator(\))operator(\)) operator(||) operator({)operator(}) + reserved(end) + + comment(# Has the session been loaded yet?) + reserved(def) method(loaded?) + operator(!)operator(!) instance_variable(@data) + reserved(end) + + ident(private) + ident(attr_writer) symbol(:data) + + reserved(def) method(marshal_data!) + reserved(return) pre_constant(false) reserved(if) operator(!)ident(loaded?) + ident(write_attribute)operator(()class_variable(@@data_column_name)operator(,) pre_constant(self)operator(.)ident(class)operator(.)ident(marshal)operator(()pre_constant(self)operator(.)ident(data)operator(\))operator(\)) + reserved(end) + + comment(# Ensures that the data about to be stored in the database is not) + comment(# larger than the data storage column. Raises) + comment(# ActionController::SessionOverflowError.) + reserved(def) method(raise_on_session_data_overflow!) + reserved(return) pre_constant(false) reserved(if) operator(!)ident(loaded?) + ident(limit) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(data_column_size_limit) + reserved(if) ident(loaded?) reserved(and) ident(limit) reserved(and) ident(read_attribute)operator(()class_variable(@@data_column_name)operator(\))operator(.)ident(size) operator(>) ident(limit) + ident(raise) constant(ActionController)operator(::)constant(SessionOverflowError) + reserved(end) + reserved(end) + reserved(end) + + comment(# A barebones session store which duck-types with the default session) + comment(# store but bypasses Active Record and issues SQL directly. This is) + comment(# an example session model class meant as a basis for your own classes.) + comment(#) + comment(# The database connection, table name, and session id and data columns) + comment(# are configurable class attributes. Marshaling and unmarshaling) + comment(# are implemented as class methods that you may override. By default,) + comment(# marshaling data is +Base64.encode64(Marshal.dump(data\)\)+ and) + comment(# unmarshaling data is +Marshal.load(Base64.decode64(data\)\)+.) + comment(#) + comment(# This marshaling behavior is intended to store the widest range of) + comment(# binary session data in a +text+ column. For higher performance,) + comment(# store in a +blob+ column instead and forgo the Base64 encoding.) + reserved(class) class(SqlBypass) + comment(# Use the ActiveRecord::Base.connection by default.) + ident(cattr_accessor) symbol(:connection) + + comment(# The table name defaults to 'sessions'.) + ident(cattr_accessor) symbol(:table_name) + class_variable(@@table_name) operator(=) string<delimiter(')content(sessions)delimiter(')> + + comment(# The session id field defaults to 'session_id'.) + ident(cattr_accessor) symbol(:session_id_column) + class_variable(@@session_id_column) operator(=) string<delimiter(')content(session_id)delimiter(')> + + comment(# The data field defaults to 'data'.) + ident(cattr_accessor) symbol(:data_column) + class_variable(@@data_column) operator(=) string<delimiter(')content(data)delimiter(')> + + reserved(class) operator(<<) class(self) + + reserved(def) method(connection) + class_variable(@@connection) operator(||=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + reserved(end) + + comment(# Look up a session by id and unmarshal its data if found.) + reserved(def) method(find_by_session_id)operator(()ident(session_id)operator(\)) + reserved(if) ident(record) operator(=) class_variable(@@connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT * FROM )inline<inline_delimiter(#{)class_variable(@@table_name)inline_delimiter(})>content( WHERE )inline<inline_delimiter(#{)class_variable(@@session_id_column)inline_delimiter(})>content(=)inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote)operator(()ident(session_id)operator(\))inline_delimiter(})>delimiter(")>operator(\)) + ident(new)operator(()symbol(:session_id) operator(=)operator(>) ident(session_id)operator(,) symbol(:marshaled_data) operator(=)operator(>) ident(record)operator([)string<delimiter(')content(data)delimiter(')>operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(marshal)operator(()ident(data)operator(\)) constant(Base64)operator(.)ident(encode64)operator(()constant(Marshal)operator(.)ident(dump)operator(()ident(data)operator(\))operator(\)) reserved(if) ident(data) reserved(end) + reserved(def) method(unmarshal)operator(()ident(data)operator(\)) constant(Marshal)operator(.)ident(load)operator(()constant(Base64)operator(.)ident(decode64)operator(()ident(data)operator(\))operator(\)) reserved(if) ident(data) reserved(end) + + reserved(def) method(create_table!) + class_variable(@@connection)operator(.)ident(execute) string<delimiter(<<-end_sql)>string<content( + CREATE TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ( + id INTEGER PRIMARY KEY, + )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()ident(session_id_column)operator(\))inline_delimiter(})>content( TEXT UNIQUE, + )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()ident(data_column)operator(\))inline_delimiter(})>content( TEXT + \))delimiter( + end_sql)> + reserved(end) + + reserved(def) method(drop_table!) + class_variable(@@connection)operator(.)ident(execute) string<delimiter(")content(DROP TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + ident(attr_reader) symbol(:session_id) + ident(attr_writer) symbol(:data) + + comment(# Look for normal and marshaled data, self.find_by_session_id's way of) + comment(# telling us to postpone unmarshaling until the data is requested.) + comment(# We need to handle a normal data attribute in case of a new record.) + reserved(def) method(initialize)operator(()ident(attributes)operator(\)) + instance_variable(@session_id)operator(,) instance_variable(@data)operator(,) instance_variable(@marshaled_data) operator(=) ident(attributes)operator([)symbol(:session_id)operator(])operator(,) ident(attributes)operator([)symbol(:data)operator(])operator(,) ident(attributes)operator([)symbol(:marshaled_data)operator(]) + instance_variable(@new_record) operator(=) instance_variable(@marshaled_data)operator(.)ident(nil?) + reserved(end) + + reserved(def) method(new_record?) + instance_variable(@new_record) + reserved(end) + + comment(# Lazy-unmarshal session state.) + reserved(def) method(data) + reserved(unless) instance_variable(@data) + reserved(if) instance_variable(@marshaled_data) + instance_variable(@data)operator(,) instance_variable(@marshaled_data) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(unmarshal)operator(()instance_variable(@marshaled_data)operator(\)) operator(||) operator({)operator(})operator(,) pre_constant(nil) + reserved(else) + instance_variable(@data) operator(=) operator({)operator(}) + reserved(end) + reserved(end) + instance_variable(@data) + reserved(end) + + reserved(def) method(loaded?) + operator(!)operator(!) instance_variable(@data) + reserved(end) + + reserved(def) method(save) + reserved(return) pre_constant(false) reserved(if) operator(!)ident(loaded?) + ident(marshaled_data) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(marshal)operator(()ident(data)operator(\)) + + reserved(if) instance_variable(@new_record) + instance_variable(@new_record) operator(=) pre_constant(false) + class_variable(@@connection)operator(.)ident(update) string<delimiter(<<-end_sql)>operator(,) string<delimiter(')content(Create session)delimiter(')>string<content( + INSERT INTO )inline<inline_delimiter(#{)class_variable(@@table_name)inline_delimiter(})>content( ( + )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()class_variable(@@session_id_column)operator(\))inline_delimiter(})>content(, + )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()class_variable(@@data_column)operator(\))inline_delimiter(})>content( \) + VALUES ( + )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote)operator(()ident(session_id)operator(\))inline_delimiter(})>content(, + )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote)operator(()ident(marshaled_data)operator(\))inline_delimiter(})>content( \))delimiter( + end_sql)> + reserved(else) + class_variable(@@connection)operator(.)ident(update) string<delimiter(<<-end_sql)>operator(,) string<delimiter(')content(Update session)delimiter(')>string<content( + UPDATE )inline<inline_delimiter(#{)class_variable(@@table_name)inline_delimiter(})>content( + SET )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()class_variable(@@data_column)operator(\))inline_delimiter(})>content(=)inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote)operator(()ident(marshaled_data)operator(\))inline_delimiter(})>content( + WHERE )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()class_variable(@@session_id_column)operator(\))inline_delimiter(})>content(=)inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote)operator(()ident(session_id)operator(\))inline_delimiter(})>delimiter( + end_sql)> + reserved(end) + reserved(end) + + reserved(def) method(destroy) + reserved(unless) instance_variable(@new_record) + class_variable(@@connection)operator(.)ident(delete) string<delimiter(<<-end_sql)>operator(,) string<delimiter(')content(Destroy session)delimiter(')>string<content( + DELETE FROM )inline<inline_delimiter(#{)class_variable(@@table_name)inline_delimiter(})>content( + WHERE )inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote_column_name)operator(()class_variable(@@session_id_column)operator(\))inline_delimiter(})>content(=)inline<inline_delimiter(#{)class_variable(@@connection)operator(.)ident(quote)operator(()ident(session_id)operator(\))inline_delimiter(})>delimiter( + end_sql)> + reserved(end) + reserved(end) + reserved(end) + + + comment(# The class used for session storage. Defaults to) + comment(# CGI::Session::ActiveRecordStore::Session.) + ident(cattr_accessor) symbol(:session_class) + pre_constant(self)operator(.)ident(session_class) operator(=) constant(Session) + + comment(# Find or instantiate a session given a CGI::Session.) + reserved(def) method(initialize)operator(()ident(session)operator(,) ident(option) operator(=) pre_constant(nil)operator(\)) + ident(session_id) operator(=) ident(session)operator(.)ident(session_id) + reserved(unless) instance_variable(@session) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(silence) operator({) class_variable(@@session_class)operator(.)ident(find_by_session_id)operator(()ident(session_id)operator(\)) operator(}) + reserved(unless) ident(session)operator(.)ident(new_session) + ident(raise) constant(CGI)operator(::)constant(Session)operator(::)constant(NoSession)operator(,) string<delimiter(')content(uninitialized session)delimiter(')> + reserved(end) + instance_variable(@session) operator(=) class_variable(@@session_class)operator(.)ident(new)operator(()symbol(:session_id) operator(=)operator(>) ident(session_id)operator(,) symbol(:data) operator(=)operator(>) operator({)operator(})operator(\)) + comment(# session saving can be lazy again, because of improved component implementation) + comment(# therefore next line gets commented out:) + comment(# @session.save) + reserved(end) + reserved(end) + + comment(# Access the underlying session model.) + reserved(def) method(model) + instance_variable(@session) + reserved(end) + + comment(# Restore session state. The session model handles unmarshaling.) + reserved(def) method(restore) + reserved(if) instance_variable(@session) + instance_variable(@session)operator(.)ident(data) + reserved(end) + reserved(end) + + comment(# Save session store.) + reserved(def) method(update) + reserved(if) instance_variable(@session) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(silence) operator({) instance_variable(@session)operator(.)ident(save) operator(}) + reserved(end) + reserved(end) + + comment(# Save and close the session store.) + reserved(def) method(close) + reserved(if) instance_variable(@session) + ident(update) + instance_variable(@session) operator(=) pre_constant(nil) + reserved(end) + reserved(end) + + comment(# Delete and close the session store.) + reserved(def) method(delete) + reserved(if) instance_variable(@session) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(silence) operator({) instance_variable(@session)operator(.)ident(destroy) operator(}) + instance_variable(@session) operator(=) pre_constant(nil) + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(logger) + constant(ActionController)operator(::)constant(Base)operator(.)ident(logger) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(#!/usr/local/bin/ruby -w) + +comment(# This is a really simple session storage daemon, basically just a hash, ) +comment(# which is enabled for DRb access.) + +ident(require) string<delimiter(')content(drb)delimiter(')> + +ident(session_hash) operator(=) constant(Hash)operator(.)ident(new) +ident(session_hash)operator(.)ident(instance_eval) operator({) instance_variable(@mutex) operator(=) constant(Mutex)operator(.)ident(new) operator(}) + +reserved(class) operator(<<)class(session_hash) + reserved(def) method([]=)operator(()ident(key)operator(,) ident(value)operator(\)) + instance_variable(@mutex)operator(.)ident(synchronize) reserved(do) + reserved(super)operator(()ident(key)operator(,) ident(value)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method([])operator(()ident(key)operator(\)) + instance_variable(@mutex)operator(.)ident(synchronize) reserved(do) + reserved(super)operator(()ident(key)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(delete)operator(()ident(key)operator(\)) + instance_variable(@mutex)operator(.)ident(synchronize) reserved(do) + reserved(super)operator(()ident(key)operator(\)) + reserved(end) + reserved(end) +reserved(end) + +constant(DRb)operator(.)ident(start_service)operator(()string<delimiter(')content(druby://127.0.0.1:9192)delimiter(')>operator(,) ident(session_hash)operator(\)) +constant(DRb)operator(.)ident(thread)operator(.)ident(joinrequire) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(cgi/session)delimiter(')> +ident(require) string<delimiter(')content(drb)delimiter(')> + +reserved(class) class(CGI) comment(#:nodoc:all) + reserved(class) class(Session) + reserved(class) class(DRbStore) + class_variable(@@session_data) operator(=) constant(DRbObject)operator(.)ident(new)operator(()pre_constant(nil)operator(,) string<delimiter(')content(druby://localhost:9192)delimiter(')>operator(\)) + + reserved(def) method(initialize)operator(()ident(session)operator(,) ident(option)operator(=)pre_constant(nil)operator(\)) + instance_variable(@session_id) operator(=) ident(session)operator(.)ident(session_id) + reserved(end) + + reserved(def) method(restore) + instance_variable(@h) operator(=) class_variable(@@session_data)operator([)instance_variable(@session_id)operator(]) operator(||) operator({)operator(}) + reserved(end) + + reserved(def) method(update) + class_variable(@@session_data)operator([)instance_variable(@session_id)operator(]) operator(=) instance_variable(@h) + reserved(end) + + reserved(def) method(close) + ident(update) + reserved(end) + + reserved(def) method(delete) + class_variable(@@session_data)operator(.)ident(delete)operator(()instance_variable(@session_id)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(# cgi/session/memcached.rb - persistent storage of marshalled session data) +comment(#) +comment(# == Overview) +comment(#) +comment(# This file provides the CGI::Session::MemCache class, which builds) +comment(# persistence of storage data on top of the MemCache library. See) +comment(# cgi/session.rb for more details on session storage managers.) +comment(#) + +reserved(begin) + ident(require) string<delimiter(')content(cgi/session)delimiter(')> + ident(require) string<delimiter(')content(memcache)delimiter(')> + + reserved(class) class(CGI) + reserved(class) class(Session) + comment(# MemCache-based session storage class.) + comment(#) + comment(# This builds upon the top-level MemCache class provided by the) + comment(# library file memcache.rb. Session data is marshalled and stored) + comment(# in a memcached cache.) + reserved(class) class(MemCacheStore) + reserved(def) method(check_id)operator(()ident(id)operator(\)) comment(#:nodoc:#) + regexp<delimiter(/)content([^0-9a-zA-Z]+)delimiter(/)> operator(=)operator(~) ident(id)operator(.)ident(to_s) operator(?) pre_constant(false) operator(:) pre_constant(true) + reserved(end) + + comment(# Create a new CGI::Session::MemCache instance) + comment(#) + comment(# This constructor is used internally by CGI::Session. The) + comment(# user does not generally need to call it directly.) + comment(#) + comment(# +session+ is the session for which this instance is being) + comment(# created. The session id must only contain alphanumeric) + comment(# characters; automatically generated session ids observe) + comment(# this requirement.) + comment(#) + comment(# +options+ is a hash of options for the initializer. The) + comment(# following options are recognized:) + comment(#) + comment(# cache:: an instance of a MemCache client to use as the) + comment(# session cache.) + comment(#) + comment(# expires:: an expiry time value to use for session entries in) + comment(# the session cache. +expires+ is interpreted in seconds) + comment(# relative to the current time if it’s less than 60*60*24*30) + comment(# (30 days\), or as an absolute Unix time (e.g., Time#to_i\) if) + comment(# greater. If +expires+ is +0+, or not passed on +options+,) + comment(# the entry will never expire.) + comment(#) + comment(# This session's memcache entry will be created if it does) + comment(# not exist, or retrieved if it does.) + reserved(def) method(initialize)operator(()ident(session)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(id) operator(=) ident(session)operator(.)ident(session_id) + reserved(unless) ident(check_id)operator(()ident(id)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(session_id '%s' is invalid)delimiter(")> operator(%) ident(id) + reserved(end) + instance_variable(@cache) operator(=) ident(options)operator([)string<delimiter(')content(cache)delimiter(')>operator(]) operator(||) constant(MemCache)operator(.)ident(new)operator(()string<delimiter(')content(localhost)delimiter(')>operator(\)) + instance_variable(@expires) operator(=) ident(options)operator([)string<delimiter(')content(expires)delimiter(')>operator(]) operator(||) integer(0) + instance_variable(@session_key) operator(=) string<delimiter(")content(session:)inline<inline_delimiter(#{)ident(id)inline_delimiter(})>delimiter(")> + instance_variable(@session_data) operator(=) operator({)operator(}) + reserved(end) + + comment(# Restore session state from the session's memcache entry.) + comment(#) + comment(# Returns the session state as a hash.) + reserved(def) method(restore) + reserved(begin) + instance_variable(@session_data) operator(=) instance_variable(@cache)operator([)instance_variable(@session_key)operator(]) operator(||) operator({)operator(}) + reserved(rescue) + instance_variable(@session_data) operator(=) operator({)operator(}) + reserved(end) + reserved(end) + + comment(# Save session state to the session's memcache entry.) + reserved(def) method(update) + reserved(begin) + instance_variable(@cache)operator(.)ident(set)operator(()instance_variable(@session_key)operator(,) instance_variable(@session_data)operator(,) instance_variable(@expires)operator(\)) + reserved(rescue) + comment(# Ignore session update failures.) + reserved(end) + reserved(end) + + comment(# Update and close the session's memcache entry.) + reserved(def) method(close) + ident(update) + reserved(end) + + comment(# Delete the session's memcache entry.) + reserved(def) method(delete) + reserved(begin) + instance_variable(@cache)operator(.)ident(delete)operator(()instance_variable(@session_key)operator(\)) + reserved(rescue) + comment(# Ignore session delete failures.) + reserved(end) + instance_variable(@session_data) operator(=) operator({)operator(}) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(rescue) constant(LoadError) + comment(# MemCache wasn't available so neither can the store be) +reserved(end) +ident(require) string<delimiter(')content(action_controller/session/drb_store)delimiter(')> +ident(require) string<delimiter(')content(action_controller/session/mem_cache_store)delimiter(')> +reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) + ident(require) string<delimiter(')content(action_controller/session/active_record_store)delimiter(')> +reserved(end) + +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(module) class(SessionManagement) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + + ident(base)operator(.)ident(send) symbol(:alias_method)operator(,) symbol(:process_without_session_management_support)operator(,) symbol(:process) + ident(base)operator(.)ident(send) symbol(:alias_method)operator(,) symbol(:process)operator(,) symbol(:process_with_session_management_support) + + ident(base)operator(.)ident(send) symbol(:alias_method)operator(,) symbol(:process_cleanup_without_session_management_support)operator(,) symbol(:process_cleanup) + ident(base)operator(.)ident(send) symbol(:alias_method)operator(,) symbol(:process_cleanup)operator(,) symbol(:process_cleanup_with_session_management_support) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Set the session store to be used for keeping the session data between requests. The default is using the) + comment(# file system, but you can also specify one of the other included stores (:active_record_store, :drb_store, ) + comment(# :mem_cache_store, or :memory_store\) or use your own class.) + reserved(def) method(session_store=)operator(()ident(store)operator(\)) + constant(ActionController)operator(::)constant(CgiRequest)operator(::)constant(DEFAULT_SESSION_OPTIONS)operator([)symbol(:database_manager)operator(]) operator(=) + ident(store)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) operator(?) constant(CGI)operator(::)constant(Session)operator(.)ident(const_get)operator(()ident(store) operator(==) symbol(:drb_store) operator(?) string<delimiter(")content(DRbStore)delimiter(")> operator(:) ident(store)operator(.)ident(to_s)operator(.)ident(camelize)operator(\)) operator(:) ident(store) + reserved(end) + + comment(# Returns the session store class currently used.) + reserved(def) method(session_store) + constant(ActionController)operator(::)constant(CgiRequest)operator(::)constant(DEFAULT_SESSION_OPTIONS)operator([)symbol(:database_manager)operator(]) + reserved(end) + + comment(# Returns the hash used to configure the session. Example use:) + comment(#) + comment(# ActionController::Base.session_options[:session_secure] = true # session only available over HTTPS) + reserved(def) method(session_options) + constant(ActionController)operator(::)constant(CgiRequest)operator(::)constant(DEFAULT_SESSION_OPTIONS) + reserved(end) + + comment(# Specify how sessions ought to be managed for a subset of the actions on) + comment(# the controller. Like filters, you can specify <tt>:only</tt> and) + comment(# <tt>:except</tt> clauses to restrict the subset, otherwise options) + comment(# apply to all actions on this controller.) + comment(#) + comment(# The session options are inheritable, as well, so if you specify them in) + comment(# a parent controller, they apply to controllers that extend the parent.) + comment(#) + comment(# Usage:) + comment(#) + comment(# # turn off session management for all actions.) + comment(# session :off) + comment(#) + comment(# # turn off session management for all actions _except_ foo and bar.) + comment(# session :off, :except => %w(foo bar\)) + comment(#) + comment(# # turn off session management for only the foo and bar actions.) + comment(# session :off, :only => %w(foo bar\)) + comment(#) + comment(# # the session will only work over HTTPS, but only for the foo action) + comment(# session :only => :foo, :session_secure => true) + comment(#) + comment(# # the session will only be disabled for 'foo', and only if it is) + comment(# # requested as a web service) + comment(# session :off, :only => :foo,) + comment(# :if => Proc.new { |req| req.parameters[:ws] }) + comment(#) + comment(# All session options described for ActionController::Base.process_cgi) + comment(# are valid arguments.) + reserved(def) method(session)operator(()operator(*)ident(args)operator(\)) + ident(options) operator(=) constant(Hash) operator(===) ident(args)operator(.)ident(last) operator(?) ident(args)operator(.)ident(pop) operator(:) operator({)operator(}) + + ident(options)operator([)symbol(:disabled)operator(]) operator(=) pre_constant(true) reserved(if) operator(!)ident(args)operator(.)ident(empty?) + ident(options)operator([)symbol(:only)operator(]) operator(=) operator([)operator(*)ident(options)operator([)symbol(:only)operator(])operator(])operator(.)ident(map) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(to_s) operator(}) reserved(if) ident(options)operator([)symbol(:only)operator(]) + ident(options)operator([)symbol(:except)operator(]) operator(=) operator([)operator(*)ident(options)operator([)symbol(:except)operator(])operator(])operator(.)ident(map) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(to_s) operator(}) reserved(if) ident(options)operator([)symbol(:except)operator(]) + reserved(if) ident(options)operator([)symbol(:only)operator(]) operator(&&) ident(options)operator([)symbol(:except)operator(]) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(only one of either :only or :except are allowed)delimiter(")> + reserved(end) + + ident(write_inheritable_array)operator(()string<delimiter(")content(session_options)delimiter(")>operator(,) operator([)ident(options)operator(])operator(\)) + reserved(end) + + reserved(def) method(cached_session_options) comment(#:nodoc:) + instance_variable(@session_options) operator(||=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(session_options)delimiter(")>operator(\)) operator(||) operator([)operator(]) + reserved(end) + + reserved(def) method(session_options_for)operator(()ident(request)operator(,) ident(action)operator(\)) comment(#:nodoc:) + reserved(if) operator(()ident(session_options) operator(=) ident(cached_session_options)operator(\))operator(.)ident(empty?) + operator({)operator(}) + reserved(else) + ident(options) operator(=) operator({)operator(}) + + ident(action) operator(=) ident(action)operator(.)ident(to_s) + ident(session_options)operator(.)ident(each) reserved(do) operator(|)ident(opts)operator(|) + reserved(next) reserved(if) ident(opts)operator([)symbol(:if)operator(]) operator(&&) operator(!)ident(opts)operator([)symbol(:if)operator(])operator(.)ident(call)operator(()ident(request)operator(\)) + reserved(if) ident(opts)operator([)symbol(:only)operator(]) operator(&&) ident(opts)operator([)symbol(:only)operator(])operator(.)ident(include?)operator(()ident(action)operator(\)) + ident(options)operator(.)ident(merge!)operator(()ident(opts)operator(\)) + reserved(elsif) ident(opts)operator([)symbol(:except)operator(]) operator(&&) operator(!)ident(opts)operator([)symbol(:except)operator(])operator(.)ident(include?)operator(()ident(action)operator(\)) + ident(options)operator(.)ident(merge!)operator(()ident(opts)operator(\)) + reserved(elsif) operator(!)ident(opts)operator([)symbol(:only)operator(]) operator(&&) operator(!)ident(opts)operator([)symbol(:except)operator(]) + ident(options)operator(.)ident(merge!)operator(()ident(opts)operator(\)) + reserved(end) + reserved(end) + + reserved(if) ident(options)operator(.)ident(empty?) reserved(then) ident(options) + reserved(else) + ident(options)operator(.)ident(delete) symbol(:only) + ident(options)operator(.)ident(delete) symbol(:except) + ident(options)operator(.)ident(delete) symbol(:if) + ident(options)operator([)symbol(:disabled)operator(]) operator(?) pre_constant(false) operator(:) ident(options) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(process_with_session_management_support)operator(()ident(request)operator(,) ident(response)operator(,) ident(method) operator(=) symbol(:perform_action)operator(,) operator(*)ident(arguments)operator(\)) comment(#:nodoc:) + ident(set_session_options)operator(()ident(request)operator(\)) + ident(process_without_session_management_support)operator(()ident(request)operator(,) ident(response)operator(,) ident(method)operator(,) operator(*)ident(arguments)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(set_session_options)operator(()ident(request)operator(\)) + ident(request)operator(.)ident(session_options) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(session_options_for)operator(()ident(request)operator(,) ident(request)operator(.)ident(parameters)operator([)string<delimiter(")content(action)delimiter(")>operator(]) operator(||) string<delimiter(")content(index)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(process_cleanup_with_session_management_support) + ident(process_cleanup_without_session_management_support) + ident(clear_persistent_model_associations) + reserved(end) + + comment(# Clear cached associations in session data so they don't overflow) + comment(# the database field. Only applies to ActiveRecordStore since there) + comment(# is not a standard way to iterate over session data.) + reserved(def) method(clear_persistent_model_associations) comment(#:doc:) + reserved(if) reserved(defined?)operator(()instance_variable(@session)operator(\)) operator(&&) instance_variable(@session)operator(.)ident(instance_variables)operator(.)ident(include?)operator(()string<delimiter(')content(@data)delimiter(')>operator(\)) + ident(session_data) operator(=) instance_variable(@session)operator(.)ident(instance_variable_get)operator(()string<delimiter(')content(@data)delimiter(')>operator(\)) + + reserved(if) ident(session_data) operator(&&) ident(session_data)operator(.)ident(respond_to?)operator(()symbol(:each_value)operator(\)) + ident(session_data)operator(.)ident(each_value) reserved(do) operator(|)ident(obj)operator(|) + ident(obj)operator(.)ident(clear_association_cache) reserved(if) ident(obj)operator(.)ident(respond_to?)operator(()symbol(:clear_association_cache)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) comment(#:nodoc:) + comment(# Methods for sending files and streams to the browser instead of rendering.) + reserved(module) class(Streaming) + constant(DEFAULT_SEND_FILE_OPTIONS) operator(=) operator({) + symbol(:type) operator(=)operator(>) string<delimiter(')content(application/octet-stream)delimiter(')>operator(.)ident(freeze)operator(,) + symbol(:disposition) operator(=)operator(>) string<delimiter(')content(attachment)delimiter(')>operator(.)ident(freeze)operator(,) + symbol(:stream) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:buffer_size) operator(=)operator(>) integer(4096) + operator(})operator(.)ident(freeze) + + ident(protected) + comment(# Sends the file by streaming it 4096 bytes at a time. This way the) + comment(# whole file doesn't need to be read into memory at once. This makes) + comment(# it feasible to send even large files.) + comment(#) + comment(# Be careful to sanitize the path parameter if it coming from a web) + comment(# page. send_file(params[:path]\) allows a malicious user to) + comment(# download any file on your server.) + comment(#) + comment(# Options:) + comment(# * <tt>:filename</tt> - suggests a filename for the browser to use.) + comment(# Defaults to File.basename(path\).) + comment(# * <tt>:type</tt> - specifies an HTTP content type.) + comment(# Defaults to 'application/octet-stream'.) + comment(# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. ) + comment(# Valid values are 'inline' and 'attachment' (default\).) + comment(# * <tt>:stream</tt> - whether to send the file to the user agent as it is read (true\)) + comment(# or to read the entire file before sending (false\). Defaults to true.) + comment(# * <tt>:buffer_size</tt> - specifies size (in bytes\) of the buffer used to stream the file.) + comment(# Defaults to 4096.) + comment(# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.) + comment(#) + comment(# The default Content-Type and Content-Disposition headers are) + comment(# set to download arbitrary binary files in as many browsers as) + comment(# possible. IE versions 4, 5, 5.5, and 6 are all known to have) + comment(# a variety of quirks (especially when downloading over SSL\).) + comment(#) + comment(# Simple download:) + comment(# send_file '/path/to.zip') + comment(#) + comment(# Show a JPEG in the browser:) + comment(# send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline') + comment(#) + comment(# Show a 404 page in the browser:) + comment(# send_file '/path/to/404.html, :type => 'text/html; charset=utf-8', :status => 404) + comment(#) + comment(# Read about the other Content-* HTTP headers if you'd like to) + comment(# provide the user with more information (such as Content-Description\).) + comment(# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11) + comment(#) + comment(# Also be aware that the document may be cached by proxies and browsers.) + comment(# The Pragma and Cache-Control headers declare how the file may be cached) + comment(# by intermediaries. They default to require clients to validate with) + comment(# the server before releasing cached responses. See) + comment(# http://www.mnot.net/cache_docs/ for an overview of web caching and) + comment(# http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9) + comment(# for the Cache-Control header spec.) + reserved(def) method(send_file)operator(()ident(path)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:doc:) + ident(raise) constant(MissingFile)operator(,) string<delimiter(")content(Cannot read file )inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")> reserved(unless) constant(File)operator(.)ident(file?)operator(()ident(path)operator(\)) reserved(and) constant(File)operator(.)ident(readable?)operator(()ident(path)operator(\)) + + ident(options)operator([)symbol(:length)operator(]) operator(||=) constant(File)operator(.)ident(size)operator(()ident(path)operator(\)) + ident(options)operator([)symbol(:filename)operator(]) operator(||=) constant(File)operator(.)ident(basename)operator(()ident(path)operator(\)) + ident(send_file_headers!) ident(options) + + instance_variable(@performed_render) operator(=) pre_constant(false) + + reserved(if) ident(options)operator([)symbol(:stream)operator(]) + ident(render) symbol(:status) operator(=)operator(>) ident(options)operator([)symbol(:status)operator(])operator(,) symbol(:text) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(response)operator(,) ident(output)operator(|) + ident(logger)operator(.)ident(info) string<delimiter(")content(Streaming file )inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")> reserved(unless) ident(logger)operator(.)ident(nil?) + ident(len) operator(=) ident(options)operator([)symbol(:buffer_size)operator(]) operator(||) integer(4096) + constant(File)operator(.)ident(open)operator(()ident(path)operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) reserved(do) operator(|)ident(file)operator(|) + reserved(if) ident(output)operator(.)ident(respond_to?)operator(()symbol(:syswrite)operator(\)) + reserved(begin) + reserved(while) pre_constant(true) + ident(output)operator(.)ident(syswrite)operator(()ident(file)operator(.)ident(sysread)operator(()ident(len)operator(\))operator(\)) + reserved(end) + reserved(rescue) constant(EOFError) + reserved(end) + reserved(else) + reserved(while) ident(buf) operator(=) ident(file)operator(.)ident(read)operator(()ident(len)operator(\)) + ident(output)operator(.)ident(write)operator(()ident(buf)operator(\)) + reserved(end) + reserved(end) + reserved(end) + operator(}) + reserved(else) + ident(logger)operator(.)ident(info) string<delimiter(")content(Sending file )inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")> reserved(unless) ident(logger)operator(.)ident(nil?) + constant(File)operator(.)ident(open)operator(()ident(path)operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) operator({) operator(|)ident(file)operator(|) ident(render) symbol(:status) operator(=)operator(>) ident(options)operator([)symbol(:status)operator(])operator(,) symbol(:text) operator(=)operator(>) ident(file)operator(.)ident(read) operator(}) + reserved(end) + reserved(end) + + comment(# Send binary data to the user as a file download. May set content type, apparent file name,) + comment(# and specify whether to show data inline or download as an attachment.) + comment(#) + comment(# Options:) + comment(# * <tt>:filename</tt> - Suggests a filename for the browser to use.) + comment(# * <tt>:type</tt> - specifies an HTTP content type.) + comment(# Defaults to 'application/octet-stream'.) + comment(# * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. ) + comment(# * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.) + comment(# Valid values are 'inline' and 'attachment' (default\).) + comment(#) + comment(# Generic data download:) + comment(# send_data buffer) + comment(#) + comment(# Download a dynamically-generated tarball:) + comment(# send_data generate_tgz('dir'\), :filename => 'dir.tgz') + comment(#) + comment(# Display an image Active Record in the browser:) + comment(# send_data image.data, :type => image.content_type, :disposition => 'inline') + comment(#) + comment(# See +send_file+ for more information on HTTP Content-* headers and caching.) + reserved(def) method(send_data)operator(()ident(data)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:doc:) + ident(logger)operator(.)ident(info) string<delimiter(")content(Sending data )inline<inline_delimiter(#{)ident(options)operator([)symbol(:filename)operator(])inline_delimiter(})>delimiter(")> reserved(unless) ident(logger)operator(.)ident(nil?) + ident(send_file_headers!) ident(options)operator(.)ident(merge)operator(()symbol(:length) operator(=)operator(>) ident(data)operator(.)ident(size)operator(\)) + instance_variable(@performed_render) operator(=) pre_constant(false) + ident(render) symbol(:status) operator(=)operator(>) ident(options)operator([)symbol(:status)operator(])operator(,) symbol(:text) operator(=)operator(>) ident(data) + reserved(end) + + ident(private) + reserved(def) method(send_file_headers!)operator(()ident(options)operator(\)) + ident(options)operator(.)ident(update)operator(()constant(DEFAULT_SEND_FILE_OPTIONS)operator(.)ident(merge)operator(()ident(options)operator(\))operator(\)) + operator([)symbol(:length)operator(,) symbol(:type)operator(,) symbol(:disposition)operator(])operator(.)ident(each) reserved(do) operator(|)ident(arg)operator(|) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(:)inline<inline_delimiter(#{)ident(arg)inline_delimiter(})>content( option required)delimiter(")> reserved(if) ident(options)operator([)ident(arg)operator(])operator(.)ident(nil?) + reserved(end) + + ident(disposition) operator(=) ident(options)operator([)symbol(:disposition)operator(])operator(.)ident(dup) operator(||) string<delimiter(')content(attachment)delimiter(')> + + ident(disposition) operator(<<)operator(=) string<delimiter(%()content(; filename=")inline<inline_delimiter(#{)ident(options)operator([)symbol(:filename)operator(])inline_delimiter(})>content(")delimiter(\))> reserved(if) ident(options)operator([)symbol(:filename)operator(]) + + instance_variable(@headers)operator(.)ident(update)operator(() + string<delimiter(')content(Content-Length)delimiter(')> operator(=)operator(>) ident(options)operator([)symbol(:length)operator(])operator(,) + string<delimiter(')content(Content-Type)delimiter(')> operator(=)operator(>) ident(options)operator([)symbol(:type)operator(])operator(.)ident(strip)operator(,) comment(# fixes a problem with extra '\\r' with some browsers) + string<delimiter(')content(Content-Disposition)delimiter(')> operator(=)operator(>) ident(disposition)operator(,) + string<delimiter(')content(Content-Transfer-Encoding)delimiter(')> operator(=)operator(>) string<delimiter(')content(binary)delimiter(')> + operator(\)) + + comment(# Fix a problem with IE 6.0 on opening downloaded files:) + comment(# If Cache-Control: no-cache is set (which Rails does by default\), ) + comment(# IE removes the file it just downloaded from its cache immediately ) + comment(# after it displays the "open/save" dialog, which means that if you ) + comment(# hit "open" the file isn't there anymore when the application that ) + comment(# is called for handling the download is run, so let's workaround that) + instance_variable(@headers)operator([)string<delimiter(')content(Cache-Control)delimiter(')>operator(]) operator(=) string<delimiter(')content(private)delimiter(')> reserved(if) instance_variable(@headers)operator([)string<delimiter(')content(Cache-Control)delimiter(')>operator(]) operator(==) string<delimiter(')content(no-cache)delimiter(')> + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/assertions)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/deprecated_assertions)delimiter(')> + +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(class) class(Base) + comment(# Process a test request called with a +TestRequest+ object.) + reserved(def) pre_constant(self)operator(.)ident(process_test)operator(()ident(request)operator(\)) + ident(new)operator(.)ident(process_test)operator(()ident(request)operator(\)) + reserved(end) + + reserved(def) method(process_test)operator(()ident(request)operator(\)) comment(#:nodoc:) + ident(process)operator(()ident(request)operator(,) constant(TestResponse)operator(.)ident(new)operator(\)) + reserved(end) + + reserved(def) method(process_with_test)operator(()operator(*)ident(args)operator(\)) + ident(returning) ident(process_without_test)operator(()operator(*)ident(args)operator(\)) reserved(do) + ident(add_variables_to_assigns) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:process_without_test)operator(,) symbol(:process) + ident(alias_method) symbol(:process)operator(,) symbol(:process_with_test) + reserved(end) + + reserved(class) class(TestRequest) operator(<) constant(AbstractRequest) comment(#:nodoc:) + ident(attr_accessor) symbol(:cookies)operator(,) symbol(:session_options) + ident(attr_accessor) symbol(:query_parameters)operator(,) symbol(:request_parameters)operator(,) symbol(:path)operator(,) symbol(:session)operator(,) symbol(:env) + ident(attr_accessor) symbol(:host) + + reserved(def) method(initialize)operator(()ident(query_parameters) operator(=) pre_constant(nil)operator(,) ident(request_parameters) operator(=) pre_constant(nil)operator(,) ident(session) operator(=) pre_constant(nil)operator(\)) + instance_variable(@query_parameters) operator(=) ident(query_parameters) operator(||) operator({)operator(}) + instance_variable(@request_parameters) operator(=) ident(request_parameters) operator(||) operator({)operator(}) + instance_variable(@session) operator(=) ident(session) operator(||) constant(TestSession)operator(.)ident(new) + + ident(initialize_containers) + ident(initialize_default_values) + + reserved(super)operator(()operator(\)) + reserved(end) + + reserved(def) method(reset_session) + instance_variable(@session) operator(=) operator({)operator(}) + reserved(end) + + reserved(def) method(raw_post) + reserved(if) ident(raw_post) operator(=) ident(env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) + ident(raw_post) + reserved(else) + ident(params) operator(=) pre_constant(self)operator(.)ident(request_parameters)operator(.)ident(dup) + string<delimiter(%w()content(controller action only_path)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(k)operator(|) + ident(params)operator(.)ident(delete)operator(()ident(k)operator(\)) + ident(params)operator(.)ident(delete)operator(()ident(k)operator(.)ident(to_sym)operator(\)) + reserved(end) + + ident(params)operator(.)ident(map) operator({) operator(|)ident(k)operator(,)ident(v)operator(|) operator([) constant(CGI)operator(.)ident(escape)operator(()ident(k)operator(.)ident(to_s)operator(\))operator(,) constant(CGI)operator(.)ident(escape)operator(()ident(v)operator(.)ident(to_s)operator(\)) operator(])operator(.)ident(join)operator(()string<delimiter(')content(=)delimiter(')>operator(\)) operator(})operator(.)ident(sort)operator(.)ident(join)operator(()string<delimiter(')content(&)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(port=)operator(()ident(number)operator(\)) + instance_variable(@env)operator([)string<delimiter(")content(SERVER_PORT)delimiter(")>operator(]) operator(=) ident(number)operator(.)ident(to_i) + instance_variable(@port_as_int) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(action=)operator(()ident(action_name)operator(\)) + instance_variable(@query_parameters)operator(.)ident(update)operator(()operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) ident(action_name) operator(})operator(\)) + instance_variable(@parameters) operator(=) pre_constant(nil) + reserved(end) + + comment(# Used to check AbstractRequest's request_uri functionality.) + comment(# Disables the use of @path and @request_uri so superclass can handle those.) + reserved(def) method(set_REQUEST_URI)operator(()ident(value)operator(\)) + instance_variable(@env)operator([)string<delimiter(")content(REQUEST_URI)delimiter(")>operator(]) operator(=) ident(value) + instance_variable(@request_uri) operator(=) pre_constant(nil) + instance_variable(@path) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(request_uri=)operator(()ident(uri)operator(\)) + instance_variable(@request_uri) operator(=) ident(uri) + instance_variable(@path) operator(=) ident(uri)operator(.)ident(split)operator(()string<delimiter(")content(?)delimiter(")>operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(remote_addr=)operator(()ident(addr)operator(\)) + instance_variable(@env)operator([)string<delimiter(')content(REMOTE_ADDR)delimiter(')>operator(]) operator(=) ident(addr) + reserved(end) + + reserved(def) method(remote_addr) + instance_variable(@env)operator([)string<delimiter(')content(REMOTE_ADDR)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(request_uri) + instance_variable(@request_uri) operator(||) reserved(super)operator(()operator(\)) + reserved(end) + + reserved(def) method(path) + instance_variable(@path) operator(||) reserved(super)operator(()operator(\)) + reserved(end) + + reserved(def) method(assign_parameters)operator(()ident(controller_path)operator(,) ident(action)operator(,) ident(parameters)operator(\)) + ident(parameters) operator(=) ident(parameters)operator(.)ident(symbolize_keys)operator(.)ident(merge)operator(()symbol(:controller) operator(=)operator(>) ident(controller_path)operator(,) symbol(:action) operator(=)operator(>) ident(action)operator(\)) + ident(extra_keys) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(extra_keys)operator(()ident(parameters)operator(\)) + ident(non_path_parameters) operator(=) ident(get?) operator(?) ident(query_parameters) operator(:) ident(request_parameters) + ident(parameters)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) ident(value)operator(.)ident(is_a?) constant(Fixnum) + ident(value) operator(=) ident(value)operator(.)ident(to_s) + reserved(elsif) ident(value)operator(.)ident(is_a?) constant(Array) + ident(value) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(PathComponent)operator(::)constant(Result)operator(.)ident(new)operator(()ident(value)operator(\)) + reserved(end) + + reserved(if) ident(extra_keys)operator(.)ident(include?)operator(()ident(key)operator(.)ident(to_sym)operator(\)) + ident(non_path_parameters)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(else) + ident(path_parameters)operator([)ident(key)operator(.)ident(to_s)operator(]) operator(=) ident(value) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(recycle!) + pre_constant(self)operator(.)ident(request_parameters) operator(=) operator({)operator(}) + pre_constant(self)operator(.)ident(query_parameters) operator(=) operator({)operator(}) + pre_constant(self)operator(.)ident(path_parameters) operator(=) operator({)operator(}) + instance_variable(@request_method)operator(,) instance_variable(@accepts)operator(,) instance_variable(@content_type) operator(=) pre_constant(nil)operator(,) pre_constant(nil)operator(,) pre_constant(nil) + reserved(end) + + ident(private) + reserved(def) method(initialize_containers) + instance_variable(@env)operator(,) instance_variable(@cookies) operator(=) operator({)operator(})operator(,) operator({)operator(}) + reserved(end) + + reserved(def) method(initialize_default_values) + instance_variable(@host) operator(=) string<delimiter(")content(test.host)delimiter(")> + instance_variable(@request_uri) operator(=) string<delimiter(")content(/)delimiter(")> + pre_constant(self)operator(.)ident(remote_addr) operator(=) string<delimiter(")content(0.0.0.0)delimiter(")> + instance_variable(@env)operator([)string<delimiter(")content(SERVER_PORT)delimiter(")>operator(]) operator(=) integer(80) + instance_variable(@env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(")content(GET)delimiter(")> + reserved(end) + reserved(end) + + comment(# A refactoring of TestResponse to allow the same behavior to be applied) + comment(# to the "real" CgiResponse class in integration tests.) + reserved(module) class(TestResponseBehavior) comment(#:nodoc:) + comment(# the response code of the request) + reserved(def) method(response_code) + ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(])operator([)integer(0)operator(,)integer(3)operator(])operator(.)ident(to_i) reserved(rescue) integer(0) + reserved(end) + + comment(# returns a String to ensure compatibility with Net::HTTPResponse) + reserved(def) method(code) + ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(])operator(.)ident(to_s)operator(.)ident(split)operator(()string<delimiter(')content( )delimiter(')>operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(message) + ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(])operator(.)ident(to_s)operator(.)ident(split)operator(()string<delimiter(')content( )delimiter(')>operator(,)integer(2)operator(\))operator([)integer(1)operator(]) + reserved(end) + + comment(# was the response successful?) + reserved(def) method(success?) + ident(response_code) operator(==) integer(200) + reserved(end) + + comment(# was the URL not found?) + reserved(def) method(missing?) + ident(response_code) operator(==) integer(404) + reserved(end) + + comment(# were we redirected?) + reserved(def) method(redirect?) + operator(()integer(300)operator(..)integer(399)operator(\))operator(.)ident(include?)operator(()ident(response_code)operator(\)) + reserved(end) + + comment(# was there a server-side error?) + reserved(def) method(error?) + operator(()integer(500)operator(..)integer(599)operator(\))operator(.)ident(include?)operator(()ident(response_code)operator(\)) + reserved(end) + + ident(alias_method) symbol(:server_error?)operator(,) symbol(:error?) + + comment(# returns the redirection location or nil) + reserved(def) method(redirect_url) + ident(redirect?) operator(?) ident(headers)operator([)string<delimiter(')content(location)delimiter(')>operator(]) operator(:) pre_constant(nil) + reserved(end) + + comment(# does the redirect location match this regexp pattern?) + reserved(def) method(redirect_url_match?)operator(() ident(pattern) operator(\)) + reserved(return) pre_constant(false) reserved(if) ident(redirect_url)operator(.)ident(nil?) + ident(p) operator(=) constant(Regexp)operator(.)ident(new)operator(()ident(pattern)operator(\)) reserved(if) ident(pattern)operator(.)ident(class) operator(==) constant(String) + ident(p) operator(=) ident(pattern) reserved(if) ident(pattern)operator(.)ident(class) operator(==) constant(Regexp) + reserved(return) pre_constant(false) reserved(if) ident(p)operator(.)ident(nil?) + ident(p)operator(.)ident(match)operator(()ident(redirect_url)operator(\)) operator(!=) pre_constant(nil) + reserved(end) + + comment(# returns the template path of the file which was used to) + comment(# render this response (or nil\) ) + reserved(def) method(rendered_file)operator(()ident(with_controller)operator(=)pre_constant(false)operator(\)) + reserved(unless) ident(template)operator(.)ident(first_render)operator(.)ident(nil?) + reserved(unless) ident(with_controller) + ident(template)operator(.)ident(first_render) + reserved(else) + ident(template)operator(.)ident(first_render)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator(.)ident(last) operator(||) ident(template)operator(.)ident(first_render) + reserved(end) + reserved(end) + reserved(end) + + comment(# was this template rendered by a file?) + reserved(def) method(rendered_with_file?) + operator(!)ident(rendered_file)operator(.)ident(nil?) + reserved(end) + + comment(# a shortcut to the flash (or an empty hash if no flash.. hey! that rhymes!\)) + reserved(def) method(flash) + ident(session)operator([)string<delimiter(')content(flash)delimiter(')>operator(]) operator(||) operator({)operator(}) + reserved(end) + + comment(# do we have a flash? ) + reserved(def) method(has_flash?) + operator(!)ident(session)operator([)string<delimiter(')content(flash)delimiter(')>operator(])operator(.)ident(empty?) + reserved(end) + + comment(# do we have a flash that has contents?) + reserved(def) method(has_flash_with_contents?) + operator(!)ident(flash)operator(.)ident(empty?) + reserved(end) + + comment(# does the specified flash object exist?) + reserved(def) method(has_flash_object?)operator(()ident(name)operator(=)pre_constant(nil)operator(\)) + operator(!)ident(flash)operator([)ident(name)operator(])operator(.)ident(nil?) + reserved(end) + + comment(# does the specified object exist in the session?) + reserved(def) method(has_session_object?)operator(()ident(name)operator(=)pre_constant(nil)operator(\)) + operator(!)ident(session)operator([)ident(name)operator(])operator(.)ident(nil?) + reserved(end) + + comment(# a shortcut to the template.assigns) + reserved(def) method(template_objects) + ident(template)operator(.)ident(assigns) operator(||) operator({)operator(}) + reserved(end) + + comment(# does the specified template object exist? ) + reserved(def) method(has_template_object?)operator(()ident(name)operator(=)pre_constant(nil)operator(\)) + operator(!)ident(template_objects)operator([)ident(name)operator(])operator(.)ident(nil?) + reserved(end) + + comment(# Returns the response cookies, converted to a Hash of (name => CGI::Cookie\) pairs) + comment(# Example:) + comment(# ) + comment(# assert_equal ['AuthorOfNewPage'], r.cookies['author'].value) + reserved(def) method(cookies) + ident(headers)operator([)string<delimiter(')content(cookie)delimiter(')>operator(])operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(hash)operator(,) ident(cookie)operator(|) ident(hash)operator([)ident(cookie)operator(.)ident(name)operator(]) operator(=) ident(cookie)operator(;) ident(hash) operator(}) + reserved(end) + + comment(# Returns binary content (downloadable file\), converted to a String) + reserved(def) method(binary_content) + ident(raise) string<delimiter(")content(Response body is not a Proc: )inline<inline_delimiter(#{)ident(body)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> reserved(unless) ident(body)operator(.)ident(kind_of?)operator(()constant(Proc)operator(\)) + ident(require) string<delimiter(')content(stringio)delimiter(')> + + ident(sio) operator(=) constant(StringIO)operator(.)ident(new) + + reserved(begin) + global_variable($stdout) operator(=) ident(sio) + ident(body)operator(.)ident(call) + reserved(ensure) + global_variable($stdout) operator(=) constant(STDOUT) + reserved(end) + + ident(sio)operator(.)ident(rewind) + ident(sio)operator(.)ident(read) + reserved(end) + reserved(end) + + reserved(class) class(TestResponse) operator(<) constant(AbstractResponse) comment(#:nodoc:) + ident(include) constant(TestResponseBehavior) + reserved(end) + + reserved(class) class(TestSession) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(attributes) operator(=) operator({)operator(})operator(\)) + instance_variable(@attributes) operator(=) ident(attributes) + reserved(end) + + reserved(def) method([])operator(()ident(key)operator(\)) + instance_variable(@attributes)operator([)ident(key)operator(]) + reserved(end) + + reserved(def) method([]=)operator(()ident(key)operator(,) ident(value)operator(\)) + instance_variable(@attributes)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(end) + + reserved(def) method(session_id) + string<delimiter(")delimiter(")> + reserved(end) + + reserved(def) method(update)operator(()operator(\)) reserved(end) + reserved(def) method(close)operator(()operator(\)) reserved(end) + reserved(def) method(delete)operator(()operator(\)) instance_variable(@attributes) operator(=) operator({)operator(}) reserved(end) + reserved(end) + + comment(# Essentially generates a modified Tempfile object similar to the object) + comment(# you'd get from the standard library CGI module in a multipart) + comment(# request. This means you can use an ActionController::TestUploadedFile) + comment(# object in the params of a test request in order to simulate) + comment(# a file upload.) + comment(#) + comment(# Usage example, within a functional test:) + comment(# post :change_avatar, :avatar => ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/spongebob.png', 'image/png'\)) + reserved(class) class(TestUploadedFile) + comment(# The filename, *not* including the path, of the "uploaded" file) + ident(attr_reader) symbol(:original_filename) + + comment(# The content type of the "uploaded" file) + ident(attr_reader) symbol(:content_type) + + reserved(def) method(initialize)operator(()ident(path)operator(,) ident(content_type) operator(=) string<delimiter(')content(text/plain)delimiter(')>operator(\)) + ident(raise) string<delimiter(")content(file does not exist)delimiter(")> reserved(unless) constant(File)operator(.)ident(exist?)operator(()ident(path)operator(\)) + instance_variable(@content_type) operator(=) ident(content_type) + instance_variable(@original_filename) operator(=) ident(path)operator(.)ident(sub)operator(()regexp<delimiter(/)content(^.*)inline<inline_delimiter(#{)constant(File)operator(::)constant(SEPARATOR)inline_delimiter(})>content(([^)inline<inline_delimiter(#{)constant(File)operator(::)constant(SEPARATOR)inline_delimiter(})>content(]+\)$)delimiter(/)>operator(\)) operator({) global_variable($1) operator(}) + instance_variable(@tempfile) operator(=) constant(Tempfile)operator(.)ident(new)operator(()instance_variable(@original_filename)operator(\)) + constant(FileUtils)operator(.)ident(copy_file)operator(()ident(path)operator(,) instance_variable(@tempfile)operator(.)ident(path)operator(\)) + reserved(end) + + reserved(def) method(path) comment(#:nodoc:) + instance_variable(@tempfile)operator(.)ident(path) + reserved(end) + + reserved(alias) method(local_path) method(path) + + reserved(def) method(method_missing)operator(()ident(method_name)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) comment(#:nodoc:) + instance_variable(@tempfile)operator(.)ident(send)operator(()ident(method_name)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(TestProcess) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + comment(# execute the request simulating a specific http method and set/volley the response) + string<delimiter(%w()content( get post put delete head )delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(base)operator(.)ident(class_eval) string<delimiter(<<-EOV)>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def )inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content((action, parameters = nil, session = nil, flash = nil\) + @request.env['REQUEST_METHOD'] = ")inline<inline_delimiter(#{)ident(method)operator(.)ident(upcase)inline_delimiter(})>content(" if @request + process(action, parameters, session, flash\) + end)delimiter( + EOV)> + reserved(end) + reserved(end) + + comment(# execute the request and set/volley the response) + reserved(def) method(process)operator(()ident(action)operator(,) ident(parameters) operator(=) pre_constant(nil)operator(,) ident(session) operator(=) pre_constant(nil)operator(,) ident(flash) operator(=) pre_constant(nil)operator(\)) + comment(# Sanity check for required instance variables so we can give an) + comment(# understandable error message.) + string<delimiter(%w()content(controller request response)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(iv_name)operator(|) + ident(raise) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(iv_name)inline_delimiter(})>content( is nil: make sure you set it in your test's setup method.)delimiter(")> reserved(if) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(iv_name)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(nil?) + reserved(end) + + instance_variable(@request)operator(.)ident(recycle!) + + instance_variable(@html_document) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(||=) string<delimiter(")content(GET)delimiter(")> + instance_variable(@request)operator(.)ident(action) operator(=) ident(action)operator(.)ident(to_s) + + ident(parameters) operator(||=) operator({)operator(}) + instance_variable(@request)operator(.)ident(assign_parameters)operator(()instance_variable(@controller)operator(.)ident(class)operator(.)ident(controller_path)operator(,) ident(action)operator(.)ident(to_s)operator(,) ident(parameters)operator(\)) + + instance_variable(@request)operator(.)ident(session) operator(=) constant(ActionController)operator(::)constant(TestSession)operator(.)ident(new)operator(()ident(session)operator(\)) reserved(unless) ident(session)operator(.)ident(nil?) + instance_variable(@request)operator(.)ident(session)operator([)string<delimiter(")content(flash)delimiter(")>operator(]) operator(=) constant(ActionController)operator(::)constant(Flash)operator(::)constant(FlashHash)operator(.)ident(new)operator(.)ident(update)operator(()ident(flash)operator(\)) reserved(if) ident(flash) + ident(build_request_uri)operator(()ident(action)operator(,) ident(parameters)operator(\)) + instance_variable(@controller)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\)) + reserved(end) + + reserved(def) method(xml_http_request)operator(()ident(request_method)operator(,) ident(action)operator(,) ident(parameters) operator(=) pre_constant(nil)operator(,) ident(session) operator(=) pre_constant(nil)operator(,) ident(flash) operator(=) pre_constant(nil)operator(\)) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_REQUESTED_WITH)delimiter(')>operator(]) operator(=) string<delimiter(')content(XMLHttpRequest)delimiter(')> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_ACCEPT)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/javascript, text/html, application/xml, text/xml, */*)delimiter(')> + ident(returning) pre_constant(self)operator(.)ident(send)operator(()ident(request_method)operator(,) ident(action)operator(,) ident(parameters)operator(,) ident(session)operator(,) ident(flash)operator(\)) reserved(do) + instance_variable(@request)operator(.)ident(env)operator(.)ident(delete) string<delimiter(')content(HTTP_X_REQUESTED_WITH)delimiter(')> + instance_variable(@request)operator(.)ident(env)operator(.)ident(delete) string<delimiter(')content(HTTP_ACCEPT)delimiter(')> + reserved(end) + reserved(end) + reserved(alias) method(xhr) symbol(:xml_http_request) + + reserved(def) method(follow_redirect) + reserved(if) instance_variable(@response)operator(.)ident(redirected_to)operator([)symbol(:controller)operator(]) + ident(raise) string<delimiter(")content(Can't follow redirects outside of current controller ()inline<inline_delimiter(#{)instance_variable(@response)operator(.)ident(redirected_to)operator([)symbol(:controller)operator(])inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + ident(get)operator(()instance_variable(@response)operator(.)ident(redirected_to)operator(.)ident(delete)operator(()symbol(:action)operator(\))operator(,) instance_variable(@response)operator(.)ident(redirected_to)operator(.)ident(stringify_keys)operator(\)) + reserved(end) + + reserved(def) method(assigns)operator(()ident(key) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(key)operator(.)ident(nil?) + instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns) + reserved(else) + instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)ident(key)operator(.)ident(to_s)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(session) + instance_variable(@response)operator(.)ident(session) + reserved(end) + + reserved(def) method(flash) + instance_variable(@response)operator(.)ident(flash) + reserved(end) + + reserved(def) method(cookies) + instance_variable(@response)operator(.)ident(cookies) + reserved(end) + + reserved(def) method(redirect_to_url) + instance_variable(@response)operator(.)ident(redirect_url) + reserved(end) + + reserved(def) method(build_request_uri)operator(()ident(action)operator(,) ident(parameters)operator(\)) + reserved(unless) instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_URI)delimiter(')>operator(]) + ident(options) operator(=) instance_variable(@controller)operator(.)ident(send)operator(()symbol(:rewrite_options)operator(,) ident(parameters)operator(\)) + ident(options)operator(.)ident(update)operator(()symbol(:only_path) operator(=)operator(>) pre_constant(true)operator(,) symbol(:action) operator(=)operator(>) ident(action)operator(\)) + + ident(url) operator(=) constant(ActionController)operator(::)constant(UrlRewriter)operator(.)ident(new)operator(()instance_variable(@request)operator(,) ident(parameters)operator(\)) + instance_variable(@request)operator(.)ident(set_REQUEST_URI)operator(()ident(url)operator(.)ident(rewrite)operator(()ident(options)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(html_document) + instance_variable(@html_document) operator(||=) constant(HTML)operator(::)constant(Document)operator(.)ident(new)operator(()instance_variable(@response)operator(.)ident(body)operator(\)) + reserved(end) + + reserved(def) method(find_tag)operator(()ident(conditions)operator(\)) + ident(html_document)operator(.)ident(find)operator(()ident(conditions)operator(\)) + reserved(end) + + reserved(def) method(find_all_tag)operator(()ident(conditions)operator(\)) + ident(html_document)operator(.)ident(find_all)operator(()ident(conditions)operator(\)) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(selector)operator(,) operator(*)ident(args)operator(\)) + reserved(return) instance_variable(@controller)operator(.)ident(send)operator(()ident(selector)operator(,) operator(*)ident(args)operator(\)) reserved(if) constant(ActionController)operator(::)constant(Routing)operator(::)constant(NamedRoutes)operator(::)constant(Helpers)operator(.)ident(include?)operator(()ident(selector)operator(\)) + reserved(return) reserved(super) + reserved(end) + + comment(# Shortcut for ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + path, type\). Example:) + comment(# post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png'\)) + reserved(def) method(fixture_file_upload)operator(()ident(path)operator(,) ident(mime_type) operator(=) pre_constant(nil)operator(\)) + constant(ActionController)operator(::)constant(TestUploadedFile)operator(.)ident(new)operator(() + constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase)operator(.)ident(respond_to?)operator(()symbol(:fixture_path)operator(\)) operator(?) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase)operator(.)ident(fixture_path) operator(+) ident(path) operator(:) ident(path)operator(,) + ident(mime_type) + operator(\)) + reserved(end) + + comment(# A helper to make it easier to test different route configurations.) + comment(# This method temporarily replaces ActionController::Routing::Routes) + comment(# with a new RouteSet instance. ) + comment(#) + comment(# The new instance is yielded to the passed block. Typically the block) + comment(# will create some routes using map.draw { map.connect ... }:) + comment(#) + comment(# with_routing do |set|) + comment(# set.draw { set.connect ':controller/:id/:action' }) + comment(# assert_equal() + comment(# ['/content/10/show', {}],) + comment(# set.generate(:controller => 'content', :id => 10, :action => 'show'\)) + comment(# \)) + comment(# end) + comment(#) + reserved(def) method(with_routing) + ident(real_routes) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes) + constant(ActionController)operator(::)constant(Routing)operator(.)ident(send) symbol(:remove_const)operator(,) symbol(:Routes) + + ident(temporary_routes) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(RouteSet)operator(.)ident(new) + constant(ActionController)operator(::)constant(Routing)operator(.)ident(send) symbol(:const_set)operator(,) symbol(:Routes)operator(,) ident(temporary_routes) + + reserved(yield) ident(temporary_routes) + reserved(ensure) + reserved(if) constant(ActionController)operator(::)constant(Routing)operator(.)ident(const_defined?) symbol(:Routes) + constant(ActionController)operator(::)constant(Routing)operator(.)ident(send)operator(()symbol(:remove_const)operator(,) symbol(:Routes)operator(\)) + reserved(end) + constant(ActionController)operator(::)constant(Routing)operator(.)ident(const_set)operator(()symbol(:Routes)operator(,) ident(real_routes)operator(\)) reserved(if) ident(real_routes) + reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(Test) + reserved(module) class(Unit) + reserved(class) class(TestCase) comment(#:nodoc:) + ident(include) constant(ActionController)operator(::)constant(TestProcess) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionController) + comment(# Rewrites URLs for Base.redirect_to and Base.url_for in the controller.) + + reserved(class) class(UrlRewriter) comment(#:nodoc:) + constant(RESERVED_OPTIONS) operator(=) operator([)symbol(:anchor)operator(,) symbol(:params)operator(,) symbol(:only_path)operator(,) symbol(:host)operator(,) symbol(:protocol)operator(,) symbol(:trailing_slash)operator(,) symbol(:skip_relative_url_root)operator(]) + reserved(def) method(initialize)operator(()ident(request)operator(,) ident(parameters)operator(\)) + instance_variable(@request)operator(,) instance_variable(@parameters) operator(=) ident(request)operator(,) ident(parameters) + reserved(end) + + reserved(def) method(rewrite)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(rewrite_url)operator(()ident(rewrite_path)operator(()ident(options)operator(\))operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(to_str) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(protocol)inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(host_with_port)inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(path)inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@parameters)operator([)symbol(:controller)operator(])inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@parameters)operator([)symbol(:action)operator(])inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(parameters)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(alias_method) symbol(:to_s)operator(,) symbol(:to_str) + + ident(private) + reserved(def) method(rewrite_url)operator(()ident(path)operator(,) ident(options)operator(\)) + ident(rewritten_url) operator(=) string<delimiter(")delimiter(")> + reserved(unless) ident(options)operator([)symbol(:only_path)operator(]) + ident(rewritten_url) operator(<<) operator(()ident(options)operator([)symbol(:protocol)operator(]) operator(||) instance_variable(@request)operator(.)ident(protocol)operator(\)) + ident(rewritten_url) operator(<<) operator(()ident(options)operator([)symbol(:host)operator(]) operator(||) instance_variable(@request)operator(.)ident(host_with_port)operator(\)) + reserved(end) + + ident(rewritten_url) operator(<<) instance_variable(@request)operator(.)ident(relative_url_root)operator(.)ident(to_s) reserved(unless) ident(options)operator([)symbol(:skip_relative_url_root)operator(]) + ident(rewritten_url) operator(<<) ident(path) + ident(rewritten_url) operator(<<) string<delimiter(')content(/)delimiter(')> reserved(if) ident(options)operator([)symbol(:trailing_slash)operator(]) + ident(rewritten_url) operator(<<) string<delimiter(")content(#)inline<inline_delimiter(#{)ident(options)operator([)symbol(:anchor)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:anchor)operator(]) + + ident(rewritten_url) + reserved(end) + + reserved(def) method(rewrite_path)operator(()ident(options)operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(symbolize_keys) + ident(options)operator(.)ident(update)operator(()ident(options)operator([)symbol(:params)operator(])operator(.)ident(symbolize_keys)operator(\)) reserved(if) ident(options)operator([)symbol(:params)operator(]) + reserved(if) operator(()ident(overwrite) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:overwrite_params)operator(\))operator(\)) + ident(options)operator(.)ident(update)operator(()instance_variable(@parameters)operator(.)ident(symbolize_keys)operator(\)) + ident(options)operator(.)ident(update)operator(()ident(overwrite)operator(\)) + reserved(end) + constant(RESERVED_OPTIONS)operator(.)ident(each) operator({)operator(|)ident(k)operator(|) ident(options)operator(.)ident(delete) ident(k)operator(}) + ident(path)operator(,) ident(extra_keys) operator(=) constant(Routing)operator(::)constant(Routes)operator(.)ident(generate)operator(()ident(options)operator(.)ident(dup)operator(,) instance_variable(@request)operator(\)) comment(# Warning: Routes will mutate and violate the options hash) + + ident(path) operator(<<) ident(build_query_string)operator(()ident(options)operator(,) ident(extra_keys)operator(\)) reserved(unless) ident(extra_keys)operator(.)ident(empty?) + + ident(path) + reserved(end) + + comment(# Returns a query string with escaped keys and values from the passed hash. If the passed hash contains an "id" it'll) + comment(# be added as a path element instead of a regular parameter pair.) + reserved(def) method(build_query_string)operator(()ident(hash)operator(,) ident(only_keys) operator(=) pre_constant(nil)operator(\)) + ident(elements) operator(=) operator([)operator(]) + ident(query_string) operator(=) string<delimiter(")delimiter(")> + + ident(only_keys) operator(||=) ident(hash)operator(.)ident(keys) + + ident(only_keys)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + ident(value) operator(=) ident(hash)operator([)ident(key)operator(]) + ident(key) operator(=) constant(CGI)operator(.)ident(escape) ident(key)operator(.)ident(to_s) + reserved(if) ident(value)operator(.)ident(class) operator(==) constant(Array) + ident(key) operator(<<) string<delimiter(')content([])delimiter(')> + reserved(else) + ident(value) operator(=) operator([) ident(value) operator(]) + reserved(end) + ident(value)operator(.)ident(each) operator({) operator(|)ident(val)operator(|) ident(elements) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(=)inline<inline_delimiter(#{)constant(Routing)operator(.)ident(extract_parameter_value)operator(()ident(val)operator(\))inline_delimiter(})>delimiter(")> operator(}) + reserved(end) + + ident(query_string) operator(<<) operator(()string<delimiter(")content(?)delimiter(")> operator(+) ident(elements)operator(.)ident(join)operator(()string<delimiter(")content(&)delimiter(")>operator(\))operator(\)) reserved(unless) ident(elements)operator(.)ident(empty?) + ident(query_string) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tokenizer)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/node)delimiter(')> + +reserved(module) class(HTML) comment(#:nodoc:) + + comment(# A top-level HTMl document. You give it a body of text, and it will parse that) + comment(# text into a tree of nodes.) + reserved(class) class(Document) comment(#:nodoc:) + + comment(# The root of the parsed document.) + ident(attr_reader) symbol(:root) + + comment(# Create a new Document from the given text.) + reserved(def) method(initialize)operator(()ident(text)operator(,) ident(strict)operator(=)pre_constant(false)operator(,) ident(xml)operator(=)pre_constant(false)operator(\)) + ident(tokenizer) operator(=) constant(Tokenizer)operator(.)ident(new)operator(()ident(text)operator(\)) + instance_variable(@root) operator(=) constant(Node)operator(.)ident(new)operator(()pre_constant(nil)operator(\)) + ident(node_stack) operator(=) operator([) instance_variable(@root) operator(]) + reserved(while) ident(token) operator(=) ident(tokenizer)operator(.)ident(next) + ident(node) operator(=) constant(Node)operator(.)ident(parse)operator(()ident(node_stack)operator(.)ident(last)operator(,) ident(tokenizer)operator(.)ident(line)operator(,) ident(tokenizer)operator(.)ident(position)operator(,) ident(token)operator(\)) + + ident(node_stack)operator(.)ident(last)operator(.)ident(children) operator(<<) ident(node) reserved(unless) ident(node)operator(.)ident(tag?) operator(&&) ident(node)operator(.)ident(closing) operator(==) symbol(:close) + reserved(if) ident(node)operator(.)ident(tag?) + reserved(if) ident(node_stack)operator(.)ident(length) operator(>) integer(1) operator(&&) ident(node)operator(.)ident(closing) operator(==) symbol(:close) + reserved(if) ident(node_stack)operator(.)ident(last)operator(.)ident(name) operator(==) ident(node)operator(.)ident(name) + ident(node_stack)operator(.)ident(pop) + reserved(else) + ident(open_start) operator(=) ident(node_stack)operator(.)ident(last)operator(.)ident(position) operator(-) integer(20) + ident(open_start) operator(=) integer(0) reserved(if) ident(open_start) operator(<) integer(0) + ident(close_start) operator(=) ident(node)operator(.)ident(position) operator(-) integer(20) + ident(close_start) operator(=) integer(0) reserved(if) ident(close_start) operator(<) integer(0) + ident(msg) operator(=) string<delimiter(<<EOF)>operator(.)ident(strip)string<content( +ignoring attempt to close )inline<inline_delimiter(#{)ident(node_stack)operator(.)ident(last)operator(.)ident(name)inline_delimiter(})>content( with )inline<inline_delimiter(#{)ident(node)operator(.)ident(name)inline_delimiter(})>content( + opened at byte )inline<inline_delimiter(#{)ident(node_stack)operator(.)ident(last)operator(.)ident(position)inline_delimiter(})>content(, line )inline<inline_delimiter(#{)ident(node_stack)operator(.)ident(last)operator(.)ident(line)inline_delimiter(})>content( + closed at byte )inline<inline_delimiter(#{)ident(node)operator(.)ident(position)inline_delimiter(})>content(, line )inline<inline_delimiter(#{)ident(node)operator(.)ident(line)inline_delimiter(})>content( + attributes at open: )inline<inline_delimiter(#{)ident(node_stack)operator(.)ident(last)operator(.)ident(attributes)operator(.)ident(inspect)inline_delimiter(})>content( + text around open: )inline<inline_delimiter(#{)ident(text)operator([)ident(open_start)operator(,)integer(40)operator(])operator(.)ident(inspect)inline_delimiter(})>content( + text around close: )inline<inline_delimiter(#{)ident(text)operator([)ident(close_start)operator(,)integer(40)operator(])operator(.)ident(inspect)inline_delimiter(})>delimiter( +EOF)> + ident(strict) operator(?) ident(raise)operator(()ident(msg)operator(\)) operator(:) ident(warn)operator(()ident(msg)operator(\)) + reserved(end) + reserved(elsif) operator(!)ident(node)operator(.)ident(childless?)operator(()ident(xml)operator(\)) operator(&&) ident(node)operator(.)ident(closing) operator(!=) symbol(:close) + ident(node_stack)operator(.)ident(push) ident(node) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Search the tree for (and return\) the first node that matches the given) + comment(# conditions. The conditions are interpreted differently for different node) + comment(# types, see HTML::Text#find and HTML::Tag#find.) + reserved(def) method(find)operator(()ident(conditions)operator(\)) + instance_variable(@root)operator(.)ident(find)operator(()ident(conditions)operator(\)) + reserved(end) + + comment(# Search the tree for (and return\) all nodes that match the given) + comment(# conditions. The conditions are interpreted differently for different node) + comment(# types, see HTML::Text#find and HTML::Tag#find.) + reserved(def) method(find_all)operator(()ident(conditions)operator(\)) + instance_variable(@root)operator(.)ident(find_all)operator(()ident(conditions)operator(\)) + reserved(end) + + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(strscan)delimiter(')> + +reserved(module) class(HTML) comment(#:nodoc:) + + reserved(class) class(Conditions) operator(<) constant(Hash) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(hash)operator(\)) + reserved(super)operator(()operator(\)) + ident(hash) operator(=) operator({) symbol(:content) operator(=)operator(>) ident(hash) operator(}) reserved(unless) constant(Hash) operator(===) ident(hash) + ident(hash) operator(=) ident(keys_to_symbols)operator(()ident(hash)operator(\)) + ident(hash)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,)ident(v)operator(|) + reserved(case) ident(k) + reserved(when) symbol(:tag)operator(,) symbol(:content) reserved(then) + comment(# keys are valid, and require no further processing) + reserved(when) symbol(:attributes) reserved(then) + ident(hash)operator([)ident(k)operator(]) operator(=) ident(keys_to_strings)operator(()ident(v)operator(\)) + reserved(when) symbol(:parent)operator(,) symbol(:child)operator(,) symbol(:ancestor)operator(,) symbol(:descendant)operator(,) symbol(:sibling)operator(,) symbol(:before)operator(,) + symbol(:after) + ident(hash)operator([)ident(k)operator(]) operator(=) constant(Conditions)operator(.)ident(new)operator(()ident(v)operator(\)) + reserved(when) symbol(:children) + ident(hash)operator([)ident(k)operator(]) operator(=) ident(v) operator(=) ident(keys_to_symbols)operator(()ident(v)operator(\)) + ident(v)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,)ident(v2)operator(|) + reserved(case) ident(k) + reserved(when) symbol(:count)operator(,) symbol(:greater_than)operator(,) symbol(:less_than) + comment(# keys are valid, and require no further processing) + reserved(when) symbol(:only) + ident(v)operator([)ident(k)operator(]) operator(=) constant(Conditions)operator(.)ident(new)operator(()ident(v2)operator(\)) + reserved(else) + ident(raise) string<delimiter(")content(illegal key )inline<inline_delimiter(#{)ident(k)operator(.)ident(inspect)inline_delimiter(})>content( => )inline<inline_delimiter(#{)ident(v2)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(else) + ident(raise) string<delimiter(")content(illegal key )inline<inline_delimiter(#{)ident(k)operator(.)ident(inspect)inline_delimiter(})>content( => )inline<inline_delimiter(#{)ident(v)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + ident(update) ident(hash) + reserved(end) + + ident(private) + + reserved(def) method(keys_to_strings)operator(()ident(hash)operator(\)) + ident(hash)operator(.)ident(keys)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(h)operator(,)ident(k)operator(|) + ident(h)operator([)ident(k)operator(.)ident(to_s)operator(]) operator(=) ident(hash)operator([)ident(k)operator(]) + ident(h) + reserved(end) + reserved(end) + + reserved(def) method(keys_to_symbols)operator(()ident(hash)operator(\)) + ident(hash)operator(.)ident(keys)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(h)operator(,)ident(k)operator(|) + ident(raise) string<delimiter(")content(illegal key )inline<inline_delimiter(#{)ident(k)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> reserved(unless) ident(k)operator(.)ident(respond_to?)operator(()symbol(:to_sym)operator(\)) + ident(h)operator([)ident(k)operator(.)ident(to_sym)operator(]) operator(=) ident(hash)operator([)ident(k)operator(]) + ident(h) + reserved(end) + reserved(end) + reserved(end) + + comment(# The base class of all nodes, textual and otherwise, in an HTML document.) + reserved(class) class(Node) comment(#:nodoc:) + comment(# The array of children of this node. Not all nodes have children.) + ident(attr_reader) symbol(:children) + + comment(# The parent node of this node. All nodes have a parent, except for the) + comment(# root node.) + ident(attr_reader) symbol(:parent) + + comment(# The line number of the input where this node was begun) + ident(attr_reader) symbol(:line) + + comment(# The byte position in the input where this node was begun) + ident(attr_reader) symbol(:position) + + comment(# Create a new node as a child of the given parent.) + reserved(def) method(initialize)operator(()ident(parent)operator(,) ident(line)operator(=)integer(0)operator(,) ident(pos)operator(=)integer(0)operator(\)) + instance_variable(@parent) operator(=) ident(parent) + instance_variable(@children) operator(=) operator([)operator(]) + instance_variable(@line)operator(,) instance_variable(@position) operator(=) ident(line)operator(,) ident(pos) + reserved(end) + + comment(# Return a textual representation of the node.) + reserved(def) method(to_s) + ident(s) operator(=) string<delimiter(")delimiter(")> + instance_variable(@children)operator(.)ident(each) operator({) operator(|)ident(child)operator(|) ident(s) operator(<<) ident(child)operator(.)ident(to_s) operator(}) + ident(s) + reserved(end) + + comment(# Return false (subclasses must override this to provide specific matching) + comment(# behavior.\) +conditions+ may be of any type.) + reserved(def) method(match)operator(()ident(conditions)operator(\)) + pre_constant(false) + reserved(end) + + comment(# Search the children of this node for the first node for which #find) + comment(# returns non +nil+. Returns the result of the #find call that succeeded.) + reserved(def) method(find)operator(()ident(conditions)operator(\)) + ident(conditions) operator(=) ident(validate_conditions)operator(()ident(conditions)operator(\)) + + instance_variable(@children)operator(.)ident(each) reserved(do) operator(|)ident(child)operator(|) + ident(node) operator(=) ident(child)operator(.)ident(find)operator(()ident(conditions)operator(\)) + reserved(return) ident(node) reserved(if) ident(node) + reserved(end) + pre_constant(nil) + reserved(end) + + comment(# Search for all nodes that match the given conditions, and return them) + comment(# as an array.) + reserved(def) method(find_all)operator(()ident(conditions)operator(\)) + ident(conditions) operator(=) ident(validate_conditions)operator(()ident(conditions)operator(\)) + + ident(matches) operator(=) operator([)operator(]) + ident(matches) operator(<<) pre_constant(self) reserved(if) ident(match)operator(()ident(conditions)operator(\)) + instance_variable(@children)operator(.)ident(each) reserved(do) operator(|)ident(child)operator(|) + ident(matches)operator(.)ident(concat) ident(child)operator(.)ident(find_all)operator(()ident(conditions)operator(\)) + reserved(end) + ident(matches) + reserved(end) + + comment(# Returns +false+. Subclasses may override this if they define a kind of) + comment(# tag.) + reserved(def) method(tag?) + pre_constant(false) + reserved(end) + + reserved(def) method(validate_conditions)operator(()ident(conditions)operator(\)) + constant(Conditions) operator(===) ident(conditions) operator(?) ident(conditions) operator(:) constant(Conditions)operator(.)ident(new)operator(()ident(conditions)operator(\)) + reserved(end) + + reserved(def) method(==)operator(()ident(node)operator(\)) + reserved(return) pre_constant(false) reserved(unless) pre_constant(self)operator(.)ident(class) operator(==) ident(node)operator(.)ident(class) operator(&&) ident(children)operator(.)ident(size) operator(==) ident(node)operator(.)ident(children)operator(.)ident(size) + + ident(equivalent) operator(=) pre_constant(true) + + ident(children)operator(.)ident(size)operator(.)ident(times) reserved(do) operator(|)ident(i)operator(|) + ident(equivalent) operator(&&=) ident(children)operator([)ident(i)operator(]) operator(==) ident(node)operator(.)ident(children)operator([)ident(i)operator(]) + reserved(end) + + ident(equivalent) + reserved(end) + + reserved(class) operator(<<)class(self) + reserved(def) method(parse)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(content)operator(,) ident(strict)operator(=)pre_constant(true)operator(\)) + reserved(if) ident(content) operator(!)operator(~) regexp<delimiter(/)content(^<)char(\\S)delimiter(/)> + constant(Text)operator(.)ident(new)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(content)operator(\)) + reserved(else) + ident(scanner) operator(=) constant(StringScanner)operator(.)ident(new)operator(()ident(content)operator(\)) + + reserved(unless) ident(scanner)operator(.)ident(skip)operator(()regexp<delimiter(/)content(<)delimiter(/)>operator(\)) + reserved(if) ident(strict) + ident(raise) string<delimiter(")content(expected <)delimiter(")> + reserved(else) + reserved(return) constant(Text)operator(.)ident(new)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(content)operator(\)) + reserved(end) + reserved(end) + + reserved(if) ident(scanner)operator(.)ident(skip)operator(()regexp<delimiter(/)content(!)char(\\[)content(CDATA)char(\\[)delimiter(/)>operator(\)) + ident(scanner)operator(.)ident(scan_until)operator(()regexp<delimiter(/)char(\\])char(\\])content(>)delimiter(/)>operator(\)) + reserved(return) constant(CDATA)operator(.)ident(new)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(scanner)operator(.)ident(pre_match)operator(\)) + reserved(end) + + ident(closing) operator(=) operator(() ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\)) operator(?) symbol(:close) operator(:) pre_constant(nil) operator(\)) + reserved(return) constant(Text)operator(.)ident(new)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(content)operator(\)) reserved(unless) ident(name) operator(=) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content([)char(\\w)content(:]+)delimiter(/)>operator(\)) + ident(name)operator(.)ident(downcase!) + + reserved(unless) ident(closing) + ident(scanner)operator(.)ident(skip)operator(()regexp<delimiter(/)char(\\s)content(*)delimiter(/)>operator(\)) + ident(attributes) operator(=) operator({)operator(}) + reserved(while) ident(attr) operator(=) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content([-)char(\\w)content(:]+)delimiter(/)>operator(\)) + ident(value) operator(=) pre_constant(true) + reserved(if) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)char(\\s)content(*=)char(\\s)content(*)delimiter(/)>operator(\)) + reserved(if) ident(delim) operator(=) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content(['"])delimiter(/)>operator(\)) + ident(value) operator(=) string<delimiter(")delimiter(")> + reserved(while) ident(text) operator(=) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content([^)inline<inline_delimiter(#{)ident(delim)inline_delimiter(})>char(\\\\)content(]+|.)delimiter(/)>operator(\)) + reserved(case) ident(text) + reserved(when) string<delimiter(")char(\\\\)delimiter(")> reserved(then) + ident(value) operator(<<) ident(text) + ident(value) operator(<<) ident(scanner)operator(.)ident(getch) + reserved(when) ident(delim) + reserved(break) + reserved(else) ident(value) operator(<<) ident(text) + reserved(end) + reserved(end) + reserved(else) + ident(value) operator(=) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content([^)char(\\s)content(>)char(\\/)content(]+)delimiter(/)>operator(\)) + reserved(end) + reserved(end) + ident(attributes)operator([)ident(attr)operator(.)ident(downcase)operator(]) operator(=) ident(value) + ident(scanner)operator(.)ident(skip)operator(()regexp<delimiter(/)char(\\s)content(*)delimiter(/)>operator(\)) + reserved(end) + + ident(closing) operator(=) operator(() ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\)) operator(?) symbol(:self) operator(:) pre_constant(nil) operator(\)) + reserved(end) + + reserved(unless) ident(scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)char(\\s)content(*>)delimiter(/)>operator(\)) + reserved(if) ident(strict) + ident(raise) string<delimiter(")content(expected > (got )inline<inline_delimiter(#{)ident(scanner)operator(.)ident(rest)operator(.)ident(inspect)inline_delimiter(})>content( for )inline<inline_delimiter(#{)ident(content)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(attributes)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> + reserved(else) + comment(# throw away all text until we find what we're looking for) + ident(scanner)operator(.)ident(skip_until)operator(()regexp<delimiter(/)content(>)delimiter(/)>operator(\)) reserved(or) ident(scanner)operator(.)ident(terminate) + reserved(end) + reserved(end) + + constant(Tag)operator(.)ident(new)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(name)operator(,) ident(attributes)operator(,) ident(closing)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# A node that represents text, rather than markup.) + reserved(class) class(Text) operator(<) constant(Node) comment(#:nodoc:) + + ident(attr_reader) symbol(:content) + + comment(# Creates a new text node as a child of the given parent, with the given) + comment(# content.) + reserved(def) method(initialize)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(content)operator(\)) + reserved(super)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(\)) + instance_variable(@content) operator(=) ident(content) + reserved(end) + + comment(# Returns the content of this node.) + reserved(def) method(to_s) + instance_variable(@content) + reserved(end) + + comment(# Returns +self+ if this node meets the given conditions. Text nodes support) + comment(# conditions of the following kinds:) + comment(#) + comment(# * if +conditions+ is a string, it must be a substring of the node's) + comment(# content) + comment(# * if +conditions+ is a regular expression, it must match the node's) + comment(# content) + comment(# * if +conditions+ is a hash, it must contain a <tt>:content</tt> key that) + comment(# is either a string or a regexp, and which is interpreted as described) + comment(# above.) + reserved(def) method(find)operator(()ident(conditions)operator(\)) + ident(match)operator(()ident(conditions)operator(\)) operator(&&) pre_constant(self) + reserved(end) + + comment(# Returns non-+nil+ if this node meets the given conditions, or +nil+) + comment(# otherwise. See the discussion of #find for the valid conditions.) + reserved(def) method(match)operator(()ident(conditions)operator(\)) + reserved(case) ident(conditions) + reserved(when) constant(String) + instance_variable(@content)operator(.)ident(index)operator(()ident(conditions)operator(\)) + reserved(when) constant(Regexp) + instance_variable(@content) operator(=)operator(~) ident(conditions) + reserved(when) constant(Hash) + ident(conditions) operator(=) ident(validate_conditions)operator(()ident(conditions)operator(\)) + + comment(# Text nodes only have :content, :parent, :ancestor) + reserved(unless) operator(()ident(conditions)operator(.)ident(keys) operator(-) operator([)symbol(:content)operator(,) symbol(:parent)operator(,) symbol(:ancestor)operator(])operator(\))operator(.)ident(empty?) + reserved(return) pre_constant(false) + reserved(end) + + ident(match)operator(()ident(conditions)operator([)symbol(:content)operator(])operator(\)) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(==)operator(()ident(node)operator(\)) + reserved(return) pre_constant(false) reserved(unless) reserved(super) + ident(content) operator(==) ident(node)operator(.)ident(content) + reserved(end) + reserved(end) + + comment(# A CDATA node is simply a text node with a specialized way of displaying) + comment(# itself.) + reserved(class) class(CDATA) operator(<) constant(Text) comment(#:nodoc:) + reserved(def) method(to_s) + string<delimiter(")content(<![CDATA[)inline<inline_delimiter(#{)reserved(super)inline_delimiter(})>content(]>)delimiter(")> + reserved(end) + reserved(end) + + comment(# A Tag is any node that represents markup. It may be an opening tag, a) + comment(# closing tag, or a self-closing tag. It has a name, and may have a hash of) + comment(# attributes.) + reserved(class) class(Tag) operator(<) constant(Node) comment(#:nodoc:) + + comment(# Either +nil+, <tt>:close</tt>, or <tt>:self</tt>) + ident(attr_reader) symbol(:closing) + + comment(# Either +nil+, or a hash of attributes for this node.) + ident(attr_reader) symbol(:attributes) + + comment(# The name of this tag.) + ident(attr_reader) symbol(:name) + + comment(# Create a new node as a child of the given parent, using the given content) + comment(# to describe the node. It will be parsed and the node name, attributes and) + comment(# closing status extracted.) + reserved(def) method(initialize)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(,) ident(name)operator(,) ident(attributes)operator(,) ident(closing)operator(\)) + reserved(super)operator(()ident(parent)operator(,) ident(line)operator(,) ident(pos)operator(\)) + instance_variable(@name) operator(=) ident(name) + instance_variable(@attributes) operator(=) ident(attributes) + instance_variable(@closing) operator(=) ident(closing) + reserved(end) + + comment(# A convenience for obtaining an attribute of the node. Returns +nil+ if) + comment(# the node has no attributes.) + reserved(def) method([])operator(()ident(attr)operator(\)) + instance_variable(@attributes) operator(?) instance_variable(@attributes)operator([)ident(attr)operator(]) operator(:) pre_constant(nil) + reserved(end) + + comment(# Returns non-+nil+ if this tag can contain child nodes.) + reserved(def) method(childless?)operator(()ident(xml) operator(=) pre_constant(false)operator(\)) + reserved(return) pre_constant(false) reserved(if) ident(xml) operator(&&) instance_variable(@closing)operator(.)ident(nil?) + operator(!)instance_variable(@closing)operator(.)ident(nil?) operator(||) + instance_variable(@name) operator(=)operator(~) regexp<delimiter(/)content(^(img|br|hr|link|meta|area|base|basefont| + col|frame|input|isindex|param\)$)delimiter(/)modifier(ox)> + reserved(end) + + comment(# Returns a textual representation of the node) + reserved(def) method(to_s) + reserved(if) instance_variable(@closing) operator(==) symbol(:close) + string<delimiter(")content(</)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content(>)delimiter(")> + reserved(else) + ident(s) operator(=) string<delimiter(")content(<)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>delimiter(")> + instance_variable(@attributes)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,)ident(v)operator(|) + ident(s) operator(<<) string<delimiter(")content( )inline<inline_delimiter(#{)ident(k)inline_delimiter(})>delimiter(")> + ident(s) operator(<<) string<delimiter(")content(=')inline<inline_delimiter(#{)ident(v)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,)string<delimiter(")char(\\\\)char(\\\\)content(')delimiter(")>operator(\))inline_delimiter(})>content(')delimiter(")> reserved(if) constant(String) operator(===) ident(v) + reserved(end) + ident(s) operator(<<) string<delimiter(")content( /)delimiter(")> reserved(if) instance_variable(@closing) operator(==) symbol(:self) + ident(s) operator(<<) string<delimiter(")content(>)delimiter(")> + instance_variable(@children)operator(.)ident(each) operator({) operator(|)ident(child)operator(|) ident(s) operator(<<) ident(child)operator(.)ident(to_s) operator(}) + ident(s) operator(<<) string<delimiter(")content(</)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content(>)delimiter(")> reserved(if) instance_variable(@closing) operator(!=) symbol(:self) operator(&&) operator(!)instance_variable(@children)operator(.)ident(empty?) + ident(s) + reserved(end) + reserved(end) + + comment(# If either the node or any of its children meet the given conditions, the) + comment(# matching node is returned. Otherwise, +nil+ is returned. (See the) + comment(# description of the valid conditions in the +match+ method.\)) + reserved(def) method(find)operator(()ident(conditions)operator(\)) + ident(match)operator(()ident(conditions)operator(\)) operator(&&) pre_constant(self) operator(||) reserved(super) + reserved(end) + + comment(# Returns +true+, indicating that this node represents an HTML tag.) + reserved(def) method(tag?) + pre_constant(true) + reserved(end) + + comment(# Returns +true+ if the node meets any of the given conditions. The) + comment(# +conditions+ parameter must be a hash of any of the following keys) + comment(# (all are optional\):) + comment(#) + comment(# * <tt>:tag</tt>: the node name must match the corresponding value) + comment(# * <tt>:attributes</tt>: a hash. The node's values must match the) + comment(# corresponding values in the hash.) + comment(# * <tt>:parent</tt>: a hash. The node's parent must match the) + comment(# corresponding hash.) + comment(# * <tt>:child</tt>: a hash. At least one of the node's immediate children) + comment(# must meet the criteria described by the hash.) + comment(# * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must) + comment(# meet the criteria described by the hash.) + comment(# * <tt>:descendant</tt>: a hash. At least one of the node's descendants) + comment(# must meet the criteria described by the hash.) + comment(# * <tt>:sibling</tt>: a hash. At least one of the node's siblings must) + comment(# meet the criteria described by the hash.) + comment(# * <tt>:after</tt>: a hash. The node must be after any sibling meeting) + comment(# the criteria described by the hash, and at least one sibling must match.) + comment(# * <tt>:before</tt>: a hash. The node must be before any sibling meeting) + comment(# the criteria described by the hash, and at least one sibling must match.) + comment(# * <tt>:children</tt>: a hash, for counting children of a node. Accepts the) + comment(# keys:) + comment(# ** <tt>:count</tt>: either a number or a range which must equal (or) + comment(# include\) the number of children that match.) + comment(# ** <tt>:less_than</tt>: the number of matching children must be less than) + comment(# this number.) + comment(# ** <tt>:greater_than</tt>: the number of matching children must be) + comment(# greater than this number.) + comment(# ** <tt>:only</tt>: another hash consisting of the keys to use) + comment(# to match on the children, and only matching children will be) + comment(# counted.) + comment(#) + comment(# Conditions are matched using the following algorithm:) + comment(#) + comment(# * if the condition is a string, it must be a substring of the value.) + comment(# * if the condition is a regexp, it must match the value.) + comment(# * if the condition is a number, the value must match number.to_s.) + comment(# * if the condition is +true+, the value must not be +nil+.) + comment(# * if the condition is +false+ or +nil+, the value must be +nil+.) + comment(#) + comment(# Usage:) + comment(#) + comment(# # test if the node is a "span" tag) + comment(# node.match :tag => "span") + comment(#) + comment(# # test if the node's parent is a "div") + comment(# node.match :parent => { :tag => "div" }) + comment(#) + comment(# # test if any of the node's ancestors are "table" tags) + comment(# node.match :ancestor => { :tag => "table" }) + comment(#) + comment(# # test if any of the node's immediate children are "em" tags) + comment(# node.match :child => { :tag => "em" }) + comment(#) + comment(# # test if any of the node's descendants are "strong" tags) + comment(# node.match :descendant => { :tag => "strong" }) + comment(#) + comment(# # test if the node has between 2 and 4 span tags as immediate children) + comment(# node.match :children => { :count => 2..4, :only => { :tag => "span" } } ) + comment(#) + comment(# # get funky: test to see if the node is a "div", has a "ul" ancestor) + comment(# # and an "li" parent (with "class" = "enum"\), and whether or not it has) + comment(# # a "span" descendant that contains # text matching /hello world/:) + comment(# node.match :tag => "div",) + comment(# :ancestor => { :tag => "ul" },) + comment(# :parent => { :tag => "li",) + comment(# :attributes => { :class => "enum" } },) + comment(# :descendant => { :tag => "span",) + comment(# :child => /hello world/ }) + reserved(def) method(match)operator(()ident(conditions)operator(\)) + ident(conditions) operator(=) ident(validate_conditions)operator(()ident(conditions)operator(\)) + + comment(# check content of child nodes) + reserved(if) ident(conditions)operator([)symbol(:content)operator(]) + reserved(if) ident(children)operator(.)ident(empty?) + reserved(return) pre_constant(false) reserved(unless) ident(match_condition)operator(()string<delimiter(")delimiter(")>operator(,) ident(conditions)operator([)symbol(:content)operator(])operator(\)) + reserved(else) + reserved(return) pre_constant(false) reserved(unless) ident(children)operator(.)ident(find) operator({) operator(|)ident(child)operator(|) ident(child)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:content)operator(])operator(\)) operator(}) + reserved(end) + reserved(end) + + comment(# test the name) + reserved(return) pre_constant(false) reserved(unless) ident(match_condition)operator(()instance_variable(@name)operator(,) ident(conditions)operator([)symbol(:tag)operator(])operator(\)) reserved(if) ident(conditions)operator([)symbol(:tag)operator(]) + + comment(# test attributes) + operator(()ident(conditions)operator([)symbol(:attributes)operator(]) operator(||) operator({)operator(})operator(\))operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(return) pre_constant(false) reserved(unless) ident(match_condition)operator(()pre_constant(self)operator([)ident(key)operator(])operator(,) ident(value)operator(\)) + reserved(end) + + comment(# test parent) + reserved(return) pre_constant(false) reserved(unless) ident(parent)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:parent)operator(])operator(\)) reserved(if) ident(conditions)operator([)symbol(:parent)operator(]) + + comment(# test children) + reserved(return) pre_constant(false) reserved(unless) ident(children)operator(.)ident(find) operator({) operator(|)ident(child)operator(|) ident(child)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:child)operator(])operator(\)) operator(}) reserved(if) ident(conditions)operator([)symbol(:child)operator(]) + + comment(# test ancestors) + reserved(if) ident(conditions)operator([)symbol(:ancestor)operator(]) + reserved(return) pre_constant(false) reserved(unless) ident(catch) symbol(:found) reserved(do) + ident(p) operator(=) pre_constant(self) + ident(throw) symbol(:found)operator(,) pre_constant(true) reserved(if) ident(p)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:ancestor)operator(])operator(\)) reserved(while) ident(p) operator(=) ident(p)operator(.)ident(parent) + reserved(end) + reserved(end) + + comment(# test descendants) + reserved(if) ident(conditions)operator([)symbol(:descendant)operator(]) + reserved(return) pre_constant(false) reserved(unless) ident(children)operator(.)ident(find) reserved(do) operator(|)ident(child)operator(|) + comment(# test the child) + ident(child)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:descendant)operator(])operator(\)) operator(||) + comment(# test the child's descendants) + ident(child)operator(.)ident(match)operator(()symbol(:descendant) operator(=)operator(>) ident(conditions)operator([)symbol(:descendant)operator(])operator(\)) + reserved(end) + reserved(end) + + comment(# count children) + reserved(if) ident(opts) operator(=) ident(conditions)operator([)symbol(:children)operator(]) + ident(matches) operator(=) ident(children)operator(.)ident(select) reserved(do) operator(|)ident(c)operator(|) + ident(c)operator(.)ident(match)operator(()regexp<delimiter(/)content(.)delimiter(/)>operator(\)) reserved(or) + operator(()ident(c)operator(.)ident(kind_of?)operator(()constant(HTML)operator(::)constant(Tag)operator(\)) reserved(and) operator(()ident(c)operator(.)ident(closing) operator(==) symbol(:self) reserved(or) operator(!) ident(c)operator(.)ident(childless?)operator(\))operator(\)) + reserved(end) + + ident(matches) operator(=) ident(matches)operator(.)ident(select) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(match)operator(()ident(opts)operator([)symbol(:only)operator(])operator(\)) operator(}) reserved(if) ident(opts)operator([)symbol(:only)operator(]) + ident(opts)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(next) reserved(if) ident(key) operator(==) symbol(:only) + reserved(case) ident(key) + reserved(when) symbol(:count) + reserved(if) constant(Integer) operator(===) ident(value) + reserved(return) pre_constant(false) reserved(if) ident(matches)operator(.)ident(length) operator(!=) ident(value) + reserved(else) + reserved(return) pre_constant(false) reserved(unless) ident(value)operator(.)ident(include?)operator(()ident(matches)operator(.)ident(length)operator(\)) + reserved(end) + reserved(when) symbol(:less_than) + reserved(return) pre_constant(false) reserved(unless) ident(matches)operator(.)ident(length) operator(<) ident(value) + reserved(when) symbol(:greater_than) + reserved(return) pre_constant(false) reserved(unless) ident(matches)operator(.)ident(length) operator(>) ident(value) + reserved(else) ident(raise) string<delimiter(")content(unknown count condition )inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + comment(# test siblings) + reserved(if) ident(conditions)operator([)symbol(:sibling)operator(]) operator(||) ident(conditions)operator([)symbol(:before)operator(]) operator(||) ident(conditions)operator([)symbol(:after)operator(]) + ident(siblings) operator(=) ident(parent) operator(?) ident(parent)operator(.)ident(children) operator(:) operator([)operator(]) + ident(self_index) operator(=) ident(siblings)operator(.)ident(index)operator(()pre_constant(self)operator(\)) + + reserved(if) ident(conditions)operator([)symbol(:sibling)operator(]) + reserved(return) pre_constant(false) reserved(unless) ident(siblings)operator(.)ident(detect) reserved(do) operator(|)ident(s)operator(|) + ident(s) operator(!=) pre_constant(self) operator(&&) ident(s)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:sibling)operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(if) ident(conditions)operator([)symbol(:before)operator(]) + reserved(return) pre_constant(false) reserved(unless) ident(siblings)operator([)ident(self_index)operator(+)integer(1)operator(..)integer(-1)operator(])operator(.)ident(detect) reserved(do) operator(|)ident(s)operator(|) + ident(s) operator(!=) pre_constant(self) operator(&&) ident(s)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:before)operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(if) ident(conditions)operator([)symbol(:after)operator(]) + reserved(return) pre_constant(false) reserved(unless) ident(siblings)operator([)integer(0)operator(,)ident(self_index)operator(])operator(.)ident(detect) reserved(do) operator(|)ident(s)operator(|) + ident(s) operator(!=) pre_constant(self) operator(&&) ident(s)operator(.)ident(match)operator(()ident(conditions)operator([)symbol(:after)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + + pre_constant(true) + reserved(end) + + reserved(def) method(==)operator(()ident(node)operator(\)) + reserved(return) pre_constant(false) reserved(unless) reserved(super) + reserved(return) pre_constant(false) reserved(unless) ident(closing) operator(==) ident(node)operator(.)ident(closing) operator(&&) pre_constant(self)operator(.)ident(name) operator(==) ident(node)operator(.)ident(name) + ident(attributes) operator(==) ident(node)operator(.)ident(attributes) + reserved(end) + + ident(private) + comment(# Match the given value to the given condition.) + reserved(def) method(match_condition)operator(()ident(value)operator(,) ident(condition)operator(\)) + reserved(case) ident(condition) + reserved(when) constant(String) + ident(value) operator(&&) ident(value) operator(==) ident(condition) + reserved(when) constant(Regexp) + ident(value) operator(&&) ident(value)operator(.)ident(match)operator(()ident(condition)operator(\)) + reserved(when) constant(Numeric) + ident(value) operator(==) ident(condition)operator(.)ident(to_s) + reserved(when) pre_constant(true) + operator(!)ident(value)operator(.)ident(nil?) + reserved(when) pre_constant(false)operator(,) pre_constant(nil) + ident(value)operator(.)ident(nil?) + reserved(else) + pre_constant(false) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(strscan)delimiter(')> + +reserved(module) class(HTML) comment(#:nodoc:) + + comment(# A simple HTML tokenizer. It simply breaks a stream of text into tokens, where each) + comment(# token is a string. Each string represents either "text", or an HTML element.) + comment(#) + comment(# This currently assumes valid XHTML, which means no free < or > characters.) + comment(#) + comment(# Usage:) + comment(#) + comment(# tokenizer = HTML::Tokenizer.new(text\)) + comment(# while token = tokenizer.next) + comment(# p token) + comment(# end) + reserved(class) class(Tokenizer) comment(#:nodoc:) + + comment(# The current (byte\) position in the text) + ident(attr_reader) symbol(:position) + + comment(# The current line number) + ident(attr_reader) symbol(:line) + + comment(# Create a new Tokenizer for the given text.) + reserved(def) method(initialize)operator(()ident(text)operator(\)) + instance_variable(@scanner) operator(=) constant(StringScanner)operator(.)ident(new)operator(()ident(text)operator(\)) + instance_variable(@position) operator(=) integer(0) + instance_variable(@line) operator(=) integer(0) + instance_variable(@current_line) operator(=) integer(1) + reserved(end) + + comment(# Return the next token in the sequence, or +nil+ if there are no more tokens in) + comment(# the stream.) + reserved(def) method(next) + reserved(return) pre_constant(nil) reserved(if) instance_variable(@scanner)operator(.)ident(eos?) + instance_variable(@position) operator(=) instance_variable(@scanner)operator(.)ident(pos) + instance_variable(@line) operator(=) instance_variable(@current_line) + reserved(if) instance_variable(@scanner)operator(.)ident(check)operator(()regexp<delimiter(/)content(<)char(\\S)delimiter(/)>operator(\)) + ident(update_current_line)operator(()ident(scan_tag)operator(\)) + reserved(else) + ident(update_current_line)operator(()ident(scan_text)operator(\)) + reserved(end) + reserved(end) + + ident(private) + + comment(# Treat the text at the current position as a tag, and scan it. Supports) + comment(# comments, doctype tags, and regular tags, and ignores less-than and) + comment(# greater-than characters within quoted strings.) + reserved(def) method(scan_tag) + ident(tag) operator(=) instance_variable(@scanner)operator(.)ident(getch) + reserved(if) instance_variable(@scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content(!--)delimiter(/)>operator(\)) comment(# comment) + ident(tag) operator(<<) instance_variable(@scanner)operator(.)ident(matched) + ident(tag) operator(<<) operator(()instance_variable(@scanner)operator(.)ident(scan_until)operator(()regexp<delimiter(/)content(--)char(\\s)content(*>)delimiter(/)>operator(\)) operator(||) instance_variable(@scanner)operator(.)ident(scan_until)operator(()regexp<delimiter(/)char(\\Z)delimiter(/)>operator(\))operator(\)) + reserved(elsif) instance_variable(@scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content(!)char(\\[)content(CDATA)char(\\[)delimiter(/)>operator(\)) + ident(tag) operator(<<) instance_variable(@scanner)operator(.)ident(matched) + ident(tag) operator(<<) instance_variable(@scanner)operator(.)ident(scan_until)operator(()regexp<delimiter(/)char(\\])char(\\])content(>)delimiter(/)>operator(\)) + reserved(elsif) instance_variable(@scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content(!)delimiter(/)>operator(\)) comment(# doctype) + ident(tag) operator(<<) instance_variable(@scanner)operator(.)ident(matched) + ident(tag) operator(<<) ident(consume_quoted_regions) + reserved(else) + ident(tag) operator(<<) ident(consume_quoted_regions) + reserved(end) + ident(tag) + reserved(end) + + comment(# Scan all text up to the next < character and return it.) + reserved(def) method(scan_text) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@scanner)operator(.)ident(getch)inline_delimiter(})>inline<inline_delimiter(#{)instance_variable(@scanner)operator(.)ident(scan)operator(()regexp<delimiter(/)content([^<]*)delimiter(/)>operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Counts the number of newlines in the text and updates the current line) + comment(# accordingly.) + reserved(def) method(update_current_line)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(scan)operator(()regexp<delimiter(/)char(\\r)content(?)char(\\n)delimiter(/)>operator(\)) operator({) instance_variable(@current_line) operator(+=) integer(1) operator(}) + reserved(end) + + comment(# Skips over quoted strings, so that less-than and greater-than characters) + comment(# within the strings are ignored.) + reserved(def) method(consume_quoted_regions) + ident(text) operator(=) string<delimiter(")delimiter(")> + ident(loop) reserved(do) + ident(match) operator(=) instance_variable(@scanner)operator(.)ident(scan_until)operator(()regexp<delimiter(/)content(['"<>])delimiter(/)>operator(\)) reserved(or) reserved(break) + + ident(delim) operator(=) instance_variable(@scanner)operator(.)ident(matched) + reserved(if) ident(delim) operator(==) string<delimiter(")content(<)delimiter(")> + ident(match) operator(=) ident(match)operator(.)ident(chop) + instance_variable(@scanner)operator(.)ident(pos) operator(-=) integer(1) + reserved(end) + + ident(text) operator(<<) ident(match) + reserved(break) reserved(if) ident(delim) operator(==) string<delimiter(")content(<)delimiter(")> operator(||) ident(delim) operator(==) string<delimiter(")content(>)delimiter(")> + + comment(# consume the quoted region) + reserved(while) ident(match) operator(=) instance_variable(@scanner)operator(.)ident(scan_until)operator(()regexp<delimiter(/)content([)char(\\\\)inline<inline_delimiter(#{)ident(delim)inline_delimiter(})>content(])delimiter(/)>operator(\)) + ident(text) operator(<<) ident(match) + reserved(break) reserved(if) instance_variable(@scanner)operator(.)ident(matched) operator(==) ident(delim) + ident(text) operator(<<) instance_variable(@scanner)operator(.)ident(getch) comment(# skip the escaped character) + reserved(end) + reserved(end) + ident(text) + reserved(end) + reserved(end) + +reserved(end) +reserved(module) class(HTML) comment(#:nodoc:) + reserved(module) class(Version) comment(#:nodoc:) + + constant(MAJOR) operator(=) integer(0) + constant(MINOR) operator(=) integer(5) + constant(TINY) operator(=) integer(3) + + constant(STRING) operator(=) operator([) constant(MAJOR)operator(,) constant(MINOR)operator(,) constant(TINY) operator(])operator(.)ident(join)operator(()string<delimiter(")content(.)delimiter(")>operator(\)) + + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(rexml/document)delimiter(')> + +comment(# SimpleXML like xml parser. Written by leon breet from the ruby on rails Mailing list) +reserved(class) class(XmlNode) comment(#:nodoc:) + ident(attr) symbol(:node) + + reserved(def) method(initialize)operator(()ident(node)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@node) operator(=) ident(node) + instance_variable(@children) operator(=) operator({)operator(}) + instance_variable(@raise_errors) operator(=) ident(options)operator([)symbol(:raise_errors)operator(]) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(from_xml)operator(()ident(xml_or_io)operator(\)) + ident(document) operator(=) constant(REXML)operator(::)constant(Document)operator(.)ident(new)operator(()ident(xml_or_io)operator(\)) + reserved(if) ident(document)operator(.)ident(root) + constant(XmlNode)operator(.)ident(new)operator(()ident(document)operator(.)ident(root)operator(\)) + reserved(else) + constant(XmlNode)operator(.)ident(new)operator(()ident(document)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(node_encoding) + instance_variable(@node)operator(.)ident(encoding) + reserved(end) + + reserved(def) method(node_name) + instance_variable(@node)operator(.)ident(name) + reserved(end) + + reserved(def) method(node_value) + instance_variable(@node)operator(.)ident(text) + reserved(end) + + reserved(def) method(node_value=)operator(()ident(value)operator(\)) + instance_variable(@node)operator(.)ident(text) operator(=) ident(value) + reserved(end) + + reserved(def) method(xpath)operator(()ident(expr)operator(\)) + ident(matches) operator(=) pre_constant(nil) + constant(REXML)operator(::)constant(XPath)operator(.)ident(each)operator(()instance_variable(@node)operator(,) ident(expr)operator(\)) reserved(do) operator(|)ident(element)operator(|) + ident(matches) operator(||=) constant(XmlNodeList)operator(.)ident(new) + ident(matches) operator(<<) operator(()instance_variable(@children)operator([)ident(element)operator(]) operator(||=) constant(XmlNode)operator(.)ident(new)operator(()ident(element)operator(\))operator(\)) + reserved(end) + ident(matches) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) + ident(name) operator(=) ident(name)operator(.)ident(to_s) + ident(nodes) operator(=) pre_constant(nil) + instance_variable(@node)operator(.)ident(each_element)operator(()ident(name)operator(\)) reserved(do) operator(|)ident(element)operator(|) + ident(nodes) operator(||=) constant(XmlNodeList)operator(.)ident(new) + ident(nodes) operator(<<) operator(()instance_variable(@children)operator([)ident(element)operator(]) operator(||=) constant(XmlNode)operator(.)ident(new)operator(()ident(element)operator(\))operator(\)) + reserved(end) + ident(nodes) + reserved(end) + + reserved(def) method(<<)operator(()ident(node)operator(\)) + reserved(if) ident(node)operator(.)ident(is_a?) constant(REXML)operator(::)constant(Node) + ident(child) operator(=) ident(node) + reserved(elsif) ident(node)operator(.)ident(respond_to?) symbol(:node) + ident(child) operator(=) ident(node)operator(.)ident(node) + reserved(end) + instance_variable(@node)operator(.)ident(add_element) ident(child) + instance_variable(@children)operator([)ident(child)operator(]) operator(||=) constant(XmlNode)operator(.)ident(new)operator(()ident(child)operator(\)) + reserved(end) + + reserved(def) method([])operator(()ident(name)operator(\)) + instance_variable(@node)operator(.)ident(attributes)operator([)ident(name)operator(.)ident(to_s)operator(]) + reserved(end) + + reserved(def) method([]=)operator(()ident(name)operator(,) ident(value)operator(\)) + instance_variable(@node)operator(.)ident(attributes)operator([)ident(name)operator(.)ident(to_s)operator(]) operator(=) ident(value) + reserved(end) + + reserved(def) method(to_s) + instance_variable(@node)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(to_i) + ident(to_s)operator(.)ident(to_i) + reserved(end) +reserved(end) + +reserved(class) class(XmlNodeList) operator(<) constant(Array) comment(#:nodoc:) + reserved(def) method([])operator(()ident(i)operator(\)) + ident(i)operator(.)ident(is_a?)operator(()constant(String)operator(\)) operator(?) reserved(super)operator(()integer(0)operator(\))operator([)ident(i)operator(]) operator(:) reserved(super)operator(()ident(i)operator(\)) + reserved(end) + + reserved(def) method([]=)operator(()ident(i)operator(,) ident(value)operator(\)) + ident(i)operator(.)ident(is_a?)operator(()constant(String)operator(\)) operator(?) pre_constant(self)operator([)integer(0)operator(])operator([)ident(i)operator(]) operator(=) ident(value) operator(:) reserved(super)operator(()ident(i)operator(,) ident(value)operator(\)) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) + ident(name) operator(=) ident(name)operator(.)ident(to_s) + pre_constant(self)operator([)integer(0)operator(])operator(.)ident(__send__)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) + reserved(end) +reserved(end)comment(# = XmlSimple) +comment(#) +comment(# Author:: Maik Schmidt <contact@maik-schmidt.de>) +comment(# Copyright:: Copyright (c\) 2003 Maik Schmidt) +comment(# License:: Distributes under the same terms as Ruby.) +comment(#) +ident(require) string<delimiter(')content(rexml/document)delimiter(')> + +comment(# Easy API to maintain XML (especially configuration files\).) +reserved(class) class(XmlSimple) comment(#:nodoc:) + ident(include) constant(REXML) + + class_variable(@@VERSION) operator(=) string<delimiter(')content(1.0.2)delimiter(')> + + comment(# A simple cache for XML documents that were already transformed) + comment(# by xml_in.) + reserved(class) class(Cache) comment(#:nodoc:) + comment(# Creates and initializes a new Cache object.) + reserved(def) method(initialize) + instance_variable(@mem_share_cache) operator(=) operator({)operator(}) + instance_variable(@mem_copy_cache) operator(=) operator({)operator(}) + reserved(end) + + comment(# Saves a data structure into a file.) + comment(# ) + comment(# data::) + comment(# Data structure to be saved.) + comment(# filename::) + comment(# Name of the file belonging to the data structure.) + reserved(def) method(save_storable)operator(()ident(data)operator(,) ident(filename)operator(\)) + ident(cache_file) operator(=) ident(get_cache_filename)operator(()ident(filename)operator(\)) + constant(File)operator(.)ident(open)operator(()ident(cache_file)operator(,) string<delimiter(")content(w+)delimiter(")>operator(\)) operator({) operator(|)ident(f)operator(|) constant(Marshal)operator(.)ident(dump)operator(()ident(data)operator(,) ident(f)operator(\)) operator(}) + reserved(end) + + comment(# Restores a data structure from a file. If restoring the data) + comment(# structure failed for any reason, nil will be returned.) + comment(#) + comment(# filename::) + comment(# Name of the file belonging to the data structure.) + reserved(def) method(restore_storable)operator(()ident(filename)operator(\)) + ident(cache_file) operator(=) ident(get_cache_filename)operator(()ident(filename)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) constant(File)operator(::)ident(exist?)operator(()ident(cache_file)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) constant(File)operator(::)ident(mtime)operator(()ident(cache_file)operator(\))operator(.)ident(to_i) operator(>) constant(File)operator(::)ident(mtime)operator(()ident(filename)operator(\))operator(.)ident(to_i) + ident(data) operator(=) pre_constant(nil) + constant(File)operator(.)ident(open)operator(()ident(cache_file)operator(\)) operator({) operator(|)ident(f)operator(|) ident(data) operator(=) constant(Marshal)operator(.)ident(load)operator(()ident(f)operator(\)) operator(}) + ident(data) + reserved(end) + + comment(# Saves a data structure in a shared memory cache.) + comment(#) + comment(# data::) + comment(# Data structure to be saved.) + comment(# filename::) + comment(# Name of the file belonging to the data structure.) + reserved(def) method(save_mem_share)operator(()ident(data)operator(,) ident(filename)operator(\)) + instance_variable(@mem_share_cache)operator([)ident(filename)operator(]) operator(=) operator([)constant(Time)operator(::)ident(now)operator(.)ident(to_i)operator(,) ident(data)operator(]) + reserved(end) + + comment(# Restores a data structure from a shared memory cache. You) + comment(# should consider these elements as "read only". If restoring) + comment(# the data structure failed for any reason, nil will be) + comment(# returned.) + comment(#) + comment(# filename::) + comment(# Name of the file belonging to the data structure.) + reserved(def) method(restore_mem_share)operator(()ident(filename)operator(\)) + ident(get_from_memory_cache)operator(()ident(filename)operator(,) instance_variable(@mem_share_cache)operator(\)) + reserved(end) + + comment(# Copies a data structure to a memory cache.) + comment(#) + comment(# data::) + comment(# Data structure to be copied.) + comment(# filename::) + comment(# Name of the file belonging to the data structure.) + reserved(def) method(save_mem_copy)operator(()ident(data)operator(,) ident(filename)operator(\)) + instance_variable(@mem_share_cache)operator([)ident(filename)operator(]) operator(=) operator([)constant(Time)operator(::)ident(now)operator(.)ident(to_i)operator(,) constant(Marshal)operator(.)ident(dump)operator(()ident(data)operator(\))operator(]) + reserved(end) + + comment(# Restores a data structure from a memory cache. If restoring) + comment(# the data structure failed for any reason, nil will be) + comment(# returned.) + comment(#) + comment(# filename::) + comment(# Name of the file belonging to the data structure.) + reserved(def) method(restore_mem_copy)operator(()ident(filename)operator(\)) + ident(data) operator(=) ident(get_from_memory_cache)operator(()ident(filename)operator(,) instance_variable(@mem_share_cache)operator(\)) + ident(data) operator(=) constant(Marshal)operator(.)ident(load)operator(()ident(data)operator(\)) reserved(unless) ident(data)operator(.)ident(nil?) + ident(data) + reserved(end) + + ident(private) + + comment(# Returns the "cache filename" belonging to a filename, i.e.) + comment(# the extension '.xml' in the original filename will be replaced) + comment(# by '.stor'. If filename does not have this extension, '.stor') + comment(# will be appended.) + comment(#) + comment(# filename::) + comment(# Filename to get "cache filename" for.) + reserved(def) method(get_cache_filename)operator(()ident(filename)operator(\)) + ident(filename)operator(.)ident(sub)operator(()regexp<delimiter(/)content(()char(\\.)content(xml\)?$)delimiter(/)>operator(,) string<delimiter(')content(.stor)delimiter(')>operator(\)) + reserved(end) + + comment(# Returns a cache entry from a memory cache belonging to a) + comment(# certain filename. If no entry could be found for any reason,) + comment(# nil will be returned.) + comment(#) + comment(# filename::) + comment(# Name of the file the cache entry belongs to.) + comment(# cache::) + comment(# Memory cache to get entry from.) + reserved(def) method(get_from_memory_cache)operator(()ident(filename)operator(,) ident(cache)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(cache)operator([)ident(filename)operator(]) + reserved(return) pre_constant(nil) reserved(unless) ident(cache)operator([)ident(filename)operator(])operator([)integer(0)operator(]) operator(>) constant(File)operator(::)ident(mtime)operator(()ident(filename)operator(\))operator(.)ident(to_i) + reserved(return) ident(cache)operator([)ident(filename)operator(])operator([)integer(1)operator(]) + reserved(end) + reserved(end) + + comment(# Create a "global" cache.) + class_variable(@@cache) operator(=) constant(Cache)operator(.)ident(new) + + comment(# Creates and intializes a new XmlSimple object.) + comment(# ) + comment(# defaults::) + comment(# Default values for options.) + reserved(def) method(initialize)operator(()ident(defaults) operator(=) pre_constant(nil)operator(\)) + reserved(unless) ident(defaults)operator(.)ident(nil?) operator(||) ident(defaults)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Options have to be a Hash.)delimiter(")> + reserved(end) + instance_variable(@default_options) operator(=) ident(normalize_option_names)operator(()ident(defaults)operator(,) constant(KNOWN_OPTIONS)operator([)string<delimiter(')content(in)delimiter(')>operator(]) operator(&) constant(KNOWN_OPTIONS)operator([)string<delimiter(')content(out)delimiter(')>operator(])operator(\)) + instance_variable(@options) operator(=) constant(Hash)operator(.)ident(new) + instance_variable(@_var_values) operator(=) pre_constant(nil) + reserved(end) + + comment(# Converts an XML document in the same way as the Perl module XML::Simple.) + comment(#) + comment(# string::) + comment(# XML source. Could be one of the following:) + comment(#) + comment(# - nil: Tries to load and parse '<scriptname>.xml'.) + comment(# - filename: Tries to load and parse filename.) + comment(# - IO object: Reads from object until EOF is detected and parses result.) + comment(# - XML string: Parses string.) + comment(# ) + comment(# options::) + comment(# Options to be used.) + reserved(def) method(xml_in)operator(()ident(string) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + ident(handle_options)operator(()string<delimiter(')content(in)delimiter(')>operator(,) ident(options)operator(\)) + + comment(# If no XML string or filename was supplied look for scriptname.xml.) + reserved(if) ident(string)operator(.)ident(nil?) + ident(string) operator(=) constant(File)operator(::)ident(basename)operator(()global_variable($0)operator(\)) + ident(string)operator(.)ident(sub!)operator(()regexp<delimiter(/)char(\\.)content([^.]+$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(string) operator(+=) string<delimiter(')content(.xml)delimiter(')> + + ident(directory) operator(=) constant(File)operator(::)ident(dirname)operator(()global_variable($0)operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(searchpath)delimiter(')>operator(])operator(.)ident(unshift)operator(()ident(directory)operator(\)) reserved(unless) ident(directory)operator(.)ident(nil?) + reserved(end) + + reserved(if) ident(string)operator(.)ident(instance_of?)operator(()constant(String)operator(\)) + reserved(if) ident(string) operator(=)operator(~) regexp<delimiter(/)content(<.*?>)delimiter(/)modifier(m)> + instance_variable(@doc) operator(=) ident(parse)operator(()ident(string)operator(\)) + reserved(elsif) ident(string) operator(==) string<delimiter(')content(-)delimiter(')> + instance_variable(@doc) operator(=) ident(parse)operator(()global_variable($stdin)operator(.)ident(readlines)operator(.)ident(to_s)operator(\)) + reserved(else) + ident(filename) operator(=) ident(find_xml_file)operator(()ident(string)operator(,) instance_variable(@options)operator([)string<delimiter(')content(searchpath)delimiter(')>operator(])operator(\)) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(cache)delimiter(')>operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(cache)delimiter(')>operator(])operator(.)ident(each) operator({) operator(|)ident(scheme)operator(|) + reserved(case)operator(()ident(scheme)operator(\)) + reserved(when) string<delimiter(')content(storable)delimiter(')> + ident(content) operator(=) class_variable(@@cache)operator(.)ident(restore_storable)operator(()ident(filename)operator(\)) + reserved(when) string<delimiter(')content(mem_share)delimiter(')> + ident(content) operator(=) class_variable(@@cache)operator(.)ident(restore_mem_share)operator(()ident(filename)operator(\)) + reserved(when) string<delimiter(')content(mem_copy)delimiter(')> + ident(content) operator(=) class_variable(@@cache)operator(.)ident(restore_mem_copy)operator(()ident(filename)operator(\)) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Unsupported caching scheme: <)inline<inline_delimiter(#{)ident(scheme)inline_delimiter(})>content(>.)delimiter(")> + reserved(end) + reserved(return) ident(content) reserved(if) ident(content) + operator(}) + reserved(end) + + instance_variable(@doc) operator(=) ident(load_xml_file)operator(()ident(filename)operator(\)) + reserved(end) + reserved(elsif) ident(string)operator(.)ident(kind_of?)operator(()constant(IO)operator(\)) + instance_variable(@doc) operator(=) ident(parse)operator(()ident(string)operator(.)ident(readlines)operator(.)ident(to_s)operator(\)) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Could not parse object of type: <)inline<inline_delimiter(#{)ident(string)operator(.)ident(type)inline_delimiter(})>content(>.)delimiter(")> + reserved(end) + + ident(result) operator(=) ident(collapse)operator(()instance_variable(@doc)operator(.)ident(root)operator(\)) + ident(result) operator(=) instance_variable(@options)operator([)string<delimiter(')content(keeproot)delimiter(')>operator(]) operator(?) ident(merge)operator(()operator({)operator(})operator(,) instance_variable(@doc)operator(.)ident(root)operator(.)ident(name)operator(,) ident(result)operator(\)) operator(:) ident(result) + ident(put_into_cache)operator(()ident(result)operator(,) ident(filename)operator(\)) + ident(result) + reserved(end) + + comment(# This is the functional version of the instance method xml_in.) + reserved(def) constant(XmlSimple)operator(.)ident(xml_in)operator(()ident(string) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + ident(xml_simple) operator(=) constant(XmlSimple)operator(.)ident(new) + ident(xml_simple)operator(.)ident(xml_in)operator(()ident(string)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Converts a data structure into an XML document.) + comment(#) + comment(# ref::) + comment(# Reference to data structure to be converted into XML.) + comment(# options::) + comment(# Options to be used.) + reserved(def) method(xml_out)operator(()ident(ref)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + ident(handle_options)operator(()string<delimiter(')content(out)delimiter(')>operator(,) ident(options)operator(\)) + reserved(if) ident(ref)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(ref) operator(=) operator({) instance_variable(@options)operator([)string<delimiter(')content(anonymoustag)delimiter(')>operator(]) operator(=)operator(>) ident(ref) operator(}) + reserved(end) + + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(keeproot)delimiter(')>operator(]) + ident(keys) operator(=) ident(ref)operator(.)ident(keys) + reserved(if) ident(keys)operator(.)ident(size) operator(==) integer(1) + ident(ref) operator(=) ident(ref)operator([)ident(keys)operator([)integer(0)operator(])operator(]) + instance_variable(@options)operator([)string<delimiter(')content(rootname)delimiter(')>operator(]) operator(=) ident(keys)operator([)integer(0)operator(]) + reserved(end) + reserved(elsif) instance_variable(@options)operator([)string<delimiter(')content(rootname)delimiter(')>operator(]) operator(==) string<delimiter(')delimiter(')> + reserved(if) ident(ref)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + ident(refsave) operator(=) ident(ref) + ident(ref) operator(=) operator({)operator(}) + ident(refsave)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) operator(!)ident(scalar)operator(()ident(value)operator(\)) + ident(ref)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(else) + ident(ref)operator([)ident(key)operator(]) operator(=) operator([) ident(value)operator(.)ident(to_s) operator(]) + reserved(end) + operator(}) + reserved(end) + reserved(end) + + instance_variable(@ancestors) operator(=) operator([)operator(]) + ident(xml) operator(=) ident(value_to_xml)operator(()ident(ref)operator(,) instance_variable(@options)operator([)string<delimiter(')content(rootname)delimiter(')>operator(])operator(,) string<delimiter(')delimiter(')>operator(\)) + instance_variable(@ancestors) operator(=) pre_constant(nil) + + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(xmldeclaration)delimiter(')>operator(]) + ident(xml) operator(=) instance_variable(@options)operator([)string<delimiter(')content(xmldeclaration)delimiter(')>operator(]) operator(+) string<delimiter(")char(\\n)delimiter(")> operator(+) ident(xml) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(outputfile)delimiter(')>operator(\)) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(outputfile)delimiter(')>operator(])operator(.)ident(kind_of?)operator(()constant(IO)operator(\)) + reserved(return) instance_variable(@options)operator([)string<delimiter(')content(outputfile)delimiter(')>operator(])operator(.)ident(write)operator(()ident(xml)operator(\)) + reserved(else) + constant(File)operator(.)ident(open)operator(()instance_variable(@options)operator([)string<delimiter(')content(outputfile)delimiter(')>operator(])operator(,) string<delimiter(")content(w)delimiter(")>operator(\)) operator({) operator(|)ident(file)operator(|) ident(file)operator(.)ident(write)operator(()ident(xml)operator(\)) operator(}) + reserved(end) + reserved(end) + ident(xml) + reserved(end) + + comment(# This is the functional version of the instance method xml_out.) + reserved(def) constant(XmlSimple)operator(.)ident(xml_out)operator(()ident(hash)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + ident(xml_simple) operator(=) constant(XmlSimple)operator(.)ident(new) + ident(xml_simple)operator(.)ident(xml_out)operator(()ident(hash)operator(,) ident(options)operator(\)) + reserved(end) + + ident(private) + + comment(# Declare options that are valid for xml_in and xml_out.) + constant(KNOWN_OPTIONS) operator(=) operator({) + string<delimiter(')content(in)delimiter(')> operator(=)operator(>) string<delimiter(%w()content( + keyattr keeproot forcecontent contentkey noattr + searchpath forcearray suppressempty anonymoustag + cache grouptags normalisespace normalizespace + variables varattr + )delimiter(\))>operator(,) + string<delimiter(')content(out)delimiter(')> operator(=)operator(>) string<delimiter(%w()content( + keyattr keeproot contentkey noattr rootname + xmldeclaration outputfile noescape suppressempty + anonymoustag indent grouptags noindent + )delimiter(\))> + operator(}) + + comment(# Define some reasonable defaults.) + constant(DEF_KEY_ATTRIBUTES) operator(=) operator([)operator(]) + constant(DEF_ROOT_NAME) operator(=) string<delimiter(')content(opt)delimiter(')> + constant(DEF_CONTENT_KEY) operator(=) string<delimiter(')content(content)delimiter(')> + constant(DEF_XML_DECLARATION) operator(=) string<delimiter(")content(<?xml version='1.0' standalone='yes'?>)delimiter(")> + constant(DEF_ANONYMOUS_TAG) operator(=) string<delimiter(')content(anon)delimiter(')> + constant(DEF_FORCE_ARRAY) operator(=) pre_constant(true) + constant(DEF_INDENTATION) operator(=) string<delimiter(')content( )delimiter(')> + + comment(# Normalizes option names in a hash, i.e., turns all) + comment(# characters to lower case and removes all underscores.) + comment(# Additionally, this method checks, if an unknown option) + comment(# was used and raises an according exception.) + comment(#) + comment(# options::) + comment(# Hash to be normalized.) + comment(# known_options::) + comment(# List of known options.) + reserved(def) method(normalize_option_names)operator(()ident(options)operator(,) ident(known_options)operator(\)) + reserved(return) pre_constant(nil) reserved(if) ident(options)operator(.)ident(nil?) + ident(result) operator(=) constant(Hash)operator(.)ident(new) + ident(options)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + ident(lkey) operator(=) ident(key)operator(.)ident(downcase) + ident(lkey)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(_)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(if) operator(!)ident(known_options)operator(.)ident(member?)operator(()ident(lkey)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Unrecognised option: )inline<inline_delimiter(#{)ident(lkey)inline_delimiter(})>content(.)delimiter(")> + reserved(end) + ident(result)operator([)ident(lkey)operator(]) operator(=) ident(value) + operator(}) + ident(result) + reserved(end) + + comment(# Merges a set of options with the default options.) + comment(# ) + comment(# direction::) + comment(# 'in': If options should be handled for xml_in.) + comment(# 'out': If options should be handled for xml_out.) + comment(# options::) + comment(# Options to be merged with the default options.) + reserved(def) method(handle_options)operator(()ident(direction)operator(,) ident(options)operator(\)) + instance_variable(@options) operator(=) ident(options) operator(||) constant(Hash)operator(.)ident(new) + + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Options must be a Hash!)delimiter(")> reserved(unless) instance_variable(@options)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + + reserved(unless) constant(KNOWN_OPTIONS)operator(.)ident(has_key?)operator(()ident(direction)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Unknown direction: <)inline<inline_delimiter(#{)ident(direction)inline_delimiter(})>content(>.)delimiter(")> + reserved(end) + + ident(known_options) operator(=) constant(KNOWN_OPTIONS)operator([)ident(direction)operator(]) + instance_variable(@options) operator(=) ident(normalize_option_names)operator(()instance_variable(@options)operator(,) ident(known_options)operator(\)) + + reserved(unless) instance_variable(@default_options)operator(.)ident(nil?) + ident(known_options)operator(.)ident(each) operator({) operator(|)ident(option)operator(|) + reserved(unless) instance_variable(@options)operator(.)ident(has_key?)operator(()ident(option)operator(\)) + reserved(if) instance_variable(@default_options)operator(.)ident(has_key?)operator(()ident(option)operator(\)) + instance_variable(@options)operator([)ident(option)operator(]) operator(=) instance_variable(@default_options)operator([)ident(option)operator(]) + reserved(end) + reserved(end) + operator(}) + reserved(end) + + reserved(unless) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(noattr)delimiter(')>operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(noattr)delimiter(')>operator(]) operator(=) pre_constant(false) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(rootname)delimiter(')>operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(rootname)delimiter(')>operator(]) operator(=) string<delimiter(')delimiter(')> reserved(if) instance_variable(@options)operator([)string<delimiter(')content(rootname)delimiter(')>operator(])operator(.)ident(nil?) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(rootname)delimiter(')>operator(]) operator(=) constant(DEF_ROOT_NAME) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(xmldeclaration)delimiter(')>operator(\)) operator(&&) instance_variable(@options)operator([)string<delimiter(')content(xmldeclaration)delimiter(')>operator(]) operator(==) pre_constant(true) + instance_variable(@options)operator([)string<delimiter(')content(xmldeclaration)delimiter(')>operator(]) operator(=) constant(DEF_XML_DECLARATION) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(contentkey)delimiter(')>operator(\)) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(]) operator(=)operator(~) regexp<delimiter(/)content(^-(.*\)$)delimiter(/)> + instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(]) operator(=) global_variable($1) + instance_variable(@options)operator([)string<delimiter(')content(collapseagain)delimiter(')>operator(]) operator(=) pre_constant(true) + reserved(end) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(]) operator(=) constant(DEF_CONTENT_KEY) + reserved(end) + + reserved(unless) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(normalisespace)delimiter(')>operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(]) operator(=) instance_variable(@options)operator([)string<delimiter(')content(normalizespace)delimiter(')>operator(]) + reserved(end) + instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(]) operator(=) integer(0) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(])operator(.)ident(nil?) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(searchpath)delimiter(')>operator(\)) + reserved(unless) instance_variable(@options)operator([)string<delimiter(')content(searchpath)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(searchpath)delimiter(')>operator(]) operator(=) operator([) instance_variable(@options)operator([)string<delimiter(')content(searchpath)delimiter(')>operator(]) operator(]) + reserved(end) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(searchpath)delimiter(')>operator(]) operator(=) operator([)operator(]) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(cache)delimiter(')>operator(\)) operator(&&) ident(scalar)operator(()instance_variable(@options)operator([)string<delimiter(')content(cache)delimiter(')>operator(])operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(cache)delimiter(')>operator(]) operator(=) operator([) instance_variable(@options)operator([)string<delimiter(')content(cache)delimiter(')>operator(]) operator(]) + reserved(end) + + instance_variable(@options)operator([)string<delimiter(')content(anonymoustag)delimiter(')>operator(]) operator(=) constant(DEF_ANONYMOUS_TAG) reserved(unless) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(anonymoustag)delimiter(')>operator(\)) + + reserved(if) operator(!)instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(indent)delimiter(')>operator(\)) operator(||) instance_variable(@options)operator([)string<delimiter(')content(indent)delimiter(')>operator(])operator(.)ident(nil?) + instance_variable(@options)operator([)string<delimiter(')content(indent)delimiter(')>operator(]) operator(=) constant(DEF_INDENTATION) + reserved(end) + + instance_variable(@options)operator([)string<delimiter(')content(indent)delimiter(')>operator(]) operator(=) string<delimiter(')delimiter(')> reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(noindent)delimiter(')>operator(\)) + + comment(# Special cleanup for 'keyattr' which could be an array or) + comment(# a hash or left to default to array.) + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(keyattr)delimiter(')>operator(\)) + reserved(if) operator(!)ident(scalar)operator(()instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(\)) + comment(# Convert keyattr => { elem => '+attr' }) + comment(# to keyattr => { elem => ['attr', '+'] }) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^([-+]\)?(.*\)$)delimiter(/)> + instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator([)ident(key)operator(]) operator(=) operator([)global_variable($2)operator(,) global_variable($1) operator(?) global_variable($1) operator(:) string<delimiter(')delimiter(')>operator(]) + reserved(end) + operator(}) + reserved(elsif) operator(!)instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content('keyattr' must be String, Hash, or Array!)delimiter(")> + reserved(end) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(]) operator(=) operator([) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(]) operator(]) + reserved(end) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(]) operator(=) constant(DEF_KEY_ATTRIBUTES) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(forcearray)delimiter(')>operator(\)) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Regexp)operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(=) operator([) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(]) + reserved(end) + + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(force_list) operator(=) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) + reserved(unless) ident(force_list)operator(.)ident(empty?) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(=) operator({)operator(}) + ident(force_list)operator(.)ident(each) operator({) operator(|)ident(tag)operator(|) + reserved(if) ident(tag)operator(.)ident(instance_of?)operator(()constant(Regexp)operator(\)) + reserved(unless) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(])operator([)string<delimiter(')content(_regex)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(])operator([)string<delimiter(')content(_regex)delimiter(')>operator(]) operator(=) operator([)operator(]) + reserved(end) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(])operator([)string<delimiter(')content(_regex)delimiter(')>operator(]) operator(<<) ident(tag) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(])operator([)ident(tag)operator(]) operator(=) pre_constant(true) + reserved(end) + operator(}) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(=) pre_constant(false) + reserved(end) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(=) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(?) pre_constant(true) operator(:) pre_constant(false) + reserved(end) + reserved(else) + instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(=) constant(DEF_FORCE_ARRAY) + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(grouptags)delimiter(')>operator(\)) operator(&&) operator(!)instance_variable(@options)operator([)string<delimiter(')content(grouptags)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Illegal value for 'GroupTags' option - expected a Hash.)delimiter(")> + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(variables)delimiter(')>operator(\)) operator(&&) operator(!)instance_variable(@options)operator([)string<delimiter(')content(variables)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Illegal value for 'Variables' option - expected a Hash.)delimiter(")> + reserved(end) + + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(variables)delimiter(')>operator(\)) + instance_variable(@_var_values) operator(=) instance_variable(@options)operator([)string<delimiter(')content(variables)delimiter(')>operator(]) + reserved(elsif) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(varattr)delimiter(')>operator(\)) + instance_variable(@_var_values) operator(=) operator({)operator(}) + reserved(end) + reserved(end) + + comment(# Actually converts an XML document element into a data structure.) + comment(#) + comment(# element::) + comment(# The document element to be collapsed.) + reserved(def) method(collapse)operator(()ident(element)operator(\)) + ident(result) operator(=) instance_variable(@options)operator([)string<delimiter(')content(noattr)delimiter(')>operator(]) operator(?) operator({)operator(}) operator(:) ident(get_attributes)operator(()ident(element)operator(\)) + + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(]) operator(==) integer(2) + ident(result)operator(.)ident(each) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(result)operator([)ident(k)operator(]) operator(=) ident(normalise_space)operator(()ident(v)operator(\)) operator(}) + reserved(end) + + reserved(if) ident(element)operator(.)ident(has_elements?) + ident(element)operator(.)ident(each_element) operator({) operator(|)ident(child)operator(|) + ident(value) operator(=) ident(collapse)operator(()ident(child)operator(\)) + reserved(if) ident(empty)operator(()ident(value)operator(\)) operator(&&) operator(()ident(element)operator(.)ident(attributes)operator(.)ident(empty?) operator(||) instance_variable(@options)operator([)string<delimiter(')content(noattr)delimiter(')>operator(])operator(\)) + reserved(next) reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(suppressempty)delimiter(')>operator(\)) operator(&&) instance_variable(@options)operator([)string<delimiter(')content(suppressempty)delimiter(')>operator(]) operator(==) pre_constant(true) + reserved(end) + ident(result) operator(=) ident(merge)operator(()ident(result)operator(,) ident(child)operator(.)ident(name)operator(,) ident(value)operator(\)) + operator(}) + reserved(if) ident(has_mixed_content?)operator(()ident(element)operator(\)) + comment(# normalisespace?) + ident(content) operator(=) ident(element)operator(.)ident(texts)operator(.)ident(map) operator({) operator(|)ident(x)operator(|) ident(x)operator(.)ident(to_s) operator(}) + ident(content) operator(=) ident(content)operator([)integer(0)operator(]) reserved(if) ident(content)operator(.)ident(size) operator(==) integer(1) + ident(result)operator([)instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(])operator(]) operator(=) ident(content) + reserved(end) + reserved(elsif) ident(element)operator(.)ident(has_text?) comment(# i.e. it has only text.) + reserved(return) ident(collapse_text_node)operator(()ident(result)operator(,) ident(element)operator(\)) + reserved(end) + + comment(# Turn Arrays into Hashes if key fields present.) + ident(count) operator(=) ident(fold_arrays)operator(()ident(result)operator(\)) + + comment(# Disintermediate grouped tags.) + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(grouptags)delimiter(')>operator(\)) + ident(result)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(next) reserved(unless) operator(()ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(&&) operator(()ident(value)operator(.)ident(size) operator(==) integer(1)operator(\))operator(\)) + ident(child_key)operator(,) ident(child_value) operator(=) ident(value)operator(.)ident(to_a)operator([)integer(0)operator(]) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(grouptags)delimiter(')>operator(])operator([)ident(key)operator(]) operator(==) ident(child_key) + ident(result)operator([)ident(key)operator(]) operator(=) ident(child_value) + reserved(end) + operator(}) + reserved(end) + + comment(# Fold Hases containing a single anonymous Array up into just the Array.) + reserved(if) ident(count) operator(==) integer(1) + ident(anonymoustag) operator(=) instance_variable(@options)operator([)string<delimiter(')content(anonymoustag)delimiter(')>operator(]) + reserved(if) ident(result)operator(.)ident(has_key?)operator(()ident(anonymoustag)operator(\)) operator(&&) ident(result)operator([)ident(anonymoustag)operator(])operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + reserved(return) ident(result)operator([)ident(anonymoustag)operator(]) + reserved(end) + reserved(end) + + reserved(if) ident(result)operator(.)ident(empty?) operator(&&) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(suppressempty)delimiter(')>operator(\)) + reserved(return) instance_variable(@options)operator([)string<delimiter(')content(suppressempty)delimiter(')>operator(]) operator(==) string<delimiter(')delimiter(')> operator(?) string<delimiter(')delimiter(')> operator(:) pre_constant(nil) + reserved(end) + + ident(result) + reserved(end) + + comment(# Collapses a text node and merges it with an existing Hash, if) + comment(# possible.) + comment(# Thanks to Curtis Schofield for reporting a subtle bug.) + comment(#) + comment(# hash::) + comment(# Hash to merge text node value with, if possible.) + comment(# element::) + comment(# Text node to be collapsed.) + reserved(def) method(collapse_text_node)operator(()ident(hash)operator(,) ident(element)operator(\)) + ident(value) operator(=) ident(node_to_text)operator(()ident(element)operator(\)) + reserved(if) ident(empty)operator(()ident(value)operator(\)) operator(&&) operator(!)ident(element)operator(.)ident(has_attributes?) + reserved(return) operator({)operator(}) + reserved(end) + + reserved(if) ident(element)operator(.)ident(has_attributes?) operator(&&) operator(!)instance_variable(@options)operator([)string<delimiter(')content(noattr)delimiter(')>operator(]) + reserved(return) ident(merge)operator(()ident(hash)operator(,) instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(])operator(,) ident(value)operator(\)) + reserved(else) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(forcecontent)delimiter(')>operator(]) + reserved(return) ident(merge)operator(()ident(hash)operator(,) instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(])operator(,) ident(value)operator(\)) + reserved(else) + reserved(return) ident(value) + reserved(end) + reserved(end) + reserved(end) + + comment(# Folds all arrays in a Hash.) + comment(# ) + comment(# hash::) + comment(# Hash to be folded.) + reserved(def) method(fold_arrays)operator(()ident(hash)operator(\)) + ident(fold_amount) operator(=) integer(0) + ident(keyattr) operator(=) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(]) + reserved(if) operator(()ident(keyattr)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) operator(||) ident(keyattr)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\))operator(\)) + ident(hash)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) ident(value)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + reserved(if) ident(keyattr)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(hash)operator([)ident(key)operator(]) operator(=) ident(fold_array)operator(()ident(value)operator(\)) + reserved(else) + ident(hash)operator([)ident(key)operator(]) operator(=) ident(fold_array_by_name)operator(()ident(key)operator(,) ident(value)operator(\)) + reserved(end) + ident(fold_amount) operator(+=) integer(1) + reserved(end) + operator(}) + reserved(end) + ident(fold_amount) + reserved(end) + + comment(# Folds an Array to a Hash, if possible. Folding happens) + comment(# according to the content of keyattr, which has to be) + comment(# an array.) + comment(#) + comment(# array::) + comment(# Array to be folded.) + reserved(def) method(fold_array)operator(()ident(array)operator(\)) + ident(hash) operator(=) constant(Hash)operator(.)ident(new) + ident(array)operator(.)ident(each) operator({) operator(|)ident(x)operator(|) + reserved(return) ident(array) reserved(unless) ident(x)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + ident(key_matched) operator(=) pre_constant(false) + instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(each) operator({) operator(|)ident(key)operator(|) + reserved(if) ident(x)operator(.)ident(has_key?)operator(()ident(key)operator(\)) + ident(key_matched) operator(=) pre_constant(true) + ident(value) operator(=) ident(x)operator([)ident(key)operator(]) + reserved(return) ident(array) reserved(if) ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(||) ident(value)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(value) operator(=) ident(normalise_space)operator(()ident(value)operator(\)) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(]) operator(==) integer(1) + ident(x)operator(.)ident(delete)operator(()ident(key)operator(\)) + ident(hash)operator([)ident(value)operator(]) operator(=) ident(x) + reserved(break) + reserved(end) + operator(}) + reserved(return) ident(array) reserved(unless) ident(key_matched) + operator(}) + ident(hash) operator(=) ident(collapse_content)operator(()ident(hash)operator(\)) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(collapseagain)delimiter(')>operator(]) + ident(hash) + reserved(end) + + comment(# Folds an Array to a Hash, if possible. Folding happens) + comment(# according to the content of keyattr, which has to be) + comment(# a Hash.) + comment(#) + comment(# name::) + comment(# Name of the attribute to be folded upon.) + comment(# array::) + comment(# Array to be folded.) + reserved(def) method(fold_array_by_name)operator(()ident(name)operator(,) ident(array)operator(\)) + reserved(return) ident(array) reserved(unless) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(has_key?)operator(()ident(name)operator(\)) + ident(key)operator(,) ident(flag) operator(=) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator([)ident(name)operator(]) + + ident(hash) operator(=) constant(Hash)operator(.)ident(new) + ident(array)operator(.)ident(each) operator({) operator(|)ident(x)operator(|) + reserved(if) ident(x)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(&&) ident(x)operator(.)ident(has_key?)operator(()ident(key)operator(\)) + ident(value) operator(=) ident(x)operator([)ident(key)operator(]) + reserved(return) ident(array) reserved(if) ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(||) ident(value)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(value) operator(=) ident(normalise_space)operator(()ident(value)operator(\)) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(]) operator(==) integer(1) + ident(hash)operator([)ident(value)operator(]) operator(=) ident(x) + ident(hash)operator([)ident(value)operator(])operator([)string<delimiter(")content(-)inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")>operator(]) operator(=) ident(hash)operator([)ident(value)operator(])operator([)ident(key)operator(]) reserved(if) ident(flag) operator(==) string<delimiter(')content(-)delimiter(')> + ident(hash)operator([)ident(value)operator(])operator(.)ident(delete)operator(()ident(key)operator(\)) reserved(unless) ident(flag) operator(==) string<delimiter(')content(+)delimiter(')> + reserved(else) + global_variable($stderr)operator(.)ident(puts)operator(()string<delimiter(")content(Warning: <)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(> element has no ')inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(' attribute.)delimiter(")>operator(\)) + reserved(return) ident(array) + reserved(end) + operator(}) + ident(hash) operator(=) ident(collapse_content)operator(()ident(hash)operator(\)) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(collapseagain)delimiter(')>operator(]) + ident(hash) + reserved(end) + + comment(# Tries to collapse a Hash even more ;-\)) + comment(#) + comment(# hash::) + comment(# Hash to be collapsed again.) + reserved(def) method(collapse_content)operator(()ident(hash)operator(\)) + ident(content_key) operator(=) instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(]) + ident(hash)operator(.)ident(each_value) operator({) operator(|)ident(value)operator(|) + reserved(return) ident(hash) reserved(unless) ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(&&) ident(value)operator(.)ident(size) operator(==) integer(1) operator(&&) ident(value)operator(.)ident(has_key?)operator(()ident(content_key)operator(\)) + ident(hash)operator(.)ident(each_key) operator({) operator(|)ident(key)operator(|) ident(hash)operator([)ident(key)operator(]) operator(=) ident(hash)operator([)ident(key)operator(])operator([)ident(content_key)operator(]) operator(}) + operator(}) + ident(hash) + reserved(end) + + comment(# Adds a new key/value pair to an existing Hash. If the key to be added) + comment(# does already exist and the existing value associated with key is not) + comment(# an Array, it will be converted into an Array. Then the new value is) + comment(# appended to that Array.) + comment(#) + comment(# hash::) + comment(# Hash to add key/value pair to.) + comment(# key::) + comment(# Key to be added.) + comment(# value::) + comment(# Value to be associated with key.) + reserved(def) method(merge)operator(()ident(hash)operator(,) ident(key)operator(,) ident(value)operator(\)) + reserved(if) ident(value)operator(.)ident(instance_of?)operator(()constant(String)operator(\)) + ident(value) operator(=) ident(normalise_space)operator(()ident(value)operator(\)) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(normalisespace)delimiter(')>operator(]) operator(==) integer(2) + + comment(# do variable substitutions) + reserved(unless) instance_variable(@_var_values)operator(.)ident(nil?) operator(||) instance_variable(@_var_values)operator(.)ident(empty?) + ident(value)operator(.)ident(gsub!)operator(()regexp<delimiter(/)char(\\$)char(\\{)content(()char(\\w)content(+\))char(\\})delimiter(/)>operator(\)) operator({) operator(|)ident(x)operator(|) ident(get_var)operator(()global_variable($1)operator(\)) operator(}) + reserved(end) + + comment(# look for variable definitions) + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(varattr)delimiter(')>operator(\)) + ident(varattr) operator(=) instance_variable(@options)operator([)string<delimiter(')content(varattr)delimiter(')>operator(]) + reserved(if) ident(hash)operator(.)ident(has_key?)operator(()ident(varattr)operator(\)) + ident(set_var)operator(()ident(hash)operator([)ident(varattr)operator(])operator(,) ident(value)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(if) ident(hash)operator(.)ident(has_key?)operator(()ident(key)operator(\)) + reserved(if) ident(hash)operator([)ident(key)operator(])operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(hash)operator([)ident(key)operator(]) operator(<<) ident(value) + reserved(else) + ident(hash)operator([)ident(key)operator(]) operator(=) operator([) ident(hash)operator([)ident(key)operator(])operator(,) ident(value) operator(]) + reserved(end) + reserved(elsif) ident(value)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) comment(# Handle anonymous arrays.) + ident(hash)operator([)ident(key)operator(]) operator(=) operator([) ident(value) operator(]) + reserved(else) + reserved(if) ident(force_array?)operator(()ident(key)operator(\)) + ident(hash)operator([)ident(key)operator(]) operator(=) operator([) ident(value) operator(]) + reserved(else) + ident(hash)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(end) + reserved(end) + ident(hash) + reserved(end) + + comment(# Checks, if the 'forcearray' option has to be used for) + comment(# a certain key.) + reserved(def) method(force_array?)operator(()ident(key)operator(\)) + reserved(return) pre_constant(false) reserved(if) ident(key) operator(==) instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(]) + reserved(return) pre_constant(true) reserved(if) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) operator(==) pre_constant(true) + ident(forcearray) operator(=) instance_variable(@options)operator([)string<delimiter(')content(forcearray)delimiter(')>operator(]) + reserved(if) ident(forcearray)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + reserved(return) pre_constant(true) reserved(if) ident(forcearray)operator(.)ident(has_key?)operator(()ident(key)operator(\)) + reserved(return) pre_constant(false) reserved(unless) ident(forcearray)operator(.)ident(has_key?)operator(()string<delimiter(')content(_regex)delimiter(')>operator(\)) + ident(forcearray)operator([)string<delimiter(')content(_regex)delimiter(')>operator(])operator(.)ident(each) operator({) operator(|)ident(x)operator(|) reserved(return) pre_constant(true) reserved(if) ident(key) operator(=)operator(~) ident(x) operator(}) + reserved(end) + reserved(return) pre_constant(false) + reserved(end) + + comment(# Converts the attributes array of a document node into a Hash.) + comment(# Returns an empty Hash, if node has no attributes.) + comment(#) + comment(# node::) + comment(# Document node to extract attributes from.) + reserved(def) method(get_attributes)operator(()ident(node)operator(\)) + ident(attributes) operator(=) operator({)operator(}) + ident(node)operator(.)ident(attributes)operator(.)ident(each) operator({) operator(|)ident(n)operator(,)ident(v)operator(|) ident(attributes)operator([)ident(n)operator(]) operator(=) ident(v) operator(}) + ident(attributes) + reserved(end) + + comment(# Determines, if a document element has mixed content.) + comment(#) + comment(# element::) + comment(# Document element to be checked.) + reserved(def) method(has_mixed_content?)operator(()ident(element)operator(\)) + reserved(if) ident(element)operator(.)ident(has_text?) operator(&&) ident(element)operator(.)ident(has_elements?) + reserved(return) pre_constant(true) reserved(if) ident(element)operator(.)ident(texts)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) operator(!)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*$)delimiter(/)modifier(s)> + reserved(end) + pre_constant(false) + reserved(end) + + comment(# Called when a variable definition is encountered in the XML.) + comment(# A variable definition looks like) + comment(# <element attrname="name">value</element>) + comment(# where attrname matches the varattr setting.) + reserved(def) method(set_var)operator(()ident(name)operator(,) ident(value)operator(\)) + instance_variable(@_var_values)operator([)ident(name)operator(]) operator(=) ident(value) + reserved(end) + + comment(# Called during variable substitution to get the value for the) + comment(# named variable.) + reserved(def) method(get_var)operator(()ident(name)operator(\)) + reserved(if) instance_variable(@_var_values)operator(.)ident(has_key?)operator(()ident(name)operator(\)) + reserved(return) instance_variable(@_var_values)operator([)ident(name)operator(]) + reserved(else) + reserved(return) string<delimiter(")content(${)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(})delimiter(")> + reserved(end) + reserved(end) + + comment(# Recurses through a data structure building up and returning an) + comment(# XML representation of that structure as a string.) + comment(#) + comment(# ref::) + comment(# Reference to the data structure to be encoded.) + comment(# name::) + comment(# The XML tag name to be used for this item.) + comment(# indent::) + comment(# A string of spaces for use as the current indent level.) + reserved(def) method(value_to_xml)operator(()ident(ref)operator(,) ident(name)operator(,) ident(indent)operator(\)) + ident(named) operator(=) operator(!)ident(name)operator(.)ident(nil?) operator(&&) ident(name) operator(!=) string<delimiter(')delimiter(')> + ident(nl) operator(=) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(noindent)delimiter(')>operator(\)) operator(?) string<delimiter(')delimiter(')> operator(:) string<delimiter(")char(\\n)delimiter(")> + + reserved(if) operator(!)ident(scalar)operator(()ident(ref)operator(\)) + reserved(if) instance_variable(@ancestors)operator(.)ident(member?)operator(()ident(ref)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Circular data structures not supported!)delimiter(")> + reserved(end) + instance_variable(@ancestors) operator(<<) ident(ref) + reserved(else) + reserved(if) ident(named) + reserved(return) operator([)ident(indent)operator(,) string<delimiter(')content(<)delimiter(')>operator(,) ident(name)operator(,) string<delimiter(')content(>)delimiter(')>operator(,) instance_variable(@options)operator([)string<delimiter(')content(noescape)delimiter(')>operator(]) operator(?) ident(ref)operator(.)ident(to_s) operator(:) ident(escape_value)operator(()ident(ref)operator(.)ident(to_s)operator(\))operator(,) string<delimiter(')content(</)delimiter(')>operator(,) ident(name)operator(,) string<delimiter(')content(>)delimiter(')>operator(,) ident(nl)operator(])operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(else) + reserved(return) ident(ref)operator(.)ident(to_s) operator(+) ident(nl) + reserved(end) + reserved(end) + + comment(# Unfold hash to array if possible.) + reserved(if) ident(ref)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(&&) operator(!)ident(ref)operator(.)ident(empty?) operator(&&) operator(!)instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(empty?) operator(&&) ident(indent) operator(!=) string<delimiter(')delimiter(')> + ident(ref) operator(=) ident(hash_to_array)operator(()ident(name)operator(,) ident(ref)operator(\)) + reserved(end) + + ident(result) operator(=) operator([)operator(]) + reserved(if) ident(ref)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + comment(# Reintermediate grouped values if applicable.) + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(grouptags)delimiter(')>operator(\)) + ident(ref)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(grouptags)delimiter(')>operator(])operator(.)ident(has_key?)operator(()ident(key)operator(\)) + ident(ref)operator([)ident(key)operator(]) operator(=) operator({) instance_variable(@options)operator([)string<delimiter(')content(grouptags)delimiter(')>operator(])operator([)ident(key)operator(]) operator(=)operator(>) ident(value) operator(}) + reserved(end) + operator(}) + reserved(end) + + ident(nested) operator(=) operator([)operator(]) + ident(text_content) operator(=) pre_constant(nil) + reserved(if) ident(named) + ident(result) operator(<<) ident(indent) operator(<<) string<delimiter(')content(<)delimiter(')> operator(<<) ident(name) + reserved(end) + + reserved(if) operator(!)ident(ref)operator(.)ident(empty?) + ident(ref)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(next) reserved(if) operator(!)ident(key)operator(.)ident(nil?) operator(&&) ident(key)operator([)integer(0)operator(,) integer(1)operator(]) operator(==) string<delimiter(')content(-)delimiter(')> + reserved(if) ident(value)operator(.)ident(nil?) + reserved(unless) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(suppressempty)delimiter(')>operator(\)) operator(&&) instance_variable(@options)operator([)string<delimiter(')content(suppressempty)delimiter(')>operator(])operator(.)ident(nil?) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Use of uninitialized value!)delimiter(")> + reserved(end) + ident(value) operator(=) operator({)operator(}) + reserved(end) + + reserved(if) operator(!)ident(scalar)operator(()ident(value)operator(\)) operator(||) instance_variable(@options)operator([)string<delimiter(')content(noattr)delimiter(')>operator(]) + ident(nested) operator(<<) ident(value_to_xml)operator(()ident(value)operator(,) ident(key)operator(,) ident(indent) operator(+) instance_variable(@options)operator([)string<delimiter(')content(indent)delimiter(')>operator(])operator(\)) + reserved(else) + ident(value) operator(=) ident(value)operator(.)ident(to_s) + ident(value) operator(=) ident(escape_value)operator(()ident(value)operator(\)) reserved(unless) instance_variable(@options)operator([)string<delimiter(')content(noescape)delimiter(')>operator(]) + reserved(if) ident(key) operator(==) instance_variable(@options)operator([)string<delimiter(')content(contentkey)delimiter(')>operator(]) + ident(text_content) operator(=) ident(value) + reserved(else) + ident(result) operator(<<) string<delimiter(')content( )delimiter(')> operator(<<) ident(key) operator(<<) string<delimiter(')content(=")delimiter(')> operator(<<) ident(value) operator(<<) string<delimiter(')content(")delimiter(')> + reserved(end) + reserved(end) + operator(}) + reserved(else) + ident(text_content) operator(=) string<delimiter(')delimiter(')> + reserved(end) + + reserved(if) operator(!)ident(nested)operator(.)ident(empty?) operator(||) operator(!)ident(text_content)operator(.)ident(nil?) + reserved(if) ident(named) + ident(result) operator(<<) string<delimiter(')content(>)delimiter(')> + reserved(if) operator(!)ident(text_content)operator(.)ident(nil?) + ident(result) operator(<<) ident(text_content) + ident(nested)operator([)integer(0)operator(])operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^)char(\\s)content(+)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) reserved(if) operator(!)ident(nested)operator(.)ident(empty?) + reserved(else) + ident(result) operator(<<) ident(nl) + reserved(end) + reserved(if) operator(!)ident(nested)operator(.)ident(empty?) + ident(result) operator(<<) ident(nested) operator(<<) ident(indent) + reserved(end) + ident(result) operator(<<) string<delimiter(')content(</)delimiter(')> operator(<<) ident(name) operator(<<) string<delimiter(')content(>)delimiter(')> operator(<<) ident(nl) + reserved(else) + ident(result) operator(<<) ident(nested) + reserved(end) + reserved(else) + ident(result) operator(<<) string<delimiter(')content( />)delimiter(')> operator(<<) ident(nl) + reserved(end) + reserved(elsif) ident(ref)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + ident(ref)operator(.)ident(each) operator({) operator(|)ident(value)operator(|) + reserved(if) ident(scalar)operator(()ident(value)operator(\)) + ident(result) operator(<<) ident(indent) operator(<<) string<delimiter(')content(<)delimiter(')> operator(<<) ident(name) operator(<<) string<delimiter(')content(>)delimiter(')> + ident(result) operator(<<) operator(()instance_variable(@options)operator([)string<delimiter(')content(noescape)delimiter(')>operator(]) operator(?) ident(value)operator(.)ident(to_s) operator(:) ident(escape_value)operator(()ident(value)operator(.)ident(to_s)operator(\))operator(\)) + ident(result) operator(<<) string<delimiter(')content(</)delimiter(')> operator(<<) ident(name) operator(<<) string<delimiter(')content(>)delimiter(')> operator(<<) ident(nl) + reserved(elsif) ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + ident(result) operator(<<) ident(value_to_xml)operator(()ident(value)operator(,) ident(name)operator(,) ident(indent)operator(\)) + reserved(else) + ident(result) operator(<<) ident(indent) operator(<<) string<delimiter(')content(<)delimiter(')> operator(<<) ident(name) operator(<<) string<delimiter(')content(>)delimiter(')> operator(<<) ident(nl) + ident(result) operator(<<) ident(value_to_xml)operator(()ident(value)operator(,) instance_variable(@options)operator([)string<delimiter(')content(anonymoustag)delimiter(')>operator(])operator(,) ident(indent) operator(+) instance_variable(@options)operator([)string<delimiter(')content(indent)delimiter(')>operator(])operator(\)) + ident(result) operator(<<) ident(indent) operator(<<) string<delimiter(')content(</)delimiter(')> operator(<<) ident(name) operator(<<) string<delimiter(')content(>)delimiter(')> operator(<<) ident(nl) + reserved(end) + operator(}) + reserved(else) + comment(# Probably, this is obsolete.) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Can't encode a value of type: )inline<inline_delimiter(#{)ident(ref)operator(.)ident(type)inline_delimiter(})>content(.)delimiter(")> + reserved(end) + instance_variable(@ancestors)operator(.)ident(pop) reserved(if) operator(!)ident(scalar)operator(()ident(ref)operator(\)) + ident(result)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + comment(# Checks, if a certain value is a "scalar" value. Whatever) + comment(# that will be in Ruby ... ;-\)) + comment(# ) + comment(# value::) + comment(# Value to be checked.) + reserved(def) method(scalar)operator(()ident(value)operator(\)) + reserved(return) pre_constant(false) reserved(if) ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) operator(||) ident(value)operator(.)ident(instance_of?)operator(()constant(Array)operator(\)) + reserved(return) pre_constant(true) + reserved(end) + + comment(# Attempts to unfold a hash of hashes into an array of hashes. Returns) + comment(# a reference to th array on success or the original hash, if unfolding) + comment(# is not possible.) + comment(# ) + comment(# parent::) + comment(# ) + comment(# hashref::) + comment(# Reference to the hash to be unfolded.) + reserved(def) method(hash_to_array)operator(()ident(parent)operator(,) ident(hashref)operator(\)) + ident(arrayref) operator(=) operator([)operator(]) + ident(hashref)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(return) ident(hashref) reserved(unless) ident(value)operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + + reserved(if) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(instance_of?)operator(()constant(Hash)operator(\)) + reserved(return) ident(hashref) reserved(unless) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator(.)ident(has_key?)operator(()ident(parent)operator(\)) + ident(arrayref) operator(<<) operator({) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator([)ident(parent)operator(])operator([)integer(0)operator(]) operator(=)operator(>) ident(key) operator(})operator(.)ident(update)operator(()ident(value)operator(\)) + reserved(else) + ident(arrayref) operator(<<) operator({) instance_variable(@options)operator([)string<delimiter(')content(keyattr)delimiter(')>operator(])operator([)integer(0)operator(]) operator(=)operator(>) ident(key) operator(})operator(.)ident(update)operator(()ident(value)operator(\)) + reserved(end) + operator(}) + ident(arrayref) + reserved(end) + + comment(# Replaces XML markup characters by their external entities.) + comment(#) + comment(# data::) + comment(# The string to be escaped.) + reserved(def) method(escape_value)operator(()ident(data)operator(\)) + reserved(return) ident(data) reserved(if) ident(data)operator(.)ident(nil?) operator(||) ident(data) operator(==) string<delimiter(')delimiter(')> + ident(result) operator(=) ident(data)operator(.)ident(dup) + ident(result)operator(.)ident(gsub!)operator(()string<delimiter(')content(&)delimiter(')>operator(,) string<delimiter(')content(&)delimiter(')>operator(\)) + ident(result)operator(.)ident(gsub!)operator(()string<delimiter(')content(<)delimiter(')>operator(,) string<delimiter(')content(<)delimiter(')>operator(\)) + ident(result)operator(.)ident(gsub!)operator(()string<delimiter(')content(>)delimiter(')>operator(,) string<delimiter(')content(>)delimiter(')>operator(\)) + ident(result)operator(.)ident(gsub!)operator(()string<delimiter(')content(")delimiter(')>operator(,) string<delimiter(')content(")delimiter(')>operator(\)) + ident(result)operator(.)ident(gsub!)operator(()string<delimiter(")content(')delimiter(")>operator(,) string<delimiter(')content(')delimiter(')>operator(\)) + ident(result) + reserved(end) + + comment(# Removes leading and trailing whitespace and sequences of) + comment(# whitespaces from a string.) + comment(#) + comment(# text::) + comment(# String to be normalised.) + reserved(def) method(normalise_space)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^)char(\\s)content(+)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(text)operator(.)ident(sub!)operator(()regexp<delimiter(/)char(\\s)content(+$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(text)operator(.)ident(gsub!)operator(()regexp<delimiter(/)char(\\s)char(\\s)content(+)delimiter(/)>operator(,) string<delimiter(')content( )delimiter(')>operator(\)) + ident(text) + reserved(end) + + comment(# Checks, if an object is nil, an empty String or an empty Hash.) + comment(# Thanks to Norbert Gawor for a bugfix.) + comment(#) + comment(# value::) + comment(# Value to be checked for emptyness.) + reserved(def) method(empty)operator(()ident(value)operator(\)) + reserved(case) ident(value) + reserved(when) constant(Hash) + reserved(return) ident(value)operator(.)ident(empty?) + reserved(when) constant(String) + reserved(return) ident(value) operator(!)operator(~) regexp<delimiter(/)char(\\S)delimiter(/)modifier(m)> + reserved(else) + reserved(return) ident(value)operator(.)ident(nil?) + reserved(end) + reserved(end) + + comment(# Converts a document node into a String.) + comment(# If the node could not be converted into a String) + comment(# for any reason, default will be returned.) + comment(#) + comment(# node::) + comment(# Document node to be converted.) + comment(# default::) + comment(# Value to be returned, if node could not be converted.) + reserved(def) method(node_to_text)operator(()ident(node)operator(,) ident(default) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(node)operator(.)ident(instance_of?)operator(()constant(Element)operator(\)) + reserved(return) ident(node)operator(.)ident(texts)operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(elsif) ident(node)operator(.)ident(instance_of?)operator(()constant(Attribute)operator(\)) + reserved(return) ident(node)operator(.)ident(value)operator(.)ident(nil?) operator(?) ident(default) operator(:) ident(node)operator(.)ident(value)operator(.)ident(strip) + reserved(elsif) ident(node)operator(.)ident(instance_of?)operator(()constant(Text)operator(\)) + reserved(return) ident(node)operator(.)ident(to_s)operator(.)ident(strip) + reserved(else) + reserved(return) ident(default) + reserved(end) + reserved(end) + + comment(# Parses an XML string and returns the according document.) + comment(#) + comment(# xml_string::) + comment(# XML string to be parsed.) + comment(#) + comment(# The following exception may be raised:) + comment(#) + comment(# REXML::ParseException::) + comment(# If the specified file is not wellformed.) + reserved(def) method(parse)operator(()ident(xml_string)operator(\)) + constant(Document)operator(.)ident(new)operator(()ident(xml_string)operator(\)) + reserved(end) + + comment(# Searches in a list of paths for a certain file. Returns) + comment(# the full path to the file, if it could be found. Otherwise,) + comment(# an exception will be raised.) + comment(#) + comment(# filename::) + comment(# Name of the file to search for.) + comment(# searchpath::) + comment(# List of paths to search in.) + reserved(def) method(find_xml_file)operator(()ident(file)operator(,) ident(searchpath)operator(\)) + ident(filename) operator(=) constant(File)operator(::)ident(basename)operator(()ident(file)operator(\)) + + reserved(if) ident(filename) operator(!=) ident(file) + reserved(return) ident(file) reserved(if) constant(File)operator(::)ident(file?)operator(()ident(file)operator(\)) + reserved(else) + ident(searchpath)operator(.)ident(each) operator({) operator(|)ident(path)operator(|) + ident(full_path) operator(=) constant(File)operator(::)ident(join)operator(()ident(path)operator(,) ident(filename)operator(\)) + reserved(return) ident(full_path) reserved(if) constant(File)operator(::)ident(file?)operator(()ident(full_path)operator(\)) + operator(}) + reserved(end) + + reserved(if) ident(searchpath)operator(.)ident(empty?) + reserved(return) ident(file) reserved(if) constant(File)operator(::)ident(file?)operator(()ident(file)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(File does not exist: )inline<inline_delimiter(#{)ident(file)inline_delimiter(})>content(.)delimiter(")> + reserved(end) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Could not find <)inline<inline_delimiter(#{)ident(filename)inline_delimiter(})>content(> in <)inline<inline_delimiter(#{)ident(searchpath)operator(.)ident(join)operator(()string<delimiter(')content(:)delimiter(')>operator(\))inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + comment(# Loads and parses an XML configuration file.) + comment(#) + comment(# filename::) + comment(# Name of the configuration file to be loaded.) + comment(#) + comment(# The following exceptions may be raised:) + comment(# ) + comment(# Errno::ENOENT::) + comment(# If the specified file does not exist.) + comment(# REXML::ParseException::) + comment(# If the specified file is not wellformed.) + reserved(def) method(load_xml_file)operator(()ident(filename)operator(\)) + ident(parse)operator(()constant(File)operator(.)ident(readlines)operator(()ident(filename)operator(\))operator(.)ident(to_s)operator(\)) + reserved(end) + + comment(# Caches the data belonging to a certain file.) + comment(#) + comment(# data::) + comment(# Data to be cached.) + comment(# filename::) + comment(# Name of file the data was read from.) + reserved(def) method(put_into_cache)operator(()ident(data)operator(,) ident(filename)operator(\)) + reserved(if) instance_variable(@options)operator(.)ident(has_key?)operator(()string<delimiter(')content(cache)delimiter(')>operator(\)) + instance_variable(@options)operator([)string<delimiter(')content(cache)delimiter(')>operator(])operator(.)ident(each) operator({) operator(|)ident(scheme)operator(|) + reserved(case)operator(()ident(scheme)operator(\)) + reserved(when) string<delimiter(')content(storable)delimiter(')> + class_variable(@@cache)operator(.)ident(save_storable)operator(()ident(data)operator(,) ident(filename)operator(\)) + reserved(when) string<delimiter(')content(mem_share)delimiter(')> + class_variable(@@cache)operator(.)ident(save_mem_share)operator(()ident(data)operator(,) ident(filename)operator(\)) + reserved(when) string<delimiter(')content(mem_copy)delimiter(')> + class_variable(@@cache)operator(.)ident(save_mem_copy)operator(()ident(data)operator(,) ident(filename)operator(\)) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Unsupported caching scheme: <)inline<inline_delimiter(#{)ident(scheme)inline_delimiter(})>content(>.)delimiter(")> + reserved(end) + operator(}) + reserved(end) + reserved(end) +reserved(end) + +comment(# vim:sw=2) +reserved(module) class(ActionController) comment(#:nodoc:) + reserved(module) class(Verification) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# This module provides a class-level method for specifying that certain) + comment(# actions are guarded against being called without certain prerequisites) + comment(# being met. This is essentially a special kind of before_filter.) + comment(#) + comment(# An action may be guarded against being invoked without certain request) + comment(# parameters being set, or without certain session values existing.) + comment(#) + comment(# When a verification is violated, values may be inserted into the flash, and) + comment(# a specified redirection is triggered.) + comment(#) + comment(# Usage:) + comment(#) + comment(# class GlobalController < ActionController::Base) + comment(# # prevent the #update_settings action from being invoked unless) + comment(# # the 'admin_privileges' request parameter exists.) + comment(# verify :params => "admin_privileges", :only => :update_post,) + comment(# :redirect_to => { :action => "settings" }) + comment(#) + comment(# # disallow a post from being updated if there was no information) + comment(# # submitted with the post, and if there is no active post in the) + comment(# # session, and if there is no "note" key in the flash.) + comment(# verify :params => "post", :session => "post", "flash" => "note",) + comment(# :only => :update_post,) + comment(# :add_flash => { "alert" => "Failed to create your message" },) + comment(# :redirect_to => :category_url) + comment(#) + reserved(module) class(ClassMethods) + comment(# Verify the given actions so that if certain prerequisites are not met,) + comment(# the user is redirected to a different action. The +options+ parameter) + comment(# is a hash consisting of the following key/value pairs:) + comment(#) + comment(# * <tt>:params</tt>: a single key or an array of keys that must) + comment(# be in the <tt>params</tt> hash in order for the action(s\) to be safely) + comment(# called.) + comment(# * <tt>:session</tt>: a single key or an array of keys that must) + comment(# be in the @session in order for the action(s\) to be safely called.) + comment(# * <tt>:flash</tt>: a single key or an array of keys that must) + comment(# be in the flash in order for the action(s\) to be safely called.) + comment(# * <tt>:method</tt>: a single key or an array of keys--any one of which) + comment(# must match the current request method in order for the action(s\) to) + comment(# be safely called. (The key should be a symbol: <tt>:get</tt> or) + comment(# <tt>:post</tt>, for example.\)) + comment(# * <tt>:xhr</tt>: true/false option to ensure that the request is coming) + comment(# from an Ajax call or not. ) + comment(# * <tt>:add_flash</tt>: a hash of name/value pairs that should be merged) + comment(# into the session's flash if the prerequisites cannot be satisfied.) + comment(# * <tt>:redirect_to</tt>: the redirection parameters to be used when) + comment(# redirecting if the prerequisites cannot be satisfied.) + comment(# * <tt>:render</tt>: the render parameters to be used when) + comment(# the prerequisites cannot be satisfied.) + comment(# * <tt>:only</tt>: only apply this verification to the actions specified) + comment(# in the associated array (may also be a single value\).) + comment(# * <tt>:except</tt>: do not apply this verification to the actions) + comment(# specified in the associated array (may also be a single value\).) + reserved(def) method(verify)operator(()ident(options)operator(=)operator({)operator(})operator(\)) + ident(filter_opts) operator(=) operator({) symbol(:only) operator(=)operator(>) ident(options)operator([)symbol(:only)operator(])operator(,) symbol(:except) operator(=)operator(>) ident(options)operator([)symbol(:except)operator(]) operator(}) + ident(before_filter)operator(()ident(filter_opts)operator(\)) reserved(do) operator(|)ident(c)operator(|) + ident(c)operator(.)ident(send) symbol(:verify_action)operator(,) ident(options) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(verify_action)operator(()ident(options)operator(\)) comment(#:nodoc:) + ident(prereqs_invalid) operator(=) + operator([)operator(*)ident(options)operator([)symbol(:params)operator(]) operator(])operator(.)ident(find) operator({) operator(|)ident(v)operator(|) instance_variable(@params)operator([)ident(v)operator(])operator(.)ident(nil?) operator(}) operator(||) + operator([)operator(*)ident(options)operator([)symbol(:session)operator(])operator(])operator(.)ident(find) operator({) operator(|)ident(v)operator(|) instance_variable(@session)operator([)ident(v)operator(])operator(.)ident(nil?) operator(}) operator(||) + operator([)operator(*)ident(options)operator([)symbol(:flash)operator(]) operator(])operator(.)ident(find) operator({) operator(|)ident(v)operator(|) ident(flash)operator([)ident(v)operator(])operator(.)ident(nil?) operator(}) + + reserved(if) operator(!)ident(prereqs_invalid) operator(&&) ident(options)operator([)symbol(:method)operator(]) + ident(prereqs_invalid) operator(||=) + operator([)operator(*)ident(options)operator([)symbol(:method)operator(])operator(])operator(.)ident(all?) operator({) operator(|)ident(v)operator(|) instance_variable(@request)operator(.)ident(method) operator(!=) ident(v)operator(.)ident(to_sym) operator(}) + reserved(end) + + ident(prereqs_invalid) operator(||=) operator(()ident(request)operator(.)ident(xhr?) operator(!=) ident(options)operator([)symbol(:xhr)operator(])operator(\)) reserved(unless) ident(options)operator([)symbol(:xhr)operator(])operator(.)ident(nil?) + + reserved(if) ident(prereqs_invalid) + ident(flash)operator(.)ident(update)operator(()ident(options)operator([)symbol(:add_flash)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:add_flash)operator(]) + reserved(unless) ident(performed?) + ident(render)operator(()ident(options)operator([)symbol(:render)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:render)operator(]) + ident(redirect_to)operator(()ident(options)operator([)symbol(:redirect_to)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:redirect_to)operator(]) + reserved(end) + reserved(return) pre_constant(false) + reserved(end) + + pre_constant(true) + reserved(end) + ident(private) symbol(:verify_action) + reserved(end) +reserved(end) +comment(#--) +comment(# Copyright (c\) 2004 David Heinemeier Hansson) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\)) reserved(unless) + global_variable($:)operator(.)ident(include?)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\)) operator(||) global_variable($:)operator(.)ident(include?)operator(()constant(File)operator(.)ident(expand_path)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\))operator(\)) + +reserved(unless) reserved(defined?)operator(()constant(ActiveSupport)operator(\)) + reserved(begin) + global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../../activesupport/lib)delimiter(")>operator(\)) + ident(require) string<delimiter(')content(active_support)delimiter(')> + reserved(rescue) constant(LoadError) + ident(require) string<delimiter(')content(rubygems)delimiter(')> + ident(require_gem) string<delimiter(')content(activesupport)delimiter(')> + reserved(end) +reserved(end) + +ident(require) string<delimiter(')content(action_controller/base)delimiter(')> +ident(require) string<delimiter(')content(action_controller/deprecated_redirects)delimiter(')> +ident(require) string<delimiter(')content(action_controller/request)delimiter(')> +ident(require) string<delimiter(')content(action_controller/deprecated_request_methods)delimiter(')> +ident(require) string<delimiter(')content(action_controller/rescue)delimiter(')> +ident(require) string<delimiter(')content(action_controller/benchmarking)delimiter(')> +ident(require) string<delimiter(')content(action_controller/flash)delimiter(')> +ident(require) string<delimiter(')content(action_controller/filters)delimiter(')> +ident(require) string<delimiter(')content(action_controller/layout)delimiter(')> +ident(require) string<delimiter(')content(action_controller/dependencies)delimiter(')> +ident(require) string<delimiter(')content(action_controller/mime_responds)delimiter(')> +ident(require) string<delimiter(')content(action_controller/pagination)delimiter(')> +ident(require) string<delimiter(')content(action_controller/scaffolding)delimiter(')> +ident(require) string<delimiter(')content(action_controller/helpers)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cookies)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cgi_process)delimiter(')> +ident(require) string<delimiter(')content(action_controller/caching)delimiter(')> +ident(require) string<delimiter(')content(action_controller/verification)delimiter(')> +ident(require) string<delimiter(')content(action_controller/streaming)delimiter(')> +ident(require) string<delimiter(')content(action_controller/session_management)delimiter(')> +ident(require) string<delimiter(')content(action_controller/components)delimiter(')> +ident(require) string<delimiter(')content(action_controller/macros/auto_complete)delimiter(')> +ident(require) string<delimiter(')content(action_controller/macros/in_place_editing)delimiter(')> + +ident(require) string<delimiter(')content(action_view)delimiter(')> +constant(ActionController)operator(::)constant(Base)operator(.)ident(template_class) operator(=) constant(ActionView)operator(::)constant(Base) + +constant(ActionController)operator(::)constant(Base)operator(.)ident(class_eval) reserved(do) + ident(include) constant(ActionController)operator(::)constant(Flash) + ident(include) constant(ActionController)operator(::)constant(Filters) + ident(include) constant(ActionController)operator(::)constant(Layout) + ident(include) constant(ActionController)operator(::)constant(Benchmarking) + ident(include) constant(ActionController)operator(::)constant(Rescue) + ident(include) constant(ActionController)operator(::)constant(Dependencies) + ident(include) constant(ActionController)operator(::)constant(MimeResponds) + ident(include) constant(ActionController)operator(::)constant(Pagination) + ident(include) constant(ActionController)operator(::)constant(Scaffolding) + ident(include) constant(ActionController)operator(::)constant(Helpers) + ident(include) constant(ActionController)operator(::)constant(Cookies) + ident(include) constant(ActionController)operator(::)constant(Caching) + ident(include) constant(ActionController)operator(::)constant(Verification) + ident(include) constant(ActionController)operator(::)constant(Streaming) + ident(include) constant(ActionController)operator(::)constant(SessionManagement) + ident(include) constant(ActionController)operator(::)constant(Components) + ident(include) constant(ActionController)operator(::)constant(Macros)operator(::)constant(AutoComplete) + ident(include) constant(ActionController)operator(::)constant(Macros)operator(::)constant(InPlaceEditing) +reserved(end) +reserved(module) class(ActionPack) comment(#:nodoc:) + reserved(module) class(VERSION) comment(#:nodoc:) + constant(MAJOR) operator(=) integer(1) + constant(MINOR) operator(=) integer(12) + constant(TINY) operator(=) integer(5) + + constant(STRING) operator(=) operator([)constant(MAJOR)operator(,) constant(MINOR)operator(,) constant(TINY)operator(])operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) +reserved(end) +comment(#--) +comment(# Copyright (c\) 2004 David Heinemeier Hansson) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +ident(require) string<delimiter(')content(action_pack/version)delimiter(')> +ident(require) string<delimiter(')content(erb)delimiter(')> + +reserved(module) class(ActionView) comment(#:nodoc:) + + reserved(class) class(ActionViewError) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + + comment(# Action View templates can be written in three ways. If the template file has a +.rhtml+ extension then it uses a mixture of ERb ) + comment(# (included in Ruby\) and HTML. If the template file has a +.rxml+ extension then Jim Weirich's Builder::XmlMarkup library is used. ) + comment(# If the template file has a +.rjs+ extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.) + comment(# ) + comment(# = ERb) + comment(# ) + comment(# You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the ) + comment(# following loop for names:) + comment(#) + comment(# <b>Names of all the people</b>) + comment(# <% for person in @people %>) + comment(# Name: <%= person.name %><br/>) + comment(# <% end %>) + comment(#) + comment(# The loop is setup in regular embedding tags <% %> and the name is written using the output embedding tag <%= %>. Note that this) + comment(# is not just a usage suggestion. Regular output functions like print or puts won't work with ERb templates. So this would be wrong:) + comment(#) + comment(# Hi, Mr. <% puts "Frodo" %>) + comment(#) + comment(# If you absolutely must write from within a function, you can use the TextHelper#concat) + comment(#) + comment(# <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>.) + comment(#) + comment(# == Using sub templates) + comment(#) + comment(# Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The) + comment(# classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts\):) + comment(#) + comment(# <%= render "shared/header" %>) + comment(# Something really specific and terrific) + comment(# <%= render "shared/footer" %>) + comment(#) + comment(# As you see, we use the output embeddings for the render methods. The render call itself will just return a string holding the) + comment(# result of the rendering. The output embedding writes it to the current template.) + comment(#) + comment(# But you don't have to restrict yourself to static includes. Templates can share variables amongst themselves by using instance) + comment(# variables defined using the regular embedding tags. Like this:) + comment(#) + comment(# <% @page_title = "A Wonderful Hello" %>) + comment(# <%= render "shared/header" %>) + comment(#) + comment(# Now the header can pick up on the @page_title variable and use it for outputting a title tag:) + comment(#) + comment(# <title><%= @page_title %></title>) + comment(#) + comment(# == Passing local variables to sub templates) + comment(# ) + comment(# You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values:) + comment(#) + comment(# <%= render "shared/header", { "headline" => "Welcome", "person" => person } %>) + comment(#) + comment(# These can now be accessed in shared/header with:) + comment(#) + comment(# Headline: <%= headline %>) + comment(# First name: <%= person.first_name %>) + comment(#) + comment(# == Template caching) + comment(#) + comment(# By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will) + comment(# check the file's modification time and recompile it.) + comment(#) + comment(# == Builder) + comment(#) + comment(# Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An +XmlMarkup+ object ) + comment(# named +xml+ is automatically made available to templates with a +.rxml+ extension. ) + comment(#) + comment(# Here are some basic examples:) + comment(#) + comment(# xml.em("emphasized"\) # => <em>emphasized</em>) + comment(# xml.em { xml.b("emp & bold"\) } # => <em><b>emph & bold</b></em>) + comment(# xml.a("A Link", "href"=>"http://onestepback.org"\) # => <a href="http://onestepback.org">A Link</a>) + comment(# xml.target("name"=>"compile", "option"=>"fast"\) # => <target option="fast" name="compile"\\>) + comment(# # NOTE: order of attributes is not specified.) + comment(# ) + comment(# Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following:) + comment(#) + comment(# xml.div {) + comment(# xml.h1(@person.name\)) + comment(# xml.p(@person.bio\)) + comment(# }) + comment(#) + comment(# would produce something like:) + comment(#) + comment(# <div>) + comment(# <h1>David Heinemeier Hansson</h1>) + comment(# <p>A product of Danish Design during the Winter of '79...</p>) + comment(# </div>) + comment(#) + comment(# A full-length RSS example actually used on Basecamp:) + comment(#) + comment(# xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/"\) do) + comment(# xml.channel do) + comment(# xml.title(@feed_title\)) + comment(# xml.link(@url\)) + comment(# xml.description "Basecamp: Recent items") + comment(# xml.language "en-us") + comment(# xml.ttl "40") + comment(# ) + comment(# for item in @recent_items) + comment(# xml.item do) + comment(# xml.title(item_title(item\)\)) + comment(# xml.description(item_description(item\)\) if item_description(item\)) + comment(# xml.pubDate(item_pubDate(item\)\)) + comment(# xml.guid(@person.firm.account.url + @recent_items.url(item\)\)) + comment(# xml.link(@person.firm.account.url + @recent_items.url(item\)\)) + comment(# ) + comment(# xml.tag!("dc:creator", item.author_name\) if item_has_creator?(item\)) + comment(# end) + comment(# end) + comment(# end) + comment(# end) + comment(#) + comment(# More builder documentation can be found at http://builder.rubyforge.org.) + comment(#) + comment(# == JavaScriptGenerator) + comment(#) + comment(# JavaScriptGenerator templates end in +.rjs+. Unlike conventional templates which are used to ) + comment(# render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to ) + comment(# modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax ) + comment(# and make updates to the page where the request originated from.) + comment(# ) + comment(# An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block. ) + comment(#) + comment(# When an .rjs action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example:) + comment(#) + comment(# link_to_remote :url => {:action => 'delete'}) + comment(#) + comment(# The subsequently rendered +delete.rjs+ might look like:) + comment(#) + comment(# page.replace_html 'sidebar', :partial => 'sidebar') + comment(# page.remove "person-#{@person.id}") + comment(# page.visual_effect :highlight, 'user-list' ) + comment(#) + comment(# This refreshes the sidebar, removes a person element and highlights the user list.) + comment(# ) + comment(# See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details.) + reserved(class) class(Base) + ident(include) constant(ERB)operator(::)constant(Util) + + ident(attr_reader) symbol(:first_render) + ident(attr_accessor) symbol(:base_path)operator(,) symbol(:assigns)operator(,) symbol(:template_extension) + ident(attr_accessor) symbol(:controller) + + ident(attr_reader) symbol(:logger)operator(,) symbol(:params)operator(,) symbol(:request)operator(,) symbol(:response)operator(,) symbol(:session)operator(,) symbol(:headers)operator(,) symbol(:flash) + + comment(# Specify trim mode for the ERB compiler. Defaults to '-'.) + comment(# See ERB documentation for suitable values.) + class_variable(@@erb_trim_mode) operator(=) string<delimiter(')content(-)delimiter(')> + ident(cattr_accessor) symbol(:erb_trim_mode) + + comment(# Specify whether file modification times should be checked to see if a template needs recompilation) + class_variable(@@cache_template_loading) operator(=) pre_constant(false) + ident(cattr_accessor) symbol(:cache_template_loading) + + comment(# Specify whether file extension lookup should be cached.) + comment(# Should be +false+ for development environments. Defaults to +true+.) + class_variable(@@cache_template_extensions) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:cache_template_extensions) + + comment(# Specify whether local_assigns should be able to use string keys.) + comment(# Defaults to +true+. String keys are deprecated and will be removed) + comment(# shortly.) + class_variable(@@local_assigns_support_string_keys) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:local_assigns_support_string_keys) + + comment(# Specify whether RJS responses should be wrapped in a try/catch block) + comment(# that alert(\)s the caught exception (and then re-raises it\). ) + class_variable(@@debug_rjs) operator(=) pre_constant(false) + ident(cattr_accessor) symbol(:debug_rjs) + + class_variable(@@template_handlers) operator(=) constant(HashWithIndifferentAccess)operator(.)ident(new) + + reserved(module) class(CompiledTemplates) comment(#:nodoc:) + comment(# holds compiled template code) + reserved(end) + ident(include) constant(CompiledTemplates) + + comment(# maps inline templates to their method names ) + class_variable(@@method_names) operator(=) operator({)operator(}) + comment(# map method names to their compile time) + class_variable(@@compile_time) operator(=) operator({)operator(}) + comment(# map method names to the names passed in local assigns so far) + class_variable(@@template_args) operator(=) operator({)operator(}) + comment(# count the number of inline templates) + class_variable(@@inline_template_count) operator(=) integer(0) + comment(# maps template paths without extension to their file extension returned by pick_template_extension.) + comment(# if for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions) + comment(# used by pick_template_extension determines whether ext1 or ext2 will be stored) + class_variable(@@cached_template_extension) operator(=) operator({)operator(}) + + reserved(class) class(ObjectWrapper) operator(<) constant(Struct)operator(.)ident(new)operator(()symbol(:value)operator(\)) comment(#:nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(load_helpers)operator(()ident(helper_dir)operator(\))comment(#:nodoc:) + constant(Dir)operator(.)ident(foreach)operator(()ident(helper_dir)operator(\)) reserved(do) operator(|)ident(helper_file)operator(|) + reserved(next) reserved(unless) ident(helper_file) operator(=)operator(~) regexp<delimiter(/)content(^([a-z][a-z_]*_helper\).rb$)delimiter(/)> + ident(require) constant(File)operator(.)ident(join)operator(()ident(helper_dir)operator(,) global_variable($1)operator(\)) + ident(helper_module_name) operator(=) global_variable($1)operator(.)ident(camelize) + ident(class_eval)operator(()string<delimiter(")content(include ActionView::Helpers::)inline<inline_delimiter(#{)ident(helper_module_name)inline_delimiter(})>delimiter(")>operator(\)) reserved(if) constant(Helpers)operator(.)ident(const_defined?)operator(()ident(helper_module_name)operator(\)) + reserved(end) + reserved(end) + + comment(# Register a class that knows how to handle template files with the given) + comment(# extension. This can be used to implement new template types.) + comment(# The constructor for the class must take the ActiveView::Base instance) + comment(# as a parameter, and the class must implement a #render method that) + comment(# takes the contents of the template to render as well as the Hash of) + comment(# local assigns available to the template. The #render method ought to) + comment(# return the rendered template as a string.) + reserved(def) pre_constant(self)operator(.)ident(register_template_handler)operator(()ident(extension)operator(,) ident(klass)operator(\)) + class_variable(@@template_handlers)operator([)ident(extension)operator(]) operator(=) ident(klass) + reserved(end) + + reserved(def) method(initialize)operator(()ident(base_path) operator(=) pre_constant(nil)operator(,) ident(assigns_for_first_render) operator(=) operator({)operator(})operator(,) ident(controller) operator(=) pre_constant(nil)operator(\))comment(#:nodoc:) + instance_variable(@base_path)operator(,) instance_variable(@assigns) operator(=) ident(base_path)operator(,) ident(assigns_for_first_render) + instance_variable(@assigns_added) operator(=) pre_constant(nil) + instance_variable(@controller) operator(=) ident(controller) + instance_variable(@logger) operator(=) ident(controller) operator(&&) ident(controller)operator(.)ident(logger) + reserved(end) + + comment(# Renders the template present at <tt>template_path</tt>. If <tt>use_full_path</tt> is set to true, ) + comment(# it's relative to the template_root, otherwise it's absolute. The hash in <tt>local_assigns</tt> ) + comment(# is made available as local variables.) + reserved(def) method(render_file)operator(()ident(template_path)operator(,) ident(use_full_path) operator(=) pre_constant(true)operator(,) ident(local_assigns) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + instance_variable(@first_render) operator(||=) ident(template_path) + + reserved(if) ident(use_full_path) + ident(template_path_without_extension)operator(,) ident(template_extension) operator(=) ident(path_and_extension)operator(()ident(template_path)operator(\)) + + reserved(if) ident(template_extension) + ident(template_file_name) operator(=) ident(full_template_path)operator(()ident(template_path_without_extension)operator(,) ident(template_extension)operator(\)) + reserved(else) + ident(template_extension) operator(=) ident(pick_template_extension)operator(()ident(template_path)operator(\))operator(.)ident(to_s) + ident(template_file_name) operator(=) ident(full_template_path)operator(()ident(template_path)operator(,) ident(template_extension)operator(\)) + reserved(end) + reserved(else) + ident(template_file_name) operator(=) ident(template_path) + ident(template_extension) operator(=) ident(template_path)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(.)ident(last) + reserved(end) + + ident(template_source) operator(=) pre_constant(nil) comment(# Don't read the source until we know that it is required) + + reserved(begin) + ident(render_template)operator(()ident(template_extension)operator(,) ident(template_source)operator(,) ident(template_file_name)operator(,) ident(local_assigns)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + reserved(if) constant(TemplateError) operator(===) ident(e) + ident(e)operator(.)ident(sub_template_of)operator(()ident(template_file_name)operator(\)) + ident(raise) ident(e) + reserved(else) + ident(raise) constant(TemplateError)operator(.)ident(new)operator(()instance_variable(@base_path)operator(,) ident(template_file_name)operator(,) instance_variable(@assigns)operator(,) ident(template_source)operator(,) ident(e)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Renders the template present at <tt>template_path</tt> (relative to the template_root\). ) + comment(# The hash in <tt>local_assigns</tt> is made available as local variables.) + reserved(def) method(render)operator(()ident(options) operator(=) operator({)operator(})operator(,) ident(old_local_assigns) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) comment(#:nodoc:) + reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(render_file)operator(()ident(options)operator(,) pre_constant(true)operator(,) ident(old_local_assigns)operator(\)) + reserved(elsif) ident(options) operator(==) symbol(:update) + ident(update_page)operator(()operator(&)ident(block)operator(\)) + reserved(elsif) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(options)operator([)symbol(:locals)operator(]) operator(||=) operator({)operator(}) + ident(options)operator([)symbol(:use_full_path)operator(]) operator(=) ident(options)operator([)symbol(:use_full_path)operator(])operator(.)ident(nil?) operator(?) pre_constant(true) operator(:) ident(options)operator([)symbol(:use_full_path)operator(]) + + reserved(if) ident(options)operator([)symbol(:file)operator(]) + ident(render_file)operator(()ident(options)operator([)symbol(:file)operator(])operator(,) ident(options)operator([)symbol(:use_full_path)operator(])operator(,) ident(options)operator([)symbol(:locals)operator(])operator(\)) + reserved(elsif) ident(options)operator([)symbol(:partial)operator(]) operator(&&) ident(options)operator([)symbol(:collection)operator(]) + ident(render_partial_collection)operator(()ident(options)operator([)symbol(:partial)operator(])operator(,) ident(options)operator([)symbol(:collection)operator(])operator(,) ident(options)operator([)symbol(:spacer_template)operator(])operator(,) ident(options)operator([)symbol(:locals)operator(])operator(\)) + reserved(elsif) ident(options)operator([)symbol(:partial)operator(]) + ident(render_partial)operator(()ident(options)operator([)symbol(:partial)operator(])operator(,) constant(ActionView)operator(::)constant(Base)operator(::)constant(ObjectWrapper)operator(.)ident(new)operator(()ident(options)operator([)symbol(:object)operator(])operator(\))operator(,) ident(options)operator([)symbol(:locals)operator(])operator(\)) + reserved(elsif) ident(options)operator([)symbol(:inline)operator(]) + ident(render_template)operator(()ident(options)operator([)symbol(:type)operator(]) operator(||) symbol(:rhtml)operator(,) ident(options)operator([)symbol(:inline)operator(])operator(,) pre_constant(nil)operator(,) ident(options)operator([)symbol(:locals)operator(]) operator(||) operator({)operator(})operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Renders the +template+ which is given as a string as either rhtml or rxml depending on <tt>template_extension</tt>.) + comment(# The hash in <tt>local_assigns</tt> is made available as local variables.) + reserved(def) method(render_template)operator(()ident(template_extension)operator(,) ident(template)operator(,) ident(file_path) operator(=) pre_constant(nil)operator(,) ident(local_assigns) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + reserved(if) ident(handler) operator(=) class_variable(@@template_handlers)operator([)ident(template_extension)operator(]) + ident(template) operator(||=) ident(read_template_file)operator(()ident(file_path)operator(,) ident(template_extension)operator(\)) comment(# Make sure that a lazyily-read template is loaded.) + ident(delegate_render)operator(()ident(handler)operator(,) ident(template)operator(,) ident(local_assigns)operator(\)) + reserved(else) + ident(compile_and_render_template)operator(()ident(template_extension)operator(,) ident(template)operator(,) ident(file_path)operator(,) ident(local_assigns)operator(\)) + reserved(end) + reserved(end) + + comment(# Render the provided template with the given local assigns. If the template has not been rendered with the provided) + comment(# local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method.) + comment(#) + + comment(# Either, but not both, of template and file_path may be nil. If file_path is given, the template) + comment(# will only be read if it has to be compiled.) + comment(#) + reserved(def) method(compile_and_render_template)operator(()ident(extension)operator(,) ident(template) operator(=) pre_constant(nil)operator(,) ident(file_path) operator(=) pre_constant(nil)operator(,) ident(local_assigns) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + comment(# compile the given template, if necessary) + reserved(if) ident(compile_template?)operator(()ident(template)operator(,) ident(file_path)operator(,) ident(local_assigns)operator(\)) + ident(template) operator(||=) ident(read_template_file)operator(()ident(file_path)operator(,) ident(extension)operator(\)) + ident(compile_template)operator(()ident(extension)operator(,) ident(template)operator(,) ident(file_path)operator(,) ident(local_assigns)operator(\)) + reserved(end) + + comment(# Get the method name for this template and run it) + ident(method_name) operator(=) class_variable(@@method_names)operator([)ident(file_path) operator(||) ident(template)operator(]) + ident(evaluate_assigns) + + ident(local_assigns) operator(=) ident(local_assigns)operator(.)ident(symbolize_keys) reserved(if) class_variable(@@local_assigns_support_string_keys) + + ident(send)operator(()ident(method_name)operator(,) ident(local_assigns)operator(\)) reserved(do) operator(|*)ident(name)operator(|) + ident(instance_variable_get) string<delimiter(")content(@content_for_)inline<inline_delimiter(#{)ident(name)operator(.)ident(first) operator(||) string<delimiter(')content(layout)delimiter(')>inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(pick_template_extension)operator(()ident(template_path)operator(\))comment(#:nodoc:) + reserved(if) class_variable(@@cache_template_extensions) + class_variable(@@cached_template_extension)operator([)ident(template_path)operator(]) operator(||=) ident(find_template_extension_for)operator(()ident(template_path)operator(\)) + reserved(else) + ident(find_template_extension_for)operator(()ident(template_path)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(delegate_template_exists?)operator(()ident(template_path)operator(\))comment(#:nodoc:) + class_variable(@@template_handlers)operator(.)ident(find) operator({) operator(|)ident(k)operator(,)operator(|) ident(template_exists?)operator(()ident(template_path)operator(,) ident(k)operator(\)) operator(}) + reserved(end) + + reserved(def) method(erb_template_exists?)operator(()ident(template_path)operator(\))comment(#:nodoc:) + ident(template_exists?)operator(()ident(template_path)operator(,) symbol(:rhtml)operator(\)) + reserved(end) + + reserved(def) method(builder_template_exists?)operator(()ident(template_path)operator(\))comment(#:nodoc:) + ident(template_exists?)operator(()ident(template_path)operator(,) symbol(:rxml)operator(\)) + reserved(end) + + reserved(def) method(javascript_template_exists?)operator(()ident(template_path)operator(\))comment(#:nodoc:) + ident(template_exists?)operator(()ident(template_path)operator(,) symbol(:rjs)operator(\)) + reserved(end) + + reserved(def) method(file_exists?)operator(()ident(template_path)operator(\))comment(#:nodoc:) + ident(template_file_name)operator(,) ident(template_file_extension) operator(=) ident(path_and_extension)operator(()ident(template_path)operator(\)) + + reserved(if) ident(template_file_extension) + ident(template_exists?)operator(()ident(template_file_name)operator(,) ident(template_file_extension)operator(\)) + reserved(else) + ident(cached_template_extension)operator(()ident(template_path)operator(\)) operator(||) + string<delimiter(%w()content(erb builder javascript delegate)delimiter(\))>operator(.)ident(any?) reserved(do) operator(|)ident(template_type)operator(|) + ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(template_type)inline_delimiter(})>content(_template_exists?)delimiter(")>operator(,) ident(template_path)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns true is the file may be rendered implicitly.) + reserved(def) method(file_public?)operator(()ident(template_path)operator(\))comment(#:nodoc:) + ident(template_path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator(.)ident(last)operator([)integer(0)operator(,)integer(1)operator(]) operator(!=) string<delimiter(')content(_)delimiter(')> + reserved(end) + + ident(private) + reserved(def) method(full_template_path)operator(()ident(template_path)operator(,) ident(extension)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@base_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(template_path)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(extension)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(template_exists?)operator(()ident(template_path)operator(,) ident(extension)operator(\)) + ident(file_path) operator(=) ident(full_template_path)operator(()ident(template_path)operator(,) ident(extension)operator(\)) + class_variable(@@method_names)operator(.)ident(has_key?)operator(()ident(file_path)operator(\)) operator(||) constant(FileTest)operator(.)ident(exists?)operator(()ident(file_path)operator(\)) + reserved(end) + + reserved(def) method(path_and_extension)operator(()ident(template_path)operator(\)) + ident(template_path_without_extension) operator(=) ident(template_path)operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\.)content(()char(\\w)content(+\)$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + operator([) ident(template_path_without_extension)operator(,) global_variable($1) operator(]) + reserved(end) + + reserved(def) method(cached_template_extension)operator(()ident(template_path)operator(\)) + class_variable(@@cache_template_extensions) operator(&&) class_variable(@@cached_template_extension)operator([)ident(template_path)operator(]) + reserved(end) + + reserved(def) method(find_template_extension_for)operator(()ident(template_path)operator(\)) + reserved(if) ident(match) operator(=) ident(delegate_template_exists?)operator(()ident(template_path)operator(\)) + ident(match)operator(.)ident(first)operator(.)ident(to_sym) + reserved(elsif) ident(erb_template_exists?)operator(()ident(template_path)operator(\))operator(:) symbol(:rhtml) + reserved(elsif) ident(builder_template_exists?)operator(()ident(template_path)operator(\))operator(:) symbol(:rxml) + reserved(elsif) ident(javascript_template_exists?)operator(()ident(template_path)operator(\))operator(:) symbol(:rjs) + reserved(else) + ident(raise) constant(ActionViewError)operator(,) string<delimiter(")content(No rhtml, rxml, rjs or delegate template found for )inline<inline_delimiter(#{)ident(template_path)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# This method reads a template file.) + reserved(def) method(read_template_file)operator(()ident(template_path)operator(,) ident(extension)operator(\)) + constant(File)operator(.)ident(read)operator(()ident(template_path)operator(\)) + reserved(end) + + reserved(def) method(evaluate_assigns) + reserved(unless) instance_variable(@assigns_added) + ident(assign_variables_from_controller) + instance_variable(@assigns_added) operator(=) pre_constant(true) + reserved(end) + reserved(end) + + reserved(def) method(delegate_render)operator(()ident(handler)operator(,) ident(template)operator(,) ident(local_assigns)operator(\)) + ident(handler)operator(.)ident(new)operator(()pre_constant(self)operator(\))operator(.)ident(render)operator(()ident(template)operator(,) ident(local_assigns)operator(\)) + reserved(end) + + reserved(def) method(assign_variables_from_controller) + instance_variable(@assigns)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(key)inline_delimiter(})>delimiter(")>operator(,) ident(value)operator(\)) operator(}) + reserved(end) + + + comment(# Return true if the given template was compiled for a superset of the keys in local_assigns) + reserved(def) method(supports_local_assigns?)operator(()ident(render_symbol)operator(,) ident(local_assigns)operator(\)) + ident(local_assigns)operator(.)ident(empty?) operator(||) + operator(()operator(()ident(args) operator(=) class_variable(@@template_args)operator([)ident(render_symbol)operator(])operator(\)) operator(&&) ident(local_assigns)operator(.)ident(all?) operator({) operator(|)ident(k)operator(,)ident(_)operator(|) ident(args)operator(.)ident(has_key?)operator(()ident(k)operator(\)) operator(})operator(\)) + reserved(end) + + comment(# Check whether compilation is necessary.) + comment(# Compile if the inline template or file has not been compiled yet.) + comment(# Or if local_assigns has a new key, which isn't supported by the compiled code yet.) + comment(# Or if the file has changed on disk and checking file mods hasn't been disabled. ) + reserved(def) method(compile_template?)operator(()ident(template)operator(,) ident(file_name)operator(,) ident(local_assigns)operator(\)) + ident(method_key) operator(=) ident(file_name) operator(||) ident(template) + ident(render_symbol) operator(=) class_variable(@@method_names)operator([)ident(method_key)operator(]) + + reserved(if) class_variable(@@compile_time)operator([)ident(render_symbol)operator(]) operator(&&) ident(supports_local_assigns?)operator(()ident(render_symbol)operator(,) ident(local_assigns)operator(\)) + reserved(if) ident(file_name) operator(&&) operator(!)class_variable(@@cache_template_loading) + class_variable(@@compile_time)operator([)ident(render_symbol)operator(]) operator(<) constant(File)operator(.)ident(mtime)operator(()ident(file_name)operator(\)) operator(||) operator(()constant(File)operator(.)ident(symlink?)operator(()ident(file_name)operator(\)) operator(?) + class_variable(@@compile_time)operator([)ident(render_symbol)operator(]) operator(<) constant(File)operator(.)ident(lstat)operator(()ident(file_name)operator(\))operator(.)ident(mtime) operator(:) pre_constant(false)operator(\)) + reserved(end) + reserved(else) + pre_constant(true) + reserved(end) + reserved(end) + + comment(# Create source code for given template) + reserved(def) method(create_template_source)operator(()ident(extension)operator(,) ident(template)operator(,) ident(render_symbol)operator(,) ident(locals)operator(\)) + reserved(if) ident(template_requires_setup?)operator(()ident(extension)operator(\)) + ident(body) operator(=) reserved(case) ident(extension)operator(.)ident(to_sym) + reserved(when) symbol(:rxml) + string<delimiter(")content(xml = Builder::XmlMarkup.new(:indent => 2\))char(\\n)delimiter(")> operator(+) + string<delimiter(")content(@controller.headers['Content-Type'] ||= 'application/xml')char(\\n)delimiter(")> operator(+) + ident(template) + reserved(when) symbol(:rjs) + string<delimiter(")content(@controller.headers['Content-Type'] ||= 'text/javascript')char(\\n)delimiter(")> operator(+) + string<delimiter(")content(update_page do |page|)char(\\n)inline<inline_delimiter(#{)ident(template)inline_delimiter(})>char(\\n)content(end)delimiter(")> + reserved(end) + reserved(else) + ident(body) operator(=) constant(ERB)operator(.)ident(new)operator(()ident(template)operator(,) pre_constant(nil)operator(,) class_variable(@@erb_trim_mode)operator(\))operator(.)ident(src) + reserved(end) + + class_variable(@@template_args)operator([)ident(render_symbol)operator(]) operator(||=) operator({)operator(}) + ident(locals_keys) operator(=) class_variable(@@template_args)operator([)ident(render_symbol)operator(])operator(.)ident(keys) operator(|) ident(locals) + class_variable(@@template_args)operator([)ident(render_symbol)operator(]) operator(=) ident(locals_keys)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(h)operator(,) ident(k)operator(|) ident(h)operator([)ident(k)operator(]) operator(=) pre_constant(true)operator(;) ident(h) operator(}) + + ident(locals_code) operator(=) string<delimiter(")delimiter(")> + ident(locals_keys)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + ident(locals_code) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content( = local_assigns[:)inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(] if local_assigns.has_key?(:)inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(\))char(\\n)delimiter(")> + reserved(end) + + string<delimiter(")content(def )inline<inline_delimiter(#{)ident(render_symbol)inline_delimiter(})>content((local_assigns\))char(\\n)inline<inline_delimiter(#{)ident(locals_code)inline_delimiter(})>inline<inline_delimiter(#{)ident(body)inline_delimiter(})>char(\\n)content(end)delimiter(")> + reserved(end) + + reserved(def) method(template_requires_setup?)operator(()ident(extension)operator(\)) + ident(templates_requiring_setup)operator(.)ident(include?) ident(extension)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(templates_requiring_setup) + string<delimiter(%w()content(rxml rjs)delimiter(\))> + reserved(end) + + reserved(def) method(assign_method_name)operator(()ident(extension)operator(,) ident(template)operator(,) ident(file_name)operator(\)) + ident(method_name) operator(=) string<delimiter(')content(_run_)delimiter(')> + ident(method_name) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(extension)inline_delimiter(})>content(_)delimiter(")> reserved(if) ident(extension) + + reserved(if) ident(file_name) + ident(file_path) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(file_name)operator(\)) + ident(base_path) operator(=) constant(File)operator(.)ident(expand_path)operator(()instance_variable(@base_path)operator(\)) + + ident(i) operator(=) ident(file_path)operator(.)ident(index)operator(()ident(base_path)operator(\)) + ident(l) operator(=) ident(base_path)operator(.)ident(length) + + ident(method_name_file_part) operator(=) ident(i) operator(?) ident(file_path)operator([)ident(i)operator(+)ident(l)operator(+)integer(1)operator(,)ident(file_path)operator(.)ident(length)operator(-)ident(l)operator(-)integer(1)operator(]) operator(:) ident(file_path)operator(.)ident(clone) + ident(method_name_file_part)operator(.)ident(sub!)operator(()regexp<delimiter(/)char(\\.)content(r(html|xml|js\)$)delimiter(/)>operator(,)string<delimiter(')delimiter(')>operator(\)) + ident(method_name_file_part)operator(.)ident(tr!)operator(()string<delimiter(')content(/:-)delimiter(')>operator(,) string<delimiter(')content(_)delimiter(')>operator(\)) + ident(method_name_file_part)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content([^a-zA-Z0-9_])delimiter(/)>operator(\))operator({)operator(|)ident(s)operator(|) ident(s)operator([)integer(0)operator(])operator(.)ident(to_s)operator(}) + + ident(method_name) operator(+=) ident(method_name_file_part) + reserved(else) + class_variable(@@inline_template_count) operator(+=) integer(1) + ident(method_name) operator(<<) class_variable(@@inline_template_count)operator(.)ident(to_s) + reserved(end) + + class_variable(@@method_names)operator([)ident(file_name) operator(||) ident(template)operator(]) operator(=) ident(method_name)operator(.)ident(intern) + reserved(end) + + reserved(def) method(compile_template)operator(()ident(extension)operator(,) ident(template)operator(,) ident(file_name)operator(,) ident(local_assigns)operator(\)) + ident(method_key) operator(=) ident(file_name) operator(||) ident(template) + + ident(render_symbol) operator(=) class_variable(@@method_names)operator([)ident(method_key)operator(]) operator(||) ident(assign_method_name)operator(()ident(extension)operator(,) ident(template)operator(,) ident(file_name)operator(\)) + ident(render_source) operator(=) ident(create_template_source)operator(()ident(extension)operator(,) ident(template)operator(,) ident(render_symbol)operator(,) ident(local_assigns)operator(.)ident(keys)operator(\)) + + ident(line_offset) operator(=) class_variable(@@template_args)operator([)ident(render_symbol)operator(])operator(.)ident(size) + reserved(if) ident(extension) + reserved(case) ident(extension)operator(.)ident(to_sym) + reserved(when) symbol(:rxml)operator(,) symbol(:rjs) + ident(line_offset) operator(+=) integer(2) + reserved(end) + reserved(end) + + reserved(begin) + reserved(unless) ident(file_name)operator(.)ident(blank?) + constant(CompiledTemplates)operator(.)ident(module_eval)operator(()ident(render_source)operator(,) ident(file_name)operator(,) operator(-)ident(line_offset)operator(\)) + reserved(else) + constant(CompiledTemplates)operator(.)ident(module_eval)operator(()ident(render_source)operator(,) string<delimiter(')content(compiled-template)delimiter(')>operator(,) operator(-)ident(line_offset)operator(\)) + reserved(end) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + reserved(if) ident(logger) + ident(logger)operator(.)ident(debug) string<delimiter(")content(ERROR: compiling )inline<inline_delimiter(#{)ident(render_symbol)inline_delimiter(})>content( RAISED )inline<inline_delimiter(#{)ident(e)inline_delimiter(})>delimiter(")> + ident(logger)operator(.)ident(debug) string<delimiter(")content(Function body: )inline<inline_delimiter(#{)ident(render_source)inline_delimiter(})>delimiter(")> + ident(logger)operator(.)ident(debug) string<delimiter(")content(Backtrace: )inline<inline_delimiter(#{)ident(e)operator(.)ident(backtrace)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + ident(raise) constant(TemplateError)operator(.)ident(new)operator(()instance_variable(@base_path)operator(,) ident(method_key)operator(,) instance_variable(@assigns)operator(,) ident(template)operator(,) ident(e)operator(\)) + reserved(end) + + class_variable(@@compile_time)operator([)ident(render_symbol)operator(]) operator(=) constant(Time)operator(.)ident(now) + comment(# logger.debug "Compiled template #{method_key}\\n ==> #{render_symbol}" if logger) + reserved(end) + reserved(end) +reserved(end) + +ident(require) string<delimiter(')content(action_view/template_error)delimiter(')> + +reserved(module) class(ActionView) + + comment(# CompiledTemplates modules hold methods that have been compiled.) + comment(# Templates are compiled into these methods so that they do not need to be) + comment(# re-read and re-parsed each request.) + comment(#) + comment(# Each template may be compiled into one or more methods. Each method accepts a given) + comment(# set of parameters which is used to implement local assigns passing.) + comment(#) + comment(# To use a compiled template module, create a new instance and include it into the class) + comment(# in which you want the template to be rendered.) + reserved(class) class(CompiledTemplates) operator(<) constant(Module) comment(#:nodoc:) + ident(attr_reader) symbol(:method_names) + + reserved(def) method(initialize) + instance_variable(@method_names) operator(=) constant(Hash)operator(.)ident(new) reserved(do) operator(|)ident(hash)operator(,) ident(key)operator(|) + ident(hash)operator([)ident(key)operator(]) operator(=) string<delimiter(")content(__compiled_method_)inline<inline_delimiter(#{)operator(()ident(hash)operator(.)ident(length) operator(+) integer(1)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + instance_variable(@mtimes) operator(=) operator({)operator(}) + reserved(end) + + comment(# Return the full key for the given identifier and argument names) + reserved(def) method(full_key)operator(()ident(identifier)operator(,) ident(arg_names)operator(\)) + operator([)ident(identifier)operator(,) ident(arg_names)operator(]) + reserved(end) + + comment(# Return the selector for this method or nil if it has not been compiled) + reserved(def) method(selector)operator(()ident(identifier)operator(,) ident(arg_names)operator(\)) + ident(key) operator(=) ident(full_key)operator(()ident(identifier)operator(,) ident(arg_names)operator(\)) + ident(method_names)operator(.)ident(key?)operator(()ident(key)operator(\)) operator(?) ident(method_names)operator([)ident(key)operator(]) operator(:) pre_constant(nil) + reserved(end) + reserved(alias) symbol(:compiled?) symbol(:selector) + + comment(# Return the time at which the method for the given identifier and argument names was compiled.) + reserved(def) method(mtime)operator(()ident(identifier)operator(,) ident(arg_names)operator(\)) + instance_variable(@mtimes)operator([)ident(full_key)operator(()ident(identifier)operator(,) ident(arg_names)operator(\))operator(]) + reserved(end) + + comment(# Compile the provided source code for the given argument names and with the given initial line number.) + comment(# The identifier should be unique to this source.) + comment(#) + comment(# The file_name, if provided will appear in backtraces. If not provded, the file_name defaults) + comment(# to the identifier.) + comment(#) + comment(# This method will return the selector for the compiled version of this method.) + reserved(def) method(compile_source)operator(()ident(identifier)operator(,) ident(arg_names)operator(,) ident(source)operator(,) ident(initial_line_number) operator(=) integer(0)operator(,) ident(file_name) operator(=) pre_constant(nil)operator(\)) + ident(file_name) operator(||=) ident(identifier) + ident(name) operator(=) ident(method_names)operator([)ident(full_key)operator(()ident(identifier)operator(,) ident(arg_names)operator(\))operator(]) + ident(arg_desc) operator(=) ident(arg_names)operator(.)ident(empty?) operator(?) string<delimiter(')delimiter(')> operator(:) string<delimiter(")content(()inline<inline_delimiter(#{)ident(arg_names) operator(*) string<delimiter(')content(, )delimiter(')>inline_delimiter(})>content(\))delimiter(")> + ident(fake_file_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>inline<inline_delimiter(#{)ident(arg_desc)inline_delimiter(})>delimiter(")> comment(# Include the arguments for this version (for now\)) + + ident(method_def) operator(=) ident(wrap_source)operator(()ident(name)operator(,) ident(arg_names)operator(,) ident(source)operator(\)) + + reserved(begin) + ident(module_eval)operator(()ident(method_def)operator(,) ident(fake_file_name)operator(,) ident(initial_line_number)operator(\)) + instance_variable(@mtimes)operator([)ident(full_key)operator(()ident(identifier)operator(,) ident(arg_names)operator(\))operator(]) operator(=) constant(Time)operator(.)ident(now) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + ident(e)operator(.)ident(blame_file!) ident(identifier) + ident(raise) + reserved(end) + ident(name) + reserved(end) + + comment(# Wrap the provided source in a def ... end block.) + reserved(def) method(wrap_source)operator(()ident(name)operator(,) ident(arg_names)operator(,) ident(source)operator(\)) + string<delimiter(")content(def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(arg_names) operator(*) string<delimiter(')content(, )delimiter(')>inline_delimiter(})>content(\))char(\\n)inline<inline_delimiter(#{)ident(source)inline_delimiter(})>char(\\n)content(end)delimiter(")> + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/form_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(class) class(Base) + class_variable(@@field_error_proc) operator(=) constant(Proc)operator(.)ident(new)operator({) operator(|)ident(html_tag)operator(,) ident(instance)operator(|) string<delimiter(")content(<div class=)char(\\")content(fieldWithErrors)char(\\")content(>)inline<inline_delimiter(#{)ident(html_tag)inline_delimiter(})>content(</div>)delimiter(")> operator(}) + ident(cattr_accessor) symbol(:field_error_proc) + reserved(end) + + reserved(module) class(Helpers) + comment(# The Active Record Helper makes it easier to create forms for records kept in instance variables. The most far-reaching is the form) + comment(# method that creates a complete form for all the basic content types of the record (not associations or aggregations, though\). This) + comment(# is a great of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form.) + comment(# In that case, it's better to use the input method and the specialized form methods in link:classes/ActionView/Helpers/FormHelper.html) + reserved(module) class(ActiveRecordHelper) + comment(# Returns a default input tag for the type of object returned by the method. Example) + comment(# (title is a VARCHAR column and holds "Hello World"\):) + comment(# input("post", "title"\) =>) + comment(# <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />) + reserved(def) method(input)operator(()ident(record_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(record_name)operator(,) ident(method)operator(,) pre_constant(self)operator(\))operator(.)ident(to_tag)operator(()ident(options)operator(\)) + reserved(end) + + comment(# Returns an entire form with input tags and everything for a specified Active Record object. Example) + comment(# (post is a new record that has a title using VARCHAR and a body using TEXT\):) + comment(# form("post"\) =>) + comment(# <form action='/post/create' method='post'>) + comment(# <p>) + comment(# <label for="post_title">Title</label><br />) + comment(# <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />) + comment(# </p>) + comment(# <p>) + comment(# <label for="post_body">Body</label><br />) + comment(# <textarea cols="40" id="post_body" name="post[body]" rows="20">) + comment(# Back to the hill and over it again!) + comment(# </textarea>) + comment(# </p>) + comment(# <input type='submit' value='Create' />) + comment(# </form>) + comment(#) + comment(# It's possible to specialize the form builder by using a different action name and by supplying another) + comment(# block renderer. Example (entry is a new record that has a message attribute using VARCHAR\):) + comment(#) + comment(# form("entry", :action => "sign", :input_block =>) + comment(# Proc.new { |record, column| "#{column.human_name}: #{input(record, column.name\)}<br />" }\) =>) + comment(#) + comment(# <form action='/post/sign' method='post'>) + comment(# Message:) + comment(# <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /><br />) + comment(# <input type='submit' value='Sign' />) + comment(# </form>) + comment(#) + comment(# It's also possible to add additional content to the form by giving it a block, such as:) + comment(#) + comment(# form("entry", :action => "sign"\) do |form|) + comment(# form << content_tag("b", "Department"\)) + comment(# form << collection_select("department", "id", @departments, "id", "name"\)) + comment(# end) + reserved(def) method(form)operator(()ident(record_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(record) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(record_name)inline_delimiter(})>delimiter(")>operator(\)) + + ident(options) operator(=) ident(options)operator(.)ident(symbolize_keys) + ident(options)operator([)symbol(:action)operator(]) operator(||=) ident(record)operator(.)ident(new_record?) operator(?) string<delimiter(")content(create)delimiter(")> operator(:) string<delimiter(")content(update)delimiter(")> + ident(action) operator(=) ident(url_for)operator(()symbol(:action) operator(=)operator(>) ident(options)operator([)symbol(:action)operator(])operator(,) symbol(:id) operator(=)operator(>) ident(record)operator(\)) + + ident(submit_value) operator(=) ident(options)operator([)symbol(:submit_value)operator(]) operator(||) ident(options)operator([)symbol(:action)operator(])operator(.)ident(gsub)operator(()regexp<delimiter(/)content([^)char(\\w)content(])delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(capitalize) + + ident(contents) operator(=) string<delimiter(')delimiter(')> + ident(contents) operator(<<) ident(hidden_field)operator(()ident(record_name)operator(,) symbol(:id)operator(\)) reserved(unless) ident(record)operator(.)ident(new_record?) + ident(contents) operator(<<) ident(all_input_tags)operator(()ident(record)operator(,) ident(record_name)operator(,) ident(options)operator(\)) + reserved(yield) ident(contents) reserved(if) ident(block_given?) + ident(contents) operator(<<) ident(submit_tag)operator(()ident(submit_value)operator(\)) + + ident(content_tag)operator(()string<delimiter(')content(form)delimiter(')>operator(,) ident(contents)operator(,) symbol(:action) operator(=)operator(>) ident(action)operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(post)delimiter(')>operator(,) symbol(:enctype) operator(=)operator(>) ident(options)operator([)symbol(:multipart)operator(]) operator(?) string<delimiter(')content(multipart/form-data)delimiter(')>operator(:) pre_constant(nil)operator(\)) + reserved(end) + + comment(# Returns a string containing the error message attached to the +method+ on the +object+, if one exists.) + comment(# This error message is wrapped in a DIV tag, which can be specialized to include both a +prepend_text+ and +append_text+) + comment(# to properly introduce the error and a +css_class+ to style it accordingly. Examples (post has an error message) + comment(# "can't be empty" on the title attribute\):) + comment(#) + comment(# <%= error_message_on "post", "title" %> =>) + comment(# <div class="formError">can't be empty</div>) + comment(#) + comment(# <%= error_message_on "post", "title", "Title simply ", " (or it won't work\)", "inputError" %> =>) + comment(# <div class="inputError">Title simply can't be empty (or it won't work\)</div>) + reserved(def) method(error_message_on)operator(()ident(object)operator(,) ident(method)operator(,) ident(prepend_text) operator(=) string<delimiter(")delimiter(")>operator(,) ident(append_text) operator(=) string<delimiter(")delimiter(")>operator(,) ident(css_class) operator(=) string<delimiter(")content(formError)delimiter(")>operator(\)) + reserved(if) ident(errors) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(object)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(errors)operator(.)ident(on)operator(()ident(method)operator(\)) + ident(content_tag)operator(()string<delimiter(")content(div)delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(prepend_text)inline_delimiter(})>inline<inline_delimiter(#{)ident(errors)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(?) ident(errors)operator(.)ident(first) operator(:) ident(errors)inline_delimiter(})>inline<inline_delimiter(#{)ident(append_text)inline_delimiter(})>delimiter(")>operator(,) symbol(:class) operator(=)operator(>) ident(css_class)operator(\)) + reserved(end) + reserved(end) + + comment(# Returns a string with a div containing all the error messages for the object located as an instance variable by the name) + comment(# of <tt>object_name</tt>. This div can be tailored by the following options:) + comment(#) + comment(# * <tt>header_tag</tt> - Used for the header of the error div (default: h2\)) + comment(# * <tt>id</tt> - The id of the error div (default: errorExplanation\)) + comment(# * <tt>class</tt> - The class of the error div (default: errorExplanation\)) + comment(#) + comment(# NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what) + comment(# you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors) + comment(# instance yourself and set it up. View the source of this method to see how easy it is.) + reserved(def) method(error_messages_for)operator(()ident(object_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(symbolize_keys) + ident(object) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(object_name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(if) ident(object) operator(&&) operator(!)ident(object)operator(.)ident(errors)operator(.)ident(empty?) + ident(content_tag)operator(()string<delimiter(")content(div)delimiter(")>operator(,) + ident(content_tag)operator(() + ident(options)operator([)symbol(:header_tag)operator(]) operator(||) string<delimiter(")content(h2)delimiter(")>operator(,) + string<delimiter(")inline<inline_delimiter(#{)ident(pluralize)operator(()ident(object)operator(.)ident(errors)operator(.)ident(count)operator(,) string<delimiter(")content(error)delimiter(")>operator(\))inline_delimiter(})>content( prohibited this )inline<inline_delimiter(#{)ident(object_name)operator(.)ident(to_s)operator(.)ident(gsub)operator(()string<delimiter(")content(_)delimiter(")>operator(,) string<delimiter(")content( )delimiter(")>operator(\))inline_delimiter(})>content( from being saved)delimiter(")> + operator(\)) operator(+) + ident(content_tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) string<delimiter(")content(There were problems with the following fields:)delimiter(")>operator(\)) operator(+) + ident(content_tag)operator(()string<delimiter(")content(ul)delimiter(")>operator(,) ident(object)operator(.)ident(errors)operator(.)ident(full_messages)operator(.)ident(collect) operator({) operator(|)ident(msg)operator(|) ident(content_tag)operator(()string<delimiter(")content(li)delimiter(")>operator(,) ident(msg)operator(\)) operator(})operator(\))operator(,) + string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(options)operator([)symbol(:id)operator(]) operator(||) string<delimiter(")content(errorExplanation)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) ident(options)operator([)symbol(:class)operator(]) operator(||) string<delimiter(")content(errorExplanation)delimiter(")> + operator(\)) + reserved(else) + string<delimiter(")delimiter(")> + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(all_input_tags)operator(()ident(record)operator(,) ident(record_name)operator(,) ident(options)operator(\)) + ident(input_block) operator(=) ident(options)operator([)symbol(:input_block)operator(]) operator(||) ident(default_input_block) + ident(record)operator(.)ident(class)operator(.)ident(content_columns)operator(.)ident(collect)operator({) operator(|)ident(column)operator(|) ident(input_block)operator(.)ident(call)operator(()ident(record_name)operator(,) ident(column)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(default_input_block) + constant(Proc)operator(.)ident(new) operator({) operator(|)ident(record)operator(,) ident(column)operator(|) string<delimiter(%()content(<p><label for=")inline<inline_delimiter(#{)ident(record)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(column)operator(.)ident(name)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(column)operator(.)ident(human_name)inline_delimiter(})>content(</label><br />)inline<inline_delimiter(#{)ident(input)operator(()ident(record)operator(,) ident(column)operator(.)ident(name)operator(\))inline_delimiter(})>content(</p>)delimiter(\))> operator(}) + reserved(end) + reserved(end) + + reserved(class) class(InstanceTag) comment(#:nodoc:) + reserved(def) method(to_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + reserved(case) ident(column_type) + reserved(when) symbol(:string) + ident(field_type) operator(=) instance_variable(@method_name)operator(.)ident(include?)operator(()string<delimiter(")content(password)delimiter(")>operator(\)) operator(?) string<delimiter(")content(password)delimiter(")> operator(:) string<delimiter(")content(text)delimiter(")> + ident(to_input_field_tag)operator(()ident(field_type)operator(,) ident(options)operator(\)) + reserved(when) symbol(:text) + ident(to_text_area_tag)operator(()ident(options)operator(\)) + reserved(when) symbol(:integer)operator(,) symbol(:float) + ident(to_input_field_tag)operator(()string<delimiter(")content(text)delimiter(")>operator(,) ident(options)operator(\)) + reserved(when) symbol(:date) + ident(to_date_select_tag)operator(()ident(options)operator(\)) + reserved(when) symbol(:datetime)operator(,) symbol(:timestamp) + ident(to_datetime_select_tag)operator(()ident(options)operator(\)) + reserved(when) symbol(:boolean) + ident(to_boolean_select_tag)operator(()ident(options)operator(\)) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:tag_without_error_wrapping)operator(,) symbol(:tag) + reserved(def) method(tag)operator(()ident(name)operator(,) ident(options)operator(\)) + reserved(if) ident(object)operator(.)ident(respond_to?)operator(()string<delimiter(")content(errors)delimiter(")>operator(\)) operator(&&) ident(object)operator(.)ident(errors)operator(.)ident(respond_to?)operator(()string<delimiter(")content(on)delimiter(")>operator(\)) + ident(error_wrapping)operator(()ident(tag_without_error_wrapping)operator(()ident(name)operator(,) ident(options)operator(\))operator(,) ident(object)operator(.)ident(errors)operator(.)ident(on)operator(()instance_variable(@method_name)operator(\))operator(\)) + reserved(else) + ident(tag_without_error_wrapping)operator(()ident(name)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:content_tag_without_error_wrapping)operator(,) symbol(:content_tag) + reserved(def) method(content_tag)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(\)) + reserved(if) ident(object)operator(.)ident(respond_to?)operator(()string<delimiter(")content(errors)delimiter(")>operator(\)) operator(&&) ident(object)operator(.)ident(errors)operator(.)ident(respond_to?)operator(()string<delimiter(")content(on)delimiter(")>operator(\)) + ident(error_wrapping)operator(()ident(content_tag_without_error_wrapping)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(\))operator(,) ident(object)operator(.)ident(errors)operator(.)ident(on)operator(()instance_variable(@method_name)operator(\))operator(\)) + reserved(else) + ident(content_tag_without_error_wrapping)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:to_date_select_tag_without_error_wrapping)operator(,) symbol(:to_date_select_tag) + reserved(def) method(to_date_select_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(object)operator(.)ident(respond_to?)operator(()string<delimiter(")content(errors)delimiter(")>operator(\)) operator(&&) ident(object)operator(.)ident(errors)operator(.)ident(respond_to?)operator(()string<delimiter(")content(on)delimiter(")>operator(\)) + ident(error_wrapping)operator(()ident(to_date_select_tag_without_error_wrapping)operator(()ident(options)operator(\))operator(,) ident(object)operator(.)ident(errors)operator(.)ident(on)operator(()instance_variable(@method_name)operator(\))operator(\)) + reserved(else) + ident(to_date_select_tag_without_error_wrapping)operator(()ident(options)operator(\)) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:to_datetime_select_tag_without_error_wrapping)operator(,) symbol(:to_datetime_select_tag) + reserved(def) method(to_datetime_select_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(object)operator(.)ident(respond_to?)operator(()string<delimiter(")content(errors)delimiter(")>operator(\)) operator(&&) ident(object)operator(.)ident(errors)operator(.)ident(respond_to?)operator(()string<delimiter(")content(on)delimiter(")>operator(\)) + ident(error_wrapping)operator(()ident(to_datetime_select_tag_without_error_wrapping)operator(()ident(options)operator(\))operator(,) ident(object)operator(.)ident(errors)operator(.)ident(on)operator(()instance_variable(@method_name)operator(\))operator(\)) + reserved(else) + ident(to_datetime_select_tag_without_error_wrapping)operator(()ident(options)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(error_wrapping)operator(()ident(html_tag)operator(,) ident(has_error)operator(\)) + ident(has_error) operator(?) constant(Base)operator(.)ident(field_error_proc)operator(.)ident(call)operator(()ident(html_tag)operator(,) pre_constant(self)operator(\)) operator(:) ident(html_tag) + reserved(end) + + reserved(def) method(error_message) + ident(object)operator(.)ident(errors)operator(.)ident(on)operator(()instance_variable(@method_name)operator(\)) + reserved(end) + + reserved(def) method(column_type) + ident(object)operator(.)ident(send)operator(()string<delimiter(")content(column_for_attribute)delimiter(")>operator(,) instance_variable(@method_name)operator(\))operator(.)ident(type) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/url_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tag_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides methods for linking a HTML page together with other assets, such as javascripts, stylesheets, and feeds.) + reserved(module) class(AssetTagHelper) + comment(# Returns a link tag that browsers and news readers can use to auto-detect a RSS or ATOM feed for this page. The +type+ can) + comment(# either be <tt>:rss</tt> (default\) or <tt>:atom</tt> and the +options+ follow the url_for style of declaring a link target.) + comment(#) + comment(# Examples:) + comment(# auto_discovery_link_tag # =>) + comment(# <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/action" />) + comment(# auto_discovery_link_tag(:atom\) # =>) + comment(# <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.curenthost.com/controller/action" />) + comment(# auto_discovery_link_tag(:rss, {:action => "feed"}\) # =>) + comment(# <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/feed" />) + comment(# auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My RSS"}\) # =>) + comment(# <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.curenthost.com/controller/feed" />) + reserved(def) method(auto_discovery_link_tag)operator(()ident(type) operator(=) symbol(:rss)operator(,) ident(url_options) operator(=) operator({)operator(})operator(,) ident(tag_options) operator(=) operator({)operator(})operator(\)) + ident(tag)operator(() + string<delimiter(")content(link)delimiter(")>operator(,) + string<delimiter(")content(rel)delimiter(")> operator(=)operator(>) ident(tag_options)operator([)symbol(:rel)operator(]) operator(||) string<delimiter(")content(alternate)delimiter(")>operator(,) + string<delimiter(")content(type)delimiter(")> operator(=)operator(>) ident(tag_options)operator([)symbol(:type)operator(]) operator(||) string<delimiter(")content(application/)inline<inline_delimiter(#{)ident(type)inline_delimiter(})>content(+xml)delimiter(")>operator(,) + string<delimiter(")content(title)delimiter(")> operator(=)operator(>) ident(tag_options)operator([)symbol(:title)operator(]) operator(||) ident(type)operator(.)ident(to_s)operator(.)ident(upcase)operator(,) + string<delimiter(")content(href)delimiter(")> operator(=)operator(>) ident(url_options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(url_for)operator(()ident(url_options)operator(.)ident(merge)operator(()symbol(:only_path) operator(=)operator(>) pre_constant(false)operator(\))operator(\)) operator(:) ident(url_options) + operator(\)) + reserved(end) + + comment(# Returns path to a javascript asset. Example:) + comment(#) + comment(# javascript_path "xmlhr" # => /javascripts/xmlhr.js) + reserved(def) method(javascript_path)operator(()ident(source)operator(\)) + ident(compute_public_path)operator(()ident(source)operator(,) string<delimiter(')content(javascripts)delimiter(')>operator(,) string<delimiter(')content(js)delimiter(')>operator(\)) + reserved(end) + + constant(JAVASCRIPT_DEFAULT_SOURCES) operator(=) operator([)string<delimiter(')content(prototype)delimiter(')>operator(,) string<delimiter(')content(effects)delimiter(')>operator(,) string<delimiter(')content(dragdrop)delimiter(')>operator(,) string<delimiter(')content(controls)delimiter(')>operator(]) reserved(unless) ident(const_defined?)operator(()symbol(:JAVASCRIPT_DEFAULT_SOURCES)operator(\)) + class_variable(@@javascript_default_sources) operator(=) constant(JAVASCRIPT_DEFAULT_SOURCES)operator(.)ident(dup) + + comment(# Returns a script include tag per source given as argument. Examples:) + comment(#) + comment(# javascript_include_tag "xmlhr" # =>) + comment(# <script type="text/javascript" src="/javascripts/xmlhr.js"></script>) + comment(#) + comment(# javascript_include_tag "common.javascript", "/elsewhere/cools" # =>) + comment(# <script type="text/javascript" src="/javascripts/common.javascript"></script>) + comment(# <script type="text/javascript" src="/elsewhere/cools.js"></script>) + comment(#) + comment(# javascript_include_tag :defaults # =>) + comment(# <script type="text/javascript" src="/javascripts/prototype.js"></script>) + comment(# <script type="text/javascript" src="/javascripts/effects.js"></script>) + comment(# ...) + comment(# <script type="text/javascript" src="/javascripts/application.js"></script> *see below) + comment(# ) + comment(# If there's an <tt>application.js</tt> file in your <tt>public/javascripts</tt> directory,) + comment(# <tt>javascript_include_tag :defaults</tt> will automatically include it. This file) + comment(# facilitates the inclusion of small snippets of JavaScript code, along the lines of) + comment(# <tt>controllers/application.rb</tt> and <tt>helpers/application_helper.rb</tt>.) + reserved(def) method(javascript_include_tag)operator(()operator(*)ident(sources)operator(\)) + ident(options) operator(=) ident(sources)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(sources)operator(.)ident(pop)operator(.)ident(stringify_keys) operator(:) operator({) operator(}) + + reserved(if) ident(sources)operator(.)ident(include?)operator(()symbol(:defaults)operator(\)) + ident(sources) operator(=) ident(sources)operator([)integer(0)operator(..)operator(()ident(sources)operator(.)ident(index)operator(()symbol(:defaults)operator(\))operator(\))operator(]) operator(+) + class_variable(@@javascript_default_sources)operator(.)ident(dup) operator(+) + ident(sources)operator([)operator(()ident(sources)operator(.)ident(index)operator(()symbol(:defaults)operator(\)) operator(+) integer(1)operator(\))operator(..)ident(sources)operator(.)ident(length)operator(]) + + ident(sources)operator(.)ident(delete)operator(()symbol(:defaults)operator(\)) + ident(sources) operator(<<) string<delimiter(")content(application)delimiter(")> reserved(if) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) operator(&&) constant(File)operator(.)ident(exists?)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(RAILS_ROOT)inline_delimiter(})>content(/public/javascripts/application.js)delimiter(")>operator(\)) + reserved(end) + + ident(sources)operator(.)ident(collect) operator({) operator(|)ident(source)operator(|) + ident(source) operator(=) ident(javascript_path)operator(()ident(source)operator(\)) + ident(content_tag)operator(()string<delimiter(")content(script)delimiter(")>operator(,) string<delimiter(")delimiter(")>operator(,) operator({) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(text/javascript)delimiter(")>operator(,) string<delimiter(")content(src)delimiter(")> operator(=)operator(>) ident(source) operator(})operator(.)ident(merge)operator(()ident(options)operator(\))operator(\)) + operator(})operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + + comment(# Register one or more additional JavaScript files to be included when) + comment(# ) + comment(# javascript_include_tag :defaults) + comment(#) + comment(# is called. This method is intended to be called only from plugin initialization) + comment(# to register extra .js files the plugin installed in <tt>public/javascripts</tt>.) + reserved(def) pre_constant(self)operator(.)ident(register_javascript_include_default)operator(()operator(*)ident(sources)operator(\)) + class_variable(@@javascript_default_sources)operator(.)ident(concat)operator(()ident(sources)operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(reset_javascript_include_default) comment(#:nodoc:) + class_variable(@@javascript_default_sources) operator(=) constant(JAVASCRIPT_DEFAULT_SOURCES)operator(.)ident(dup) + reserved(end) + + comment(# Returns path to a stylesheet asset. Example:) + comment(#) + comment(# stylesheet_path "style" # => /stylesheets/style.css) + reserved(def) method(stylesheet_path)operator(()ident(source)operator(\)) + ident(compute_public_path)operator(()ident(source)operator(,) string<delimiter(')content(stylesheets)delimiter(')>operator(,) string<delimiter(')content(css)delimiter(')>operator(\)) + reserved(end) + + comment(# Returns a css link tag per source given as argument. Examples:) + comment(#) + comment(# stylesheet_link_tag "style" # =>) + comment(# <link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />) + comment(#) + comment(# stylesheet_link_tag "style", :media => "all" # =>) + comment(# <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />) + comment(#) + comment(# stylesheet_link_tag "random.styles", "/css/stylish" # =>) + comment(# <link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />) + comment(# <link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />) + reserved(def) method(stylesheet_link_tag)operator(()operator(*)ident(sources)operator(\)) + ident(options) operator(=) ident(sources)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(sources)operator(.)ident(pop)operator(.)ident(stringify_keys) operator(:) operator({) operator(}) + ident(sources)operator(.)ident(collect) operator({) operator(|)ident(source)operator(|) + ident(source) operator(=) ident(stylesheet_path)operator(()ident(source)operator(\)) + ident(tag)operator(()string<delimiter(")content(link)delimiter(")>operator(,) operator({) string<delimiter(")content(rel)delimiter(")> operator(=)operator(>) string<delimiter(")content(Stylesheet)delimiter(")>operator(,) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(text/css)delimiter(")>operator(,) string<delimiter(")content(media)delimiter(")> operator(=)operator(>) string<delimiter(")content(screen)delimiter(")>operator(,) string<delimiter(")content(href)delimiter(")> operator(=)operator(>) ident(source) operator(})operator(.)ident(merge)operator(()ident(options)operator(\))operator(\)) + operator(})operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + + comment(# Returns path to an image asset. Example:) + comment(#) + comment(# The +src+ can be supplied as a...) + comment(# * full path, like "/my_images/image.gif") + comment(# * file name, like "rss.gif", that gets expanded to "/images/rss.gif") + comment(# * file name without extension, like "logo", that gets expanded to "/images/logo.png") + reserved(def) method(image_path)operator(()ident(source)operator(\)) + ident(compute_public_path)operator(()ident(source)operator(,) string<delimiter(')content(images)delimiter(')>operator(,) string<delimiter(')content(png)delimiter(')>operator(\)) + reserved(end) + + comment(# Returns an image tag converting the +options+ into html options on the tag, but with these special cases:) + comment(#) + comment(# * <tt>:alt</tt> - If no alt text is given, the file name part of the +src+ is used (capitalized and without the extension\)) + comment(# * <tt>:size</tt> - Supplied as "XxY", so "30x45" becomes width="30" and height="45") + comment(#) + comment(# The +src+ can be supplied as a...) + comment(# * full path, like "/my_images/image.gif") + comment(# * file name, like "rss.gif", that gets expanded to "/images/rss.gif") + comment(# * file name without extension, like "logo", that gets expanded to "/images/logo.png") + reserved(def) method(image_tag)operator(()ident(source)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator(.)ident(symbolize_keys!) + + ident(options)operator([)symbol(:src)operator(]) operator(=) ident(image_path)operator(()ident(source)operator(\)) + ident(options)operator([)symbol(:alt)operator(]) operator(||=) constant(File)operator(.)ident(basename)operator(()ident(options)operator([)symbol(:src)operator(])operator(,) string<delimiter(')content(.*)delimiter(')>operator(\))operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(.)ident(first)operator(.)ident(capitalize) + + reserved(if) ident(options)operator([)symbol(:size)operator(]) + ident(options)operator([)symbol(:width)operator(])operator(,) ident(options)operator([)symbol(:height)operator(]) operator(=) ident(options)operator([)symbol(:size)operator(])operator(.)ident(split)operator(()string<delimiter(")content(x)delimiter(")>operator(\)) + ident(options)operator(.)ident(delete) symbol(:size) + reserved(end) + + ident(tag)operator(()string<delimiter(")content(img)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(compute_public_path)operator(()ident(source)operator(,) ident(dir)operator(,) ident(ext)operator(\)) + ident(source) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(dir)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(source)inline_delimiter(})>delimiter(")> reserved(unless) ident(source)operator(.)ident(first) operator(==) string<delimiter(")content(/)delimiter(")> operator(||) ident(source)operator(.)ident(include?)operator(()string<delimiter(")content(:)delimiter(")>operator(\)) + ident(source) operator(<<) string<delimiter(")content(.)inline<inline_delimiter(#{)ident(ext)inline_delimiter(})>delimiter(")> reserved(unless) ident(source)operator(.)ident(split)operator(()string<delimiter(")content(/)delimiter(")>operator(\))operator(.)ident(last)operator(.)ident(include?)operator(()string<delimiter(")content(.)delimiter(")>operator(\)) + ident(source) operator(<<) string<delimiter(')content(?)delimiter(')> operator(+) ident(rails_asset_id)operator(()ident(source)operator(\)) reserved(if) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) operator(&&) regexp<delimiter(%r{)content(^[-a-z]+://)delimiter(})> operator(!)operator(~) ident(source) + ident(source) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@controller)operator(.)ident(request)operator(.)ident(relative_url_root)inline_delimiter(})>inline<inline_delimiter(#{)ident(source)inline_delimiter(})>delimiter(")> reserved(unless) regexp<delimiter(%r{)content(^[-a-z]+://)delimiter(})> operator(=)operator(~) ident(source) + ident(source) operator(=) constant(ActionController)operator(::)constant(Base)operator(.)ident(asset_host) operator(+) ident(source) reserved(unless) ident(source)operator(.)ident(include?)operator(()string<delimiter(")content(:)delimiter(")>operator(\)) + ident(source) + reserved(end) + + reserved(def) method(rails_asset_id)operator(()ident(source)operator(\)) + constant(ENV)operator([)string<delimiter(")content(RAILS_ASSET_ID)delimiter(")>operator(]) operator(||) + constant(File)operator(.)ident(mtime)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(RAILS_ROOT)inline_delimiter(})>content(/public/)inline<inline_delimiter(#{)ident(source)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(to_i)operator(.)ident(to_s) reserved(rescue) string<delimiter(")delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(benchmark)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + reserved(module) class(BenchmarkHelper) + comment(# Measures the execution time of a block in a template and reports the result to the log. Example:) + comment(#) + comment(# <% benchmark "Notes section" do %>) + comment(# <%= expensive_notes_operation %>) + comment(# <% end %>) + comment(#) + comment(# Will add something like "Notes section (0.34523\)" to the log.) + comment(#) + comment(# You may give an optional logger level as the second argument) + comment(# (:debug, :info, :warn, :error\). The default is :info.) + reserved(def) method(benchmark)operator(()ident(message) operator(=) string<delimiter(")content(Benchmarking)delimiter(")>operator(,) ident(level) operator(=) symbol(:info)operator(\)) + reserved(if) instance_variable(@logger) + ident(real) operator(=) constant(Benchmark)operator(.)ident(realtime) operator({) reserved(yield) operator(}) + instance_variable(@logger)operator(.)ident(send) ident(level)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(message)inline_delimiter(})>content( ()inline<inline_delimiter(#{)string<delimiter(')content(%.5f)delimiter(')> operator(%) ident(real)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# See ActionController::Caching::Fragments for usage instructions.) + reserved(module) class(CacheHelper) + reserved(def) method(cache)operator(()ident(name) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + instance_variable(@controller)operator(.)ident(cache_erb_fragment)operator(()ident(block)operator(,) ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Capture lets you extract parts of code which) + comment(# can be used in other points of the template or even layout file.) + comment(#) + comment(# == Capturing a block into an instance variable) + comment(#) + comment(# <% @script = capture do %>) + comment(# [some html...]) + comment(# <% end %>) + comment(#) + comment(# == Add javascript to header using content_for) + comment(#) + comment(# content_for("name"\) is a wrapper for capture which will ) + comment(# make the fragment available by name to a yielding layout or template.) + comment(#) + comment(# layout.rhtml:) + comment(#) + comment(# <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">) + comment(# <head>) + comment(# <title>layout with js</title>) + comment(# <script type="text/javascript">) + comment(# <%= yield :script %>) + comment(# </script>) + comment(# </head>) + comment(# <body>) + comment(# <%= yield %>) + comment(# </body>) + comment(# </html>) + comment(#) + comment(# view.rhtml) + comment(# ) + comment(# This page shows an alert box!) + comment(#) + comment(# <% content_for("script"\) do %>) + comment(# alert('hello world'\)) + comment(# <% end %>) + comment(#) + comment(# Normal view text) + reserved(module) class(CaptureHelper) + comment(# Capture allows you to extract a part of the template into an ) + comment(# instance variable. You can use this instance variable anywhere) + comment(# in your templates and even in your layout. ) + comment(# ) + comment(# Example of capture being used in a .rhtml page:) + comment(# ) + comment(# <% @greeting = capture do %>) + comment(# Welcome To my shiny new web page!) + comment(# <% end %>) + comment(#) + comment(# Example of capture being used in a .rxml page:) + comment(# ) + comment(# @greeting = capture do) + comment(# 'Welcome To my shiny new web page!') + comment(# end) + reserved(def) method(capture)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + comment(# execute the block) + reserved(begin) + ident(buffer) operator(=) ident(eval)operator(()string<delimiter(")content(_erbout)delimiter(")>operator(,) ident(block)operator(.)ident(binding)operator(\)) + reserved(rescue) + ident(buffer) operator(=) pre_constant(nil) + reserved(end) + + reserved(if) ident(buffer)operator(.)ident(nil?) + ident(capture_block)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(else) + ident(capture_erb_with_buffer)operator(()ident(buffer)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + comment(# Calling content_for stores the block of markup for later use.) + comment(# Subsequently, you can make calls to it by name with <tt>yield</tt>) + comment(# in another template or in the layout. ) + comment(# ) + comment(# Example:) + comment(# ) + comment(# <% content_for("header"\) do %>) + comment(# alert('hello world'\)) + comment(# <% end %>) + comment(#) + comment(# You can use yield :header anywhere in your templates.) + comment(#) + comment(# <%= yield :header %>) + comment(#) + comment(# NOTE: Beware that content_for is ignored in caches. So you shouldn't use it) + comment(# for elements that are going to be fragment cached.) + comment(#) + comment(# The deprecated way of accessing a content_for block was to use a instance variable) + comment(# named @@content_for_#{name_of_the_content_block}@. So <tt><%= content_for('footer'\) %></tt>) + comment(# would be avaiable as <tt><%= @content_for_footer %></tt>. The preferred notation now is) + comment(# <tt><%= yield :footer %></tt>.) + reserved(def) method(content_for)operator(()ident(name)operator(,) operator(&)ident(block)operator(\)) + ident(eval) string<delimiter(")content(@content_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( = (@content_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( || ''\) + capture(&block\))delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(capture_block)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(block)operator(.)ident(call)operator(()operator(*)ident(args)operator(\)) + reserved(end) + + reserved(def) method(capture_erb)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(buffer) operator(=) ident(eval)operator(()string<delimiter(")content(_erbout)delimiter(")>operator(,) ident(block)operator(.)ident(binding)operator(\)) + ident(capture_erb_with_buffer)operator(()ident(buffer)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(capture_erb_with_buffer)operator(()ident(buffer)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(pos) operator(=) ident(buffer)operator(.)ident(length) + ident(block)operator(.)ident(call)operator(()operator(*)ident(args)operator(\)) + + comment(# extract the block ) + ident(data) operator(=) ident(buffer)operator([)ident(pos)operator(..)integer(-1)operator(]) + + comment(# replace it in the original with empty string) + ident(buffer)operator([)ident(pos)operator(..)integer(-1)operator(]) operator(=) string<delimiter(')delimiter(')> + + ident(data) + reserved(end) + + reserved(def) method(erb_content_for)operator(()ident(name)operator(,) operator(&)ident(block)operator(\)) + ident(eval) string<delimiter(")content(@content_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( = (@content_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( || ''\) + capture_erb(&block\))delimiter(")> + reserved(end) + + reserved(def) method(block_content_for)operator(()ident(name)operator(,) operator(&)ident(block)operator(\)) + ident(eval) string<delimiter(")content(@content_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( = (@content_for_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( || ''\) + capture_block(&block\))delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(")content(date)delimiter(")> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# The Date Helper primarily creates select/option tags for different kinds of dates and date elements. All of the select-type methods) + comment(# share a number of common options that are as follows:) + comment(#) + comment(# * <tt>:prefix</tt> - overwrites the default prefix of "date" used for the select names. So specifying "birthday" would give) + comment(# birthday[month] instead of date[month] if passed to the select_month method.) + comment(# * <tt>:include_blank</tt> - set to true if it should be possible to set an empty date.) + comment(# * <tt>:discard_type</tt> - set to true if you want to discard the type part of the select name. If set to true, the select_month) + comment(# method would use simply "date" (which can be overwritten using <tt>:prefix</tt>\) instead of "date[month]".) + reserved(module) class(DateHelper) + constant(DEFAULT_PREFIX) operator(=) string<delimiter(')content(date)delimiter(')> reserved(unless) ident(const_defined?)operator(()string<delimiter(')content(DEFAULT_PREFIX)delimiter(')>operator(\)) + + comment(# Reports the approximate distance in time between two Time objects or integers. ) + comment(# For example, if the distance is 47 minutes, it'll return) + comment(# "about 1 hour". See the source for the complete wording list.) + comment(#) + comment(# Integers are interpreted as seconds. So,) + comment(# <tt>distance_of_time_in_words(50\)</tt> returns "less than a minute".) + comment(#) + comment(# Set <tt>include_seconds</tt> to true if you want more detailed approximations if distance < 1 minute) + reserved(def) method(distance_of_time_in_words)operator(()ident(from_time)operator(,) ident(to_time) operator(=) integer(0)operator(,) ident(include_seconds) operator(=) pre_constant(false)operator(\)) + ident(from_time) operator(=) ident(from_time)operator(.)ident(to_time) reserved(if) ident(from_time)operator(.)ident(respond_to?)operator(()symbol(:to_time)operator(\)) + ident(to_time) operator(=) ident(to_time)operator(.)ident(to_time) reserved(if) ident(to_time)operator(.)ident(respond_to?)operator(()symbol(:to_time)operator(\)) + ident(distance_in_minutes) operator(=) operator(()operator(()operator(()ident(to_time) operator(-) ident(from_time)operator(\))operator(.)ident(abs)operator(\))operator(/)integer(60)operator(\))operator(.)ident(round) + ident(distance_in_seconds) operator(=) operator(()operator(()ident(to_time) operator(-) ident(from_time)operator(\))operator(.)ident(abs)operator(\))operator(.)ident(round) + + reserved(case) ident(distance_in_minutes) + reserved(when) integer(0)operator(..)integer(1) + reserved(return) operator(()ident(distance_in_minutes)operator(==)integer(0)operator(\)) operator(?) string<delimiter(')content(less than a minute)delimiter(')> operator(:) string<delimiter(')content(1 minute)delimiter(')> reserved(unless) ident(include_seconds) + reserved(case) ident(distance_in_seconds) + reserved(when) integer(0)operator(..)integer(5) reserved(then) string<delimiter(')content(less than 5 seconds)delimiter(')> + reserved(when) integer(6)operator(..)integer(10) reserved(then) string<delimiter(')content(less than 10 seconds)delimiter(')> + reserved(when) integer(11)operator(..)integer(20) reserved(then) string<delimiter(')content(less than 20 seconds)delimiter(')> + reserved(when) integer(21)operator(..)integer(40) reserved(then) string<delimiter(')content(half a minute)delimiter(')> + reserved(when) integer(41)operator(..)integer(59) reserved(then) string<delimiter(')content(less than a minute)delimiter(')> + reserved(else) string<delimiter(')content(1 minute)delimiter(')> + reserved(end) + + reserved(when) integer(2)operator(..)integer(45) reserved(then) string<delimiter(")inline<inline_delimiter(#{)ident(distance_in_minutes)inline_delimiter(})>content( minutes)delimiter(")> + reserved(when) integer(46)operator(..)integer(90) reserved(then) string<delimiter(')content(about 1 hour)delimiter(')> + reserved(when) integer(90)operator(..)integer(1440) reserved(then) string<delimiter(")content(about )inline<inline_delimiter(#{)operator(()ident(distance_in_minutes)operator(.)ident(to_f) operator(/) float(60.0)operator(\))operator(.)ident(round)inline_delimiter(})>content( hours)delimiter(")> + reserved(when) integer(1441)operator(..)integer(2880) reserved(then) string<delimiter(')content(1 day)delimiter(')> + reserved(else) string<delimiter(")inline<inline_delimiter(#{)operator(()ident(distance_in_minutes) operator(/) integer(1440)operator(\))operator(.)ident(round)inline_delimiter(})>content( days)delimiter(")> + reserved(end) + reserved(end) + + comment(# Like distance_of_time_in_words, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.) + reserved(def) method(time_ago_in_words)operator(()ident(from_time)operator(,) ident(include_seconds) operator(=) pre_constant(false)operator(\)) + ident(distance_of_time_in_words)operator(()ident(from_time)operator(,) constant(Time)operator(.)ident(now)operator(,) ident(include_seconds)operator(\)) + reserved(end) + + ident(alias_method) symbol(:distance_of_time_in_words_to_now)operator(,) symbol(:time_ago_in_words) + + comment(# Returns a set of select tags (one for year, month, and day\) pre-selected for accessing a specified date-based attribute (identified by) + comment(# +method+\) on an object assigned to the template (identified by +object+\). It's possible to tailor the selects through the +options+ hash,) + comment(# which accepts all the keys that each of the individual select builders do (like :use_month_numbers for select_month\) as well as a range of) + comment(# discard options. The discard options are <tt>:discard_year</tt>, <tt>:discard_month</tt> and <tt>:discard_day</tt>. Set to true, they'll) + comment(# drop the respective select. Discarding the month select will also automatically discard the day select. It's also possible to explicitly) + comment(# set the order of the tags using the <tt>:order</tt> option with an array of symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in) + comment(# the desired order. Symbols may be omitted and the respective select is not included.) + comment(#) + comment(# Passing :disabled => true as part of the +options+ will make elements inaccessible for change.) + comment(#) + comment(# NOTE: Discarded selects will default to 1. So if no month select is available, January will be assumed.) + comment(#) + comment(# Examples:) + comment(#) + comment(# date_select("post", "written_on"\)) + comment(# date_select("post", "written_on", :start_year => 1995\)) + comment(# date_select("post", "written_on", :start_year => 1995, :use_month_numbers => true,) + comment(# :discard_day => true, :include_blank => true\)) + comment(# date_select("post", "written_on", :order => [:day, :month, :year]\)) + comment(# date_select("user", "birthday", :order => [:month, :day]\)) + comment(#) + comment(# The selects are prepared for multi-parameter assignment to an Active Record object.) + reserved(def) method(date_select)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_date_select_tag)operator(()ident(options)operator(\)) + reserved(end) + + comment(# Returns a set of select tags (one for year, month, day, hour, and minute\) pre-selected for accessing a specified datetime-based) + comment(# attribute (identified by +method+\) on an object assigned to the template (identified by +object+\). Examples:) + comment(#) + comment(# datetime_select("post", "written_on"\)) + comment(# datetime_select("post", "written_on", :start_year => 1995\)) + comment(#) + comment(# The selects are prepared for multi-parameter assignment to an Active Record object.) + reserved(def) method(datetime_select)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_datetime_select_tag)operator(()ident(options)operator(\)) + reserved(end) + + comment(# Returns a set of html select-tags (one for year, month, and day\) pre-selected with the +date+.) + reserved(def) method(select_date)operator(()ident(date) operator(=) constant(Date)operator(.)ident(today)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(select_year)operator(()ident(date)operator(,) ident(options)operator(\)) operator(+) ident(select_month)operator(()ident(date)operator(,) ident(options)operator(\)) operator(+) ident(select_day)operator(()ident(date)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Returns a set of html select-tags (one for year, month, day, hour, and minute\) pre-selected with the +datetime+.) + reserved(def) method(select_datetime)operator(()ident(datetime) operator(=) constant(Time)operator(.)ident(now)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(select_year)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(+) ident(select_month)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(+) ident(select_day)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(+) + ident(select_hour)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(+) ident(select_minute)operator(()ident(datetime)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Returns a set of html select-tags (one for hour and minute\)) + reserved(def) method(select_time)operator(()ident(datetime) operator(=) constant(Time)operator(.)ident(now)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(h) operator(=) ident(select_hour)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(+) ident(select_minute)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(+) operator(()ident(options)operator([)symbol(:include_seconds)operator(]) operator(?) ident(select_second)operator(()ident(datetime)operator(,) ident(options)operator(\)) operator(:) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + comment(# Returns a select tag with options for each of the seconds 0 through 59 with the current second selected.) + comment(# The <tt>second</tt> can also be substituted for a second number.) + comment(# Override the field name using the <tt>:field_name</tt> option, 'second' by default.) + reserved(def) method(select_second)operator(()ident(datetime)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(second_options) operator(=) operator([)operator(]) + + integer(0)operator(.)ident(upto)operator(()integer(59)operator(\)) reserved(do) operator(|)ident(second)operator(|) + ident(second_options) operator(<<) operator(()operator(()ident(datetime) operator(&&) operator(()ident(datetime)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) ident(datetime) operator(:) ident(datetime)operator(.)ident(sec)operator(\)) operator(==) ident(second)operator(\)) operator(?) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(second)operator(\))inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(second)operator(\))inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(:) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(second)operator(\))inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(second)operator(\))inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + operator(\)) + reserved(end) + + ident(select_html)operator(()ident(options)operator([)symbol(:field_name)operator(]) operator(||) string<delimiter(')content(second)delimiter(')>operator(,) ident(second_options)operator(,) ident(options)operator([)symbol(:prefix)operator(])operator(,) ident(options)operator([)symbol(:include_blank)operator(])operator(,) ident(options)operator([)symbol(:discard_type)operator(])operator(,) ident(options)operator([)symbol(:disabled)operator(])operator(\)) + reserved(end) + + comment(# Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected.) + comment(# Also can return a select tag with options by <tt>minute_step</tt> from 0 through 59 with the 00 minute selected) + comment(# The <tt>minute</tt> can also be substituted for a minute number.) + comment(# Override the field name using the <tt>:field_name</tt> option, 'minute' by default.) + reserved(def) method(select_minute)operator(()ident(datetime)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(minute_options) operator(=) operator([)operator(]) + + integer(0)operator(.)ident(step)operator(()integer(59)operator(,) ident(options)operator([)symbol(:minute_step)operator(]) operator(||) integer(1)operator(\)) reserved(do) operator(|)ident(minute)operator(|) + ident(minute_options) operator(<<) operator(()operator(()ident(datetime) operator(&&) operator(()ident(datetime)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) ident(datetime) operator(:) ident(datetime)operator(.)ident(min)operator(\)) operator(==) ident(minute)operator(\)) operator(?) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(minute)operator(\))inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(minute)operator(\))inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(:) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(minute)operator(\))inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(minute)operator(\))inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + operator(\)) + reserved(end) + + ident(select_html)operator(()ident(options)operator([)symbol(:field_name)operator(]) operator(||) string<delimiter(')content(minute)delimiter(')>operator(,) ident(minute_options)operator(,) ident(options)operator([)symbol(:prefix)operator(])operator(,) ident(options)operator([)symbol(:include_blank)operator(])operator(,) ident(options)operator([)symbol(:discard_type)operator(])operator(,) ident(options)operator([)symbol(:disabled)operator(])operator(\)) + reserved(end) + + comment(# Returns a select tag with options for each of the hours 0 through 23 with the current hour selected.) + comment(# The <tt>hour</tt> can also be substituted for a hour number.) + comment(# Override the field name using the <tt>:field_name</tt> option, 'hour' by default.) + reserved(def) method(select_hour)operator(()ident(datetime)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(hour_options) operator(=) operator([)operator(]) + + integer(0)operator(.)ident(upto)operator(()integer(23)operator(\)) reserved(do) operator(|)ident(hour)operator(|) + ident(hour_options) operator(<<) operator(()operator(()ident(datetime) operator(&&) operator(()ident(datetime)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) ident(datetime) operator(:) ident(datetime)operator(.)ident(hour)operator(\)) operator(==) ident(hour)operator(\)) operator(?) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(hour)operator(\))inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(hour)operator(\))inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(:) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(hour)operator(\))inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(leading_zero_on_single_digits)operator(()ident(hour)operator(\))inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + operator(\)) + reserved(end) + + ident(select_html)operator(()ident(options)operator([)symbol(:field_name)operator(]) operator(||) string<delimiter(')content(hour)delimiter(')>operator(,) ident(hour_options)operator(,) ident(options)operator([)symbol(:prefix)operator(])operator(,) ident(options)operator([)symbol(:include_blank)operator(])operator(,) ident(options)operator([)symbol(:discard_type)operator(])operator(,) ident(options)operator([)symbol(:disabled)operator(])operator(\)) + reserved(end) + + comment(# Returns a select tag with options for each of the days 1 through 31 with the current day selected.) + comment(# The <tt>date</tt> can also be substituted for a hour number.) + comment(# Override the field name using the <tt>:field_name</tt> option, 'day' by default.) + reserved(def) method(select_day)operator(()ident(date)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(day_options) operator(=) operator([)operator(]) + + integer(1)operator(.)ident(upto)operator(()integer(31)operator(\)) reserved(do) operator(|)ident(day)operator(|) + ident(day_options) operator(<<) operator(()operator(()ident(date) operator(&&) operator(()ident(date)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) ident(date) operator(:) ident(date)operator(.)ident(day)operator(\)) operator(==) ident(day)operator(\)) operator(?) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(day)inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(day)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(:) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(day)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(day)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + operator(\)) + reserved(end) + + ident(select_html)operator(()ident(options)operator([)symbol(:field_name)operator(]) operator(||) string<delimiter(')content(day)delimiter(')>operator(,) ident(day_options)operator(,) ident(options)operator([)symbol(:prefix)operator(])operator(,) ident(options)operator([)symbol(:include_blank)operator(])operator(,) ident(options)operator([)symbol(:discard_type)operator(])operator(,) ident(options)operator([)symbol(:disabled)operator(])operator(\)) + reserved(end) + + comment(# Returns a select tag with options for each of the months January through December with the current month selected.) + comment(# The month names are presented as keys (what's shown to the user\) and the month numbers (1-12\) are used as values) + comment(# (what's submitted to the server\). It's also possible to use month numbers for the presentation instead of names --) + comment(# set the <tt>:use_month_numbers</tt> key in +options+ to true for this to happen. If you want both numbers and names,) + comment(# set the <tt>:add_month_numbers</tt> key in +options+ to true. Examples:) + comment(#) + comment(# select_month(Date.today\) # Will use keys like "January", "March") + comment(# select_month(Date.today, :use_month_numbers => true\) # Will use keys like "1", "3") + comment(# select_month(Date.today, :add_month_numbers => true\) # Will use keys like "1 - January", "3 - March") + comment(#) + comment(# Override the field name using the <tt>:field_name</tt> option, 'month' by default.) + comment(#) + comment(# If you would prefer to show month names as abbreviations, set the) + comment(# <tt>:use_short_month</tt> key in +options+ to true.) + reserved(def) method(select_month)operator(()ident(date)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(month_options) operator(=) operator([)operator(]) + ident(month_names) operator(=) ident(options)operator([)symbol(:use_short_month)operator(]) operator(?) constant(Date)operator(::)constant(ABBR_MONTHNAMES) operator(:) constant(Date)operator(::)constant(MONTHNAMES) + + integer(1)operator(.)ident(upto)operator(()integer(12)operator(\)) reserved(do) operator(|)ident(month_number)operator(|) + ident(month_name) operator(=) reserved(if) ident(options)operator([)symbol(:use_month_numbers)operator(]) + ident(month_number) + reserved(elsif) ident(options)operator([)symbol(:add_month_numbers)operator(]) + ident(month_number)operator(.)ident(to_s) operator(+) string<delimiter(')content( - )delimiter(')> operator(+) ident(month_names)operator([)ident(month_number)operator(]) + reserved(else) + ident(month_names)operator([)ident(month_number)operator(]) + reserved(end) + + ident(month_options) operator(<<) operator(()operator(()ident(date) operator(&&) operator(()ident(date)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) ident(date) operator(:) ident(date)operator(.)ident(month)operator(\)) operator(==) ident(month_number)operator(\)) operator(?) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(month_number)inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(month_name)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(:) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(month_number)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(month_name)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + operator(\)) + reserved(end) + + ident(select_html)operator(()ident(options)operator([)symbol(:field_name)operator(]) operator(||) string<delimiter(')content(month)delimiter(')>operator(,) ident(month_options)operator(,) ident(options)operator([)symbol(:prefix)operator(])operator(,) ident(options)operator([)symbol(:include_blank)operator(])operator(,) ident(options)operator([)symbol(:discard_type)operator(])operator(,) ident(options)operator([)symbol(:disabled)operator(])operator(\)) + reserved(end) + + comment(# Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius) + comment(# can be changed using the <tt>:start_year</tt> and <tt>:end_year</tt> keys in the +options+. Both ascending and descending year) + comment(# lists are supported by making <tt>:start_year</tt> less than or greater than <tt>:end_year</tt>. The <tt>date</tt> can also be) + comment(# substituted for a year given as a number. Example:) + comment(#) + comment(# select_year(Date.today, :start_year => 1992, :end_year => 2007\) # ascending year values) + comment(# select_year(Date.today, :start_year => 2005, :end_year => 1900\) # descending year values) + comment(#) + comment(# Override the field name using the <tt>:field_name</tt> option, 'year' by default.) + reserved(def) method(select_year)operator(()ident(date)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(year_options) operator(=) operator([)operator(]) + ident(y) operator(=) ident(date) operator(?) operator(()ident(date)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) operator(()ident(y) operator(=) operator(()ident(date) operator(==) integer(0)operator(\)) operator(?) constant(Date)operator(.)ident(today)operator(.)ident(year) operator(:) ident(date)operator(\)) operator(:) ident(date)operator(.)ident(year)operator(\)) operator(:) constant(Date)operator(.)ident(today)operator(.)ident(year) + + ident(start_year)operator(,) ident(end_year) operator(=) operator(()ident(options)operator([)symbol(:start_year)operator(]) operator(||) ident(y)operator(-)integer(5)operator(\))operator(,) operator(()ident(options)operator([)symbol(:end_year)operator(]) operator(||) ident(y)operator(+)integer(5)operator(\)) + ident(step_val) operator(=) ident(start_year) operator(<) ident(end_year) operator(?) integer(1) operator(:) integer(-1) + + ident(start_year)operator(.)ident(step)operator(()ident(end_year)operator(,) ident(step_val)operator(\)) reserved(do) operator(|)ident(year)operator(|) + ident(year_options) operator(<<) operator(()operator(()ident(date) operator(&&) operator(()ident(date)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(?) ident(date) operator(:) ident(date)operator(.)ident(year)operator(\)) operator(==) ident(year)operator(\)) operator(?) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(year)inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(year)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(:) + string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(year)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(year)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + operator(\)) + reserved(end) + + ident(select_html)operator(()ident(options)operator([)symbol(:field_name)operator(]) operator(||) string<delimiter(')content(year)delimiter(')>operator(,) ident(year_options)operator(,) ident(options)operator([)symbol(:prefix)operator(])operator(,) ident(options)operator([)symbol(:include_blank)operator(])operator(,) ident(options)operator([)symbol(:discard_type)operator(])operator(,) ident(options)operator([)symbol(:disabled)operator(])operator(\)) + reserved(end) + + ident(private) + reserved(def) method(select_html)operator(()ident(type)operator(,) ident(options)operator(,) ident(prefix) operator(=) pre_constant(nil)operator(,) ident(include_blank) operator(=) pre_constant(false)operator(,) ident(discard_type) operator(=) pre_constant(false)operator(,) ident(disabled) operator(=) pre_constant(false)operator(\)) + ident(select_html) operator(=) string<delimiter(%()content(<select name=")inline<inline_delimiter(#{)ident(prefix) operator(||) constant(DEFAULT_PREFIX)inline_delimiter(})>delimiter(\))> + ident(select_html) operator(<<) string<delimiter(")content([)inline<inline_delimiter(#{)ident(type)inline_delimiter(})>content(])delimiter(")> reserved(unless) ident(discard_type) + ident(select_html) operator(<<) string<delimiter(%()content(")delimiter(\))> + ident(select_html) operator(<<) string<delimiter(%()content( disabled="disabled")delimiter(\))> reserved(if) ident(disabled) + ident(select_html) operator(<<) string<delimiter(%()content(>)char(\\n)delimiter(\))> + ident(select_html) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)delimiter(\))> reserved(if) ident(include_blank) + ident(select_html) operator(<<) ident(options)operator(.)ident(to_s) + ident(select_html) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + reserved(end) + + reserved(def) method(leading_zero_on_single_digits)operator(()ident(number)operator(\)) + ident(number) operator(>) integer(9) operator(?) ident(number) operator(:) string<delimiter(")content(0)inline<inline_delimiter(#{)ident(number)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(InstanceTag) comment(#:nodoc:) + ident(include) constant(DateHelper) + + reserved(def) method(to_date_select_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(defaults) operator(=) operator({) symbol(:discard_type) operator(=)operator(>) pre_constant(true) operator(}) + ident(options) operator(=) ident(defaults)operator(.)ident(merge)operator(()ident(options)operator(\)) + ident(options_with_prefix) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(position)operator(|) ident(options)operator(.)ident(merge)operator(()symbol(:prefix) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(position)inline_delimiter(})>content(i\)])delimiter(")>operator(\)) operator(}) + ident(date) operator(=) ident(options)operator([)symbol(:include_blank)operator(]) operator(?) operator(()ident(value) operator(||) integer(0)operator(\)) operator(:) operator(()ident(value) operator(||) constant(Date)operator(.)ident(today)operator(\)) + + ident(date_select) operator(=) string<delimiter(')delimiter(')> + ident(options)operator([)symbol(:order)operator(]) operator(=) operator([)symbol(:month)operator(,) symbol(:year)operator(,) symbol(:day)operator(]) reserved(if) ident(options)operator([)symbol(:month_before_year)operator(]) comment(# For backwards compatibility) + ident(options)operator([)symbol(:order)operator(]) operator(||=) operator([)symbol(:year)operator(,) symbol(:month)operator(,) symbol(:day)operator(]) + + ident(position) operator(=) operator({)symbol(:year) operator(=)operator(>) integer(1)operator(,) symbol(:month) operator(=)operator(>) integer(2)operator(,) symbol(:day) operator(=)operator(>) integer(3)operator(}) + + ident(discard) operator(=) operator({)operator(}) + ident(discard)operator([)symbol(:year)operator(]) operator(=) pre_constant(true) reserved(if) ident(options)operator([)symbol(:discard_year)operator(]) + ident(discard)operator([)symbol(:month)operator(]) operator(=) pre_constant(true) reserved(if) ident(options)operator([)symbol(:discard_month)operator(]) + ident(discard)operator([)symbol(:day)operator(]) operator(=) pre_constant(true) reserved(if) ident(options)operator([)symbol(:discard_day)operator(]) reserved(or) ident(options)operator([)symbol(:discard_month)operator(]) + + ident(options)operator([)symbol(:order)operator(])operator(.)ident(each) reserved(do) operator(|)ident(param)operator(|) + ident(date_select) operator(<<) pre_constant(self)operator(.)ident(send)operator(()string<delimiter(")content(select_)inline<inline_delimiter(#{)ident(param)inline_delimiter(})>delimiter(")>operator(,) ident(date)operator(,) ident(options_with_prefix)operator(.)ident(call)operator(()ident(position)operator([)ident(param)operator(])operator(\))operator(\)) reserved(unless) ident(discard)operator([)ident(param)operator(]) + reserved(end) + + ident(date_select) + reserved(end) + + reserved(def) method(to_datetime_select_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(defaults) operator(=) operator({) symbol(:discard_type) operator(=)operator(>) pre_constant(true) operator(}) + ident(options) operator(=) ident(defaults)operator(.)ident(merge)operator(()ident(options)operator(\)) + ident(options_with_prefix) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(position)operator(|) ident(options)operator(.)ident(merge)operator(()symbol(:prefix) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(position)inline_delimiter(})>content(i\)])delimiter(")>operator(\)) operator(}) + ident(datetime) operator(=) ident(options)operator([)symbol(:include_blank)operator(]) operator(?) operator(()ident(value) operator(||) pre_constant(nil)operator(\)) operator(:) operator(()ident(value) operator(||) constant(Time)operator(.)ident(now)operator(\)) + + ident(datetime_select) operator(=) ident(select_year)operator(()ident(datetime)operator(,) ident(options_with_prefix)operator(.)ident(call)operator(()integer(1)operator(\))operator(\)) + ident(datetime_select) operator(<<) ident(select_month)operator(()ident(datetime)operator(,) ident(options_with_prefix)operator(.)ident(call)operator(()integer(2)operator(\))operator(\)) reserved(unless) ident(options)operator([)symbol(:discard_month)operator(]) + ident(datetime_select) operator(<<) ident(select_day)operator(()ident(datetime)operator(,) ident(options_with_prefix)operator(.)ident(call)operator(()integer(3)operator(\))operator(\)) reserved(unless) ident(options)operator([)symbol(:discard_day)operator(]) operator(||) ident(options)operator([)symbol(:discard_month)operator(]) + ident(datetime_select) operator(<<) string<delimiter(')content( — )delimiter(')> operator(+) ident(select_hour)operator(()ident(datetime)operator(,) ident(options_with_prefix)operator(.)ident(call)operator(()integer(4)operator(\))operator(\)) reserved(unless) ident(options)operator([)symbol(:discard_hour)operator(]) + ident(datetime_select) operator(<<) string<delimiter(')content( : )delimiter(')> operator(+) ident(select_minute)operator(()ident(datetime)operator(,) ident(options_with_prefix)operator(.)ident(call)operator(()integer(5)operator(\))operator(\)) reserved(unless) ident(options)operator([)symbol(:discard_minute)operator(]) operator(||) ident(options)operator([)symbol(:discard_hour)operator(]) + + ident(datetime_select) + reserved(end) + reserved(end) + + reserved(class) class(FormBuilder) + reserved(def) method(date_select)operator(()ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(date_select)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(\)) + reserved(end) + + reserved(def) method(datetime_select)operator(()ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(datetime_select)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a set of methods for making it easier to locate problems.) + reserved(module) class(DebugHelper) + comment(# Returns a <pre>-tag set with the +object+ dumped by YAML. Very readable way to inspect an object.) + reserved(def) method(debug)operator(()ident(object)operator(\)) + reserved(begin) + constant(Marshal)operator(::)ident(dump)operator(()ident(object)operator(\)) + string<delimiter(")content(<pre class='debug_dump'>)inline<inline_delimiter(#{)ident(h)operator(()ident(object)operator(.)ident(to_yaml)operator(\))operator(.)ident(gsub)operator(()string<delimiter(")content( )delimiter(")>operator(,) string<delimiter(")content( )delimiter(")>operator(\))inline_delimiter(})>content(</pre>)delimiter(")> + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + comment(# Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback) + string<delimiter(")content(<code class='debug_dump'>)inline<inline_delimiter(#{)ident(h)operator(()ident(object)operator(.)ident(inspect)operator(\))inline_delimiter(})>content(</code>)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) string<delimiter(')content(cgi)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/date_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tag_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a set of methods for working with forms and especially forms related to objects assigned to the template.) + comment(# The following is an example of a complete form for a person object that works for both creates and updates built) + comment(# with all the form helpers. The <tt>@person</tt> object was assigned by an action on the controller:) + comment(# <form action="save_person" method="post">) + comment(# Name:) + comment(# <%= text_field "person", "name", "size" => 20 %>) + comment(#) + comment(# Password:) + comment(# <%= password_field "person", "password", "maxsize" => 20 %>) + comment(#) + comment(# Single?:) + comment(# <%= check_box "person", "single" %>) + comment(#) + comment(# Description:) + comment(# <%= text_area "person", "description", "cols" => 20 %>) + comment(#) + comment(# <input type="submit" value="Save">) + comment(# </form>) + comment(#) + comment(# ...is compiled to:) + comment(#) + comment(# <form action="save_person" method="post">) + comment(# Name:) + comment(# <input type="text" id="person_name" name="person[name]") + comment(# size="20" value="<%= @person.name %>" />) + comment(#) + comment(# Password:) + comment(# <input type="password" id="person_password" name="person[password]") + comment(# size="20" maxsize="20" value="<%= @person.password %>" />) + comment(#) + comment(# Single?:) + comment(# <input type="checkbox" id="person_single" name="person[single]" value="1" />) + comment(#) + comment(# Description:) + comment(# <textarea cols="20" rows="40" id="person_description" name="person[description]">) + comment(# <%= @person.description %>) + comment(# </textarea>) + comment(#) + comment(# <input type="submit" value="Save">) + comment(# </form>) + comment(#) + comment(# If the object name contains square brackets the id for the object will be inserted. Example:) + comment(#) + comment(# <%= text_field "person[]", "name" %> ) + comment(# ) + comment(# ...becomes:) + comment(#) + comment(# <input type="text" id="person_<%= @person.id %>_name" name="person[<%= @person.id %>][name]" value="<%= @person.name %>" />) + comment(#) + comment(# If the helper is being used to generate a repetitive sequence of similar form elements, for example in a partial) + comment(# used by render_collection_of_partials, the "index" option may come in handy. Example:) + comment(#) + comment(# <%= text_field "person", "name", "index" => 1 %>) + comment(#) + comment(# becomes) + comment(#) + comment(# <input type="text" id="person_1_name" name="person[1][name]" value="<%= @person.name %>" />) + comment(#) + comment(# There's also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html,) + comment(# link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html) + reserved(module) class(FormHelper) + comment(# Creates a form and a scope around a specific model object, which is then used as a base for questioning about) + comment(# values for the fields. Examples:) + comment(#) + comment(# <% form_for :person, @person, :url => { :action => "update" } do |f| %>) + comment(# First name: <%= f.text_field :first_name %>) + comment(# Last name : <%= f.text_field :last_name %>) + comment(# Biography : <%= f.text_area :biography %>) + comment(# Admin? : <%= f.check_box :admin %>) + comment(# <% end %>) + comment(#) + comment(# Worth noting is that the form_for tag is called in a ERb evaluation block, not a ERb output block. So that's <tt><% %></tt>, ) + comment(# not <tt><%= %></tt>. Also worth noting is that the form_for yields a form_builder object, in this example as f, which emulates) + comment(# the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>,) + comment(# you get away with <tt>f.text_field :name</tt>. ) + comment(#) + comment(# That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance) + comment(# variable convention, so while the stand-alone approach would require <tt>text_field :person, :name, :object => person</tt> ) + comment(# to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with ) + comment(# <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>.) + comment(#) + comment(# Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods) + comment(# and methods from FormTagHelper. Example:) + comment(#) + comment(# <% form_for :person, @person, :url => { :action => "update" } do |f| %>) + comment(# First name: <%= f.text_field :first_name %>) + comment(# Last name : <%= f.text_field :last_name %>) + comment(# Biography : <%= text_area :person, :biography %>) + comment(# Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %>) + comment(# <% end %>) + comment(#) + comment(# Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base.) + comment(# Like collection_select and datetime_select.) + comment(#) + comment(# Html attributes for the form tag can be given as :html => {...}. Example:) + comment(# ) + comment(# <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %>) + comment(# ...) + comment(# <% end %>) + comment(#) + comment(# You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers,) + comment(# then use your custom builder like so:) + comment(# ) + comment(# <% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>) + comment(# <%= f.text_field :first_name %>) + comment(# <%= f.text_field :last_name %>) + comment(# <%= text_area :person, :biography %>) + comment(# <%= check_box_tag "person[admin]", @person.company.admin? %>) + comment(# <% end %>) + comment(# ) + comment(# In many cases you will want to wrap the above in another helper, such as:) + comment(#) + comment(# def labelled_form_for(name, object, options, &proc\)) + comment(# form_for(name, object, options.merge(:builder => LabellingFormBuiler\), &proc\)) + comment(# end) + comment(#) + reserved(def) method(form_for)operator(()ident(object_name)operator(,) operator(*)ident(args)operator(,) operator(&)ident(proc)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Missing block)delimiter(")> reserved(unless) ident(block_given?) + ident(options) operator(=) ident(args)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(args)operator(.)ident(pop) operator(:) operator({)operator(}) + ident(concat)operator(()ident(form_tag)operator(()ident(options)operator(.)ident(delete)operator(()symbol(:url)operator(\)) operator(||) operator({)operator(})operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:html)operator(\)) operator(||) operator({)operator(})operator(\))operator(,) ident(proc)operator(.)ident(binding)operator(\)) + ident(fields_for)operator(()ident(object_name)operator(,) operator(*)operator(()ident(args) operator(<<) ident(options)operator(\))operator(,) operator(&)ident(proc)operator(\)) + ident(concat)operator(()string<delimiter(')content(</form>)delimiter(')>operator(,) ident(proc)operator(.)ident(binding)operator(\)) + reserved(end) + + comment(# Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes) + comment(# fields_for suitable for specifying additional model objects in the same form. Example:) + comment(#) + comment(# <% form_for :person, @person, :url => { :action => "update" } do |person_form| %>) + comment(# First name: <%= person_form.text_field :first_name %>) + comment(# Last name : <%= person_form.text_field :last_name %>) + comment(# ) + comment(# <% fields_for :permission, @person.permission do |permission_fields| %>) + comment(# Admin? : <%= permission_fields.check_box :admin %>) + comment(# <% end %>) + comment(# <% end %>) + comment(#) + comment(# Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base.) + comment(# Like collection_select and datetime_select.) + reserved(def) method(fields_for)operator(()ident(object_name)operator(,) operator(*)ident(args)operator(,) operator(&)ident(proc)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Missing block)delimiter(")> reserved(unless) ident(block_given?) + ident(options) operator(=) ident(args)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(args)operator(.)ident(pop) operator(:) operator({)operator(}) + ident(object) operator(=) ident(args)operator(.)ident(first) + reserved(yield)operator(()operator(()ident(options)operator([)symbol(:builder)operator(]) operator(||) constant(FormBuilder)operator(\))operator(.)ident(new)operator(()ident(object_name)operator(,) ident(object)operator(,) pre_constant(self)operator(,) ident(options)operator(,) ident(proc)operator(\))operator(\)) + reserved(end) + + comment(# Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+\) on an object) + comment(# assigned to the template (identified by +object+\). Additional options on the input tag can be passed as a) + comment(# hash with +options+.) + comment(#) + comment(# Examples (call, result\):) + comment(# text_field("post", "title", "size" => 20\)) + comment(# <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />) + reserved(def) method(text_field)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_input_field_tag)operator(()string<delimiter(")content(text)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Works just like text_field, but returns an input tag of the "password" type instead.) + reserved(def) method(password_field)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_input_field_tag)operator(()string<delimiter(")content(password)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Works just like text_field, but returns an input tag of the "hidden" type instead.) + reserved(def) method(hidden_field)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_input_field_tag)operator(()string<delimiter(")content(hidden)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Works just like text_field, but returns an input tag of the "file" type instead, which won't have a default value.) + reserved(def) method(file_field)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_input_field_tag)operator(()string<delimiter(")content(file)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+\)) + comment(# on an object assigned to the template (identified by +object+\). Additional options on the input tag can be passed as a) + comment(# hash with +options+.) + comment(#) + comment(# Example (call, result\):) + comment(# text_area("post", "body", "cols" => 20, "rows" => 40\)) + comment(# <textarea cols="20" rows="40" id="post_body" name="post[body]">) + comment(# #{@post.body}) + comment(# </textarea>) + reserved(def) method(text_area)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_text_area_tag)operator(()ident(options)operator(\)) + reserved(end) + + comment(# Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+\) on an object) + comment(# assigned to the template (identified by +object+\). It's intended that +method+ returns an integer and if that) + comment(# integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a) + comment(# hash with +options+. The +checked_value+ defaults to 1 while the default +unchecked_value+) + comment(# is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don't post anything.) + comment(# We work around this problem by adding a hidden value with the same name as the checkbox.) + comment(#) + comment(# Example (call, result\). Imagine that @post.validated? returns 1:) + comment(# check_box("post", "validated"\)) + comment(# <input type="checkbox" id="post_validate" name="post[validated]" value="1" checked="checked" />) + comment(# <input name="post[validated]" type="hidden" value="0" />) + comment(#) + comment(# Example (call, result\). Imagine that @puppy.gooddog returns no:) + comment(# check_box("puppy", "gooddog", {}, "yes", "no"\)) + comment(# <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />) + comment(# <input name="puppy[gooddog]" type="hidden" value="no" />) + reserved(def) method(check_box)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(checked_value) operator(=) string<delimiter(")content(1)delimiter(")>operator(,) ident(unchecked_value) operator(=) string<delimiter(")content(0)delimiter(")>operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_check_box_tag)operator(()ident(options)operator(,) ident(checked_value)operator(,) ident(unchecked_value)operator(\)) + reserved(end) + + comment(# Returns a radio button tag for accessing a specified attribute (identified by +method+\) on an object) + comment(# assigned to the template (identified by +object+\). If the current value of +method+ is +tag_value+ the) + comment(# radio button will be checked. Additional options on the input tag can be passed as a) + comment(# hash with +options+.) + comment(# Example (call, result\). Imagine that @post.category returns "rails":) + comment(# radio_button("post", "category", "rails"\)) + comment(# radio_button("post", "category", "java"\)) + comment(# <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" />) + comment(# <input type="radio" id="post_category" name="post[category]" value="java" />) + comment(#) + reserved(def) method(radio_button)operator(()ident(object_name)operator(,) ident(method)operator(,) ident(tag_value)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object_name)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_radio_button_tag)operator(()ident(tag_value)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(InstanceTag) comment(#:nodoc:) + ident(include) constant(Helpers)operator(::)constant(TagHelper) + + ident(attr_reader) symbol(:method_name)operator(,) symbol(:object_name) + + constant(DEFAULT_FIELD_OPTIONS) operator(=) operator({) string<delimiter(")content(size)delimiter(")> operator(=)operator(>) integer(30) operator(})operator(.)ident(freeze) reserved(unless) ident(const_defined?)operator(()symbol(:DEFAULT_FIELD_OPTIONS)operator(\)) + constant(DEFAULT_RADIO_OPTIONS) operator(=) operator({) operator(})operator(.)ident(freeze) reserved(unless) ident(const_defined?)operator(()symbol(:DEFAULT_RADIO_OPTIONS)operator(\)) + constant(DEFAULT_TEXT_AREA_OPTIONS) operator(=) operator({) string<delimiter(")content(cols)delimiter(")> operator(=)operator(>) integer(40)operator(,) string<delimiter(")content(rows)delimiter(")> operator(=)operator(>) integer(20) operator(})operator(.)ident(freeze) reserved(unless) ident(const_defined?)operator(()symbol(:DEFAULT_TEXT_AREA_OPTIONS)operator(\)) + constant(DEFAULT_DATE_OPTIONS) operator(=) operator({) symbol(:discard_type) operator(=)operator(>) pre_constant(true) operator(})operator(.)ident(freeze) reserved(unless) ident(const_defined?)operator(()symbol(:DEFAULT_DATE_OPTIONS)operator(\)) + + reserved(def) method(initialize)operator(()ident(object_name)operator(,) ident(method_name)operator(,) ident(template_object)operator(,) ident(local_binding) operator(=) pre_constant(nil)operator(,) ident(object) operator(=) pre_constant(nil)operator(\)) + instance_variable(@object_name)operator(,) instance_variable(@method_name) operator(=) ident(object_name)operator(.)ident(to_s)operator(.)ident(dup)operator(,) ident(method_name)operator(.)ident(to_s)operator(.)ident(dup) + instance_variable(@template_object)operator(,) instance_variable(@local_binding) operator(=) ident(template_object)operator(,) ident(local_binding) + instance_variable(@object) operator(=) ident(object) + reserved(if) instance_variable(@object_name)operator(.)ident(sub!)operator(()regexp<delimiter(/)char(\\[)char(\\])content($)delimiter(/)>operator(,)string<delimiter(")delimiter(")>operator(\)) + instance_variable(@auto_index) operator(=) instance_variable(@template_object)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(last_match)operator(.)ident(pre_match)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(id_before_type_cast) + reserved(end) + reserved(end) + + reserved(def) method(to_input_field_tag)operator(()ident(field_type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(stringify_keys) + ident(options)operator([)string<delimiter(")content(size)delimiter(")>operator(]) operator(||=) ident(options)operator([)string<delimiter(")content(maxlength)delimiter(")>operator(]) operator(||) constant(DEFAULT_FIELD_OPTIONS)operator([)string<delimiter(")content(size)delimiter(")>operator(]) + ident(options) operator(=) constant(DEFAULT_FIELD_OPTIONS)operator(.)ident(merge)operator(()ident(options)operator(\)) + reserved(if) ident(field_type) operator(==) string<delimiter(")content(hidden)delimiter(")> + ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(size)delimiter(")>operator(\)) + reserved(end) + ident(options)operator([)string<delimiter(")content(type)delimiter(")>operator(]) operator(=) ident(field_type) + ident(options)operator([)string<delimiter(")content(value)delimiter(")>operator(]) operator(||=) ident(value_before_type_cast) reserved(unless) ident(field_type) operator(==) string<delimiter(")content(file)delimiter(")> + ident(add_default_name_and_id)operator(()ident(options)operator(\)) + ident(tag)operator(()string<delimiter(")content(input)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(to_radio_button_tag)operator(()ident(tag_value)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) constant(DEFAULT_RADIO_OPTIONS)operator(.)ident(merge)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + ident(options)operator([)string<delimiter(")content(type)delimiter(")>operator(]) operator(=) string<delimiter(")content(radio)delimiter(")> + ident(options)operator([)string<delimiter(")content(value)delimiter(")>operator(]) operator(=) ident(tag_value) + ident(options)operator([)string<delimiter(")content(checked)delimiter(")>operator(]) operator(=) string<delimiter(")content(checked)delimiter(")> reserved(if) ident(value)operator(.)ident(to_s) operator(==) ident(tag_value)operator(.)ident(to_s) + ident(pretty_tag_value) operator(=) ident(tag_value)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\s)delimiter(/)>operator(,) string<delimiter(")content(_)delimiter(")>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\W)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\))operator(.)ident(downcase) + ident(options)operator([)string<delimiter(")content(id)delimiter(")>operator(]) operator(=) instance_variable(@auto_index) operator(?) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)instance_variable(@auto_index)inline_delimiter(})>content(_)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(pretty_tag_value)inline_delimiter(})>delimiter(")> operator(:) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(pretty_tag_value)inline_delimiter(})>delimiter(")> + ident(add_default_name_and_id)operator(()ident(options)operator(\)) + ident(tag)operator(()string<delimiter(")content(input)delimiter(")>operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(to_text_area_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) constant(DEFAULT_TEXT_AREA_OPTIONS)operator(.)ident(merge)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + ident(add_default_name_and_id)operator(()ident(options)operator(\)) + ident(content_tag)operator(()string<delimiter(")content(textarea)delimiter(")>operator(,) ident(html_escape)operator(()ident(options)operator(.)ident(delete)operator(()string<delimiter(')content(value)delimiter(')>operator(\)) operator(||) ident(value_before_type_cast)operator(\))operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(to_check_box_tag)operator(()ident(options) operator(=) operator({)operator(})operator(,) ident(checked_value) operator(=) string<delimiter(")content(1)delimiter(")>operator(,) ident(unchecked_value) operator(=) string<delimiter(")content(0)delimiter(")>operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(stringify_keys) + ident(options)operator([)string<delimiter(")content(type)delimiter(")>operator(]) operator(=) string<delimiter(")content(checkbox)delimiter(")> + ident(options)operator([)string<delimiter(")content(value)delimiter(")>operator(]) operator(=) ident(checked_value) + ident(checked) operator(=) reserved(case) ident(value) + reserved(when) constant(TrueClass)operator(,) constant(FalseClass) + ident(value) + reserved(when) constant(NilClass) + pre_constant(false) + reserved(when) constant(Integer) + ident(value) operator(!=) integer(0) + reserved(when) constant(String) + ident(value) operator(==) ident(checked_value) + reserved(else) + ident(value)operator(.)ident(to_i) operator(!=) integer(0) + reserved(end) + reserved(if) ident(checked) operator(||) ident(options)operator([)string<delimiter(")content(checked)delimiter(")>operator(]) operator(==) string<delimiter(")content(checked)delimiter(")> + ident(options)operator([)string<delimiter(")content(checked)delimiter(")>operator(]) operator(=) string<delimiter(")content(checked)delimiter(")> + reserved(else) + ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(checked)delimiter(")>operator(\)) + reserved(end) + ident(add_default_name_and_id)operator(()ident(options)operator(\)) + ident(tag)operator(()string<delimiter(")content(input)delimiter(")>operator(,) ident(options)operator(\)) operator(<<) ident(tag)operator(()string<delimiter(")content(input)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(options)operator([)string<delimiter(")content(name)delimiter(")>operator(])operator(,) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(hidden)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(unchecked_value)operator(\)) + reserved(end) + + reserved(def) method(to_date_tag)operator(()operator(\)) + ident(defaults) operator(=) constant(DEFAULT_DATE_OPTIONS)operator(.)ident(dup) + ident(date) operator(=) ident(value) operator(||) constant(Date)operator(.)ident(today) + ident(options) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(position)operator(|) ident(defaults)operator(.)ident(merge)operator(()symbol(:prefix) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(position)inline_delimiter(})>content(i\)])delimiter(")>operator(\)) operator(}) + ident(html_day_select)operator(()ident(date)operator(,) ident(options)operator(.)ident(call)operator(()integer(3)operator(\))operator(\)) operator(+) + ident(html_month_select)operator(()ident(date)operator(,) ident(options)operator(.)ident(call)operator(()integer(2)operator(\))operator(\)) operator(+) + ident(html_year_select)operator(()ident(date)operator(,) ident(options)operator(.)ident(call)operator(()integer(1)operator(\))operator(\)) + reserved(end) + + reserved(def) method(to_boolean_select_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(stringify_keys) + ident(add_default_name_and_id)operator(()ident(options)operator(\)) + ident(tag_text) operator(=) string<delimiter(")content(<select)delimiter(")> + ident(tag_text) operator(<<) ident(tag_options)operator(()ident(options)operator(\)) + ident(tag_text) operator(<<) string<delimiter(")content(><option value=)char(\\")content(false)char(\\")delimiter(")> + ident(tag_text) operator(<<) string<delimiter(")content( selected)delimiter(")> reserved(if) ident(value) operator(==) pre_constant(false) + ident(tag_text) operator(<<) string<delimiter(")content(>False</option><option value=)char(\\")content(true)char(\\")delimiter(")> + ident(tag_text) operator(<<) string<delimiter(")content( selected)delimiter(")> reserved(if) ident(value) + ident(tag_text) operator(<<) string<delimiter(")content(>True</option></select>)delimiter(")> + reserved(end) + + reserved(def) method(to_content_tag)operator(()ident(tag_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(content_tag)operator(()ident(tag_name)operator(,) ident(value)operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(object) + instance_variable(@object) operator(||) instance_variable(@template_object)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(value) + reserved(unless) ident(object)operator(.)ident(nil?) + ident(object)operator(.)ident(send)operator(()instance_variable(@method_name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(value_before_type_cast) + reserved(unless) ident(object)operator(.)ident(nil?) + ident(object)operator(.)ident(respond_to?)operator(()instance_variable(@method_name) operator(+) string<delimiter(")content(_before_type_cast)delimiter(")>operator(\)) operator(?) + ident(object)operator(.)ident(send)operator(()instance_variable(@method_name) operator(+) string<delimiter(")content(_before_type_cast)delimiter(")>operator(\)) operator(:) + ident(object)operator(.)ident(send)operator(()instance_variable(@method_name)operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(add_default_name_and_id)operator(()ident(options)operator(\)) + reserved(if) ident(options)operator(.)ident(has_key?)operator(()string<delimiter(")content(index)delimiter(")>operator(\)) + ident(options)operator([)string<delimiter(")content(name)delimiter(")>operator(]) operator(||=) ident(tag_name_with_index)operator(()ident(options)operator([)string<delimiter(")content(index)delimiter(")>operator(])operator(\)) + ident(options)operator([)string<delimiter(")content(id)delimiter(")>operator(]) operator(||=) ident(tag_id_with_index)operator(()ident(options)operator([)string<delimiter(")content(index)delimiter(")>operator(])operator(\)) + ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(index)delimiter(")>operator(\)) + reserved(elsif) instance_variable(@auto_index) + ident(options)operator([)string<delimiter(")content(name)delimiter(")>operator(]) operator(||=) ident(tag_name_with_index)operator(()instance_variable(@auto_index)operator(\)) + ident(options)operator([)string<delimiter(")content(id)delimiter(")>operator(]) operator(||=) ident(tag_id_with_index)operator(()instance_variable(@auto_index)operator(\)) + reserved(else) + ident(options)operator([)string<delimiter(")content(name)delimiter(")>operator(]) operator(||=) ident(tag_name) + ident(options)operator([)string<delimiter(")content(id)delimiter(")>operator(]) operator(||=) ident(tag_id) + reserved(end) + reserved(end) + + reserved(def) method(tag_name) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(])delimiter(")> + reserved(end) + + reserved(def) method(tag_name_with_index)operator(()ident(index)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(index)inline_delimiter(})>content(][)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>content(])delimiter(")> + reserved(end) + + reserved(def) method(tag_id) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(tag_id_with_index)operator(()ident(index)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@object_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(index)inline_delimiter(})>content(_)inline<inline_delimiter(#{)instance_variable(@method_name)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(FormBuilder) comment(#:nodoc:) + comment(# The methods which wrap a form helper call.) + ident(class_inheritable_accessor) symbol(:field_helpers) + pre_constant(self)operator(.)ident(field_helpers) operator(=) operator(()constant(FormHelper)operator(.)ident(instance_methods) operator(-) operator([)string<delimiter(')content(form_for)delimiter(')>operator(])operator(\)) + + ident(attr_accessor) symbol(:object_name)operator(,) symbol(:object) + + reserved(def) method(initialize)operator(()ident(object_name)operator(,) ident(object)operator(,) ident(template)operator(,) ident(options)operator(,) ident(proc)operator(\)) + instance_variable(@object_name)operator(,) instance_variable(@object)operator(,) instance_variable(@template)operator(,) instance_variable(@options)operator(,) instance_variable(@proc) operator(=) ident(object_name)operator(,) ident(object)operator(,) ident(template)operator(,) ident(options)operator(,) ident(proc) + reserved(end) + + operator(()ident(field_helpers) operator(-) string<delimiter(%w()content(check_box radio_button)delimiter(\))>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(selector)operator(|) + ident(src) operator(=) string<delimiter(<<-end_src)>string<content( + def )inline<inline_delimiter(#{)ident(selector)inline_delimiter(})>content((method, options = {}\) + @template.send()inline<inline_delimiter(#{)ident(selector)operator(.)ident(inspect)inline_delimiter(})>content(, @object_name, method, options.merge(:object => @object\)\) + end)delimiter( + end_src)> + ident(class_eval) ident(src)operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__) + reserved(end) + + reserved(def) method(check_box)operator(()ident(method)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(checked_value) operator(=) string<delimiter(")content(1)delimiter(")>operator(,) ident(unchecked_value) operator(=) string<delimiter(")content(0)delimiter(")>operator(\)) + instance_variable(@template)operator(.)ident(check_box)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(,) ident(checked_value)operator(,) ident(unchecked_value)operator(\)) + reserved(end) + + reserved(def) method(radio_button)operator(()ident(method)operator(,) ident(tag_value)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(radio_button)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(tag_value)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(erb)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/form_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a number of methods for turning different kinds of containers into a set of option tags.) + comment(# == Options) + comment(# The <tt>collection_select</tt>, <tt>country_select</tt>, <tt>select</tt>,) + comment(# and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter,) + comment(# a hash.) + comment(#) + comment(# * <tt>:include_blank</tt> - set to true if the first option element of the select element is a blank. Useful if there is not a default value required for the select element. For example,) + comment(#) + comment(# select("post", "category", Post::CATEGORIES, {:include_blank => true}\)) + comment(#) + comment(# could become:) + comment(#) + comment(# <select name="post[category]">) + comment(# <option></option>) + comment(# <option>joke</option>) + comment(# <option>poem</option>) + comment(# </select>) + comment(#) + comment(# * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string.) + comment(#) + comment(# Another common case is a select tag for an <tt>belongs_to</tt>-associated object. For example,) + comment(#) + comment(# select("post", "person_id", Person.find_all.collect {|p| [ p.name, p.id ] }\)) + comment(#) + comment(# could become:) + comment(#) + comment(# <select name="post[person_id]">) + comment(# <option value="1">David</option>) + comment(# <option value="2">Sam</option>) + comment(# <option value="3">Tobias</option>) + comment(# </select>) + reserved(module) class(FormOptionsHelper) + ident(include) constant(ERB)operator(::)constant(Util) + + comment(# Create a select tag and a series of contained option tags for the provided object and method.) + comment(# The option currently held by the object will be selected, provided that the object is available.) + comment(# See options_for_select for the required format of the choices parameter.) + comment(#) + comment(# Example with @post.person_id => 1:) + comment(# select("post", "person_id", Person.find_all.collect {|p| [ p.name, p.id ] }, { :include_blank => true }\)) + comment(#) + comment(# could become:) + comment(#) + comment(# <select name="post[person_id]">) + comment(# <option></option>) + comment(# <option value="1" selected="selected">David</option>) + comment(# <option value="2">Sam</option>) + comment(# <option value="3">Tobias</option>) + comment(# </select>) + comment(#) + comment(# This can be used to provide a default set of options in the standard way: before rendering the create form, a) + comment(# new model instance is assigned the default options and bound to @model_name. Usually this model is not saved) + comment(# to the database. Instead, a second model object is created when the create request is received.) + comment(# This allows the user to submit a form page more than once with the expected results of creating multiple records.) + comment(# In addition, this allows a single partial to be used to generate form inputs for both edit and create forms.) + comment(#) + comment(# By default, post.person_id is the selected option. Specify :selected => value to use a different selection) + comment(# or :selected => nil to leave all options unselected.) + reserved(def) method(select)operator(()ident(object)operator(,) ident(method)operator(,) ident(choices)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_select_tag)operator(()ident(choices)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + reserved(end) + + comment(# Return select and option tags for the given object and method using options_from_collection_for_select to generate the list of option tags.) + reserved(def) method(collection_select)operator(()ident(object)operator(,) ident(method)operator(,) ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_collection_select_tag)operator(()ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + reserved(end) + + comment(# Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags.) + reserved(def) method(country_select)operator(()ident(object)operator(,) ident(method)operator(,) ident(priority_countries) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_country_select_tag)operator(()ident(priority_countries)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + reserved(end) + + comment(# Return select and option tags for the given object and method, using) + comment(# #time_zone_options_for_select to generate the list of option tags.) + comment(#) + comment(# In addition to the <tt>:include_blank</tt> option documented above,) + comment(# this method also supports a <tt>:model</tt> option, which defaults) + comment(# to TimeZone. This may be used by users to specify a different time) + comment(# zone model object. (See #time_zone_options_for_select for more) + comment(# information.\)) + reserved(def) method(time_zone_select)operator(()ident(object)operator(,) ident(method)operator(,) ident(priority_zones) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + constant(InstanceTag)operator(.)ident(new)operator(()ident(object)operator(,) ident(method)operator(,) pre_constant(self)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(delete)operator(()symbol(:object)operator(\))operator(\))operator(.)ident(to_time_zone_select_tag)operator(()ident(priority_zones)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + reserved(end) + + comment(# Accepts a container (hash, array, enumerable, your type\) and returns a string of option tags. Given a container) + comment(# where the elements respond to first and last (such as a two-element array\), the "lasts" serve as option values and) + comment(# the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values) + comment(# become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +Selected+) + comment(# may also be an array of values to be selected when using a multiple select.) + comment(#) + comment(# Examples (call, result\):) + comment(# options_for_select([["Dollar", "$"], ["Kroner", "DKK"]]\)) + comment(# <option value="$">Dollar</option>\\n<option value="DKK">Kroner</option>) + comment(#) + comment(# options_for_select([ "VISA", "MasterCard" ], "MasterCard"\)) + comment(# <option>VISA</option>\\n<option selected="selected">MasterCard</option>) + comment(#) + comment(# options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40"\)) + comment(# <option value="$20">Basic</option>\\n<option value="$40" selected="selected">Plus</option>) + comment(#) + comment(# options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"]\)) + comment(# <option selected="selected">VISA</option>\\n<option>MasterCard</option>\\n<option selected="selected">Discover</option>) + comment(#) + comment(# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.) + reserved(def) method(options_for_select)operator(()ident(container)operator(,) ident(selected) operator(=) pre_constant(nil)operator(\)) + ident(container) operator(=) ident(container)operator(.)ident(to_a) reserved(if) constant(Hash) operator(===) ident(container) + + ident(options_for_select) operator(=) ident(container)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(options)operator(,) ident(element)operator(|) + reserved(if) operator(!)ident(element)operator(.)ident(is_a?)operator(()constant(String)operator(\)) reserved(and) ident(element)operator(.)ident(respond_to?)operator(()symbol(:first)operator(\)) reserved(and) ident(element)operator(.)ident(respond_to?)operator(()symbol(:last)operator(\)) + ident(is_selected) operator(=) operator(() operator(()ident(selected)operator(.)ident(respond_to?)operator(()symbol(:include?)operator(\)) operator(?) ident(selected)operator(.)ident(include?)operator(()ident(element)operator(.)ident(last)operator(\)) operator(:) ident(element)operator(.)ident(last) operator(==) ident(selected)operator(\)) operator(\)) + ident(is_selected) operator(=) operator(() operator(()ident(selected)operator(.)ident(respond_to?)operator(()symbol(:include?)operator(\)) operator(&&) operator(!)ident(selected)operator(.)ident(is_a?)operator(()constant(String)operator(\)) operator(?) ident(selected)operator(.)ident(include?)operator(()ident(element)operator(.)ident(last)operator(\)) operator(:) ident(element)operator(.)ident(last) operator(==) ident(selected)operator(\)) operator(\)) + reserved(if) ident(is_selected) + ident(options) operator(<<) string<delimiter(")content(<option value=)char(\\")inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(last)operator(.)ident(to_s)operator(\))inline_delimiter(})>char(\\")content( selected=)char(\\")content(selected)char(\\")content(>)inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(first)operator(.)ident(to_s)operator(\))inline_delimiter(})>content(</option>)delimiter(")> + reserved(else) + ident(options) operator(<<) string<delimiter(")content(<option value=)char(\\")inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(last)operator(.)ident(to_s)operator(\))inline_delimiter(})>char(\\")content(>)inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(first)operator(.)ident(to_s)operator(\))inline_delimiter(})>content(</option>)delimiter(")> + reserved(end) + reserved(else) + ident(is_selected) operator(=) operator(() operator(()ident(selected)operator(.)ident(respond_to?)operator(()symbol(:include?)operator(\)) operator(?) ident(selected)operator(.)ident(include?)operator(()ident(element)operator(\)) operator(:) ident(element) operator(==) ident(selected)operator(\)) operator(\)) + ident(is_selected) operator(=) operator(() operator(()ident(selected)operator(.)ident(respond_to?)operator(()symbol(:include?)operator(\)) operator(&&) operator(!)ident(selected)operator(.)ident(is_a?)operator(()constant(String)operator(\)) operator(?) ident(selected)operator(.)ident(include?)operator(()ident(element)operator(\)) operator(:) ident(element) operator(==) ident(selected)operator(\)) operator(\)) + ident(options) operator(<<) operator(()operator(()ident(is_selected)operator(\)) operator(?) string<delimiter(")content(<option value=)char(\\")inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(to_s)operator(\))inline_delimiter(})>char(\\")content( selected=)char(\\")content(selected)char(\\")content(>)inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(to_s)operator(\))inline_delimiter(})>content(</option>)delimiter(")> operator(:) string<delimiter(")content(<option value=)char(\\")inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(to_s)operator(\))inline_delimiter(})>char(\\")content(>)inline<inline_delimiter(#{)ident(html_escape)operator(()ident(element)operator(.)ident(to_s)operator(\))inline_delimiter(})>content(</option>)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(options_for_select)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + + comment(# Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the) + comment(# the result of a call to the +value_method+ as the option value and the +text_method+ as the option text.) + comment(# If +selected_value+ is specified, the element returning a match on +value_method+ will get the selected option tag.) + comment(#) + comment(# Example (call, result\). Imagine a loop iterating over each +person+ in <tt>@project.people</tt> to generate an input tag:) + comment(# options_from_collection_for_select(@project.people, "id", "name"\)) + comment(# <option value="#{person.id}">#{person.name}</option>) + comment(#) + comment(# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.) + reserved(def) method(options_from_collection_for_select)operator(()ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(selected_value) operator(=) pre_constant(nil)operator(\)) + ident(options_for_select)operator(() + ident(collection)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) operator({) operator(|)ident(options)operator(,) ident(object)operator(|) ident(options) operator(<<) operator([) ident(object)operator(.)ident(send)operator(()ident(text_method)operator(\))operator(,) ident(object)operator(.)ident(send)operator(()ident(value_method)operator(\)) operator(]) operator(})operator(,) + ident(selected_value) + operator(\)) + reserved(end) + + comment(# Returns a string of option tags, like options_from_collection_for_select, but surrounds them with <optgroup> tags.) + comment(#) + comment(# An array of group objects are passed. Each group should return an array of options when calling group_method) + comment(# Each group should return its name when calling group_label_method.) + comment(#) + comment(# html_option_groups_from_collection(@continents, "countries", "continent_name", "country_id", "country_name", @selected_country.id\)) + comment(#) + comment(# Could become:) + comment(# <optgroup label="Africa">) + comment(# <select>Egypt</select>) + comment(# <select>Rwanda</select>) + comment(# ...) + comment(# </optgroup>) + comment(# <optgroup label="Asia">) + comment(# <select>China</select>) + comment(# <select>India</select>) + comment(# <select>Japan</select>) + comment(# ...) + comment(# </optgroup>) + comment(#) + comment(# with objects of the following classes:) + comment(# class Continent) + comment(# def initialize(p_name, p_countries\) @continent_name = p_name; @countries = p_countries; end) + comment(# def continent_name(\) @continent_name; end) + comment(# def countries(\) @countries; end) + comment(# end) + comment(# class Country) + comment(# def initialize(id, name\) @id = id; @name = name end) + comment(# def country_id(\) @id; end) + comment(# def country_name(\) @name; end) + comment(# end) + comment(#) + comment(# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.) + reserved(def) method(option_groups_from_collection_for_select)operator(()ident(collection)operator(,) ident(group_method)operator(,) ident(group_label_method)operator(,) + ident(option_key_method)operator(,) ident(option_value_method)operator(,) ident(selected_key) operator(=) pre_constant(nil)operator(\)) + ident(collection)operator(.)ident(inject)operator(()string<delimiter(")delimiter(")>operator(\)) reserved(do) operator(|)ident(options_for_select)operator(,) ident(group)operator(|) + ident(group_label_string) operator(=) ident(eval)operator(()string<delimiter(")content(group.)inline<inline_delimiter(#{)ident(group_label_method)inline_delimiter(})>delimiter(")>operator(\)) + ident(options_for_select) operator(+=) string<delimiter(")content(<optgroup label=)char(\\")inline<inline_delimiter(#{)ident(html_escape)operator(()ident(group_label_string)operator(\))inline_delimiter(})>char(\\")content(>)delimiter(")> + ident(options_for_select) operator(+=) ident(options_from_collection_for_select)operator(()ident(eval)operator(()string<delimiter(")content(group.)inline<inline_delimiter(#{)ident(group_method)inline_delimiter(})>delimiter(")>operator(\))operator(,) ident(option_key_method)operator(,) ident(option_value_method)operator(,) ident(selected_key)operator(\)) + ident(options_for_select) operator(+=) string<delimiter(')content(</optgroup>)delimiter(')> + reserved(end) + reserved(end) + + comment(# Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to) + comment(# have it marked as the selected option tag. You can also supply an array of countries as +priority_countries+, so) + comment(# that they will be listed above the rest of the (long\) list.) + comment(#) + comment(# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.) + reserved(def) method(country_options_for_select)operator(()ident(selected) operator(=) pre_constant(nil)operator(,) ident(priority_countries) operator(=) pre_constant(nil)operator(\)) + ident(country_options) operator(=) string<delimiter(")delimiter(")> + + reserved(if) ident(priority_countries) + ident(country_options) operator(+=) ident(options_for_select)operator(()ident(priority_countries)operator(,) ident(selected)operator(\)) + ident(country_options) operator(+=) string<delimiter(")content(<option value=)char(\\")char(\\")content(>-------------</option>)char(\\n)delimiter(")> + reserved(end) + + reserved(if) ident(priority_countries) operator(&&) ident(priority_countries)operator(.)ident(include?)operator(()ident(selected)operator(\)) + ident(country_options) operator(+=) ident(options_for_select)operator(()constant(COUNTRIES) operator(-) ident(priority_countries)operator(,) ident(selected)operator(\)) + reserved(else) + ident(country_options) operator(+=) ident(options_for_select)operator(()constant(COUNTRIES)operator(,) ident(selected)operator(\)) + reserved(end) + + reserved(return) ident(country_options) + reserved(end) + + comment(# Returns a string of option tags for pretty much any time zone in the) + comment(# world. Supply a TimeZone name as +selected+ to have it marked as the) + comment(# selected option tag. You can also supply an array of TimeZone objects) + comment(# as +priority_zones+, so that they will be listed above the rest of the) + comment(# (long\) list. (You can use TimeZone.us_zones as a convenience for) + comment(# obtaining a list of the US time zones.\)) + comment(#) + comment(# The +selected+ parameter must be either +nil+, or a string that names) + comment(# a TimeZone.) + comment(#) + comment(# By default, +model+ is the TimeZone constant (which can be obtained) + comment(# in ActiveRecord as a value object\). The only requirement is that the) + comment(# +model+ parameter be an object that responds to #all, and returns) + comment(# an array of objects that represent time zones.) + comment(#) + comment(# NOTE: Only the option tags are returned, you have to wrap this call in) + comment(# a regular HTML select tag.) + reserved(def) method(time_zone_options_for_select)operator(()ident(selected) operator(=) pre_constant(nil)operator(,) ident(priority_zones) operator(=) pre_constant(nil)operator(,) ident(model) operator(=) constant(TimeZone)operator(\)) + ident(zone_options) operator(=) string<delimiter(")delimiter(")> + + ident(zones) operator(=) ident(model)operator(.)ident(all) + ident(convert_zones) operator(=) ident(lambda) operator({) operator(|)ident(list)operator(|) ident(list)operator(.)ident(map) operator({) operator(|)ident(z)operator(|) operator([) ident(z)operator(.)ident(to_s)operator(,) ident(z)operator(.)ident(name) operator(]) operator(}) operator(}) + + reserved(if) ident(priority_zones) + ident(zone_options) operator(+=) ident(options_for_select)operator(()ident(convert_zones)operator([)ident(priority_zones)operator(])operator(,) ident(selected)operator(\)) + ident(zone_options) operator(+=) string<delimiter(")content(<option value=)char(\\")char(\\")content(>-------------</option>)char(\\n)delimiter(")> + + ident(zones) operator(=) ident(zones)operator(.)ident(reject) operator({) operator(|)ident(z)operator(|) ident(priority_zones)operator(.)ident(include?)operator(() ident(z) operator(\)) operator(}) + reserved(end) + + ident(zone_options) operator(+=) ident(options_for_select)operator(()ident(convert_zones)operator([)ident(zones)operator(])operator(,) ident(selected)operator(\)) + ident(zone_options) + reserved(end) + + ident(private) + comment(# All the countries included in the country_options output.) + constant(COUNTRIES) operator(=) operator([) string<delimiter(")content(Afghanistan)delimiter(")>operator(,) string<delimiter(")content(Albania)delimiter(")>operator(,) string<delimiter(")content(Algeria)delimiter(")>operator(,) string<delimiter(")content(American Samoa)delimiter(")>operator(,) string<delimiter(")content(Andorra)delimiter(")>operator(,) string<delimiter(")content(Angola)delimiter(")>operator(,) string<delimiter(")content(Anguilla)delimiter(")>operator(,) + string<delimiter(")content(Antarctica)delimiter(")>operator(,) string<delimiter(")content(Antigua And Barbuda)delimiter(")>operator(,) string<delimiter(")content(Argentina)delimiter(")>operator(,) string<delimiter(")content(Armenia)delimiter(")>operator(,) string<delimiter(")content(Aruba)delimiter(")>operator(,) string<delimiter(")content(Australia)delimiter(")>operator(,) + string<delimiter(")content(Austria)delimiter(")>operator(,) string<delimiter(")content(Azerbaijan)delimiter(")>operator(,) string<delimiter(")content(Bahamas)delimiter(")>operator(,) string<delimiter(")content(Bahrain)delimiter(")>operator(,) string<delimiter(")content(Bangladesh)delimiter(")>operator(,) string<delimiter(")content(Barbados)delimiter(")>operator(,) string<delimiter(")content(Belarus)delimiter(")>operator(,) + string<delimiter(")content(Belgium)delimiter(")>operator(,) string<delimiter(")content(Belize)delimiter(")>operator(,) string<delimiter(")content(Benin)delimiter(")>operator(,) string<delimiter(")content(Bermuda)delimiter(")>operator(,) string<delimiter(")content(Bhutan)delimiter(")>operator(,) string<delimiter(")content(Bolivia)delimiter(")>operator(,) string<delimiter(")content(Bosnia and Herzegowina)delimiter(")>operator(,) + string<delimiter(")content(Botswana)delimiter(")>operator(,) string<delimiter(")content(Bouvet Island)delimiter(")>operator(,) string<delimiter(")content(Brazil)delimiter(")>operator(,) string<delimiter(")content(British Indian Ocean Territory)delimiter(")>operator(,) + string<delimiter(")content(Brunei Darussalam)delimiter(")>operator(,) string<delimiter(")content(Bulgaria)delimiter(")>operator(,) string<delimiter(")content(Burkina Faso)delimiter(")>operator(,) string<delimiter(")content(Burma)delimiter(")>operator(,) string<delimiter(")content(Burundi)delimiter(")>operator(,) string<delimiter(")content(Cambodia)delimiter(")>operator(,) + string<delimiter(")content(Cameroon)delimiter(")>operator(,) string<delimiter(")content(Canada)delimiter(")>operator(,) string<delimiter(")content(Cape Verde)delimiter(")>operator(,) string<delimiter(")content(Cayman Islands)delimiter(")>operator(,) string<delimiter(")content(Central African Republic)delimiter(")>operator(,) + string<delimiter(")content(Chad)delimiter(")>operator(,) string<delimiter(")content(Chile)delimiter(")>operator(,) string<delimiter(")content(China)delimiter(")>operator(,) string<delimiter(")content(Christmas Island)delimiter(")>operator(,) string<delimiter(")content(Cocos (Keeling\) Islands)delimiter(")>operator(,) string<delimiter(")content(Colombia)delimiter(")>operator(,) + string<delimiter(")content(Comoros)delimiter(")>operator(,) string<delimiter(")content(Congo)delimiter(")>operator(,) string<delimiter(")content(Congo, the Democratic Republic of the)delimiter(")>operator(,) string<delimiter(")content(Cook Islands)delimiter(")>operator(,) + string<delimiter(")content(Costa Rica)delimiter(")>operator(,) string<delimiter(")content(Cote d'Ivoire)delimiter(")>operator(,) string<delimiter(")content(Croatia)delimiter(")>operator(,) string<delimiter(")content(Cuba)delimiter(")>operator(,) string<delimiter(")content(Cyprus)delimiter(")>operator(,) string<delimiter(")content(Czech Republic)delimiter(")>operator(,) string<delimiter(")content(Denmark)delimiter(")>operator(,) + string<delimiter(")content(Djibouti)delimiter(")>operator(,) string<delimiter(")content(Dominica)delimiter(")>operator(,) string<delimiter(")content(Dominican Republic)delimiter(")>operator(,) string<delimiter(")content(East Timor)delimiter(")>operator(,) string<delimiter(")content(Ecuador)delimiter(")>operator(,) string<delimiter(")content(Egypt)delimiter(")>operator(,) + string<delimiter(")content(El Salvador)delimiter(")>operator(,) string<delimiter(")content(England)delimiter(")>operator(,) string<delimiter(")content(Equatorial Guinea)delimiter(")>operator(,) string<delimiter(")content(Eritrea)delimiter(")>operator(,) string<delimiter(")content(Espana)delimiter(")>operator(,) string<delimiter(")content(Estonia)delimiter(")>operator(,) + string<delimiter(")content(Ethiopia)delimiter(")>operator(,) string<delimiter(")content(Falkland Islands)delimiter(")>operator(,) string<delimiter(")content(Faroe Islands)delimiter(")>operator(,) string<delimiter(")content(Fiji)delimiter(")>operator(,) string<delimiter(")content(Finland)delimiter(")>operator(,) string<delimiter(")content(France)delimiter(")>operator(,) + string<delimiter(")content(French Guiana)delimiter(")>operator(,) string<delimiter(")content(French Polynesia)delimiter(")>operator(,) string<delimiter(")content(French Southern Territories)delimiter(")>operator(,) string<delimiter(")content(Gabon)delimiter(")>operator(,) string<delimiter(")content(Gambia)delimiter(")>operator(,) + string<delimiter(")content(Georgia)delimiter(")>operator(,) string<delimiter(")content(Germany)delimiter(")>operator(,) string<delimiter(")content(Ghana)delimiter(")>operator(,) string<delimiter(")content(Gibraltar)delimiter(")>operator(,) string<delimiter(")content(Great Britain)delimiter(")>operator(,) string<delimiter(")content(Greece)delimiter(")>operator(,) string<delimiter(")content(Greenland)delimiter(")>operator(,) + string<delimiter(")content(Grenada)delimiter(")>operator(,) string<delimiter(")content(Guadeloupe)delimiter(")>operator(,) string<delimiter(")content(Guam)delimiter(")>operator(,) string<delimiter(")content(Guatemala)delimiter(")>operator(,) string<delimiter(")content(Guinea)delimiter(")>operator(,) string<delimiter(")content(Guinea-Bissau)delimiter(")>operator(,) string<delimiter(")content(Guyana)delimiter(")>operator(,) + string<delimiter(")content(Haiti)delimiter(")>operator(,) string<delimiter(")content(Heard and Mc Donald Islands)delimiter(")>operator(,) string<delimiter(")content(Honduras)delimiter(")>operator(,) string<delimiter(")content(Hong Kong)delimiter(")>operator(,) string<delimiter(")content(Hungary)delimiter(")>operator(,) string<delimiter(")content(Iceland)delimiter(")>operator(,) + string<delimiter(")content(India)delimiter(")>operator(,) string<delimiter(")content(Indonesia)delimiter(")>operator(,) string<delimiter(")content(Ireland)delimiter(")>operator(,) string<delimiter(")content(Israel)delimiter(")>operator(,) string<delimiter(")content(Italy)delimiter(")>operator(,) string<delimiter(")content(Iran)delimiter(")>operator(,) string<delimiter(")content(Iraq)delimiter(")>operator(,) string<delimiter(")content(Jamaica)delimiter(")>operator(,) string<delimiter(")content(Japan)delimiter(")>operator(,) string<delimiter(")content(Jordan)delimiter(")>operator(,) + string<delimiter(")content(Kazakhstan)delimiter(")>operator(,) string<delimiter(")content(Kenya)delimiter(")>operator(,) string<delimiter(")content(Kiribati)delimiter(")>operator(,) string<delimiter(")content(Korea, Republic of)delimiter(")>operator(,) string<delimiter(")content(Korea (South\))delimiter(")>operator(,) string<delimiter(")content(Kuwait)delimiter(")>operator(,) + string<delimiter(")content(Kyrgyzstan)delimiter(")>operator(,) string<delimiter(")content(Lao People's Democratic Republic)delimiter(")>operator(,) string<delimiter(")content(Latvia)delimiter(")>operator(,) string<delimiter(")content(Lebanon)delimiter(")>operator(,) string<delimiter(")content(Lesotho)delimiter(")>operator(,) + string<delimiter(")content(Liberia)delimiter(")>operator(,) string<delimiter(")content(Liechtenstein)delimiter(")>operator(,) string<delimiter(")content(Lithuania)delimiter(")>operator(,) string<delimiter(")content(Luxembourg)delimiter(")>operator(,) string<delimiter(")content(Macau)delimiter(")>operator(,) string<delimiter(")content(Macedonia)delimiter(")>operator(,) + string<delimiter(")content(Madagascar)delimiter(")>operator(,) string<delimiter(")content(Malawi)delimiter(")>operator(,) string<delimiter(")content(Malaysia)delimiter(")>operator(,) string<delimiter(")content(Maldives)delimiter(")>operator(,) string<delimiter(")content(Mali)delimiter(")>operator(,) string<delimiter(")content(Malta)delimiter(")>operator(,) string<delimiter(")content(Marshall Islands)delimiter(")>operator(,) + string<delimiter(")content(Martinique)delimiter(")>operator(,) string<delimiter(")content(Mauritania)delimiter(")>operator(,) string<delimiter(")content(Mauritius)delimiter(")>operator(,) string<delimiter(")content(Mayotte)delimiter(")>operator(,) string<delimiter(")content(Mexico)delimiter(")>operator(,) + string<delimiter(")content(Micronesia, Federated States of)delimiter(")>operator(,) string<delimiter(")content(Moldova, Republic of)delimiter(")>operator(,) string<delimiter(")content(Monaco)delimiter(")>operator(,) string<delimiter(")content(Mongolia)delimiter(")>operator(,) + string<delimiter(")content(Montserrat)delimiter(")>operator(,) string<delimiter(")content(Morocco)delimiter(")>operator(,) string<delimiter(")content(Mozambique)delimiter(")>operator(,) string<delimiter(")content(Myanmar)delimiter(")>operator(,) string<delimiter(")content(Namibia)delimiter(")>operator(,) string<delimiter(")content(Nauru)delimiter(")>operator(,) string<delimiter(")content(Nepal)delimiter(")>operator(,) + string<delimiter(")content(Netherlands)delimiter(")>operator(,) string<delimiter(")content(Netherlands Antilles)delimiter(")>operator(,) string<delimiter(")content(New Caledonia)delimiter(")>operator(,) string<delimiter(")content(New Zealand)delimiter(")>operator(,) string<delimiter(")content(Nicaragua)delimiter(")>operator(,) + string<delimiter(")content(Niger)delimiter(")>operator(,) string<delimiter(")content(Nigeria)delimiter(")>operator(,) string<delimiter(")content(Niue)delimiter(")>operator(,) string<delimiter(")content(Norfolk Island)delimiter(")>operator(,) string<delimiter(")content(Northern Ireland)delimiter(")>operator(,) + string<delimiter(")content(Northern Mariana Islands)delimiter(")>operator(,) string<delimiter(")content(Norway)delimiter(")>operator(,) string<delimiter(")content(Oman)delimiter(")>operator(,) string<delimiter(")content(Pakistan)delimiter(")>operator(,) string<delimiter(")content(Palau)delimiter(")>operator(,) string<delimiter(")content(Panama)delimiter(")>operator(,) + string<delimiter(")content(Papua New Guinea)delimiter(")>operator(,) string<delimiter(")content(Paraguay)delimiter(")>operator(,) string<delimiter(")content(Peru)delimiter(")>operator(,) string<delimiter(")content(Philippines)delimiter(")>operator(,) string<delimiter(")content(Pitcairn)delimiter(")>operator(,) string<delimiter(")content(Poland)delimiter(")>operator(,) + string<delimiter(")content(Portugal)delimiter(")>operator(,) string<delimiter(")content(Puerto Rico)delimiter(")>operator(,) string<delimiter(")content(Qatar)delimiter(")>operator(,) string<delimiter(")content(Reunion)delimiter(")>operator(,) string<delimiter(")content(Romania)delimiter(")>operator(,) string<delimiter(")content(Russia)delimiter(")>operator(,) string<delimiter(")content(Rwanda)delimiter(")>operator(,) + string<delimiter(")content(Saint Kitts and Nevis)delimiter(")>operator(,) string<delimiter(")content(Saint Lucia)delimiter(")>operator(,) string<delimiter(")content(Saint Vincent and the Grenadines)delimiter(")>operator(,) + string<delimiter(")content(Samoa (Independent\))delimiter(")>operator(,) string<delimiter(")content(San Marino)delimiter(")>operator(,) string<delimiter(")content(Sao Tome and Principe)delimiter(")>operator(,) string<delimiter(")content(Saudi Arabia)delimiter(")>operator(,) + string<delimiter(")content(Scotland)delimiter(")>operator(,) string<delimiter(")content(Senegal)delimiter(")>operator(,) string<delimiter(")content(Serbia and Montenegro)delimiter(")>operator(,) string<delimiter(")content(Seychelles)delimiter(")>operator(,) string<delimiter(")content(Sierra Leone)delimiter(")>operator(,) string<delimiter(")content(Singapore)delimiter(")>operator(,) + string<delimiter(")content(Slovakia)delimiter(")>operator(,) string<delimiter(")content(Slovenia)delimiter(")>operator(,) string<delimiter(")content(Solomon Islands)delimiter(")>operator(,) string<delimiter(")content(Somalia)delimiter(")>operator(,) string<delimiter(")content(South Africa)delimiter(")>operator(,) + string<delimiter(")content(South Georgia and the South Sandwich Islands)delimiter(")>operator(,) string<delimiter(")content(South Korea)delimiter(")>operator(,) string<delimiter(")content(Spain)delimiter(")>operator(,) string<delimiter(")content(Sri Lanka)delimiter(")>operator(,) + string<delimiter(")content(St. Helena)delimiter(")>operator(,) string<delimiter(")content(St. Pierre and Miquelon)delimiter(")>operator(,) string<delimiter(")content(Suriname)delimiter(")>operator(,) string<delimiter(")content(Svalbard and Jan Mayen Islands)delimiter(")>operator(,) + string<delimiter(")content(Swaziland)delimiter(")>operator(,) string<delimiter(")content(Sweden)delimiter(")>operator(,) string<delimiter(")content(Switzerland)delimiter(")>operator(,) string<delimiter(")content(Taiwan)delimiter(")>operator(,) string<delimiter(")content(Tajikistan)delimiter(")>operator(,) string<delimiter(")content(Tanzania)delimiter(")>operator(,) string<delimiter(")content(Thailand)delimiter(")>operator(,) + string<delimiter(")content(Togo)delimiter(")>operator(,) string<delimiter(")content(Tokelau)delimiter(")>operator(,) string<delimiter(")content(Tonga)delimiter(")>operator(,) string<delimiter(")content(Trinidad)delimiter(")>operator(,) string<delimiter(")content(Trinidad and Tobago)delimiter(")>operator(,) string<delimiter(")content(Tunisia)delimiter(")>operator(,) string<delimiter(")content(Turkey)delimiter(")>operator(,) + string<delimiter(")content(Turkmenistan)delimiter(")>operator(,) string<delimiter(")content(Turks and Caicos Islands)delimiter(")>operator(,) string<delimiter(")content(Tuvalu)delimiter(")>operator(,) string<delimiter(")content(Uganda)delimiter(")>operator(,) string<delimiter(")content(Ukraine)delimiter(")>operator(,) + string<delimiter(")content(United Arab Emirates)delimiter(")>operator(,) string<delimiter(")content(United Kingdom)delimiter(")>operator(,) string<delimiter(")content(United States)delimiter(")>operator(,) + string<delimiter(")content(United States Minor Outlying Islands)delimiter(")>operator(,) string<delimiter(")content(Uruguay)delimiter(")>operator(,) string<delimiter(")content(Uzbekistan)delimiter(")>operator(,) string<delimiter(")content(Vanuatu)delimiter(")>operator(,) + string<delimiter(")content(Vatican City State (Holy See\))delimiter(")>operator(,) string<delimiter(")content(Venezuela)delimiter(")>operator(,) string<delimiter(")content(Viet Nam)delimiter(")>operator(,) string<delimiter(")content(Virgin Islands (British\))delimiter(")>operator(,) + string<delimiter(")content(Virgin Islands (U.S.\))delimiter(")>operator(,) string<delimiter(")content(Wales)delimiter(")>operator(,) string<delimiter(")content(Wallis and Futuna Islands)delimiter(")>operator(,) string<delimiter(")content(Western Sahara)delimiter(")>operator(,) + string<delimiter(")content(Yemen)delimiter(")>operator(,) string<delimiter(")content(Zambia)delimiter(")>operator(,) string<delimiter(")content(Zimbabwe)delimiter(")> operator(]) reserved(unless) ident(const_defined?)operator(()string<delimiter(")content(COUNTRIES)delimiter(")>operator(\)) + reserved(end) + + reserved(class) class(InstanceTag) comment(#:nodoc:) + ident(include) constant(FormOptionsHelper) + + reserved(def) method(to_select_tag)operator(()ident(choices)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + ident(add_default_name_and_id)operator(()ident(html_options)operator(\)) + ident(selected_value) operator(=) ident(options)operator(.)ident(has_key?)operator(()symbol(:selected)operator(\)) operator(?) ident(options)operator([)symbol(:selected)operator(]) operator(:) ident(value) + ident(content_tag)operator(()string<delimiter(")content(select)delimiter(")>operator(,) ident(add_options)operator(()ident(options_for_select)operator(()ident(choices)operator(,) ident(selected_value)operator(\))operator(,) ident(options)operator(,) ident(value)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + + reserved(def) method(to_collection_select_tag)operator(()ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + ident(add_default_name_and_id)operator(()ident(html_options)operator(\)) + ident(content_tag)operator(() + string<delimiter(")content(select)delimiter(")>operator(,) ident(add_options)operator(()ident(options_from_collection_for_select)operator(()ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(value)operator(\))operator(,) ident(options)operator(,) ident(value)operator(\))operator(,) ident(html_options) + operator(\)) + reserved(end) + + reserved(def) method(to_country_select_tag)operator(()ident(priority_countries)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + ident(add_default_name_and_id)operator(()ident(html_options)operator(\)) + ident(content_tag)operator(()string<delimiter(")content(select)delimiter(")>operator(,) ident(add_options)operator(()ident(country_options_for_select)operator(()ident(value)operator(,) ident(priority_countries)operator(\))operator(,) ident(options)operator(,) ident(value)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + + reserved(def) method(to_time_zone_select_tag)operator(()ident(priority_zones)operator(,) ident(options)operator(,) ident(html_options)operator(\)) + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + ident(add_default_name_and_id)operator(()ident(html_options)operator(\)) + ident(content_tag)operator(()string<delimiter(")content(select)delimiter(")>operator(,) + ident(add_options)operator(() + ident(time_zone_options_for_select)operator(()ident(value)operator(,) ident(priority_zones)operator(,) ident(options)operator([)symbol(:model)operator(]) operator(||) constant(TimeZone)operator(\))operator(,) + ident(options)operator(,) ident(value) + operator(\))operator(,) ident(html_options) + operator(\)) + reserved(end) + + ident(private) + reserved(def) method(add_options)operator(()ident(option_tags)operator(,) ident(options)operator(,) ident(value) operator(=) pre_constant(nil)operator(\)) + ident(option_tags) operator(=) string<delimiter(")content(<option value=)char(\\")char(\\")content(></option>)char(\\n)delimiter(")> operator(+) ident(option_tags) reserved(if) ident(options)operator([)symbol(:include_blank)operator(]) + + reserved(if) ident(value)operator(.)ident(blank?) operator(&&) ident(options)operator([)symbol(:prompt)operator(]) + operator(()string<delimiter(")content(<option value=)char(\\")char(\\")content(>)inline<inline_delimiter(#{)ident(options)operator([)symbol(:prompt)operator(])operator(.)ident(kind_of?)operator(()constant(String)operator(\)) operator(?) ident(options)operator([)symbol(:prompt)operator(]) operator(:) string<delimiter(')content(Please select)delimiter(')>inline_delimiter(})>content(</option>)char(\\n)delimiter(")>operator(\)) operator(+) ident(option_tags) + reserved(else) + ident(option_tags) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(FormBuilder) + reserved(def) method(select)operator(()ident(method)operator(,) ident(choices)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(select)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(choices)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + + reserved(def) method(collection_select)operator(()ident(method)operator(,) ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(collection_select)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(collection)operator(,) ident(value_method)operator(,) ident(text_method)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + + reserved(def) method(country_select)operator(()ident(method)operator(,) ident(priority_countries) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(country_select)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(priority_countries)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + + reserved(def) method(time_zone_select)operator(()ident(method)operator(,) ident(priority_zones) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + instance_variable(@template)operator(.)ident(time_zone_select)operator(()instance_variable(@object_name)operator(,) ident(method)operator(,) ident(priority_zones)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:object) operator(=)operator(>) instance_variable(@object)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tag_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a number of methods for creating form tags that doesn't rely on conventions with an object assigned to the template like) + comment(# FormHelper does. With the FormTagHelper, you provide the names and values yourself.) + comment(#) + comment(# NOTE: The html options disabled, readonly, and multiple can all be treated as booleans. So specifying <tt>:disabled => true</tt>) + comment(# will give <tt>disabled="disabled"</tt>.) + reserved(module) class(FormTagHelper) + comment(# Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like) + comment(# ActionController::Base#url_for. The method for the form defaults to POST.) + comment(#) + comment(# Options:) + comment(# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".) + comment(# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".) + reserved(def) method(form_tag)operator(()ident(url_for_options) operator(=) operator({)operator(})operator(,) ident(options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_url)operator(,) operator(&)ident(proc)operator(\)) + ident(html_options) operator(=) operator({) string<delimiter(")content(method)delimiter(")> operator(=)operator(>) string<delimiter(")content(post)delimiter(")> operator(})operator(.)ident(merge)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + ident(html_options)operator([)string<delimiter(")content(enctype)delimiter(")>operator(]) operator(=) string<delimiter(")content(multipart/form-data)delimiter(")> reserved(if) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(multipart)delimiter(")>operator(\)) + ident(html_options)operator([)string<delimiter(")content(action)delimiter(")>operator(]) operator(=) ident(url_for)operator(()ident(url_for_options)operator(,) operator(*)ident(parameters_for_url)operator(\)) + ident(tag) symbol(:form)operator(,) ident(html_options)operator(,) pre_constant(true) + reserved(end) + + ident(alias_method) symbol(:start_form_tag)operator(,) symbol(:form_tag) + + comment(# Outputs "</form>") + reserved(def) method(end_form_tag) + string<delimiter(")content(</form>)delimiter(")> + reserved(end) + + comment(# Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple) + comment(# choice selection box.) + comment(#) + comment(# Helpers::FormOptions can be used to create common select boxes such as countries, time zones, or) + comment(# associated records.) + comment(#) + comment(# <tt>option_tags</tt> is a string containing the option tags for the select box:) + comment(# # Outputs <select id="people" name="people"><option>David</option></select>) + comment(# select_tag "people", "<option>David</option>") + comment(#) + comment(# Options:) + comment(# * <tt>:multiple</tt> - If set to true the selection will allow multiple choices.) + reserved(def) method(select_tag)operator(()ident(name)operator(,) ident(option_tags) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(content_tag) symbol(:select)operator(,) ident(option_tags)operator(,) operator({) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(name) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + reserved(end) + + comment(# Creates a standard text field.) + comment(#) + comment(# Options:) + comment(# * <tt>:disabled</tt> - If set to true, the user will not be able to use this input.) + comment(# * <tt>:size</tt> - The number of visible characters that will fit in the input.) + comment(# * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter.) + comment(# ) + comment(# A hash of standard HTML options for the tag.) + reserved(def) method(text_field_tag)operator(()ident(name)operator(,) ident(value) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(tag) symbol(:input)operator(,) operator({) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(text)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(value) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + reserved(end) + + comment(# Creates a hidden field.) + comment(#) + comment(# Takes the same options as text_field_tag) + reserved(def) method(hidden_field_tag)operator(()ident(name)operator(,) ident(value) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(text_field_tag)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(.)ident(stringify_keys)operator(.)ident(update)operator(()string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(hidden)delimiter(")>operator(\))operator(\)) + reserved(end) + + comment(# Creates a file upload field.) + comment(#) + comment(# If you are using file uploads then you will also need to set the multipart option for the form:) + comment(# <%= form_tag { :action => "post" }, { :multipart => true } %>) + comment(# <label for="file">File to Upload</label> <%= file_field_tag "file" %>) + comment(# <%= submit_tag %>) + comment(# <%= end_form_tag %>) + comment(#) + comment(# The specified URL will then be passed a File object containing the selected file, or if the field ) + comment(# was left blank, a StringIO object.) + reserved(def) method(file_field_tag)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(text_field_tag)operator(()ident(name)operator(,) pre_constant(nil)operator(,) ident(options)operator(.)ident(update)operator(()string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(file)delimiter(")>operator(\))operator(\)) + reserved(end) + + comment(# Creates a password field.) + comment(#) + comment(# Takes the same options as text_field_tag) + reserved(def) method(password_field_tag)operator(()ident(name) operator(=) string<delimiter(")content(password)delimiter(")>operator(,) ident(value) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(text_field_tag)operator(()ident(name)operator(,) ident(value)operator(,) ident(options)operator(.)ident(update)operator(()string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(password)delimiter(")>operator(\))operator(\)) + reserved(end) + + comment(# Creates a text input area.) + comment(#) + comment(# Options:) + comment(# * <tt>:size</tt> - A string specifying the dimensions of the textarea.) + comment(# # Outputs <textarea name="body" id="body" cols="25" rows="10"></textarea>) + comment(# <%= text_area_tag "body", nil, :size => "25x10" %>) + reserved(def) method(text_area_tag)operator(()ident(name)operator(,) ident(content) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator(.)ident(stringify_keys!) + + reserved(if) ident(size) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(size)delimiter(")>operator(\)) + ident(options)operator([)string<delimiter(")content(cols)delimiter(")>operator(])operator(,) ident(options)operator([)string<delimiter(")content(rows)delimiter(")>operator(]) operator(=) ident(size)operator(.)ident(split)operator(()string<delimiter(")content(x)delimiter(")>operator(\)) + reserved(end) + + ident(content_tag) symbol(:textarea)operator(,) ident(content)operator(,) operator({) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(name) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + reserved(end) + + comment(# Creates a check box.) + reserved(def) method(check_box_tag)operator(()ident(name)operator(,) ident(value) operator(=) string<delimiter(")content(1)delimiter(")>operator(,) ident(checked) operator(=) pre_constant(false)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(html_options) operator(=) operator({) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(checkbox)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(value) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + ident(html_options)operator([)string<delimiter(")content(checked)delimiter(")>operator(]) operator(=) string<delimiter(")content(checked)delimiter(")> reserved(if) ident(checked) + ident(tag) symbol(:input)operator(,) ident(html_options) + reserved(end) + + comment(# Creates a radio button.) + reserved(def) method(radio_button_tag)operator(()ident(name)operator(,) ident(value)operator(,) ident(checked) operator(=) pre_constant(false)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(html_options) operator(=) operator({) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(radio)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(name)operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(value) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + ident(html_options)operator([)string<delimiter(")content(checked)delimiter(")>operator(]) operator(=) string<delimiter(")content(checked)delimiter(")> reserved(if) ident(checked) + ident(tag) symbol(:input)operator(,) ident(html_options) + reserved(end) + + comment(# Creates a submit button with the text <tt>value</tt> as the caption. If options contains a pair with the key of "disable_with",) + comment(# then the value will be used to rename a disabled version of the submit button.) + reserved(def) method(submit_tag)operator(()ident(value) operator(=) string<delimiter(")content(Save changes)delimiter(")>operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator(.)ident(stringify_keys!) + + reserved(if) ident(disable_with) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(disable_with)delimiter(")>operator(\)) + ident(options)operator([)string<delimiter(")content(onclick)delimiter(")>operator(]) operator(=) string<delimiter(")content(this.disabled=true;this.value=')inline<inline_delimiter(#{)ident(disable_with)inline_delimiter(})>content(';this.form.submit(\);)inline<inline_delimiter(#{)ident(options)operator([)string<delimiter(")content(onclick)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + ident(tag) symbol(:input)operator(,) operator({) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(submit)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(commit)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(value) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + reserved(end) + + comment(# Displays an image which when clicked will submit the form.) + comment(#) + comment(# <tt>source</tt> is passed to AssetTagHelper#image_path) + reserved(def) method(image_submit_tag)operator(()ident(source)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(tag) symbol(:input)operator(,) operator({) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(image)delimiter(")>operator(,) string<delimiter(")content(src)delimiter(")> operator(=)operator(>) ident(image_path)operator(()ident(source)operator(\)) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tag_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a set of helpers for creating JavaScript macros that rely on and often bundle methods from JavaScriptHelper into) + comment(# larger units. These macros also rely on counterparts in the controller that provide them with their backing. The in-place) + comment(# editing relies on ActionController::Base.in_place_edit_for and the autocompletion relies on ) + comment(# ActionController::Base.auto_complete_for.) + reserved(module) class(JavaScriptMacrosHelper) + comment(# Makes an HTML element specified by the DOM ID +field_id+ become an in-place) + comment(# editor of a property.) + comment(#) + comment(# A form is automatically created and displayed when the user clicks the element,) + comment(# something like this:) + comment(# <form id="myElement-in-place-edit-form" target="specified url">) + comment(# <input name="value" text="The content of myElement"/>) + comment(# <input type="submit" value="ok"/>) + comment(# <a onclick="javascript to cancel the editing">cancel</a>) + comment(# </form>) + comment(# ) + comment(# The form is serialized and sent to the server using an AJAX call, the action on) + comment(# the server should process the value and return the updated value in the body of) + comment(# the reponse. The element will automatically be updated with the changed value) + comment(# (as returned from the server\).) + comment(# ) + comment(# Required +options+ are:) + comment(# <tt>:url</tt>:: Specifies the url where the updated value should) + comment(# be sent after the user presses "ok".) + comment(# ) + comment(#) + comment(# Addtional +options+ are:) + comment(# <tt>:rows</tt>:: Number of rows (more than 1 will use a TEXTAREA\)) + comment(# <tt>:cols</tt>:: Number of characters the text input should span (works for both INPUT and TEXTAREA\)) + comment(# <tt>:size</tt>:: Synonym for :cols when using a single line text input.) + comment(# <tt>:cancel_text</tt>:: The text on the cancel link. (default: "cancel"\)) + comment(# <tt>:save_text</tt>:: The text on the save link. (default: "ok"\)) + comment(# <tt>:loading_text</tt>:: The text to display when submitting to the server (default: "Saving..."\)) + comment(# <tt>:external_control</tt>:: The id of an external control used to enter edit mode.) + comment(# <tt>:load_text_url</tt>:: URL where initial value of editor (content\) is retrieved.) + comment(# <tt>:options</tt>:: Pass through options to the AJAX call (see prototype's Ajax.Updater\)) + comment(# <tt>:with</tt>:: JavaScript snippet that should return what is to be sent) + comment(# in the AJAX call, +form+ is an implicit parameter) + comment(# <tt>:script</tt>:: Instructs the in-place editor to evaluate the remote JavaScript response (default: false\)) + reserved(def) method(in_place_editor)operator(()ident(field_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(function) operator(=) string<delimiter(")content(new Ajax.InPlaceEditor()delimiter(")> + ident(function) operator(<<) string<delimiter(")content(')inline<inline_delimiter(#{)ident(field_id)inline_delimiter(})>content(', )delimiter(")> + ident(function) operator(<<) string<delimiter(")content(')inline<inline_delimiter(#{)ident(url_for)operator(()ident(options)operator([)symbol(:url)operator(])operator(\))inline_delimiter(})>content(')delimiter(")> + + ident(js_options) operator(=) operator({)operator(}) + ident(js_options)operator([)string<delimiter(')content(cancelText)delimiter(')>operator(]) operator(=) string<delimiter(%()content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:cancel_text)operator(])inline_delimiter(})>content(')delimiter(\))> reserved(if) ident(options)operator([)symbol(:cancel_text)operator(]) + ident(js_options)operator([)string<delimiter(')content(okText)delimiter(')>operator(]) operator(=) string<delimiter(%()content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:save_text)operator(])inline_delimiter(})>content(')delimiter(\))> reserved(if) ident(options)operator([)symbol(:save_text)operator(]) + ident(js_options)operator([)string<delimiter(')content(loadingText)delimiter(')>operator(]) operator(=) string<delimiter(%()content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:loading_text)operator(])inline_delimiter(})>content(')delimiter(\))> reserved(if) ident(options)operator([)symbol(:loading_text)operator(]) + ident(js_options)operator([)string<delimiter(')content(rows)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:rows)operator(]) reserved(if) ident(options)operator([)symbol(:rows)operator(]) + ident(js_options)operator([)string<delimiter(')content(cols)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:cols)operator(]) reserved(if) ident(options)operator([)symbol(:cols)operator(]) + ident(js_options)operator([)string<delimiter(')content(size)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:size)operator(]) reserved(if) ident(options)operator([)symbol(:size)operator(]) + ident(js_options)operator([)string<delimiter(')content(externalControl)delimiter(')>operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:external_control)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:external_control)operator(]) + ident(js_options)operator([)string<delimiter(')content(loadTextURL)delimiter(')>operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(url_for)operator(()ident(options)operator([)symbol(:load_text_url)operator(])operator(\))inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:load_text_url)operator(]) + ident(js_options)operator([)string<delimiter(')content(ajaxOptions)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:options)operator(]) reserved(if) ident(options)operator([)symbol(:options)operator(]) + ident(js_options)operator([)string<delimiter(')content(evalScripts)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:script)operator(]) reserved(if) ident(options)operator([)symbol(:script)operator(]) + ident(js_options)operator([)string<delimiter(')content(callback)delimiter(')>operator(]) operator(=) string<delimiter(")content(function(form\) { return )inline<inline_delimiter(#{)ident(options)operator([)symbol(:with)operator(])inline_delimiter(})>content( })delimiter(")> reserved(if) ident(options)operator([)symbol(:with)operator(]) + ident(function) operator(<<) operator(()string<delimiter(')content(, )delimiter(')> operator(+) ident(options_for_javascript)operator(()ident(js_options)operator(\))operator(\)) reserved(unless) ident(js_options)operator(.)ident(empty?) + + ident(function) operator(<<) string<delimiter(')content(\))delimiter(')> + + ident(javascript_tag)operator(()ident(function)operator(\)) + reserved(end) + + comment(# Renders the value of the specified object and method with in-place editing capabilities.) + comment(#) + comment(# See the RDoc on ActionController::InPlaceEditing to learn more about this.) + reserved(def) method(in_place_editor_field)operator(()ident(object)operator(,) ident(method)operator(,) ident(tag_options) operator(=) operator({)operator(})operator(,) ident(in_place_editor_options) operator(=) operator({)operator(})operator(\)) + ident(tag) operator(=) operator(::)constant(ActionView)operator(::)constant(Helpers)operator(::)constant(InstanceTag)operator(.)ident(new)operator(()ident(object)operator(,) ident(method)operator(,) pre_constant(self)operator(\)) + ident(tag_options) operator(=) operator({)symbol(:tag) operator(=)operator(>) string<delimiter(")content(span)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(tag)operator(.)ident(object)operator(.)ident(id)inline_delimiter(})>content(_in_place_editor)delimiter(")>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(")content(in_place_editor_field)delimiter(")>operator(})operator(.)ident(merge!)operator(()ident(tag_options)operator(\)) + ident(in_place_editor_options)operator([)symbol(:url)operator(]) operator(=) ident(in_place_editor_options)operator([)symbol(:url)operator(]) operator(||) ident(url_for)operator(()operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(set_)inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>delimiter(")>operator(,) symbol(:id) operator(=)operator(>) ident(tag)operator(.)ident(object)operator(.)ident(id) operator(})operator(\)) + ident(tag)operator(.)ident(to_content_tag)operator(()ident(tag_options)operator(.)ident(delete)operator(()symbol(:tag)operator(\))operator(,) ident(tag_options)operator(\)) operator(+) + ident(in_place_editor)operator(()ident(tag_options)operator([)symbol(:id)operator(])operator(,) ident(in_place_editor_options)operator(\)) + reserved(end) + + comment(# Adds AJAX autocomplete functionality to the text input field with the ) + comment(# DOM ID specified by +field_id+.) + comment(#) + comment(# This function expects that the called action returns a HTML <ul> list,) + comment(# or nothing if no entries should be displayed for autocompletion.) + comment(#) + comment(# You'll probably want to turn the browser's built-in autocompletion off,) + comment(# so be sure to include a autocomplete="off" attribute with your text) + comment(# input field.) + comment(#) + comment(# The autocompleter object is assigned to a Javascript variable named <tt>field_id</tt>_auto_completer.) + comment(# This object is useful if you for example want to trigger the auto-complete suggestions through) + comment(# other means than user input (for that specific case, call the <tt>activate</tt> method on that object\). ) + comment(# ) + comment(# Required +options+ are:) + comment(# <tt>:url</tt>:: URL to call for autocompletion results) + comment(# in url_for format.) + comment(# ) + comment(# Addtional +options+ are:) + comment(# <tt>:update</tt>:: Specifies the DOM ID of the element whose ) + comment(# innerHTML should be updated with the autocomplete) + comment(# entries returned by the AJAX request. ) + comment(# Defaults to field_id + '_auto_complete') + comment(# <tt>:with</tt>:: A JavaScript expression specifying the) + comment(# parameters for the XMLHttpRequest. This defaults) + comment(# to 'fieldname=value'.) + comment(# <tt>:frequency</tt>:: Determines the time to wait after the last keystroke) + comment(# for the AJAX request to be initiated.) + comment(# <tt>:indicator</tt>:: Specifies the DOM ID of an element which will be) + comment(# displayed while autocomplete is running.) + comment(# <tt>:tokens</tt>:: A string or an array of strings containing) + comment(# separator tokens for tokenized incremental ) + comment(# autocompletion. Example: <tt>:tokens => ','</tt> would) + comment(# allow multiple autocompletion entries, separated) + comment(# by commas.) + comment(# <tt>:min_chars</tt>:: The minimum number of characters that should be) + comment(# in the input field before an Ajax call is made) + comment(# to the server.) + comment(# <tt>:on_hide</tt>:: A Javascript expression that is called when the) + comment(# autocompletion div is hidden. The expression) + comment(# should take two variables: element and update.) + comment(# Element is a DOM element for the field, update) + comment(# is a DOM element for the div from which the) + comment(# innerHTML is replaced.) + comment(# <tt>:on_show</tt>:: Like on_hide, only now the expression is called) + comment(# then the div is shown.) + comment(# <tt>:after_update_element</tt>:: A Javascript expression that is called when the) + comment(# user has selected one of the proposed values. ) + comment(# The expression should take two variables: element and value.) + comment(# Element is a DOM element for the field, value) + comment(# is the value selected by the user.) + comment(# <tt>:select</tt>:: Pick the class of the element from which the value for ) + comment(# insertion should be extracted. If this is not specified,) + comment(# the entire element is used.) + reserved(def) method(auto_complete_field)operator(()ident(field_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(function) operator(=) string<delimiter(")content(var )inline<inline_delimiter(#{)ident(field_id)inline_delimiter(})>content(_auto_completer = new Ajax.Autocompleter()delimiter(")> + ident(function) operator(<<) string<delimiter(")content(')inline<inline_delimiter(#{)ident(field_id)inline_delimiter(})>content(', )delimiter(")> + ident(function) operator(<<) string<delimiter(")content(')delimiter(")> operator(+) operator(()ident(options)operator([)symbol(:update)operator(]) operator(||) string<delimiter(")inline<inline_delimiter(#{)ident(field_id)inline_delimiter(})>content(_auto_complete)delimiter(")>operator(\)) operator(+) string<delimiter(")content(', )delimiter(")> + ident(function) operator(<<) string<delimiter(")content(')inline<inline_delimiter(#{)ident(url_for)operator(()ident(options)operator([)symbol(:url)operator(])operator(\))inline_delimiter(})>content(')delimiter(")> + + ident(js_options) operator(=) operator({)operator(}) + ident(js_options)operator([)symbol(:tokens)operator(]) operator(=) ident(array_or_string_for_javascript)operator(()ident(options)operator([)symbol(:tokens)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:tokens)operator(]) + ident(js_options)operator([)symbol(:callback)operator(]) operator(=) string<delimiter(")content(function(element, value\) { return )inline<inline_delimiter(#{)ident(options)operator([)symbol(:with)operator(])inline_delimiter(})>content( })delimiter(")> reserved(if) ident(options)operator([)symbol(:with)operator(]) + ident(js_options)operator([)symbol(:indicator)operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:indicator)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:indicator)operator(]) + ident(js_options)operator([)symbol(:select)operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:select)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:select)operator(]) + ident(js_options)operator([)symbol(:frequency)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:frequency)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:frequency)operator(]) + + operator({) symbol(:after_update_element) operator(=)operator(>) symbol(:afterUpdateElement)operator(,) + symbol(:on_show) operator(=)operator(>) symbol(:onShow)operator(,) symbol(:on_hide) operator(=)operator(>) symbol(:onHide)operator(,) symbol(:min_chars) operator(=)operator(>) symbol(:minChars) operator(})operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,)ident(v)operator(|) + ident(js_options)operator([)ident(v)operator(]) operator(=) ident(options)operator([)ident(k)operator(]) reserved(if) ident(options)operator([)ident(k)operator(]) + reserved(end) + + ident(function) operator(<<) operator(()string<delimiter(')content(, )delimiter(')> operator(+) ident(options_for_javascript)operator(()ident(js_options)operator(\)) operator(+) string<delimiter(')content(\))delimiter(')>operator(\)) + + ident(javascript_tag)operator(()ident(function)operator(\)) + reserved(end) + + comment(# Use this method in your view to generate a return for the AJAX autocomplete requests.) + comment(#) + comment(# Example action:) + comment(#) + comment(# def auto_complete_for_item_title) + comment(# @items = Item.find(:all, ) + comment(# :conditions => [ 'LOWER(description\) LIKE ?', ) + comment(# '%' + request.raw_post.downcase + '%' ]\)) + comment(# render :inline => '<%= auto_complete_result(@items, 'description'\) %>') + comment(# end) + comment(#) + comment(# The auto_complete_result can of course also be called from a view belonging to the ) + comment(# auto_complete action if you need to decorate it further.) + reserved(def) method(auto_complete_result)operator(()ident(entries)operator(,) ident(field)operator(,) ident(phrase) operator(=) pre_constant(nil)operator(\)) + reserved(return) reserved(unless) ident(entries) + ident(items) operator(=) ident(entries)operator(.)ident(map) operator({) operator(|)ident(entry)operator(|) ident(content_tag)operator(()string<delimiter(")content(li)delimiter(")>operator(,) ident(phrase) operator(?) ident(highlight)operator(()ident(entry)operator([)ident(field)operator(])operator(,) ident(phrase)operator(\)) operator(:) ident(h)operator(()ident(entry)operator([)ident(field)operator(])operator(\))operator(\)) operator(}) + ident(content_tag)operator(()string<delimiter(")content(ul)delimiter(")>operator(,) ident(items)operator(.)ident(uniq)operator(\)) + reserved(end) + + comment(# Wrapper for text_field with added AJAX autocompletion functionality.) + comment(#) + comment(# In your controller, you'll need to define an action called) + comment(# auto_complete_for_object_method to respond the AJAX calls,) + comment(# ) + comment(# See the RDoc on ActionController::AutoComplete to learn more about this.) + reserved(def) method(text_field_with_auto_complete)operator(()ident(object)operator(,) ident(method)operator(,) ident(tag_options) operator(=) operator({)operator(})operator(,) ident(completion_options) operator(=) operator({)operator(})operator(\)) + operator(()ident(completion_options)operator([)symbol(:skip_style)operator(]) operator(?) string<delimiter(")delimiter(")> operator(:) ident(auto_complete_stylesheet)operator(\)) operator(+) + ident(text_field)operator(()ident(object)operator(,) ident(method)operator(,) ident(tag_options)operator(\)) operator(+) + ident(content_tag)operator(()string<delimiter(")content(div)delimiter(")>operator(,) string<delimiter(")delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(_auto_complete)delimiter(")>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(")content(auto_complete)delimiter(")>operator(\)) operator(+) + ident(auto_complete_field)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>delimiter(")>operator(,) operator({) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(auto_complete_for_)inline<inline_delimiter(#{)ident(object)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>delimiter(")> operator(}) operator(})operator(.)ident(update)operator(()ident(completion_options)operator(\))operator(\)) + reserved(end) + + ident(private) + reserved(def) method(auto_complete_stylesheet) + ident(content_tag)operator(()string<delimiter(")content(style)delimiter(")>operator(,) string<delimiter(<<-EOT)>string<content( + div.auto_complete { + width: 350px; + background: #fff; + } + div.auto_complete ul { + border:1px solid #888; + margin:0; + padding:0; + width:100%; + list-style-type:none; + } + div.auto_complete ul li { + margin:0; + padding:3px; + } + div.auto_complete ul li.selected { + background-color: #ffb; + } + div.auto_complete ul strong.highlight { + color: #800; + margin:0; + padding:0; + })delimiter( + EOT)> + operator(\)) + reserved(end) + + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tag_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides functionality for working with JavaScript in your views.) + comment(# ) + comment(# == Ajax, controls and visual effects) + comment(# ) + comment(# * For information on using Ajax, see ) + comment(# ActionView::Helpers::PrototypeHelper.) + comment(# * For information on using controls and visual effects, see) + comment(# ActionView::Helpers::ScriptaculousHelper.) + comment(#) + comment(# == Including the JavaScript libraries into your pages) + comment(#) + comment(# Rails includes the Prototype JavaScript framework and the Scriptaculous) + comment(# JavaScript controls and visual effects library. If you wish to use) + comment(# these libraries and their helpers (ActionView::Helpers::PrototypeHelper) + comment(# and ActionView::Helpers::ScriptaculousHelper\), you must do one of the) + comment(# following:) + comment(#) + comment(# * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD ) + comment(# section of your page (recommended\): This function will return ) + comment(# references to the JavaScript files created by the +rails+ command in) + comment(# your <tt>public/javascripts</tt> directory. Using it is recommended as) + comment(# the browser can then cache the libraries instead of fetching all the ) + comment(# functions anew on every request.) + comment(# * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but ) + comment(# will only include the Prototype core library, which means you are able) + comment(# to use all basic AJAX functionality. For the Scriptaculous-based ) + comment(# JavaScript helpers, like visual effects, autocompletion, drag and drop ) + comment(# and so on, you should use the method described above.) + comment(# * Use <tt><%= define_javascript_functions %></tt>: this will copy all the) + comment(# JavaScript support functions within a single script block. Not) + comment(# recommended.) + comment(#) + comment(# For documentation on +javascript_include_tag+ see ) + comment(# ActionView::Helpers::AssetTagHelper.) + reserved(module) class(JavaScriptHelper) + reserved(unless) ident(const_defined?) symbol(:JAVASCRIPT_PATH) + constant(JAVASCRIPT_PATH) operator(=) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(')content(javascripts)delimiter(')>operator(\)) + reserved(end) + + comment(# Returns a link that'll trigger a JavaScript +function+ using the ) + comment(# onclick handler and return false after the fact.) + comment(#) + comment(# Examples:) + comment(# link_to_function "Greeting", "alert('Hello world!'\)") + comment(# link_to_function(image_tag("delete"\), "if confirm('Really?'\){ do_delete(\); }"\)) + reserved(def) method(link_to_function)operator(()ident(name)operator(,) ident(function)operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + ident(html_options)operator(.)ident(symbolize_keys!) + ident(content_tag)operator(() + string<delimiter(")content(a)delimiter(")>operator(,) ident(name)operator(,) + ident(html_options)operator(.)ident(merge)operator(()operator({) + symbol(:href) operator(=)operator(>) ident(html_options)operator([)symbol(:href)operator(]) operator(||) string<delimiter(")content(#)delimiter(")>operator(,) + symbol(:onclick) operator(=)operator(>) operator(()ident(html_options)operator([)symbol(:onclick)operator(]) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(html_options)operator([)symbol(:onclick)operator(])inline_delimiter(})>content(; )delimiter(")> operator(:) string<delimiter(")delimiter(")>operator(\)) operator(+) string<delimiter(")inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(; return false;)delimiter(")> + operator(})operator(\)) + operator(\)) + reserved(end) + + comment(# Returns a link that'll trigger a JavaScript +function+ using the ) + comment(# onclick handler.) + comment(#) + comment(# Examples:) + comment(# button_to_function "Greeting", "alert('Hello world!'\)") + comment(# button_to_function "Delete", "if confirm('Really?'\){ do_delete(\); }"\)) + reserved(def) method(button_to_function)operator(()ident(name)operator(,) ident(function)operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + ident(html_options)operator(.)ident(symbolize_keys!) + ident(tag)operator(()symbol(:input)operator(,) ident(html_options)operator(.)ident(merge)operator(()operator({) + symbol(:type) operator(=)operator(>) string<delimiter(")content(button)delimiter(")>operator(,) symbol(:value) operator(=)operator(>) ident(name)operator(,) + symbol(:onclick) operator(=)operator(>) operator(()ident(html_options)operator([)symbol(:onclick)operator(]) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(html_options)operator([)symbol(:onclick)operator(])inline_delimiter(})>content(; )delimiter(")> operator(:) string<delimiter(")delimiter(")>operator(\)) operator(+) string<delimiter(")inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(;)delimiter(")> + operator(})operator(\))operator(\)) + reserved(end) + + comment(# Includes the Action Pack JavaScript libraries inside a single <script> ) + comment(# tag. The function first includes prototype.js and then its core extensions,) + comment(# (determined by filenames starting with "prototype"\).) + comment(# Afterwards, any additional scripts will be included in undefined order.) + comment(#) + comment(# Note: The recommended approach is to copy the contents of) + comment(# lib/action_view/helpers/javascripts/ into your application's) + comment(# public/javascripts/ directory, and use +javascript_include_tag+ to ) + comment(# create remote <script> links.) + reserved(def) method(define_javascript_functions) + ident(javascript) operator(=) string<delimiter(')content(<script type="text/javascript">)delimiter(')> + + comment(# load prototype.js and its extensions first ) + ident(prototype_libs) operator(=) constant(Dir)operator(.)ident(glob)operator(()constant(File)operator(.)ident(join)operator(()constant(JAVASCRIPT_PATH)operator(,) string<delimiter(')content(prototype*)delimiter(')>operator(\))operator(\))operator(.)ident(sort)operator(.)ident(reverse) + ident(prototype_libs)operator(.)ident(each) reserved(do) operator(|)ident(filename)operator(|) + ident(javascript) operator(<<) string<delimiter(")char(\\n)delimiter(")> operator(<<) constant(IO)operator(.)ident(read)operator(()ident(filename)operator(\)) + reserved(end) + + comment(# load other librairies) + operator(()constant(Dir)operator(.)ident(glob)operator(()constant(File)operator(.)ident(join)operator(()constant(JAVASCRIPT_PATH)operator(,) string<delimiter(')content(*)delimiter(')>operator(\))operator(\)) operator(-) ident(prototype_libs)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(filename)operator(|) + ident(javascript) operator(<<) string<delimiter(")char(\\n)delimiter(")> operator(<<) constant(IO)operator(.)ident(read)operator(()ident(filename)operator(\)) + reserved(end) + ident(javascript) operator(<<) string<delimiter(')content(</script>)delimiter(')> + reserved(end) + + comment(# Escape carrier returns and single and double quotes for JavaScript segments.) + reserved(def) method(escape_javascript)operator(()ident(javascript)operator(\)) + operator(()ident(javascript) operator(||) string<delimiter(')delimiter(')>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\r)char(\\n)content(|)char(\\n)content(|)char(\\r)delimiter(/)>operator(,) string<delimiter(")char(\\\\)content(n)delimiter(")>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)content(["'])delimiter(/)>operator(\)) operator({) operator(|)ident(m)operator(|) string<delimiter(")char(\\\\)inline<inline_delimiter(#{)ident(m)inline_delimiter(})>delimiter(")> operator(}) + reserved(end) + + comment(# Returns a JavaScript tag with the +content+ inside. Example:) + comment(# javascript_tag "alert('All is good'\)" # => <script type="text/javascript">alert('All is good'\)</script>) + reserved(def) method(javascript_tag)operator(()ident(content)operator(\)) + ident(content_tag)operator(()string<delimiter(")content(script)delimiter(")>operator(,) ident(javascript_cdata_section)operator(()ident(content)operator(\))operator(,) symbol(:type) operator(=)operator(>) string<delimiter(")content(text/javascript)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(javascript_cdata_section)operator(()ident(content)operator(\)) comment(#:nodoc:) + string<delimiter(")char(\\n)content(//)inline<inline_delimiter(#{)ident(cdata_section)operator(()string<delimiter(")char(\\n)inline<inline_delimiter(#{)ident(content)inline_delimiter(})>char(\\n)content(//)delimiter(")>operator(\))inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + + ident(protected) + reserved(def) method(options_for_javascript)operator(()ident(options)operator(\)) + string<delimiter(')content({)delimiter(')> operator(+) ident(options)operator(.)ident(map) operator({)operator(|)ident(k)operator(,) ident(v)operator(|) string<delimiter(")inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(v)inline_delimiter(})>delimiter(")>operator(})operator(.)ident(sort)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\)) operator(+) string<delimiter(')content(})delimiter(')> + reserved(end) + + reserved(def) method(array_or_string_for_javascript)operator(()ident(option)operator(\)) + ident(js_option) operator(=) reserved(if) ident(option)operator(.)ident(kind_of?)operator(()constant(Array)operator(\)) + string<delimiter(")content([')inline<inline_delimiter(#{)ident(option)operator(.)ident(join)operator(()string<delimiter(')char(\\')content(,)char(\\')delimiter(')>operator(\))inline_delimiter(})>content('])delimiter(")> + reserved(elsif) operator(!)ident(option)operator(.)ident(nil?) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(option)inline_delimiter(})>content(')delimiter(")> + reserved(end) + ident(js_option) + reserved(end) + reserved(end) + + constant(JavascriptHelper) operator(=) constant(JavaScriptHelper) reserved(unless) ident(const_defined?) symbol(:JavascriptHelper) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides methods for converting a number into a formatted string that currently represents) + comment(# one of the following forms: phone number, percentage, money, or precision level.) + reserved(module) class(NumberHelper) + + comment(# Formats a +number+ into a US phone number string. The +options+ can be a hash used to customize the format of the output.) + comment(# The area code can be surrounded by parentheses by setting +:area_code+ to true; default is false) + comment(# The delimiter can be set using +:delimiter+; default is "-") + comment(# Examples:) + comment(# number_to_phone(1235551234\) => 123-555-1234) + comment(# number_to_phone(1235551234, {:area_code => true}\) => (123\) 555-1234) + comment(# number_to_phone(1235551234, {:delimiter => " "}\) => 123 555 1234) + comment(# number_to_phone(1235551234, {:area_code => true, :extension => 555}\) => (123\) 555-1234 x 555) + reserved(def) method(number_to_phone)operator(()ident(number)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(stringify_keys) + ident(area_code) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(area_code)delimiter(")>operator(\)) operator({) pre_constant(false) operator(}) + ident(delimiter) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(delimiter)delimiter(")>operator(\)) operator({) string<delimiter(")content(-)delimiter(")> operator(}) + ident(extension) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(extension)delimiter(")>operator(\)) operator({) string<delimiter(")delimiter(")> operator(}) + reserved(begin) + ident(str) operator(=) ident(area_code) operator(==) pre_constant(true) operator(?) ident(number)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(([0-9]{3}\)([0-9]{3}\)([0-9]{4}\))delimiter(/)>operator(,)string<delimiter(")content(()char(\\\\)content(1\) )char(\\\\)content(2)inline<inline_delimiter(#{)ident(delimiter)inline_delimiter(})>char(\\\\)content(3)delimiter(")>operator(\)) operator(:) ident(number)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(([0-9]{3}\)([0-9]{3}\)([0-9]{4}\))delimiter(/)>operator(,)string<delimiter(")char(\\\\)content(1)inline<inline_delimiter(#{)ident(delimiter)inline_delimiter(})>char(\\\\)content(2)inline<inline_delimiter(#{)ident(delimiter)inline_delimiter(})>char(\\\\)content(3)delimiter(")>operator(\)) + ident(extension)operator(.)ident(to_s)operator(.)ident(strip)operator(.)ident(empty?) operator(?) ident(str) operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(str)inline_delimiter(})>content( x )inline<inline_delimiter(#{)ident(extension)operator(.)ident(to_s)operator(.)ident(strip)inline_delimiter(})>delimiter(")> + reserved(rescue) + ident(number) + reserved(end) + reserved(end) + + comment(# Formats a +number+ into a currency string. The +options+ hash can be used to customize the format of the output.) + comment(# The +number+ can contain a level of precision using the +precision+ key; default is 2) + comment(# The currency type can be set using the +unit+ key; default is "$") + comment(# The unit separator can be set using the +separator+ key; default is ".") + comment(# The delimiter can be set using the +delimiter+ key; default is ",") + comment(# Examples:) + comment(# number_to_currency(1234567890.50\) => $1,234,567,890.50) + comment(# number_to_currency(1234567890.506\) => $1,234,567,890.51) + comment(# number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""}\) => £1234567890,50) + reserved(def) method(number_to_currency)operator(()ident(number)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(stringify_keys) + ident(precision)operator(,) ident(unit)operator(,) ident(separator)operator(,) ident(delimiter) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(precision)delimiter(")>operator(\)) operator({) integer(2) operator(})operator(,) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(unit)delimiter(")>operator(\)) operator({) string<delimiter(")content($)delimiter(")> operator(})operator(,) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(separator)delimiter(")>operator(\)) operator({) string<delimiter(")content(.)delimiter(")> operator(})operator(,) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(delimiter)delimiter(")>operator(\)) operator({) string<delimiter(")content(,)delimiter(")> operator(}) + ident(separator) operator(=) string<delimiter(")delimiter(")> reserved(unless) ident(precision) operator(>) integer(0) + reserved(begin) + ident(parts) operator(=) ident(number_with_precision)operator(()ident(number)operator(,) ident(precision)operator(\))operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + ident(unit) operator(+) ident(number_with_delimiter)operator(()ident(parts)operator([)integer(0)operator(])operator(,) ident(delimiter)operator(\)) operator(+) ident(separator) operator(+) ident(parts)operator([)integer(1)operator(])operator(.)ident(to_s) + reserved(rescue) + ident(number) + reserved(end) + reserved(end) + + comment(# Formats a +number+ as into a percentage string. The +options+ hash can be used to customize the format of the output.) + comment(# The +number+ can contain a level of precision using the +precision+ key; default is 3) + comment(# The unit separator can be set using the +separator+ key; default is ".") + comment(# Examples:) + comment(# number_to_percentage(100\) => 100.000%) + comment(# number_to_percentage(100, {:precision => 0}\) => 100%) + comment(# number_to_percentage(302.0574, {:precision => 2}\) => 302.06%) + reserved(def) method(number_to_percentage)operator(()ident(number)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(stringify_keys) + ident(precision)operator(,) ident(separator) operator(=) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(precision)delimiter(")>operator(\)) operator({) integer(3) operator(})operator(,) ident(options)operator(.)ident(delete)operator(()string<delimiter(")content(separator)delimiter(")>operator(\)) operator({) string<delimiter(")content(.)delimiter(")> operator(}) + reserved(begin) + ident(number) operator(=) ident(number_with_precision)operator(()ident(number)operator(,) ident(precision)operator(\)) + ident(parts) operator(=) ident(number)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(if) ident(parts)operator(.)ident(at)operator(()integer(1)operator(\))operator(.)ident(nil?) + ident(parts)operator([)integer(0)operator(]) operator(+) string<delimiter(")content(%)delimiter(")> + reserved(else) + ident(parts)operator([)integer(0)operator(]) operator(+) ident(separator) operator(+) ident(parts)operator([)integer(1)operator(])operator(.)ident(to_s) operator(+) string<delimiter(")content(%)delimiter(")> + reserved(end) + reserved(rescue) + ident(number) + reserved(end) + reserved(end) + + comment(# Formats a +number+ with a +delimiter+.) + comment(# Example:) + comment(# number_with_delimiter(12345678\) => 12,345,678) + reserved(def) method(number_with_delimiter)operator(()ident(number)operator(,) ident(delimiter)operator(=)string<delimiter(")content(,)delimiter(")>operator(\)) + ident(number)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(()char(\\d)content(\)(?=()char(\\d)char(\\d)char(\\d)content(\)+(?!)char(\\d)content(\)\))delimiter(/)>operator(,) string<delimiter(")char(\\\\)content(1)inline<inline_delimiter(#{)ident(delimiter)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + comment(# Returns a formatted-for-humans file size.) + comment(# ) + comment(# Examples:) + comment(# human_size(123\) => 123 Bytes) + comment(# human_size(1234\) => 1.2 KB) + comment(# human_size(12345\) => 12.1 KB) + comment(# human_size(1234567\) => 1.2 MB) + comment(# human_size(1234567890\) => 1.1 GB) + reserved(def) method(number_to_human_size)operator(()ident(size)operator(\)) + reserved(case) + reserved(when) ident(size) operator(<) integer(1)operator(.)ident(kilobyte)operator(:) string<delimiter(')content(%d Bytes)delimiter(')> operator(%) ident(size) + reserved(when) ident(size) operator(<) integer(1)operator(.)ident(megabyte)operator(:) string<delimiter(')content(%.1f KB)delimiter(')> operator(%) operator(()ident(size) operator(/) float(1.0)operator(.)ident(kilobyte)operator(\)) + reserved(when) ident(size) operator(<) integer(1)operator(.)ident(gigabyte)operator(:) string<delimiter(')content(%.1f MB)delimiter(')> operator(%) operator(()ident(size) operator(/) float(1.0)operator(.)ident(megabyte)operator(\)) + reserved(when) ident(size) operator(<) integer(1)operator(.)ident(terabyte)operator(:) string<delimiter(')content(%.1f GB)delimiter(')> operator(%) operator(()ident(size) operator(/) float(1.0)operator(.)ident(gigabyte)operator(\)) + reserved(else) string<delimiter(')content(%.1f TB)delimiter(')> operator(%) operator(()ident(size) operator(/) float(1.0)operator(.)ident(terabyte)operator(\)) + reserved(end)operator(.)ident(sub)operator(()string<delimiter(')content(.0)delimiter(')>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(rescue) + pre_constant(nil) + reserved(end) + + ident(alias_method) symbol(:human_size)operator(,) symbol(:number_to_human_size) comment(# deprecated alias) + + comment(# Formats a +number+ with a level of +precision+.) + comment(# Example:) + comment(# number_with_precision(111.2345\) => 111.235) + reserved(def) method(number_with_precision)operator(()ident(number)operator(,) ident(precision)operator(=)integer(3)operator(\)) + ident(sprintf)operator(()string<delimiter(")content(%01.)inline<inline_delimiter(#{)ident(precision)inline_delimiter(})>content(f)delimiter(")>operator(,) ident(number)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides methods for linking to ActionController::Pagination objects.) + comment(#) + comment(# You can also build your links manually, like in this example:) + comment(#) + comment(# <%= link_to "Previous page", { :page => paginator.current.previous } if paginator.current.previous %>) + comment(#) + comment(# <%= link_to "Next page", { :page => paginator.current.next } if paginator.current.next %>) + reserved(module) class(PaginationHelper) + reserved(unless) ident(const_defined?)operator(()symbol(:DEFAULT_OPTIONS)operator(\)) + constant(DEFAULT_OPTIONS) operator(=) operator({) + symbol(:name) operator(=)operator(>) symbol(:page)operator(,) + symbol(:window_size) operator(=)operator(>) integer(2)operator(,) + symbol(:always_show_anchors) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:link_to_current_page) operator(=)operator(>) pre_constant(false)operator(,) + symbol(:params) operator(=)operator(>) operator({)operator(}) + operator(}) + reserved(end) + + comment(# Creates a basic HTML link bar for the given +paginator+.) + comment(# +html_options+ are passed to +link_to+.) + comment(#) + comment(# +options+ are:) + comment(# <tt>:name</tt>:: the routing name for this paginator) + comment(# (defaults to +page+\)) + comment(# <tt>:window_size</tt>:: the number of pages to show around ) + comment(# the current page (defaults to +2+\)) + comment(# <tt>:always_show_anchors</tt>:: whether or not the first and last) + comment(# pages should always be shown) + comment(# (defaults to +true+\)) + comment(# <tt>:link_to_current_page</tt>:: whether or not the current page) + comment(# should be linked to (defaults to) + comment(# +false+\)) + comment(# <tt>:params</tt>:: any additional routing parameters) + comment(# for page URLs) + reserved(def) method(pagination_links)operator(()ident(paginator)operator(,) ident(options)operator(=)operator({)operator(})operator(,) ident(html_options)operator(=)operator({)operator(})operator(\)) + ident(name) operator(=) ident(options)operator([)symbol(:name)operator(]) operator(||) constant(DEFAULT_OPTIONS)operator([)symbol(:name)operator(]) + ident(params) operator(=) operator(()ident(options)operator([)symbol(:params)operator(]) operator(||) constant(DEFAULT_OPTIONS)operator([)symbol(:params)operator(])operator(\))operator(.)ident(clone) + + ident(pagination_links_each)operator(()ident(paginator)operator(,) ident(options)operator(\)) reserved(do) operator(|)ident(n)operator(|) + ident(params)operator([)ident(name)operator(]) operator(=) ident(n) + ident(link_to)operator(()ident(n)operator(.)ident(to_s)operator(,) ident(params)operator(,) ident(html_options)operator(\)) + reserved(end) + reserved(end) + + comment(# Iterate through the pages of a given +paginator+, invoking a) + comment(# block for each page number that needs to be rendered as a link.) + reserved(def) method(pagination_links_each)operator(()ident(paginator)operator(,) ident(options)operator(\)) + ident(options) operator(=) constant(DEFAULT_OPTIONS)operator(.)ident(merge)operator(()ident(options)operator(\)) + ident(link_to_current_page) operator(=) ident(options)operator([)symbol(:link_to_current_page)operator(]) + ident(always_show_anchors) operator(=) ident(options)operator([)symbol(:always_show_anchors)operator(]) + + ident(current_page) operator(=) ident(paginator)operator(.)ident(current_page) + ident(window_pages) operator(=) ident(current_page)operator(.)ident(window)operator(()ident(options)operator([)symbol(:window_size)operator(])operator(\))operator(.)ident(pages) + reserved(return) reserved(if) ident(window_pages)operator(.)ident(length) operator(<=) integer(1) reserved(unless) ident(link_to_current_page) + + ident(first)operator(,) ident(last) operator(=) ident(paginator)operator(.)ident(first)operator(,) ident(paginator)operator(.)ident(last) + + ident(html) operator(=) string<delimiter(')delimiter(')> + reserved(if) ident(always_show_anchors) reserved(and) reserved(not) operator(()ident(wp_first) operator(=) ident(window_pages)operator([)integer(0)operator(])operator(\))operator(.)ident(first?) + ident(html) operator(<<) reserved(yield)operator(()ident(first)operator(.)ident(number)operator(\)) + ident(html) operator(<<) string<delimiter(')content( ... )delimiter(')> reserved(if) ident(wp_first)operator(.)ident(number) operator(-) ident(first)operator(.)ident(number) operator(>) integer(1) + ident(html) operator(<<) string<delimiter(')content( )delimiter(')> + reserved(end) + + ident(window_pages)operator(.)ident(each) reserved(do) operator(|)ident(page)operator(|) + reserved(if) ident(current_page) operator(==) ident(page) operator(&&) operator(!)ident(link_to_current_page) + ident(html) operator(<<) ident(page)operator(.)ident(number)operator(.)ident(to_s) + reserved(else) + ident(html) operator(<<) reserved(yield)operator(()ident(page)operator(.)ident(number)operator(\)) + reserved(end) + ident(html) operator(<<) string<delimiter(')content( )delimiter(')> + reserved(end) + + reserved(if) ident(always_show_anchors) reserved(and) reserved(not) operator(()ident(wp_last) operator(=) ident(window_pages)operator([)integer(-1)operator(])operator(\))operator(.)ident(last?) + ident(html) operator(<<) string<delimiter(')content( ... )delimiter(')> reserved(if) ident(last)operator(.)ident(number) operator(-) ident(wp_last)operator(.)ident(number) operator(>) integer(1) + ident(html) operator(<<) reserved(yield)operator(()ident(last)operator(.)ident(number)operator(\)) + reserved(end) + + ident(html) + reserved(end) + + reserved(end) comment(# PaginationHelper) + reserved(end) comment(# Helpers) +reserved(end) comment(# ActionView) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/javascript_helper)delimiter(')> +ident(require) string<delimiter(')content(set)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a set of helpers for calling Prototype JavaScript functions, ) + comment(# including functionality to call remote methods using ) + comment(# Ajax[http://www.adaptivepath.com/publications/essays/archives/000385.php]. ) + comment(# This means that you can call actions in your controllers without ) + comment(# reloading the page, but still update certain parts of it using ) + comment(# injections into the DOM. The common use case is having a form that adds) + comment(# a new element to a list without reloading the page.) + comment(#) + comment(# To be able to use these helpers, you must include the Prototype ) + comment(# JavaScript framework in your pages. See the documentation for ) + comment(# ActionView::Helpers::JavaScriptHelper for more information on including ) + comment(# the necessary JavaScript.) + comment(#) + comment(# See link_to_remote for documentation of options common to all Ajax) + comment(# helpers.) + comment(#) + comment(# See also ActionView::Helpers::ScriptaculousHelper for helpers which work) + comment(# with the Scriptaculous controls and visual effects library.) + comment(#) + comment(# See JavaScriptGenerator for information on updating multiple elements) + comment(# on the page in an Ajax response. ) + reserved(module) class(PrototypeHelper) + reserved(unless) ident(const_defined?) symbol(:CALLBACKS) + constant(CALLBACKS) operator(=) constant(Set)operator(.)ident(new)operator(()operator([) symbol(:uninitialized)operator(,) symbol(:loading)operator(,) symbol(:loaded)operator(,) + symbol(:interactive)operator(,) symbol(:complete)operator(,) symbol(:failure)operator(,) symbol(:success) operator(]) operator(+) + operator(()integer(100)operator(..)integer(599)operator(\))operator(.)ident(to_a)operator(\)) + constant(AJAX_OPTIONS) operator(=) constant(Set)operator(.)ident(new)operator(()operator([) symbol(:before)operator(,) symbol(:after)operator(,) symbol(:condition)operator(,) symbol(:url)operator(,) + symbol(:asynchronous)operator(,) symbol(:method)operator(,) symbol(:insertion)operator(,) symbol(:position)operator(,) + symbol(:form)operator(,) symbol(:with)operator(,) symbol(:update)operator(,) symbol(:script) operator(])operator(\))operator(.)ident(merge)operator(()constant(CALLBACKS)operator(\)) + reserved(end) + + comment(# Returns a link to a remote action defined by <tt>options[:url]</tt> ) + comment(# (using the url_for format\) that's called in the background using ) + comment(# XMLHttpRequest. The result of that request can then be inserted into a) + comment(# DOM object whose id can be specified with <tt>options[:update]</tt>. ) + comment(# Usually, the result would be a partial prepared by the controller with) + comment(# either render_partial or render_partial_collection. ) + comment(#) + comment(# Examples:) + comment(# link_to_remote "Delete this post", :update => "posts", ) + comment(# :url => { :action => "destroy", :id => post.id }) + comment(# link_to_remote(image_tag("refresh"\), :update => "emails", ) + comment(# :url => { :action => "list_emails" }\)) + comment(#) + comment(# You can also specify a hash for <tt>options[:update]</tt> to allow for) + comment(# easy redirection of output to an other DOM element if a server-side ) + comment(# error occurs:) + comment(#) + comment(# Example:) + comment(# link_to_remote "Delete this post",) + comment(# :url => { :action => "destroy", :id => post.id },) + comment(# :update => { :success => "posts", :failure => "error" }) + comment(#) + comment(# Optionally, you can use the <tt>options[:position]</tt> parameter to ) + comment(# influence how the target DOM element is updated. It must be one of ) + comment(# <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>.) + comment(#) + comment(# By default, these remote requests are processed asynchronous during ) + comment(# which various JavaScript callbacks can be triggered (for progress ) + comment(# indicators and the likes\). All callbacks get access to the ) + comment(# <tt>request</tt> object, which holds the underlying XMLHttpRequest. ) + comment(#) + comment(# To access the server response, use <tt>request.responseText</tt>, to) + comment(# find out the HTTP status, use <tt>request.status</tt>.) + comment(#) + comment(# Example:) + comment(# link_to_remote word,) + comment(# :url => { :action => "undo", :n => word_counter },) + comment(# :complete => "undoRequestCompleted(request\)") + comment(#) + comment(# The callbacks that may be specified are (in order\):) + comment(#) + comment(# <tt>:loading</tt>:: Called when the remote document is being ) + comment(# loaded with data by the browser.) + comment(# <tt>:loaded</tt>:: Called when the browser has finished loading) + comment(# the remote document.) + comment(# <tt>:interactive</tt>:: Called when the user can interact with the ) + comment(# remote document, even though it has not ) + comment(# finished loading.) + comment(# <tt>:success</tt>:: Called when the XMLHttpRequest is completed,) + comment(# and the HTTP status code is in the 2XX range.) + comment(# <tt>:failure</tt>:: Called when the XMLHttpRequest is completed,) + comment(# and the HTTP status code is not in the 2XX) + comment(# range.) + comment(# <tt>:complete</tt>:: Called when the XMLHttpRequest is complete ) + comment(# (fires after success/failure if they are ) + comment(# present\).) + comment(# ) + comment(# You can further refine <tt>:success</tt> and <tt>:failure</tt> by ) + comment(# adding additional callbacks for specific status codes.) + comment(#) + comment(# Example:) + comment(# link_to_remote word,) + comment(# :url => { :action => "action" },) + comment(# 404 => "alert('Not found...? Wrong URL...?'\)",) + comment(# :failure => "alert('HTTP Error ' + request.status + '!'\)") + comment(#) + comment(# A status code callback overrides the success/failure handlers if ) + comment(# present.) + comment(#) + comment(# If you for some reason or another need synchronous processing (that'll) + comment(# block the browser while the request is happening\), you can specify ) + comment(# <tt>options[:type] = :synchronous</tt>.) + comment(#) + comment(# You can customize further browser side call logic by passing in) + comment(# JavaScript code snippets via some optional parameters. In their order ) + comment(# of use these are:) + comment(#) + comment(# <tt>:confirm</tt>:: Adds confirmation dialog.) + comment(# <tt>:condition</tt>:: Perform remote request conditionally) + comment(# by this expression. Use this to) + comment(# describe browser-side conditions when) + comment(# request should not be initiated.) + comment(# <tt>:before</tt>:: Called before request is initiated.) + comment(# <tt>:after</tt>:: Called immediately after request was) + comment(# initiated and before <tt>:loading</tt>.) + comment(# <tt>:submit</tt>:: Specifies the DOM element ID that's used) + comment(# as the parent of the form elements. By ) + comment(# default this is the current form, but) + comment(# it could just as well be the ID of a) + comment(# table row or any other DOM element.) + reserved(def) method(link_to_remote)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + ident(link_to_function)operator(()ident(name)operator(,) ident(remote_function)operator(()ident(options)operator(\))operator(,) ident(html_options)operator(\)) + reserved(end) + + comment(# Periodically calls the specified url (<tt>options[:url]</tt>\) every ) + comment(# <tt>options[:frequency]</tt> seconds (default is 10\). Usually used to) + comment(# update a specified div (<tt>options[:update]</tt>\) with the results ) + comment(# of the remote call. The options for specifying the target with :url ) + comment(# and defining callbacks is the same as link_to_remote.) + reserved(def) method(periodically_call_remote)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(frequency) operator(=) ident(options)operator([)symbol(:frequency)operator(]) operator(||) integer(10) comment(# every ten seconds by default) + ident(code) operator(=) string<delimiter(")content(new PeriodicalExecuter(function(\) {)inline<inline_delimiter(#{)ident(remote_function)operator(()ident(options)operator(\))inline_delimiter(})>content(}, )inline<inline_delimiter(#{)ident(frequency)inline_delimiter(})>content(\))delimiter(")> + ident(javascript_tag)operator(()ident(code)operator(\)) + reserved(end) + + comment(# Returns a form tag that will submit using XMLHttpRequest in the ) + comment(# background instead of the regular reloading POST arrangement. Even ) + comment(# though it's using JavaScript to serialize the form elements, the form) + comment(# submission will work just like a regular submission as viewed by the) + comment(# receiving side (all elements available in <tt>params</tt>\). The options for ) + comment(# specifying the target with :url and defining callbacks is the same as) + comment(# link_to_remote.) + comment(#) + comment(# A "fall-through" target for browsers that doesn't do JavaScript can be) + comment(# specified with the :action/:method options on :html.) + comment(#) + comment(# Example:) + comment(# form_remote_tag :html => { :action => ) + comment(# url_for(:controller => "some", :action => "place"\) }) + comment(#) + comment(# The Hash passed to the :html key is equivalent to the options (2nd\) ) + comment(# argument in the FormTagHelper.form_tag method.) + comment(#) + comment(# By default the fall-through action is the same as the one specified in ) + comment(# the :url (and the default method is :post\).) + reserved(def) method(form_remote_tag)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator([)symbol(:form)operator(]) operator(=) pre_constant(true) + + ident(options)operator([)symbol(:html)operator(]) operator(||=) operator({)operator(}) + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:onsubmit)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(remote_function)operator(()ident(options)operator(\))inline_delimiter(})>content(; return false;)delimiter(")> + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:action)operator(]) operator(=) ident(options)operator([)symbol(:html)operator(])operator([)symbol(:action)operator(]) operator(||) ident(url_for)operator(()ident(options)operator([)symbol(:url)operator(])operator(\)) + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:method)operator(]) operator(=) ident(options)operator([)symbol(:html)operator(])operator([)symbol(:method)operator(]) operator(||) string<delimiter(")content(post)delimiter(")> + + ident(tag)operator(()string<delimiter(")content(form)delimiter(")>operator(,) ident(options)operator([)symbol(:html)operator(])operator(,) pre_constant(true)operator(\)) + reserved(end) + + comment(# Works like form_remote_tag, but uses form_for semantics.) + reserved(def) method(remote_form_for)operator(()ident(object_name)operator(,) operator(*)ident(args)operator(,) operator(&)ident(proc)operator(\)) + ident(options) operator(=) ident(args)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(args)operator(.)ident(pop) operator(:) operator({)operator(}) + ident(concat)operator(()ident(form_remote_tag)operator(()ident(options)operator(\))operator(,) ident(proc)operator(.)ident(binding)operator(\)) + ident(fields_for)operator(()ident(object_name)operator(,) operator(*)operator(()ident(args) operator(<<) ident(options)operator(\))operator(,) operator(&)ident(proc)operator(\)) + ident(concat)operator(()string<delimiter(')content(</form>)delimiter(')>operator(,) ident(proc)operator(.)ident(binding)operator(\)) + reserved(end) + ident(alias_method) symbol(:form_remote_for)operator(,) symbol(:remote_form_for) + + comment(# Returns a button input tag that will submit form using XMLHttpRequest ) + comment(# in the background instead of regular reloading POST arrangement. ) + comment(# <tt>options</tt> argument is the same as in <tt>form_remote_tag</tt>.) + reserved(def) method(submit_to_remote)operator(()ident(name)operator(,) ident(value)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator([)symbol(:with)operator(]) operator(||=) string<delimiter(')content(Form.serialize(this.form\))delimiter(')> + + ident(options)operator([)symbol(:html)operator(]) operator(||=) operator({)operator(}) + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:type)operator(]) operator(=) string<delimiter(')content(button)delimiter(')> + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:onclick)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(remote_function)operator(()ident(options)operator(\))inline_delimiter(})>content(; return false;)delimiter(")> + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:name)operator(]) operator(=) ident(name) + ident(options)operator([)symbol(:html)operator(])operator([)symbol(:value)operator(]) operator(=) ident(value) + + ident(tag)operator(()string<delimiter(")content(input)delimiter(")>operator(,) ident(options)operator([)symbol(:html)operator(])operator(,) pre_constant(false)operator(\)) + reserved(end) + + comment(# Returns a JavaScript function (or expression\) that'll update a DOM ) + comment(# element according to the options passed.) + comment(#) + comment(# * <tt>:content</tt>: The content to use for updating. Can be left out) + comment(# if using block, see example.) + comment(# * <tt>:action</tt>: Valid options are :update (assumed by default\), ) + comment(# :empty, :remove) + comment(# * <tt>:position</tt> If the :action is :update, you can optionally ) + comment(# specify one of the following positions: :before, :top, :bottom, ) + comment(# :after.) + comment(#) + comment(# Examples:) + comment(# <%= javascript_tag(update_element_function("products", ) + comment(# :position => :bottom, :content => "<p>New product!</p>"\)\) %>) + comment(#) + comment(# <% replacement_function = update_element_function("products"\) do %>) + comment(# <p>Product 1</p>) + comment(# <p>Product 2</p>) + comment(# <% end %>) + comment(# <%= javascript_tag(replacement_function\) %>) + comment(#) + comment(# This method can also be used in combination with remote method call ) + comment(# where the result is evaluated afterwards to cause multiple updates on) + comment(# a page. Example:) + comment(#) + comment(# # Calling view) + comment(# <%= form_remote_tag :url => { :action => "buy" }, ) + comment(# :complete => evaluate_remote_response %>) + comment(# all the inputs here...) + comment(#) + comment(# # Controller action) + comment(# def buy) + comment(# @product = Product.find(1\)) + comment(# end) + comment(#) + comment(# # Returning view) + comment(# <%= update_element_function() + comment(# "cart", :action => :update, :position => :bottom, ) + comment(# :content => "<p>New Product: #{@product.name}</p>"\)\) %>) + comment(# <% update_element_function("status", :binding => binding\) do %>) + comment(# You've bought a new product!) + comment(# <% end %>) + comment(#) + comment(# Notice how the second call doesn't need to be in an ERb output block) + comment(# since it uses a block and passes in the binding to render directly. ) + comment(# This trick will however only work in ERb (not Builder or other ) + comment(# template forms\).) + comment(#) + comment(# See also JavaScriptGenerator and update_page.) + reserved(def) method(update_element_function)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + ident(content) operator(=) ident(escape_javascript)operator(()ident(options)operator([)symbol(:content)operator(]) operator(||) string<delimiter(')delimiter(')>operator(\)) + ident(content) operator(=) ident(escape_javascript)operator(()ident(capture)operator(()operator(&)ident(block)operator(\))operator(\)) reserved(if) ident(block) + + ident(javascript_function) operator(=) reserved(case) operator(()ident(options)operator([)symbol(:action)operator(]) operator(||) symbol(:update)operator(\)) + reserved(when) symbol(:update) + reserved(if) ident(options)operator([)symbol(:position)operator(]) + string<delimiter(")content(new Insertion.)inline<inline_delimiter(#{)ident(options)operator([)symbol(:position)operator(])operator(.)ident(to_s)operator(.)ident(camelize)inline_delimiter(})>content((')inline<inline_delimiter(#{)ident(element_id)inline_delimiter(})>content(',')inline<inline_delimiter(#{)ident(content)inline_delimiter(})>content('\))delimiter(")> + reserved(else) + string<delimiter(")content($(')inline<inline_delimiter(#{)ident(element_id)inline_delimiter(})>content('\).innerHTML = ')inline<inline_delimiter(#{)ident(content)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(when) symbol(:empty) + string<delimiter(")content($(')inline<inline_delimiter(#{)ident(element_id)inline_delimiter(})>content('\).innerHTML = '')delimiter(")> + + reserved(when) symbol(:remove) + string<delimiter(")content(Element.remove(')inline<inline_delimiter(#{)ident(element_id)inline_delimiter(})>content('\))delimiter(")> + + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Invalid action, choose one of :update, :remove, :empty)delimiter(")> + reserved(end) + + ident(javascript_function) operator(<<) string<delimiter(")content(;)char(\\n)delimiter(")> + ident(options)operator([)symbol(:binding)operator(]) operator(?) ident(concat)operator(()ident(javascript_function)operator(,) ident(options)operator([)symbol(:binding)operator(])operator(\)) operator(:) ident(javascript_function) + reserved(end) + + comment(# Returns 'eval(request.responseText\)' which is the JavaScript function) + comment(# that form_remote_tag can call in :complete to evaluate a multiple) + comment(# update return document using update_element_function calls.) + reserved(def) method(evaluate_remote_response) + string<delimiter(")content(eval(request.responseText\))delimiter(")> + reserved(end) + + comment(# Returns the JavaScript needed for a remote function.) + comment(# Takes the same arguments as link_to_remote.) + comment(# ) + comment(# Example:) + comment(# <select id="options" onchange="<%= remote_function(:update => "options", ) + comment(# :url => { :action => :update_options }\) %>">) + comment(# <option value="0">Hello</option>) + comment(# <option value="1">World</option>) + comment(# </select>) + reserved(def) method(remote_function)operator(()ident(options)operator(\)) + ident(javascript_options) operator(=) ident(options_for_ajax)operator(()ident(options)operator(\)) + + ident(update) operator(=) string<delimiter(')delimiter(')> + reserved(if) ident(options)operator([)symbol(:update)operator(]) reserved(and) ident(options)operator([)symbol(:update)operator(])operator(.)ident(is_a?)constant(Hash) + ident(update) operator(=) operator([)operator(]) + ident(update) operator(<<) string<delimiter(")content(success:')inline<inline_delimiter(#{)ident(options)operator([)symbol(:update)operator(])operator([)symbol(:success)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:update)operator(])operator([)symbol(:success)operator(]) + ident(update) operator(<<) string<delimiter(")content(failure:')inline<inline_delimiter(#{)ident(options)operator([)symbol(:update)operator(])operator([)symbol(:failure)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:update)operator(])operator([)symbol(:failure)operator(]) + ident(update) operator(=) string<delimiter(')content({)delimiter(')> operator(+) ident(update)operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) operator(+) string<delimiter(')content(})delimiter(')> + reserved(elsif) ident(options)operator([)symbol(:update)operator(]) + ident(update) operator(<<) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:update)operator(])inline_delimiter(})>content(')delimiter(")> + reserved(end) + + ident(function) operator(=) ident(update)operator(.)ident(empty?) operator(?) + string<delimiter(")content(new Ajax.Request()delimiter(")> operator(:) + string<delimiter(")content(new Ajax.Updater()inline<inline_delimiter(#{)ident(update)inline_delimiter(})>content(, )delimiter(")> + + ident(url_options) operator(=) ident(options)operator([)symbol(:url)operator(]) + ident(url_options) operator(=) ident(url_options)operator(.)ident(merge)operator(()symbol(:escape) operator(=)operator(>) pre_constant(false)operator(\)) reserved(if) ident(url_options)operator(.)ident(is_a?) constant(Hash) + ident(function) operator(<<) string<delimiter(")content(')inline<inline_delimiter(#{)ident(url_for)operator(()ident(url_options)operator(\))inline_delimiter(})>content(')delimiter(")> + ident(function) operator(<<) string<delimiter(")content(, )inline<inline_delimiter(#{)ident(javascript_options)inline_delimiter(})>content(\))delimiter(")> + + ident(function) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:before)operator(])inline_delimiter(})>content(; )inline<inline_delimiter(#{)ident(function)inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:before)operator(]) + ident(function) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(; )inline<inline_delimiter(#{)ident(options)operator([)symbol(:after)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:after)operator(]) + ident(function) operator(=) string<delimiter(")content(if ()inline<inline_delimiter(#{)ident(options)operator([)symbol(:condition)operator(])inline_delimiter(})>content(\) { )inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(; })delimiter(")> reserved(if) ident(options)operator([)symbol(:condition)operator(]) + ident(function) operator(=) string<delimiter(")content(if (confirm(')inline<inline_delimiter(#{)ident(escape_javascript)operator(()ident(options)operator([)symbol(:confirm)operator(])operator(\))inline_delimiter(})>content('\)\) { )inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(; })delimiter(")> reserved(if) ident(options)operator([)symbol(:confirm)operator(]) + + reserved(return) ident(function) + reserved(end) + + comment(# Observes the field with the DOM ID specified by +field_id+ and makes) + comment(# an Ajax call when its contents have changed.) + comment(# ) + comment(# Required +options+ are either of:) + comment(# <tt>:url</tt>:: +url_for+-style options for the action to call) + comment(# when the field has changed.) + comment(# <tt>:function</tt>:: Instead of making a remote call to a URL, you) + comment(# can specify a function to be called instead.) + comment(# ) + comment(# Additional options are:) + comment(# <tt>:frequency</tt>:: The frequency (in seconds\) at which changes to) + comment(# this field will be detected. Not setting this) + comment(# option at all or to a value equal to or less than) + comment(# zero will use event based observation instead of) + comment(# time based observation.) + comment(# <tt>:update</tt>:: Specifies the DOM ID of the element whose ) + comment(# innerHTML should be updated with the) + comment(# XMLHttpRequest response text.) + comment(# <tt>:with</tt>:: A JavaScript expression specifying the) + comment(# parameters for the XMLHttpRequest. This defaults) + comment(# to 'value', which in the evaluated context ) + comment(# refers to the new field value. If you specify a) + comment(# string without a "=", it'll be extended to mean) + comment(# the form key that the value should be assigned to.) + comment(# So :with => "term" gives "'term'=value". If a "=" is) + comment(# present, no extension will happen.) + comment(# <tt>:on</tt>:: Specifies which event handler to observe. By default,) + comment(# it's set to "changed" for text fields and areas and) + comment(# "click" for radio buttons and checkboxes. With this,) + comment(# you can specify it instead to be "blur" or "focus" or) + comment(# any other event.) + comment(#) + comment(# Additionally, you may specify any of the options documented in) + comment(# link_to_remote.) + reserved(def) method(observe_field)operator(()ident(field_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(options)operator([)symbol(:frequency)operator(]) operator(&&) ident(options)operator([)symbol(:frequency)operator(]) operator(>) integer(0) + ident(build_observer)operator(()string<delimiter(')content(Form.Element.Observer)delimiter(')>operator(,) ident(field_id)operator(,) ident(options)operator(\)) + reserved(else) + ident(build_observer)operator(()string<delimiter(')content(Form.Element.EventObserver)delimiter(')>operator(,) ident(field_id)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + comment(# Like +observe_field+, but operates on an entire form identified by the) + comment(# DOM ID +form_id+. +options+ are the same as +observe_field+, except ) + comment(# the default value of the <tt>:with</tt> option evaluates to the) + comment(# serialized (request string\) value of the form.) + reserved(def) method(observe_form)operator(()ident(form_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(options)operator([)symbol(:frequency)operator(]) + ident(build_observer)operator(()string<delimiter(')content(Form.Observer)delimiter(')>operator(,) ident(form_id)operator(,) ident(options)operator(\)) + reserved(else) + ident(build_observer)operator(()string<delimiter(')content(Form.EventObserver)delimiter(')>operator(,) ident(form_id)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + comment(# All the methods were moved to GeneratorMethods so that ) + comment(# #include_helpers_from_context has nothing to overwrite.) + reserved(class) class(JavaScriptGenerator) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(context)operator(,) operator(&)ident(block)operator(\)) comment(#:nodoc:) + instance_variable(@context)operator(,) instance_variable(@lines) operator(=) ident(context)operator(,) operator([)operator(]) + ident(include_helpers_from_context) + instance_variable(@context)operator(.)ident(instance_exec)operator(()pre_constant(self)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(include_helpers_from_context) + instance_variable(@context)operator(.)ident(extended_by)operator(.)ident(each) reserved(do) operator(|)ident(mod)operator(|) + ident(extend) ident(mod) reserved(unless) ident(mod)operator(.)ident(name) operator(=)operator(~) regexp<delimiter(/)content(^ActionView::Helpers)delimiter(/)> + reserved(end) + ident(extend) constant(GeneratorMethods) + reserved(end) + + comment(# JavaScriptGenerator generates blocks of JavaScript code that allow you ) + comment(# to change the content and presentation of multiple DOM elements. Use ) + comment(# this in your Ajax response bodies, either in a <script> tag or as plain) + comment(# JavaScript sent with a Content-type of "text/javascript".) + comment(#) + comment(# Create new instances with PrototypeHelper#update_page or with ) + comment(# ActionController::Base#render, then call #insert_html, #replace_html, ) + comment(# #remove, #show, #hide, #visual_effect, or any other of the built-in ) + comment(# methods on the yielded generator in any order you like to modify the ) + comment(# content and appearance of the current page. ) + comment(#) + comment(# Example:) + comment(#) + comment(# update_page do |page|) + comment(# page.insert_html :bottom, 'list', "<li>#{@item.name}</li>") + comment(# page.visual_effect :highlight, 'list') + comment(# page.hide 'status-indicator', 'cancel-link') + comment(# end) + comment(# ) + comment(# generates the following JavaScript:) + comment(#) + comment(# new Insertion.Bottom("list", "<li>Some item</li>"\);) + comment(# new Effect.Highlight("list"\);) + comment(# ["status-indicator", "cancel-link"].each(Element.hide\);) + comment(#) + comment(# Helper methods can be used in conjunction with JavaScriptGenerator.) + comment(# When a helper method is called inside an update block on the +page+ ) + comment(# object, that method will also have access to a +page+ object.) + comment(# ) + comment(# Example:) + comment(#) + comment(# module ApplicationHelper) + comment(# def update_time) + comment(# page.replace_html 'time', Time.now.to_s(:db\)) + comment(# page.visual_effect :highlight, 'time') + comment(# end) + comment(# end) + comment(#) + comment(# # Controller action) + comment(# def poll) + comment(# render(:update\) { |page| page.update_time }) + comment(# end) + comment(#) + comment(# You can also use PrototypeHelper#update_page_tag instead of ) + comment(# PrototypeHelper#update_page to wrap the generated JavaScript in a) + comment(# <script> tag.) + reserved(module) class(GeneratorMethods) + reserved(def) method(to_s) comment(#:nodoc:) + ident(returning) ident(javascript) operator(=) instance_variable(@lines) operator(*) global_variable($/) reserved(do) + reserved(if) constant(ActionView)operator(::)constant(Base)operator(.)ident(debug_rjs) + ident(source) operator(=) ident(javascript)operator(.)ident(dup) + ident(javascript)operator(.)ident(replace) string<delimiter(")content(try {)char(\\n)inline<inline_delimiter(#{)ident(source)inline_delimiter(})>char(\\n)content(} catch (e\) )delimiter(")> + ident(javascript) operator(<<) string<delimiter(")content({ alert('RJS error:)char(\\\\)content(n)char(\\\\)content(n' + e.toString(\)\); alert(')inline<inline_delimiter(#{)ident(source)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\r)char(\\n)content(|)char(\\n)content(|)char(\\r)delimiter(/)>operator(,) string<delimiter(")char(\\\\)content(n)delimiter(")>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)content(["'])delimiter(/)>operator(\)) operator({) operator(|)ident(m)operator(|) string<delimiter(")char(\\\\)inline<inline_delimiter(#{)ident(m)inline_delimiter(})>delimiter(")> operator(})inline_delimiter(})>content('\); throw e })delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns a element reference by finding it through +id+ in the DOM. This element can then be) + comment(# used for further method calls. Examples:) + comment(#) + comment(# page['blank_slate'] # => $('blank_slate'\);) + comment(# page['blank_slate'].show # => $('blank_slate'\).show(\);) + comment(# page['blank_slate'].show('first'\).up # => $('blank_slate'\).show('first'\).up(\);) + reserved(def) method([])operator(()ident(id)operator(\)) + constant(JavaScriptElementProxy)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(id)operator(\)) + reserved(end) + + comment(# Returns a collection reference by finding it through a CSS +pattern+ in the DOM. This collection can then be) + comment(# used for further method calls. Examples:) + comment(#) + comment(# page.select('p'\) # => $$('p'\);) + comment(# page.select('p.welcome b'\).first # => $$('p.welcome b'\).first(\);) + comment(# page.select('p.welcome b'\).first.hide # => $$('p.welcome b'\).first(\).hide(\);) + comment(# ) + comment(# You can also use prototype enumerations with the collection. Observe:) + comment(# ) + comment(# page.select('#items li'\).each do |value|) + comment(# value.hide) + comment(# end ) + comment(# # => $$('#items li'\).each(function(value\) { value.hide(\); }\);) + comment(#) + comment(# Though you can call the block param anything you want, they are always rendered in the ) + comment(# javascript as 'value, index.' Other enumerations, like collect(\) return the last statement:) + comment(# ) + comment(# page.select('#items li'\).collect('hidden'\) do |item|) + comment(# item.hide) + comment(# end) + comment(# # => var hidden = $$('#items li'\).collect(function(value, index\) { return value.hide(\); }\);) + reserved(def) method(select)operator(()ident(pattern)operator(\)) + constant(JavaScriptElementCollectionProxy)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(pattern)operator(\)) + reserved(end) + + comment(# Inserts HTML at the specified +position+ relative to the DOM element) + comment(# identified by the given +id+.) + comment(# ) + comment(# +position+ may be one of:) + comment(# ) + comment(# <tt>:top</tt>:: HTML is inserted inside the element, before the ) + comment(# element's existing content.) + comment(# <tt>:bottom</tt>:: HTML is inserted inside the element, after the) + comment(# element's existing content.) + comment(# <tt>:before</tt>:: HTML is inserted immediately preceeding the element.) + comment(# <tt>:after</tt>:: HTML is inserted immediately following the element.) + comment(#) + comment(# +options_for_render+ may be either a string of HTML to insert, or a hash) + comment(# of options to be passed to ActionView::Base#render. For example:) + comment(#) + comment(# # Insert the rendered 'navigation' partial just before the DOM) + comment(# # element with ID 'content'.) + comment(# insert_html :before, 'content', :partial => 'navigation') + comment(#) + comment(# # Add a list item to the bottom of the <ul> with ID 'list'.) + comment(# insert_html :bottom, 'list', '<li>Last item</li>') + comment(#) + reserved(def) method(insert_html)operator(()ident(position)operator(,) ident(id)operator(,) operator(*)ident(options_for_render)operator(\)) + ident(insertion) operator(=) ident(position)operator(.)ident(to_s)operator(.)ident(camelize) + ident(call) string<delimiter(")content(new Insertion.)inline<inline_delimiter(#{)ident(insertion)inline_delimiter(})>delimiter(")>operator(,) ident(id)operator(,) ident(render)operator(()operator(*)ident(options_for_render)operator(\)) + reserved(end) + + comment(# Replaces the inner HTML of the DOM element with the given +id+.) + comment(#) + comment(# +options_for_render+ may be either a string of HTML to insert, or a hash) + comment(# of options to be passed to ActionView::Base#render. For example:) + comment(#) + comment(# # Replace the HTML of the DOM element having ID 'person-45' with the) + comment(# # 'person' partial for the appropriate object.) + comment(# replace_html 'person-45', :partial => 'person', :object => @person) + comment(#) + reserved(def) method(replace_html)operator(()ident(id)operator(,) operator(*)ident(options_for_render)operator(\)) + ident(call) string<delimiter(')content(Element.update)delimiter(')>operator(,) ident(id)operator(,) ident(render)operator(()operator(*)ident(options_for_render)operator(\)) + reserved(end) + + comment(# Replaces the "outer HTML" (i.e., the entire element, not just its) + comment(# contents\) of the DOM element with the given +id+.) + comment(#) + comment(# +options_for_render+ may be either a string of HTML to insert, or a hash) + comment(# of options to be passed to ActionView::Base#render. For example:) + comment(#) + comment(# # Replace the DOM element having ID 'person-45' with the) + comment(# # 'person' partial for the appropriate object.) + comment(# replace_html 'person-45', :partial => 'person', :object => @person) + comment(#) + comment(# This allows the same partial that is used for the +insert_html+ to) + comment(# be also used for the input to +replace+ without resorting to) + comment(# the use of wrapper elements.) + comment(#) + comment(# Examples:) + comment(#) + comment(# <div id="people">) + comment(# <%= render :partial => 'person', :collection => @people %>) + comment(# </div>) + comment(#) + comment(# # Insert a new person) + comment(# page.insert_html :bottom, :partial => 'person', :object => @person) + comment(#) + comment(# # Replace an existing person) + comment(# page.replace 'person_45', :partial => 'person', :object => @person) + comment(#) + reserved(def) method(replace)operator(()ident(id)operator(,) operator(*)ident(options_for_render)operator(\)) + ident(call) string<delimiter(')content(Element.replace)delimiter(')>operator(,) ident(id)operator(,) ident(render)operator(()operator(*)ident(options_for_render)operator(\)) + reserved(end) + + comment(# Removes the DOM elements with the given +ids+ from the page.) + reserved(def) method(remove)operator(()operator(*)ident(ids)operator(\)) + ident(record) string<delimiter(")inline<inline_delimiter(#{)ident(javascript_object_for)operator(()ident(ids)operator(\))inline_delimiter(})>content(.each(Element.remove\))delimiter(")> + reserved(end) + + comment(# Shows hidden DOM elements with the given +ids+.) + reserved(def) method(show)operator(()operator(*)ident(ids)operator(\)) + ident(call) string<delimiter(')content(Element.show)delimiter(')>operator(,) operator(*)ident(ids) + reserved(end) + + comment(# Hides the visible DOM elements with the given +ids+.) + reserved(def) method(hide)operator(()operator(*)ident(ids)operator(\)) + ident(call) string<delimiter(')content(Element.hide)delimiter(')>operator(,) operator(*)ident(ids) + reserved(end) + + comment(# Toggles the visibility of the DOM elements with the given +ids+.) + reserved(def) method(toggle)operator(()operator(*)ident(ids)operator(\)) + ident(call) string<delimiter(')content(Element.toggle)delimiter(')>operator(,) operator(*)ident(ids) + reserved(end) + + comment(# Displays an alert dialog with the given +message+.) + reserved(def) method(alert)operator(()ident(message)operator(\)) + ident(call) string<delimiter(')content(alert)delimiter(')>operator(,) ident(message) + reserved(end) + + comment(# Redirects the browser to the given +location+, in the same form as) + comment(# +url_for+.) + reserved(def) method(redirect_to)operator(()ident(location)operator(\)) + ident(assign) string<delimiter(')content(window.location.href)delimiter(')>operator(,) instance_variable(@context)operator(.)ident(url_for)operator(()ident(location)operator(\)) + reserved(end) + + comment(# Calls the JavaScript +function+, optionally with the given ) + comment(# +arguments+.) + reserved(def) method(call)operator(()ident(function)operator(,) operator(*)ident(arguments)operator(\)) + ident(record) string<delimiter(")inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(arguments_for_call)operator(()ident(arguments)operator(\))inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + comment(# Assigns the JavaScript +variable+ the given +value+.) + reserved(def) method(assign)operator(()ident(variable)operator(,) ident(value)operator(\)) + ident(record) string<delimiter(")inline<inline_delimiter(#{)ident(variable)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(javascript_object_for)operator(()ident(value)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Writes raw JavaScript to the page.) + reserved(def) method(<<)operator(()ident(javascript)operator(\)) + instance_variable(@lines) operator(<<) ident(javascript) + reserved(end) + + comment(# Executes the content of the block after a delay of +seconds+. Example:) + comment(#) + comment(# page.delay(20\) do) + comment(# page.visual_effect :fade, 'notice') + comment(# end) + reserved(def) method(delay)operator(()ident(seconds) operator(=) integer(1)operator(\)) + ident(record) string<delimiter(")content(setTimeout(function(\) {)char(\\n)char(\\n)delimiter(")> + reserved(yield) + ident(record) string<delimiter(")content(}, )inline<inline_delimiter(#{)operator(()ident(seconds) operator(*) integer(1000)operator(\))operator(.)ident(to_i)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + comment(# Starts a script.aculo.us visual effect. See ) + comment(# ActionView::Helpers::ScriptaculousHelper for more information.) + reserved(def) method(visual_effect)operator(()ident(name)operator(,) ident(id) operator(=) pre_constant(nil)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(record) instance_variable(@context)operator(.)ident(send)operator(()symbol(:visual_effect)operator(,) ident(name)operator(,) ident(id)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Creates a script.aculo.us sortable element. Useful) + comment(# to recreate sortable elements after items get added) + comment(# or deleted.) + comment(# See ActionView::Helpers::ScriptaculousHelper for more information.) + reserved(def) method(sortable)operator(()ident(id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(record) instance_variable(@context)operator(.)ident(send)operator(()symbol(:sortable_element_js)operator(,) ident(id)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Creates a script.aculo.us draggable element.) + comment(# See ActionView::Helpers::ScriptaculousHelper for more information.) + reserved(def) method(draggable)operator(()ident(id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(record) instance_variable(@context)operator(.)ident(send)operator(()symbol(:draggable_element_js)operator(,) ident(id)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Creates a script.aculo.us drop receiving element.) + comment(# See ActionView::Helpers::ScriptaculousHelper for more information.) + reserved(def) method(drop_receiving)operator(()ident(id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(record) instance_variable(@context)operator(.)ident(send)operator(()symbol(:drop_receiving_element_js)operator(,) ident(id)operator(,) ident(options)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(page) + pre_constant(self) + reserved(end) + + reserved(def) method(record)operator(()ident(line)operator(\)) + ident(returning) ident(line) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(line)operator(.)ident(to_s)operator(.)ident(chomp)operator(.)ident(gsub) regexp<delimiter(/)char(\\;)content($)delimiter(/)>operator(,) string<delimiter(')delimiter(')>inline_delimiter(})>content(;)delimiter(")> reserved(do) + pre_constant(self) operator(<<) ident(line) + reserved(end) + reserved(end) + + reserved(def) method(render)operator(()operator(*)ident(options_for_render)operator(\)) + constant(Hash) operator(===) ident(options_for_render)operator(.)ident(first) operator(?) + instance_variable(@context)operator(.)ident(render)operator(()operator(*)ident(options_for_render)operator(\)) operator(:) + ident(options_for_render)operator(.)ident(first)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(javascript_object_for)operator(()ident(object)operator(\)) + ident(object)operator(.)ident(respond_to?)operator(()symbol(:to_json)operator(\)) operator(?) ident(object)operator(.)ident(to_json) operator(:) ident(object)operator(.)ident(inspect) + reserved(end) + + reserved(def) method(arguments_for_call)operator(()ident(arguments)operator(\)) + ident(arguments)operator(.)ident(map) operator({) operator(|)ident(argument)operator(|) ident(javascript_object_for)operator(()ident(argument)operator(\)) operator(})operator(.)ident(join) string<delimiter(')content(, )delimiter(')> + reserved(end) + + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(\)) + constant(JavaScriptProxy)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(method)operator(.)ident(to_s)operator(.)ident(camelize)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Yields a JavaScriptGenerator and returns the generated JavaScript code.) + comment(# Use this to update multiple elements on a page in an Ajax response.) + comment(# See JavaScriptGenerator for more information.) + reserved(def) method(update_page)operator(()operator(&)ident(block)operator(\)) + constant(JavaScriptGenerator)operator(.)ident(new)operator(()instance_variable(@template)operator(,) operator(&)ident(block)operator(\))operator(.)ident(to_s) + reserved(end) + + comment(# Works like update_page but wraps the generated JavaScript in a <script>) + comment(# tag. Use this to include generated JavaScript in an ERb template.) + comment(# See JavaScriptGenerator for more information.) + reserved(def) method(update_page_tag)operator(()operator(&)ident(block)operator(\)) + ident(javascript_tag) ident(update_page)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + ident(protected) + reserved(def) method(options_for_ajax)operator(()ident(options)operator(\)) + ident(js_options) operator(=) ident(build_callbacks)operator(()ident(options)operator(\)) + + ident(js_options)operator([)string<delimiter(')content(asynchronous)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:type)operator(]) operator(!=) symbol(:synchronous) + ident(js_options)operator([)string<delimiter(')content(method)delimiter(')>operator(]) operator(=) ident(method_option_to_s)operator(()ident(options)operator([)symbol(:method)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:method)operator(]) + ident(js_options)operator([)string<delimiter(')content(insertion)delimiter(')>operator(]) operator(=) string<delimiter(")content(Insertion.)inline<inline_delimiter(#{)ident(options)operator([)symbol(:position)operator(])operator(.)ident(to_s)operator(.)ident(camelize)inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:position)operator(]) + ident(js_options)operator([)string<delimiter(')content(evalScripts)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:script)operator(])operator(.)ident(nil?) operator(||) ident(options)operator([)symbol(:script)operator(]) + + reserved(if) ident(options)operator([)symbol(:form)operator(]) + ident(js_options)operator([)string<delimiter(')content(parameters)delimiter(')>operator(]) operator(=) string<delimiter(')content(Form.serialize(this\))delimiter(')> + reserved(elsif) ident(options)operator([)symbol(:submit)operator(]) + ident(js_options)operator([)string<delimiter(')content(parameters)delimiter(')>operator(]) operator(=) string<delimiter(")content(Form.serialize(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:submit)operator(])inline_delimiter(})>content('\))delimiter(")> + reserved(elsif) ident(options)operator([)symbol(:with)operator(]) + ident(js_options)operator([)string<delimiter(')content(parameters)delimiter(')>operator(]) operator(=) ident(options)operator([)symbol(:with)operator(]) + reserved(end) + + ident(options_for_javascript)operator(()ident(js_options)operator(\)) + reserved(end) + + reserved(def) method(method_option_to_s)operator(()ident(method)operator(\)) + operator(()ident(method)operator(.)ident(is_a?)operator(()constant(String)operator(\)) reserved(and) operator(!)ident(method)operator(.)ident(index)operator(()string<delimiter(")content(')delimiter(")>operator(\))operator(.)ident(nil?)operator(\)) operator(?) ident(method) operator(:) string<delimiter(")content(')inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(def) method(build_observer)operator(()ident(klass)operator(,) ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(options)operator([)symbol(:with)operator(]) operator(&&) operator(!)ident(options)operator([)symbol(:with)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(=)delimiter(")>operator(\)) + ident(options)operator([)symbol(:with)operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:with)operator(])inline_delimiter(})>content(=' + value)delimiter(")> + reserved(else) + ident(options)operator([)symbol(:with)operator(]) operator(||=) string<delimiter(')content(value)delimiter(')> reserved(if) ident(options)operator([)symbol(:update)operator(]) + reserved(end) + + ident(callback) operator(=) ident(options)operator([)symbol(:function)operator(]) operator(||) ident(remote_function)operator(()ident(options)operator(\)) + ident(javascript) operator(=) string<delimiter(")content(new )inline<inline_delimiter(#{)ident(klass)inline_delimiter(})>content((')inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(', )delimiter(")> + ident(javascript) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:frequency)operator(])inline_delimiter(})>content(, )delimiter(")> reserved(if) ident(options)operator([)symbol(:frequency)operator(]) + ident(javascript) operator(<<) string<delimiter(")content(function(element, value\) {)delimiter(")> + ident(javascript) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(callback)inline_delimiter(})>content(})delimiter(")> + ident(javascript) operator(<<) string<delimiter(")content(, ')inline<inline_delimiter(#{)ident(options)operator([)symbol(:on)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:on)operator(]) + ident(javascript) operator(<<) string<delimiter(")content(\))delimiter(")> + ident(javascript_tag)operator(()ident(javascript)operator(\)) + reserved(end) + + reserved(def) method(build_callbacks)operator(()ident(options)operator(\)) + ident(callbacks) operator(=) operator({)operator(}) + ident(options)operator(.)ident(each) reserved(do) operator(|)ident(callback)operator(,) ident(code)operator(|) + reserved(if) constant(CALLBACKS)operator(.)ident(include?)operator(()ident(callback)operator(\)) + ident(name) operator(=) string<delimiter(')content(on)delimiter(')> operator(+) ident(callback)operator(.)ident(to_s)operator(.)ident(capitalize) + ident(callbacks)operator([)ident(name)operator(]) operator(=) string<delimiter(")content(function(request\){)inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content(})delimiter(")> + reserved(end) + reserved(end) + ident(callbacks) + reserved(end) + reserved(end) + + comment(# Converts chained method calls on DOM proxy elements into JavaScript chains ) + reserved(class) class(JavaScriptProxy) operator(<) constant(Builder)operator(::)constant(BlankSlate) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(generator)operator(,) ident(root) operator(=) pre_constant(nil)operator(\)) + instance_variable(@generator) operator(=) ident(generator) + instance_variable(@generator) operator(<<) ident(root) reserved(if) ident(root) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(\)) + reserved(if) ident(method)operator(.)ident(to_s) operator(=)operator(~) regexp<delimiter(/)content((.*\)=$)delimiter(/)> + ident(assign)operator(()global_variable($1)operator(,) ident(arguments)operator(.)ident(first)operator(\)) + reserved(else) + ident(call)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(method)operator(.)ident(to_s)operator(.)ident(camelize)operator(()symbol(:lower)operator(\))inline_delimiter(})>delimiter(")>operator(,) operator(*)ident(arguments)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(call)operator(()ident(function)operator(,) operator(*)ident(arguments)operator(\)) + ident(append_to_function_chain!)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(function)inline_delimiter(})>content(()inline<inline_delimiter(#{)instance_variable(@generator)operator(.)ident(send)operator(()symbol(:arguments_for_call)operator(,) ident(arguments)operator(\))inline_delimiter(})>content(\))delimiter(")>operator(\)) + pre_constant(self) + reserved(end) + + reserved(def) method(assign)operator(()ident(variable)operator(,) ident(value)operator(\)) + ident(append_to_function_chain!)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(variable)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@generator)operator(.)ident(send)operator(()symbol(:javascript_object_for)operator(,) ident(value)operator(\))inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(function_chain) + instance_variable(@function_chain) operator(||=) instance_variable(@generator)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@lines)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(append_to_function_chain!)operator(()ident(call)operator(\)) + ident(function_chain)operator([)integer(-1)operator(])operator(.)ident(chomp!)operator(()string<delimiter(')content(;)delimiter(')>operator(\)) + ident(function_chain)operator([)integer(-1)operator(]) operator(+=) string<delimiter(")content(.)inline<inline_delimiter(#{)ident(call)inline_delimiter(})>content(;)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(JavaScriptElementProxy) operator(<) constant(JavaScriptProxy) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(generator)operator(,) ident(id)operator(\)) + instance_variable(@id) operator(=) ident(id) + reserved(super)operator(()ident(generator)operator(,) string<delimiter(")content($()inline<inline_delimiter(#{)ident(id)operator(.)ident(to_json)inline_delimiter(})>content(\))delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(replace_html)operator(()operator(*)ident(options_for_render)operator(\)) + ident(call) string<delimiter(')content(update)delimiter(')>operator(,) instance_variable(@generator)operator(.)ident(send)operator(()symbol(:render)operator(,) operator(*)ident(options_for_render)operator(\)) + reserved(end) + + reserved(def) method(replace)operator(()operator(*)ident(options_for_render)operator(\)) + ident(call) string<delimiter(')content(replace)delimiter(')>operator(,) instance_variable(@generator)operator(.)ident(send)operator(()symbol(:render)operator(,) operator(*)ident(options_for_render)operator(\)) + reserved(end) + + reserved(def) method(reload) + ident(replace) symbol(:partial) operator(=)operator(>) instance_variable(@id)operator(.)ident(to_s) + reserved(end) + + reserved(end) + + reserved(class) class(JavaScriptVariableProxy) operator(<) constant(JavaScriptProxy) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(generator)operator(,) ident(variable)operator(\)) + instance_variable(@variable) operator(=) ident(variable) + instance_variable(@empty) operator(=) pre_constant(true) comment(# only record lines if we have to. gets rid of unnecessary linebreaks) + reserved(super)operator(()ident(generator)operator(\)) + reserved(end) + + comment(# The JSON Encoder calls this to check for the #to_json method) + comment(# Since it's a blank slate object, I suppose it responds to anything.) + reserved(def) method(respond_to?)operator(()ident(method)operator(\)) + pre_constant(true) + reserved(end) + + reserved(def) method(to_json) + instance_variable(@variable) + reserved(end) + + ident(private) + reserved(def) method(append_to_function_chain!)operator(()ident(call)operator(\)) + instance_variable(@generator) operator(<<) instance_variable(@variable) reserved(if) instance_variable(@empty) + instance_variable(@empty) operator(=) pre_constant(false) + reserved(super) + reserved(end) + reserved(end) + + reserved(class) class(JavaScriptCollectionProxy) operator(<) constant(JavaScriptProxy) comment(#:nodoc:) + constant(ENUMERABLE_METHODS_WITH_RETURN) operator(=) operator([)symbol(:all)operator(,) symbol(:any)operator(,) symbol(:collect)operator(,) symbol(:map)operator(,) symbol(:detect)operator(,) symbol(:find)operator(,) symbol(:find_all)operator(,) symbol(:select)operator(,) symbol(:max)operator(,) symbol(:min)operator(,) symbol(:partition)operator(,) symbol(:reject)operator(,) symbol(:sort_by)operator(]) + constant(ENUMERABLE_METHODS) operator(=) constant(ENUMERABLE_METHODS_WITH_RETURN) operator(+) operator([)symbol(:each)operator(]) + ident(attr_reader) symbol(:generator) + ident(delegate) symbol(:arguments_for_call)operator(,) symbol(:to) operator(=)operator(>) symbol(:generator) + + reserved(def) method(initialize)operator(()ident(generator)operator(,) ident(pattern)operator(\)) + reserved(super)operator(()ident(generator)operator(,) instance_variable(@pattern) operator(=) ident(pattern)operator(\)) + reserved(end) + + reserved(def) method(grep)operator(()ident(variable)operator(,) ident(pattern)operator(,) operator(&)ident(block)operator(\)) + ident(enumerate) symbol(:grep)operator(,) symbol(:variable) operator(=)operator(>) ident(variable)operator(,) symbol(:return) operator(=)operator(>) pre_constant(true)operator(,) symbol(:method_args) operator(=)operator(>) operator([)ident(pattern)operator(])operator(,) symbol(:yield_args) operator(=)operator(>) string<delimiter(%w()content(value index)delimiter(\))>operator(,) operator(&)ident(block) + reserved(end) + + reserved(def) method(inject)operator(()ident(variable)operator(,) ident(memo)operator(,) operator(&)ident(block)operator(\)) + ident(enumerate) symbol(:inject)operator(,) symbol(:variable) operator(=)operator(>) ident(variable)operator(,) symbol(:method_args) operator(=)operator(>) operator([)ident(memo)operator(])operator(,) symbol(:yield_args) operator(=)operator(>) string<delimiter(%w()content(memo value index)delimiter(\))>operator(,) symbol(:return) operator(=)operator(>) pre_constant(true)operator(,) operator(&)ident(block) + reserved(end) + + reserved(def) method(pluck)operator(()ident(variable)operator(,) ident(property)operator(\)) + ident(add_variable_assignment!)operator(()ident(variable)operator(\)) + ident(append_enumerable_function!)operator(()string<delimiter(")content(pluck()inline<inline_delimiter(#{)ident(property)operator(.)ident(to_json)inline_delimiter(})>content(\);)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(zip)operator(()ident(variable)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + ident(add_variable_assignment!)operator(()ident(variable)operator(\)) + ident(append_enumerable_function!)operator(()string<delimiter(")content(zip()inline<inline_delimiter(#{)ident(arguments_for_call) ident(arguments)inline_delimiter(})>delimiter(")>operator(\)) + reserved(if) ident(block) + ident(function_chain)operator([)integer(-1)operator(]) operator(+=) string<delimiter(")content(, function(array\) {)delimiter(")> + reserved(yield) constant(ActiveSupport)operator(::)constant(JSON)operator(::)constant(Variable)operator(.)ident(new)operator(()string<delimiter(')content(array)delimiter(')>operator(\)) + ident(add_return_statement!) + instance_variable(@generator) operator(<<) string<delimiter(')content(}\);)delimiter(')> + reserved(else) + ident(function_chain)operator([)integer(-1)operator(]) operator(+=) string<delimiter(')content(\);)delimiter(')> + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + reserved(if) constant(ENUMERABLE_METHODS)operator(.)ident(include?)operator(()ident(method)operator(\)) + ident(returnable) operator(=) constant(ENUMERABLE_METHODS_WITH_RETURN)operator(.)ident(include?)operator(()ident(method)operator(\)) + ident(variable) operator(=) ident(arguments)operator(.)ident(first) reserved(if) ident(returnable) + ident(enumerate)operator(()ident(method)operator(,) operator({)symbol(:variable) operator(=)operator(>) operator(()ident(arguments)operator(.)ident(first) reserved(if) ident(returnable)operator(\))operator(,) symbol(:return) operator(=)operator(>) ident(returnable)operator(,) symbol(:yield_args) operator(=)operator(>) string<delimiter(%w()content(value index)delimiter(\))>operator(})operator(,) operator(&)ident(block)operator(\)) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + comment(# Options) + comment(# * variable - name of the variable to set the result of the enumeration to) + comment(# * method_args - array of the javascript enumeration method args that occur before the function) + comment(# * yield_args - array of the javascript yield args) + comment(# * return - true if the enumeration should return the last statement) + reserved(def) method(enumerate)operator(()ident(enumerable)operator(,) ident(options) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + ident(options)operator([)symbol(:method_args)operator(]) operator(||=) operator([)operator(]) + ident(options)operator([)symbol(:yield_args)operator(]) operator(||=) operator([)operator(]) + ident(yield_args) operator(=) ident(options)operator([)symbol(:yield_args)operator(]) operator(*) string<delimiter(')content(, )delimiter(')> + ident(method_args) operator(=) ident(arguments_for_call) ident(options)operator([)symbol(:method_args)operator(]) comment(# foo, bar, function) + ident(method_args) operator(<<) string<delimiter(')content(, )delimiter(')> reserved(unless) ident(method_args)operator(.)ident(blank?) + ident(add_variable_assignment!)operator(()ident(options)operator([)symbol(:variable)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:variable)operator(]) + ident(append_enumerable_function!)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(enumerable)operator(.)ident(to_s)operator(.)ident(camelize)operator(()symbol(:lower)operator(\))inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(method_args)inline_delimiter(})>content(function()inline<inline_delimiter(#{)ident(yield_args)inline_delimiter(})>content(\) {)delimiter(")>operator(\)) + comment(# only yield as many params as were passed in the block) + reserved(yield) operator(*)ident(options)operator([)symbol(:yield_args)operator(])operator(.)ident(collect) operator({) operator(|)ident(p)operator(|) constant(JavaScriptVariableProxy)operator(.)ident(new)operator(()instance_variable(@generator)operator(,) ident(p)operator(\)) operator(})operator([)integer(0)operator(..)ident(block)operator(.)ident(arity)operator(-)integer(1)operator(]) + ident(add_return_statement!) reserved(if) ident(options)operator([)symbol(:return)operator(]) + instance_variable(@generator) operator(<<) string<delimiter(')content(}\);)delimiter(')> + reserved(end) + + reserved(def) method(add_variable_assignment!)operator(()ident(variable)operator(\)) + ident(function_chain)operator(.)ident(push)operator(()string<delimiter(")content(var )inline<inline_delimiter(#{)ident(variable)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(function_chain)operator(.)ident(pop)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(add_return_statement!) + reserved(unless) ident(function_chain)operator(.)ident(last) operator(=)operator(~) regexp<delimiter(/)content(return)delimiter(/)> + ident(function_chain)operator(.)ident(push)operator(()string<delimiter(")content(return )inline<inline_delimiter(#{)ident(function_chain)operator(.)ident(pop)operator(.)ident(chomp)operator(()string<delimiter(')content(;)delimiter(')>operator(\))inline_delimiter(})>content(;)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(append_enumerable_function!)operator(()ident(call)operator(\)) + ident(function_chain)operator([)integer(-1)operator(])operator(.)ident(chomp!)operator(()string<delimiter(')content(;)delimiter(')>operator(\)) + ident(function_chain)operator([)integer(-1)operator(]) operator(+=) string<delimiter(")content(.)inline<inline_delimiter(#{)ident(call)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(JavaScriptElementCollectionProxy) operator(<) constant(JavaScriptCollectionProxy) comment(#:nodoc:\\) + reserved(def) method(initialize)operator(()ident(generator)operator(,) ident(pattern)operator(\)) + reserved(super)operator(()ident(generator)operator(,) string<delimiter(")content($$()inline<inline_delimiter(#{)ident(pattern)operator(.)ident(to_json)inline_delimiter(})>content(\))delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/javascript_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a set of helpers for calling Scriptaculous JavaScript ) + comment(# functions, including those which create Ajax controls and visual effects.) + comment(#) + comment(# To be able to use these helpers, you must include the Prototype ) + comment(# JavaScript framework and the Scriptaculous JavaScript library in your ) + comment(# pages. See the documentation for ActionView::Helpers::JavaScriptHelper) + comment(# for more information on including the necessary JavaScript.) + comment(#) + comment(# The Scriptaculous helpers' behavior can be tweaked with various options.) + comment(# See the documentation at http://script.aculo.us for more information on) + comment(# using these helpers in your application.) + reserved(module) class(ScriptaculousHelper) + reserved(unless) ident(const_defined?) symbol(:TOGGLE_EFFECTS) + constant(TOGGLE_EFFECTS) operator(=) operator([)symbol(:toggle_appear)operator(,) symbol(:toggle_slide)operator(,) symbol(:toggle_blind)operator(]) + reserved(end) + + comment(# Returns a JavaScript snippet to be used on the Ajax callbacks for) + comment(# starting visual effects.) + comment(#) + comment(# Example:) + comment(# <%= link_to_remote "Reload", :update => "posts", ) + comment(# :url => { :action => "reload" }, ) + comment(# :complete => visual_effect(:highlight, "posts", :duration => 0.5\)) + comment(#) + comment(# If no element_id is given, it assumes "element" which should be a local) + comment(# variable in the generated JavaScript execution context. This can be ) + comment(# used for example with drop_receiving_element:) + comment(#) + comment(# <%= drop_receving_element (...\), :loading => visual_effect(:fade\) %>) + comment(#) + comment(# This would fade the element that was dropped on the drop receiving ) + comment(# element.) + comment(#) + comment(# For toggling visual effects, you can use :toggle_appear, :toggle_slide, and) + comment(# :toggle_blind which will alternate between appear/fade, slidedown/slideup, and) + comment(# blinddown/blindup respectively.) + comment(#) + comment(# You can change the behaviour with various options, see) + comment(# http://script.aculo.us for more documentation.) + reserved(def) method(visual_effect)operator(()ident(name)operator(,) ident(element_id) operator(=) pre_constant(false)operator(,) ident(js_options) operator(=) operator({)operator(})operator(\)) + ident(element) operator(=) ident(element_id) operator(?) ident(element_id)operator(.)ident(to_json) operator(:) string<delimiter(")content(element)delimiter(")> + + ident(js_options)operator([)symbol(:queue)operator(]) operator(=) reserved(if) ident(js_options)operator([)symbol(:queue)operator(])operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + string<delimiter(')content({)delimiter(')> operator(+) ident(js_options)operator([)symbol(:queue)operator(])operator(.)ident(map) operator({)operator(|)ident(k)operator(,) ident(v)operator(|) ident(k) operator(==) symbol(:limit) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(v)inline_delimiter(})>delimiter(")> operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content(:')inline<inline_delimiter(#{)ident(v)inline_delimiter(})>content(')delimiter(")> operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) operator(+) string<delimiter(')content(})delimiter(')> + reserved(elsif) ident(js_options)operator([)symbol(:queue)operator(]) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(js_options)operator([)symbol(:queue)operator(])inline_delimiter(})>content(')delimiter(")> + reserved(end) reserved(if) ident(js_options)operator([)symbol(:queue)operator(]) + + reserved(if) constant(TOGGLE_EFFECTS)operator(.)ident(include?) ident(name)operator(.)ident(to_sym) + string<delimiter(")content(Effect.toggle()inline<inline_delimiter(#{)ident(element)inline_delimiter(})>content(,')inline<inline_delimiter(#{)ident(name)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(^toggle_)delimiter(/)>operator(,)string<delimiter(')delimiter(')>operator(\))inline_delimiter(})>content(',)inline<inline_delimiter(#{)ident(options_for_javascript)operator(()ident(js_options)operator(\))inline_delimiter(})>content(\);)delimiter(")> + reserved(else) + string<delimiter(")content(new Effect.)inline<inline_delimiter(#{)ident(name)operator(.)ident(to_s)operator(.)ident(camelize)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(element)inline_delimiter(})>content(,)inline<inline_delimiter(#{)ident(options_for_javascript)operator(()ident(js_options)operator(\))inline_delimiter(})>content(\);)delimiter(")> + reserved(end) + reserved(end) + + comment(# Makes the element with the DOM ID specified by +element_id+ sortable) + comment(# by drag-and-drop and make an Ajax call whenever the sort order has) + comment(# changed. By default, the action called gets the serialized sortable) + comment(# element as parameters.) + comment(#) + comment(# Example:) + comment(# <%= sortable_element("my_list", :url => { :action => "order" }\) %>) + comment(#) + comment(# In the example, the action gets a "my_list" array parameter ) + comment(# containing the values of the ids of elements the sortable consists ) + comment(# of, in the current order.) + comment(#) + comment(# You can change the behaviour with various options, see) + comment(# http://script.aculo.us for more documentation.) + reserved(def) method(sortable_element)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(javascript_tag)operator(()ident(sortable_element_js)operator(()ident(element_id)operator(,) ident(options)operator(\))operator(.)ident(chop!)operator(\)) + reserved(end) + + reserved(def) method(sortable_element_js)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(options)operator([)symbol(:with)operator(]) operator(||=) string<delimiter(")content(Sortable.serialize()inline<inline_delimiter(#{)ident(element_id)operator(.)ident(to_json)inline_delimiter(})>content(\))delimiter(")> + ident(options)operator([)symbol(:onUpdate)operator(]) operator(||=) string<delimiter(")content(function(\){)delimiter(")> operator(+) ident(remote_function)operator(()ident(options)operator(\)) operator(+) string<delimiter(")content(})delimiter(")> + ident(options)operator(.)ident(delete_if) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) constant(PrototypeHelper)operator(::)constant(AJAX_OPTIONS)operator(.)ident(include?)operator(()ident(key)operator(\)) operator(}) + + operator([)symbol(:tag)operator(,) symbol(:overlap)operator(,) symbol(:constraint)operator(,) symbol(:handle)operator(])operator(.)ident(each) reserved(do) operator(|)ident(option)operator(|) + ident(options)operator([)ident(option)operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)ident(option)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)ident(option)operator(]) + reserved(end) + + ident(options)operator([)symbol(:containment)operator(]) operator(=) ident(array_or_string_for_javascript)operator(()ident(options)operator([)symbol(:containment)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:containment)operator(]) + ident(options)operator([)symbol(:only)operator(]) operator(=) ident(array_or_string_for_javascript)operator(()ident(options)operator([)symbol(:only)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:only)operator(]) + + string<delimiter(%()content(Sortable.create)nesting_delimiter(()inline<inline_delimiter(#{)ident(element_id)operator(.)ident(to_json)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(options_for_javascript)operator(()ident(options)operator(\))inline_delimiter(})>nesting_delimiter(\))content(;)delimiter(\))> + reserved(end) + + comment(# Makes the element with the DOM ID specified by +element_id+ draggable.) + comment(#) + comment(# Example:) + comment(# <%= draggable_element("my_image", :revert => true\)) + comment(# ) + comment(# You can change the behaviour with various options, see) + comment(# http://script.aculo.us for more documentation.) + reserved(def) method(draggable_element)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(javascript_tag)operator(()ident(draggable_element_js)operator(()ident(element_id)operator(,) ident(options)operator(\))operator(.)ident(chop!)operator(\)) + reserved(end) + + reserved(def) method(draggable_element_js)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + string<delimiter(%()content(new Draggable)nesting_delimiter(()inline<inline_delimiter(#{)ident(element_id)operator(.)ident(to_json)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(options_for_javascript)operator(()ident(options)operator(\))inline_delimiter(})>nesting_delimiter(\))content(;)delimiter(\))> + reserved(end) + + comment(# Makes the element with the DOM ID specified by +element_id+ receive) + comment(# dropped draggable elements (created by draggable_element\).) + comment(# and make an AJAX call By default, the action called gets the DOM ID ) + comment(# of the element as parameter.) + comment(#) + comment(# Example:) + comment(# <%= drop_receiving_element("my_cart", :url => ) + comment(# { :controller => "cart", :action => "add" }\) %>) + comment(#) + comment(# You can change the behaviour with various options, see) + comment(# http://script.aculo.us for more documentation.) + reserved(def) method(drop_receiving_element)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(javascript_tag)operator(()ident(drop_receiving_element_js)operator(()ident(element_id)operator(,) ident(options)operator(\))operator(.)ident(chop!)operator(\)) + reserved(end) + + reserved(def) method(drop_receiving_element_js)operator(()ident(element_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(options)operator([)symbol(:with)operator(]) operator(||=) string<delimiter(")content('id=' + encodeURIComponent(element.id\))delimiter(")> + ident(options)operator([)symbol(:onDrop)operator(]) operator(||=) string<delimiter(")content(function(element\){)delimiter(")> operator(+) ident(remote_function)operator(()ident(options)operator(\)) operator(+) string<delimiter(")content(})delimiter(")> + ident(options)operator(.)ident(delete_if) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) constant(PrototypeHelper)operator(::)constant(AJAX_OPTIONS)operator(.)ident(include?)operator(()ident(key)operator(\)) operator(}) + + ident(options)operator([)symbol(:accept)operator(]) operator(=) ident(array_or_string_for_javascript)operator(()ident(options)operator([)symbol(:accept)operator(])operator(\)) reserved(if) ident(options)operator([)symbol(:accept)operator(]) + ident(options)operator([)symbol(:hoverclass)operator(]) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(options)operator([)symbol(:hoverclass)operator(])inline_delimiter(})>content(')delimiter(")> reserved(if) ident(options)operator([)symbol(:hoverclass)operator(]) + + string<delimiter(%()content(Droppables.add)nesting_delimiter(()inline<inline_delimiter(#{)ident(element_id)operator(.)ident(to_json)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(options_for_javascript)operator(()ident(options)operator(\))inline_delimiter(})>nesting_delimiter(\))content(;)delimiter(\))> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(erb)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# This is poor man's Builder for the rare cases where you need to programmatically make tags but can't use Builder.) + reserved(module) class(TagHelper) + ident(include) constant(ERB)operator(::)constant(Util) + + comment(# Examples:) + comment(# * <tt>tag("br"\) => <br /></tt>) + comment(# * <tt>tag("input", { "type" => "text"}\) => <input type="text" /></tt>) + reserved(def) method(tag)operator(()ident(name)operator(,) ident(options) operator(=) pre_constant(nil)operator(,) ident(open) operator(=) pre_constant(false)operator(\)) + string<delimiter(")content(<)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>inline<inline_delimiter(#{)ident(tag_options)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) reserved(if) ident(options)inline_delimiter(})>delimiter(")> operator(+) operator(()ident(open) operator(?) string<delimiter(")content(>)delimiter(")> operator(:) string<delimiter(")content( />)delimiter(")>operator(\)) + reserved(end) + + comment(# Examples:) + comment(# * <tt>content_tag("p", "Hello world!"\) => <p>Hello world!</p></tt>) + comment(# * <tt>content_tag("div", content_tag("p", "Hello world!"\), "class" => "strong"\) => </tt>) + comment(# <tt><div class="strong"><p>Hello world!</p></div></tt>) + reserved(def) method(content_tag)operator(()ident(name)operator(,) ident(content)operator(,) ident(options) operator(=) pre_constant(nil)operator(\)) + string<delimiter(")content(<)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>inline<inline_delimiter(#{)ident(tag_options)operator(()ident(options)operator(.)ident(stringify_keys)operator(\)) reserved(if) ident(options)inline_delimiter(})>content(>)inline<inline_delimiter(#{)ident(content)inline_delimiter(})>content(</)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + comment(# Returns a CDATA section for the given +content+. CDATA sections) + comment(# are used to escape blocks of text containing characters which would) + comment(# otherwise be recognized as markup. CDATA sections begin with the string) + comment(# <tt><![CDATA[</tt> and end with (and may not contain\) the string ) + comment(# <tt>]]></tt>. ) + reserved(def) method(cdata_section)operator(()ident(content)operator(\)) + string<delimiter(")content(<![CDATA[)inline<inline_delimiter(#{)ident(content)inline_delimiter(})>content(]]>)delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(tag_options)operator(()ident(options)operator(\)) + ident(cleaned_options) operator(=) ident(convert_booleans)operator(()ident(options)operator(.)ident(stringify_keys)operator(.)ident(reject) operator({)operator(|)ident(key)operator(,) ident(value)operator(|) ident(value)operator(.)ident(nil?)operator(})operator(\)) + string<delimiter(')content( )delimiter(')> operator(+) ident(cleaned_options)operator(.)ident(map) operator({)operator(|)ident(key)operator(,) ident(value)operator(|) string<delimiter(%()inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(=")inline<inline_delimiter(#{)ident(html_escape)operator(()ident(value)operator(.)ident(to_s)operator(\))inline_delimiter(})>content(")delimiter(\))>operator(})operator(.)ident(sort) operator(*) string<delimiter(')content( )delimiter(')> reserved(unless) ident(cleaned_options)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(convert_booleans)operator(()ident(options)operator(\)) + string<delimiter(%w()content( disabled readonly multiple )delimiter(\))>operator(.)ident(each) operator({) operator(|)ident(a)operator(|) ident(boolean_attribute)operator(()ident(options)operator(,) ident(a)operator(\)) operator(}) + ident(options) + reserved(end) + + reserved(def) method(boolean_attribute)operator(()ident(options)operator(,) ident(attribute)operator(\)) + ident(options)operator([)ident(attribute)operator(]) operator(?) ident(options)operator([)ident(attribute)operator(]) operator(=) ident(attribute) operator(:) ident(options)operator(.)ident(delete)operator(()ident(attribute)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/tag_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) comment(#:nodoc:) + comment(# Provides a set of methods for working with text strings that can help unburden the level of inline Ruby code in the) + comment(# templates. In the example below we iterate over a collection of posts provided to the template and print each title) + comment(# after making sure it doesn't run longer than 20 characters:) + comment(# <% for post in @posts %>) + comment(# Title: <%= truncate(post.title, 20\) %>) + comment(# <% end %>) + reserved(module) class(TextHelper) + comment(# The regular puts and print are outlawed in eRuby. It's recommended to use the <%= "hello" %> form instead of print "hello".) + comment(# If you absolutely must use a method-based output, you can use concat. It's used like this: <% concat "hello", binding %>. Notice that) + comment(# it doesn't have an equal sign in front. Using <%= concat "hello" %> would result in a double hello.) + reserved(def) method(concat)operator(()ident(string)operator(,) ident(binding)operator(\)) + ident(eval)operator(()string<delimiter(")content(_erbout)delimiter(")>operator(,) ident(binding)operator(\))operator(.)ident(concat)operator(()ident(string)operator(\)) + reserved(end) + + comment(# Truncates +text+ to the length of +length+ and replaces the last three characters with the +truncate_string+) + comment(# if the +text+ is longer than +length+.) + reserved(def) method(truncate)operator(()ident(text)operator(,) ident(length) operator(=) integer(30)operator(,) ident(truncate_string) operator(=) string<delimiter(")content(...)delimiter(")>operator(\)) + reserved(if) ident(text)operator(.)ident(nil?) reserved(then) reserved(return) reserved(end) + ident(l) operator(=) ident(length) operator(-) ident(truncate_string)operator(.)ident(length) + reserved(if) global_variable($KCODE) operator(==) string<delimiter(")content(NONE)delimiter(")> + ident(text)operator(.)ident(length) operator(>) ident(length) operator(?) ident(text)operator([)integer(0)operator(...)ident(l)operator(]) operator(+) ident(truncate_string) operator(:) ident(text) + reserved(else) + ident(chars) operator(=) ident(text)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\)) + ident(chars)operator(.)ident(length) operator(>) ident(length) operator(?) ident(chars)operator([)integer(0)operator(...)ident(l)operator(])operator(.)ident(join) operator(+) ident(truncate_string) operator(:) ident(text) + reserved(end) + reserved(end) + + comment(# Highlights the +phrase+ where it is found in the +text+ by surrounding it like) + comment(# <strong class="highlight">I'm a highlight phrase</strong>. The highlighter can be specialized by) + comment(# passing +highlighter+ as single-quoted string with \\1 where the phrase is supposed to be inserted.) + comment(# N.B.: The +phrase+ is sanitized to include only letters, digits, and spaces before use.) + reserved(def) method(highlight)operator(()ident(text)operator(,) ident(phrase)operator(,) ident(highlighter) operator(=) string<delimiter(')content(<strong class="highlight">)content(\\1)content(</strong>)delimiter(')>operator(\)) + reserved(if) ident(phrase)operator(.)ident(blank?) reserved(then) reserved(return) ident(text) reserved(end) + ident(text)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(()inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(escape)operator(()ident(phrase)operator(\))inline_delimiter(})>content(\))delimiter(/)modifier(i)>operator(,) ident(highlighter)operator(\)) reserved(unless) ident(text)operator(.)ident(nil?) + reserved(end) + + comment(# Extracts an excerpt from the +text+ surrounding the +phrase+ with a number of characters on each side determined) + comment(# by +radius+. If the phrase isn't found, nil is returned. Ex:) + comment(# excerpt("hello my world", "my", 3\) => "...lo my wo...") + reserved(def) method(excerpt)operator(()ident(text)operator(,) ident(phrase)operator(,) ident(radius) operator(=) integer(100)operator(,) ident(excerpt_string) operator(=) string<delimiter(")content(...)delimiter(")>operator(\)) + reserved(if) ident(text)operator(.)ident(nil?) operator(||) ident(phrase)operator(.)ident(nil?) reserved(then) reserved(return) reserved(end) + ident(phrase) operator(=) constant(Regexp)operator(.)ident(escape)operator(()ident(phrase)operator(\)) + + reserved(if) ident(found_pos) operator(=) ident(text) operator(=)operator(~) regexp<delimiter(/)content(()inline<inline_delimiter(#{)ident(phrase)inline_delimiter(})>content(\))delimiter(/)modifier(i)> + ident(start_pos) operator(=) operator([) ident(found_pos) operator(-) ident(radius)operator(,) integer(0) operator(])operator(.)ident(max) + ident(end_pos) operator(=) operator([) ident(found_pos) operator(+) ident(phrase)operator(.)ident(length) operator(+) ident(radius)operator(,) ident(text)operator(.)ident(length) operator(])operator(.)ident(min) + + ident(prefix) operator(=) ident(start_pos) operator(>) integer(0) operator(?) ident(excerpt_string) operator(:) string<delimiter(")delimiter(")> + ident(postfix) operator(=) ident(end_pos) operator(<) ident(text)operator(.)ident(length) operator(?) ident(excerpt_string) operator(:) string<delimiter(")delimiter(")> + + ident(prefix) operator(+) ident(text)operator([)ident(start_pos)operator(..)ident(end_pos)operator(])operator(.)ident(strip) operator(+) ident(postfix) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + comment(# Attempts to pluralize the +singular+ word unless +count+ is 1. See source for pluralization rules.) + reserved(def) method(pluralize)operator(()ident(count)operator(,) ident(singular)operator(,) ident(plural) operator(=) pre_constant(nil)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(count)inline_delimiter(})>content( )delimiter(")> operator(+) reserved(if) ident(count) operator(==) integer(1) + ident(singular) + reserved(elsif) ident(plural) + ident(plural) + reserved(elsif) constant(Object)operator(.)ident(const_defined?)operator(()string<delimiter(")content(Inflector)delimiter(")>operator(\)) + constant(Inflector)operator(.)ident(pluralize)operator(()ident(singular)operator(\)) + reserved(else) + ident(singular) operator(+) string<delimiter(")content(s)delimiter(")> + reserved(end) + reserved(end) + + comment(# Word wrap long lines to line_width.) + reserved(def) method(word_wrap)operator(()ident(text)operator(,) ident(line_width) operator(=) integer(80)operator(\)) + ident(text)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\n)delimiter(/)>operator(,) string<delimiter(")char(\\n)char(\\n)delimiter(")>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)content((.{1,)inline<inline_delimiter(#{)ident(line_width)inline_delimiter(})>content(}\)()char(\\s)content(+|$\))delimiter(/)>operator(,) string<delimiter(")char(\\\\)content(1)char(\\n)delimiter(")>operator(\))operator(.)ident(strip) + reserved(end) + + reserved(begin) + ident(require_library_or_gem) string<delimiter(")content(redcloth)delimiter(")> reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:RedCloth)operator(\)) + + comment(# Returns the text with all the Textile codes turned into HTML-tags.) + comment(# <i>This method is only available if RedCloth can be required</i>.) + reserved(def) method(textilize)operator(()ident(text)operator(\)) + reserved(if) ident(text)operator(.)ident(blank?) + string<delimiter(")delimiter(")> + reserved(else) + ident(textilized) operator(=) constant(RedCloth)operator(.)ident(new)operator(()ident(text)operator(,) operator([) symbol(:hard_breaks) operator(])operator(\)) + ident(textilized)operator(.)ident(hard_breaks) operator(=) pre_constant(true) reserved(if) ident(textilized)operator(.)ident(respond_to?)operator(()string<delimiter(")content(hard_breaks=)delimiter(")>operator(\)) + ident(textilized)operator(.)ident(to_html) + reserved(end) + reserved(end) + + comment(# Returns the text with all the Textile codes turned into HTML-tags, but without the regular bounding <p> tag.) + comment(# <i>This method is only available if RedCloth can be required</i>.) + reserved(def) method(textilize_without_paragraph)operator(()ident(text)operator(\)) + ident(textiled) operator(=) ident(textilize)operator(()ident(text)operator(\)) + reserved(if) ident(textiled)operator([)integer(0)operator(..)integer(2)operator(]) operator(==) string<delimiter(")content(<p>)delimiter(")> reserved(then) ident(textiled) operator(=) ident(textiled)operator([)integer(3)operator(..)integer(-1)operator(]) reserved(end) + reserved(if) ident(textiled)operator([)integer(-4)operator(..)integer(-1)operator(]) operator(==) string<delimiter(")content(</p>)delimiter(")> reserved(then) ident(textiled) operator(=) ident(textiled)operator([)integer(0)operator(..)integer(-5)operator(]) reserved(end) + reserved(return) ident(textiled) + reserved(end) + reserved(rescue) constant(LoadError) + comment(# We can't really help what's not there) + reserved(end) + + reserved(begin) + ident(require_library_or_gem) string<delimiter(")content(bluecloth)delimiter(")> reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:BlueCloth)operator(\)) + + comment(# Returns the text with all the Markdown codes turned into HTML-tags.) + comment(# <i>This method is only available if BlueCloth can be required</i>.) + reserved(def) method(markdown)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(blank?) operator(?) string<delimiter(")delimiter(")> operator(:) constant(BlueCloth)operator(.)ident(new)operator(()ident(text)operator(\))operator(.)ident(to_html) + reserved(end) + reserved(rescue) constant(LoadError) + comment(# We can't really help what's not there) + reserved(end) + + comment(# Returns +text+ transformed into HTML using very simple formatting rules) + comment(# Surrounds paragraphs with <tt><p></tt> tags, and converts line breaks into <tt><br/></tt>) + comment(# Two consecutive newlines(<tt>\\n\\n</tt>\) are considered as a paragraph, one newline (<tt>\\n</tt>\) is) + comment(# considered a linebreak, three or more consecutive newlines are turned into two newlines ) + reserved(def) method(simple_format)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(()char(\\r)char(\\n)content(|)char(\\n)content(|)char(\\r)content(\))delimiter(/)>operator(,) string<delimiter(")char(\\n)delimiter(")>operator(\)) comment(# lets make them newlines crossplatform) + ident(text)operator(.)ident(gsub!)operator(()regexp<delimiter(/)char(\\n)char(\\n)content(+)delimiter(/)>operator(,) string<delimiter(")char(\\n)char(\\n)delimiter(")>operator(\)) comment(# zap dupes) + ident(text)operator(.)ident(gsub!)operator(()regexp<delimiter(/)char(\\n)char(\\n)delimiter(/)>operator(,) string<delimiter(')content(</p>)content(\\0)content(<p>)delimiter(')>operator(\)) comment(# turn two newlines into paragraph) + ident(text)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(([^)char(\\n)content(]\)()char(\\n)content(\)([^)char(\\n)content(]\))delimiter(/)>operator(,) string<delimiter(')content(\\1)content(\\2)content(<br />)content(\\3)delimiter(')>operator(\)) comment(# turn single newline into <br />) + + ident(content_tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) ident(text)operator(\)) + reserved(end) + + comment(# Turns all urls and email addresses into clickable links. The +link+ parameter can limit what should be linked.) + comment(# Options are <tt>:all</tt> (default\), <tt>:email_addresses</tt>, and <tt>:urls</tt>.) + comment(#) + comment(# Example:) + comment(# auto_link("Go to http://www.rubyonrails.com and say hello to david@loudthinking.com"\) =>) + comment(# Go to <a href="http://www.rubyonrails.com">http://www.rubyonrails.com</a> and) + comment(# say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a>) + comment(#) + comment(# If a block is given, each url and email address is yielded and the) + comment(# result is used as the link text. Example:) + comment(# auto_link(post.body, :all, :target => '_blank'\) do |text|) + comment(# truncate(text, 15\)) + comment(# end) + reserved(def) method(auto_link)operator(()ident(text)operator(,) ident(link) operator(=) symbol(:all)operator(,) ident(href_options) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + reserved(return) string<delimiter(')delimiter(')> reserved(if) ident(text)operator(.)ident(blank?) + reserved(case) ident(link) + reserved(when) symbol(:all) reserved(then) ident(auto_link_urls)operator(()ident(auto_link_email_addresses)operator(()ident(text)operator(,) operator(&)ident(block)operator(\))operator(,) ident(href_options)operator(,) operator(&)ident(block)operator(\)) + reserved(when) symbol(:email_addresses) reserved(then) ident(auto_link_email_addresses)operator(()ident(text)operator(,) operator(&)ident(block)operator(\)) + reserved(when) symbol(:urls) reserved(then) ident(auto_link_urls)operator(()ident(text)operator(,) ident(href_options)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + comment(# Turns all links into words, like "<a href="something">else</a>" to "else".) + reserved(def) method(strip_links)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(<a.*>(.*\)<)char(\\/)content(a>)delimiter(/)modifier(m)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + reserved(end) + + comment(# Try to require the html-scanner library) + reserved(begin) + ident(require) string<delimiter(')content(html/tokenizer)delimiter(')> + ident(require) string<delimiter(')content(html/node)delimiter(')> + reserved(rescue) constant(LoadError) + comment(# if there isn't a copy installed, use the vendor version in) + comment(# action controller) + global_variable($:)operator(.)ident(unshift) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(")content(..)delimiter(")>operator(,) string<delimiter(")content(..)delimiter(")>operator(,) + string<delimiter(")content(action_controller)delimiter(")>operator(,) string<delimiter(")content(vendor)delimiter(")>operator(,) string<delimiter(")content(html-scanner)delimiter(")>operator(\)) + ident(require) string<delimiter(')content(html/tokenizer)delimiter(')> + ident(require) string<delimiter(')content(html/node)delimiter(')> + reserved(end) + + constant(VERBOTEN_TAGS) operator(=) string<delimiter(%w()content(form script)delimiter(\))> reserved(unless) reserved(defined?)operator(()constant(VERBOTEN_TAGS)operator(\)) + constant(VERBOTEN_ATTRS) operator(=) regexp<delimiter(/)content(^on)delimiter(/)modifier(i)> reserved(unless) reserved(defined?)operator(()constant(VERBOTEN_ATTRS)operator(\)) + + comment(# Sanitizes the given HTML by making form and script tags into regular) + comment(# text, and removing all "onxxx" attributes (so that arbitrary Javascript) + comment(# cannot be executed\). Also removes href attributes that start with) + comment(# "javascript:".) + comment(#) + comment(# Returns the sanitized text.) + reserved(def) method(sanitize)operator(()ident(html)operator(\)) + comment(# only do this if absolutely necessary) + reserved(if) ident(html)operator(.)ident(index)operator(()string<delimiter(")content(<)delimiter(")>operator(\)) + ident(tokenizer) operator(=) constant(HTML)operator(::)constant(Tokenizer)operator(.)ident(new)operator(()ident(html)operator(\)) + ident(new_text) operator(=) string<delimiter(")delimiter(")> + + reserved(while) ident(token) operator(=) ident(tokenizer)operator(.)ident(next) + ident(node) operator(=) constant(HTML)operator(::)constant(Node)operator(.)ident(parse)operator(()pre_constant(nil)operator(,) integer(0)operator(,) integer(0)operator(,) ident(token)operator(,) pre_constant(false)operator(\)) + ident(new_text) operator(<<) reserved(case) ident(node) + reserved(when) constant(HTML)operator(::)constant(Tag) + reserved(if) constant(VERBOTEN_TAGS)operator(.)ident(include?)operator(()ident(node)operator(.)ident(name)operator(\)) + ident(node)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(<)delimiter(/)>operator(,) string<delimiter(")content(<)delimiter(")>operator(\)) + reserved(else) + reserved(if) ident(node)operator(.)ident(closing) operator(!=) symbol(:close) + ident(node)operator(.)ident(attributes)operator(.)ident(delete_if) operator({) operator(|)ident(attr)operator(,)ident(v)operator(|) ident(attr) operator(=)operator(~) constant(VERBOTEN_ATTRS) operator(}) + reserved(if) ident(node)operator(.)ident(attributes)operator([)string<delimiter(")content(href)delimiter(")>operator(]) operator(=)operator(~) regexp<delimiter(/)content(^javascript:)delimiter(/)modifier(i)> + ident(node)operator(.)ident(attributes)operator(.)ident(delete) string<delimiter(")content(href)delimiter(")> + reserved(end) + reserved(end) + ident(node)operator(.)ident(to_s) + reserved(end) + reserved(else) + ident(node)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(<)delimiter(/)>operator(,) string<delimiter(")content(<)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(html) operator(=) ident(new_text) + reserved(end) + + ident(html) + reserved(end) + + comment(# Strips all HTML tags from the input, including comments. This uses the html-scanner) + comment(# tokenizer and so it's HTML parsing ability is limited by that of html-scanner.) + comment(#) + comment(# Returns the tag free text.) + reserved(def) method(strip_tags)operator(()ident(html)operator(\)) + reserved(if) ident(html)operator(.)ident(index)operator(()string<delimiter(")content(<)delimiter(")>operator(\)) + ident(text) operator(=) string<delimiter(")delimiter(")> + ident(tokenizer) operator(=) constant(HTML)operator(::)constant(Tokenizer)operator(.)ident(new)operator(()ident(html)operator(\)) + + reserved(while) ident(token) operator(=) ident(tokenizer)operator(.)ident(next) + ident(node) operator(=) constant(HTML)operator(::)constant(Node)operator(.)ident(parse)operator(()pre_constant(nil)operator(,) integer(0)operator(,) integer(0)operator(,) ident(token)operator(,) pre_constant(false)operator(\)) + comment(# result is only the content of any Text nodes) + ident(text) operator(<<) ident(node)operator(.)ident(to_s) reserved(if) ident(node)operator(.)ident(class) operator(==) constant(HTML)operator(::)constant(Text) + reserved(end) + comment(# strip any comments, and if they have a newline at the end (ie. line with) + comment(# only a comment\) strip that too) + ident(text)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(<!--(.*?\)-->[)char(\\n)content(]?)delimiter(/)modifier(m)>operator(,) string<delimiter(")delimiter(")>operator(\)) + reserved(else) + ident(html) comment(# already plain text) + reserved(end) + reserved(end) + + comment(# Returns a Cycle object whose to_s value cycles through items of an) + comment(# array every time it is called. This can be used to alternate classes) + comment(# for table rows:) + comment(#) + comment(# <%- for item in @items do -%>) + comment(# <tr class="<%= cycle("even", "odd"\) %>">) + comment(# ... use item ...) + comment(# </tr>) + comment(# <%- end -%>) + comment(#) + comment(# You can use named cycles to prevent clashes in nested loops. You'll) + comment(# have to reset the inner cycle, manually:) + comment(#) + comment(# <%- for item in @items do -%>) + comment(# <tr class="<%= cycle("even", "odd", :name => "row_class"\)) + comment(# <td>) + comment(# <%- for value in item.values do -%>) + comment(# <span style="color:'<%= cycle("red", "green", "blue") + comment(# :name => "colors"\) %>'">) + comment(# item) + comment(# </span>) + comment(# <%- end -%>) + comment(# <%- reset_cycle("colors"\) -%>) + comment(# </td>) + comment(# </tr>) + comment(# <%- end -%>) + reserved(def) method(cycle)operator(()ident(first_value)operator(,) operator(*)ident(values)operator(\)) + reserved(if) operator(()ident(values)operator(.)ident(last)operator(.)ident(instance_of?) constant(Hash)operator(\)) + ident(params) operator(=) ident(values)operator(.)ident(pop) + ident(name) operator(=) ident(params)operator([)symbol(:name)operator(]) + reserved(else) + ident(name) operator(=) string<delimiter(")content(default)delimiter(")> + reserved(end) + ident(values)operator(.)ident(unshift)operator(()ident(first_value)operator(\)) + + ident(cycle) operator(=) ident(get_cycle)operator(()ident(name)operator(\)) + reserved(if) operator(()ident(cycle)operator(.)ident(nil?) operator(||) ident(cycle)operator(.)ident(values) operator(!=) ident(values)operator(\)) + ident(cycle) operator(=) ident(set_cycle)operator(()ident(name)operator(,) constant(Cycle)operator(.)ident(new)operator(()operator(*)ident(values)operator(\))operator(\)) + reserved(end) + reserved(return) ident(cycle)operator(.)ident(to_s) + reserved(end) + + comment(# Resets a cycle so that it starts from the first element in the array) + comment(# the next time it is used.) + reserved(def) method(reset_cycle)operator(()ident(name) operator(=) string<delimiter(")content(default)delimiter(")>operator(\)) + ident(cycle) operator(=) ident(get_cycle)operator(()ident(name)operator(\)) + reserved(return) reserved(if) ident(cycle)operator(.)ident(nil?) + ident(cycle)operator(.)ident(reset) + reserved(end) + + reserved(class) class(Cycle) comment(#:nodoc:) + ident(attr_reader) symbol(:values) + + reserved(def) method(initialize)operator(()ident(first_value)operator(,) operator(*)ident(values)operator(\)) + instance_variable(@values) operator(=) ident(values)operator(.)ident(unshift)operator(()ident(first_value)operator(\)) + ident(reset) + reserved(end) + + reserved(def) method(reset) + instance_variable(@index) operator(=) integer(0) + reserved(end) + + reserved(def) method(to_s) + ident(value) operator(=) instance_variable(@values)operator([)instance_variable(@index)operator(])operator(.)ident(to_s) + instance_variable(@index) operator(=) operator(()instance_variable(@index) operator(+) integer(1)operator(\)) operator(%) instance_variable(@values)operator(.)ident(size) + reserved(return) ident(value) + reserved(end) + reserved(end) + + ident(private) + comment(# The cycle helpers need to store the cycles in a place that is) + comment(# guaranteed to be reset every time a page is rendered, so it) + comment(# uses an instance variable of ActionView::Base.) + reserved(def) method(get_cycle)operator(()ident(name)operator(\)) + instance_variable(@_cycles) operator(=) constant(Hash)operator(.)ident(new) reserved(if) instance_variable(@_cycles)operator(.)ident(nil?) + reserved(return) instance_variable(@_cycles)operator([)ident(name)operator(]) + reserved(end) + + reserved(def) method(set_cycle)operator(()ident(name)operator(,) ident(cycle_object)operator(\)) + instance_variable(@_cycles) operator(=) constant(Hash)operator(.)ident(new) reserved(if) instance_variable(@_cycles)operator(.)ident(nil?) + instance_variable(@_cycles)operator([)ident(name)operator(]) operator(=) ident(cycle_object) + reserved(end) + + constant(AUTO_LINK_RE) operator(=) regexp<delimiter(/)content( + ( # leading text + <)char(\\w)content(+.*?>| # leading HTML tag, or + [^=!:'")char(\\/)content(]| # leading punctuation, or + ^ # beginning of line + \) + ( + (?:http[s]?:)char(\\/)char(\\/)content(\)| # protocol spec, or + (?:www)char(\\.)content(\) # www.* + \) + ( + ([)char(\\w)content(]+:?[=?&)char(\\/)content(.-]?\)* # url segment + )char(\\w)content(+[)char(\\/)content(]? # url tail + (?:)char(\\#)char(\\w)content(*\)? # trailing anchor + \) + ([[:punct:]]|)char(\\s)content(|<|$\) # trailing text + )delimiter(/)modifier(x)> reserved(unless) ident(const_defined?)operator(()symbol(:AUTO_LINK_RE)operator(\)) + + comment(# Turns all urls into clickable links. If a block is given, each url) + comment(# is yielded and the result is used as the link text. Example:) + comment(# auto_link_urls(post.body, :all, :target => '_blank'\) do |text|) + comment(# truncate(text, 15\)) + comment(# end) + reserved(def) method(auto_link_urls)operator(()ident(text)operator(,) ident(href_options) operator(=) operator({)operator(})operator(\)) + ident(extra_options) operator(=) ident(tag_options)operator(()ident(href_options)operator(.)ident(stringify_keys)operator(\)) operator(||) string<delimiter(")delimiter(")> + ident(text)operator(.)ident(gsub)operator(()constant(AUTO_LINK_RE)operator(\)) reserved(do) + ident(all)operator(,) ident(a)operator(,) ident(b)operator(,) ident(c)operator(,) ident(d) operator(=) global_variable($&)operator(,) global_variable($1)operator(,) global_variable($2)operator(,) global_variable($3)operator(,) global_variable($5) + reserved(if) ident(a) operator(=)operator(~) regexp<delimiter(/)content(<a)char(\\s)delimiter(/)modifier(i)> comment(# don't replace URL's that are already linked) + ident(all) + reserved(else) + ident(text) operator(=) ident(b) operator(+) ident(c) + ident(text) operator(=) reserved(yield)operator(()ident(text)operator(\)) reserved(if) ident(block_given?) + string<delimiter(%()inline<inline_delimiter(#{)ident(a)inline_delimiter(})>content(<a href=")inline<inline_delimiter(#{)ident(b)operator(==)string<delimiter(")content(www.)delimiter(")>operator(?)string<delimiter(")content(http://www.)delimiter(")>symbol(:b)inline_delimiter(})>inline<inline_delimiter(#{)ident(c)inline_delimiter(})>content(")inline<inline_delimiter(#{)ident(extra_options)inline_delimiter(})>content(>)inline<inline_delimiter(#{)ident(text)inline_delimiter(})>content(</a>)inline<inline_delimiter(#{)ident(d)inline_delimiter(})>delimiter(\))> + operator(})operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Turns all email addresses into clickable links. If a block is given,) + comment(# each email is yielded and the result is used as the link text.) + comment(# Example:) + comment(# auto_link_email_addresses(post.body\) do |text|) + comment(# truncate(text, 15\)) + comment(# end) + reserved(def) method(auto_link_email_addresses)operator(()ident(text)operator(\)) + ident(text)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(([)char(\\w)char(\\.)content(!#)char(\\$)content(%)char(\\-)content(+.]+@[A-Za-z0-9)char(\\-)content(]+()char(\\.)content([A-Za-z0-9)char(\\-)content(]+\)+\))delimiter(/)>operator(\)) reserved(do) + ident(text) operator(=) global_variable($1) + ident(text) operator(=) reserved(yield)operator(()ident(text)operator(\)) reserved(if) ident(block_given?) + string<delimiter(%{)content(<a href="mailto:)inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(text)inline_delimiter(})>content(</a>)delimiter(})> + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/javascript_helper)delimiter(')> + +reserved(module) class(ActionView) + reserved(module) class(Helpers) + comment(# Provides a set of methods for making easy links and getting urls that depend on the controller and action. This means that) + comment(# you can use the same format for links in the views that you do in the controller. The different methods are even named) + comment(# synchronously, so link_to uses that same url as is generated by url_for, which again is the same url used for) + comment(# redirection in redirect_to.) + reserved(module) class(UrlHelper) + ident(include) constant(JavaScriptHelper) + + comment(# Returns the URL for the set of +options+ provided. This takes the same options ) + comment(# as url_for. For a list, see the documentation for ActionController::Base#url_for.) + comment(# Note that it'll set :only_path => true so you'll get /controller/action instead of the ) + comment(# http://example.com/controller/action part (makes it harder to parse httpd log files\)) + comment(# ) + comment(# When called from a view, url_for returns an HTML escaped url. If you need an unescaped) + comment(# url, pass :escape => false to url_for.) + comment(# ) + reserved(def) method(url_for)operator(()ident(options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + reserved(if) ident(options)operator(.)ident(kind_of?) constant(Hash) + ident(options) operator(=) operator({) symbol(:only_path) operator(=)operator(>) pre_constant(true) operator(})operator(.)ident(update)operator(()ident(options)operator(.)ident(symbolize_keys)operator(\)) + ident(escape) operator(=) ident(options)operator(.)ident(key?)operator(()symbol(:escape)operator(\)) operator(?) ident(options)operator(.)ident(delete)operator(()symbol(:escape)operator(\)) operator(:) pre_constant(true) + reserved(else) + ident(escape) operator(=) pre_constant(true) + reserved(end) + ident(url) operator(=) instance_variable(@controller)operator(.)ident(send)operator(()symbol(:url_for)operator(,) ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(escape) operator(?) ident(html_escape)operator(()ident(url)operator(\)) operator(:) ident(url) + reserved(end) + + comment(# Creates a link tag of the given +name+ using an URL created by the set of +options+. See the valid options in) + comment(# the documentation for ActionController::Base#url_for. It's also possible to pass a string instead of an options hash to) + comment(# get a link tag that just points without consideration. If nil is passed as a name, the link itself will become the name.) + comment(#) + comment(# The html_options has three special features. One for creating javascript confirm alerts where if you pass :confirm => 'Are you sure?',) + comment(# the link will be guarded with a JS popup asking that question. If the user accepts, the link is processed, otherwise not.) + comment(#) + comment(# Another for creating a popup window, which is done by either passing :popup with true or the options of the window in ) + comment(# Javascript form.) + comment(#) + comment(# And a third for making the link do a POST request (instead of the regular GET\) through a dynamically added form element that) + comment(# is instantly submitted. Note that if the user has turned off Javascript, the request will fall back on the GET. So its) + comment(# your responsibility to determine what the action should be once it arrives at the controller. The POST form is turned on by) + comment(# passing :post as true. Note, it's not possible to use POST requests and popup targets at the same time (an exception will be thrown\).) + comment(#) + comment(# Examples:) + comment(# link_to "Delete this page", { :action => "destroy", :id => @page.id }, :confirm => "Are you sure?") + comment(# link_to "Help", { :action => "help" }, :popup => true) + comment(# link_to "Busy loop", { :action => "busy" }, :popup => ['new_window', 'height=300,width=600']) + comment(# link_to "Destroy account", { :action => "destroy" }, :confirm => "Are you sure?", :post => true) + reserved(def) method(link_to)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) pre_constant(nil)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + reserved(if) ident(html_options) + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + ident(convert_options_to_javascript!)operator(()ident(html_options)operator(\)) + ident(tag_options) operator(=) ident(tag_options)operator(()ident(html_options)operator(\)) + reserved(else) + ident(tag_options) operator(=) pre_constant(nil) + reserved(end) + ident(url) operator(=) ident(options)operator(.)ident(is_a?)operator(()constant(String)operator(\)) operator(?) ident(options) operator(:) pre_constant(self)operator(.)ident(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + string<delimiter(")content(<a href=)char(\\")inline<inline_delimiter(#{)ident(url)inline_delimiter(})>char(\\")inline<inline_delimiter(#{)ident(tag_options)inline_delimiter(})>content(>)inline<inline_delimiter(#{)ident(name) operator(||) ident(url)inline_delimiter(})>content(</a>)delimiter(")> + reserved(end) + + comment(# Generates a form containing a sole button that submits to the) + comment(# URL given by _options_. Use this method instead of +link_to+) + comment(# for actions that do not have the safe HTTP GET semantics) + comment(# implied by using a hypertext link.) + comment(#) + comment(# The parameters are the same as for +link_to+. Any _html_options_) + comment(# that you pass will be applied to the inner +input+ element.) + comment(# In particular, pass) + comment(# ) + comment(# :disabled => true/false) + comment(#) + comment(# as part of _html_options_ to control whether the button is) + comment(# disabled. The generated form element is given the class) + comment(# 'button-to', to which you can attach CSS styles for display) + comment(# purposes.) + comment(#) + comment(# Example 1:) + comment(#) + comment(# # inside of controller for "feeds") + comment(# button_to "Edit", :action => 'edit', :id => 3) + comment(#) + comment(# Generates the following HTML (sans formatting\):) + comment(#) + comment(# <form method="post" action="/feeds/edit/3" class="button-to">) + comment(# <div><input value="Edit" type="submit" /></div>) + comment(# </form>) + comment(#) + comment(# Example 2:) + comment(#) + comment(# button_to "Destroy", { :action => 'destroy', :id => 3 },) + comment(# :confirm => "Are you sure?") + comment(#) + comment(# Generates the following HTML (sans formatting\):) + comment(#) + comment(# <form method="post" action="/feeds/destroy/3" class="button-to">) + comment(# <div><input onclick="return confirm('Are you sure?'\);") + comment(# value="Destroy" type="submit" />) + comment(# </div>) + comment(# </form>) + comment(#) + comment(# *NOTE*: This method generates HTML code that represents a form.) + comment(# Forms are "block" content, which means that you should not try to) + comment(# insert them into your HTML where only inline content is expected.) + comment(# For example, you can legally insert a form inside of a +div+ or) + comment(# +td+ element or in between +p+ elements, but not in the middle of) + comment(# a run of text, nor can you place a form within another form.) + comment(# (Bottom line: Always validate your HTML before going public.\)) + reserved(def) method(button_to)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) pre_constant(nil)operator(\)) + ident(html_options) operator(=) operator(()ident(html_options) operator(||) operator({)operator(})operator(\))operator(.)ident(stringify_keys) + ident(convert_boolean_attributes!)operator(()ident(html_options)operator(,) string<delimiter(%w()content( disabled )delimiter(\))>operator(\)) + + reserved(if) ident(confirm) operator(=) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(confirm)delimiter(")>operator(\)) + ident(html_options)operator([)string<delimiter(")content(onclick)delimiter(")>operator(]) operator(=) string<delimiter(")content(return )inline<inline_delimiter(#{)ident(confirm_javascript_function)operator(()ident(confirm)operator(\))inline_delimiter(})>content(;)delimiter(")> + reserved(end) + + ident(url) operator(=) ident(options)operator(.)ident(is_a?)operator(()constant(String)operator(\)) operator(?) ident(options) operator(:) ident(url_for)operator(()ident(options)operator(\)) + ident(name) operator(||=) ident(url) + + ident(html_options)operator(.)ident(merge!)operator(()string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(submit)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) ident(name)operator(\)) + + string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")inline<inline_delimiter(#{)ident(h) ident(url)inline_delimiter(})>char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div>)delimiter(")> operator(+) + ident(tag)operator(()string<delimiter(")content(input)delimiter(")>operator(,) ident(html_options)operator(\)) operator(+) string<delimiter(")content(</div></form>)delimiter(")> + reserved(end) + + + comment(# This tag is deprecated. Combine the link_to and AssetTagHelper::image_tag yourself instead, like:) + comment(# link_to(image_tag("rss", :size => "30x45", :border => 0\), "http://www.example.com"\)) + reserved(def) method(link_image_to)operator(()ident(src)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(image_options) operator(=) operator({) string<delimiter(")content(src)delimiter(")> operator(=)operator(>) ident(src)operator(.)ident(include?)operator(()string<delimiter(")content(/)delimiter(")>operator(\)) operator(?) ident(src) operator(:) string<delimiter(")content(/images/)inline<inline_delimiter(#{)ident(src)inline_delimiter(})>delimiter(")> operator(}) + ident(image_options)operator([)string<delimiter(")content(src)delimiter(")>operator(]) operator(+=) string<delimiter(")content(.png)delimiter(")> reserved(unless) ident(image_options)operator([)string<delimiter(")content(src)delimiter(")>operator(])operator(.)ident(include?)operator(()string<delimiter(")content(.)delimiter(")>operator(\)) + + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + reserved(if) ident(html_options)operator([)string<delimiter(")content(alt)delimiter(")>operator(]) + ident(image_options)operator([)string<delimiter(")content(alt)delimiter(")>operator(]) operator(=) ident(html_options)operator([)string<delimiter(")content(alt)delimiter(")>operator(]) + ident(html_options)operator(.)ident(delete) string<delimiter(")content(alt)delimiter(")> + reserved(else) + ident(image_options)operator([)string<delimiter(")content(alt)delimiter(")>operator(]) operator(=) ident(src)operator(.)ident(split)operator(()string<delimiter(")content(/)delimiter(")>operator(\))operator(.)ident(last)operator(.)ident(split)operator(()string<delimiter(")content(.)delimiter(")>operator(\))operator(.)ident(first)operator(.)ident(capitalize) + reserved(end) + + reserved(if) ident(html_options)operator([)string<delimiter(")content(size)delimiter(")>operator(]) + ident(image_options)operator([)string<delimiter(")content(width)delimiter(")>operator(])operator(,) ident(image_options)operator([)string<delimiter(")content(height)delimiter(")>operator(]) operator(=) ident(html_options)operator([)string<delimiter(")content(size)delimiter(")>operator(])operator(.)ident(split)operator(()string<delimiter(")content(x)delimiter(")>operator(\)) + ident(html_options)operator(.)ident(delete) string<delimiter(")content(size)delimiter(")> + reserved(end) + + reserved(if) ident(html_options)operator([)string<delimiter(")content(border)delimiter(")>operator(]) + ident(image_options)operator([)string<delimiter(")content(border)delimiter(")>operator(]) operator(=) ident(html_options)operator([)string<delimiter(")content(border)delimiter(")>operator(]) + ident(html_options)operator(.)ident(delete) string<delimiter(")content(border)delimiter(")> + reserved(end) + + reserved(if) ident(html_options)operator([)string<delimiter(")content(align)delimiter(")>operator(]) + ident(image_options)operator([)string<delimiter(")content(align)delimiter(")>operator(]) operator(=) ident(html_options)operator([)string<delimiter(")content(align)delimiter(")>operator(]) + ident(html_options)operator(.)ident(delete) string<delimiter(")content(align)delimiter(")> + reserved(end) + + ident(link_to)operator(()ident(tag)operator(()string<delimiter(")content(img)delimiter(")>operator(,) ident(image_options)operator(\))operator(,) ident(options)operator(,) ident(html_options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + reserved(end) + + ident(alias_method) symbol(:link_to_image)operator(,) symbol(:link_image_to) comment(# deprecated name) + + comment(# Creates a link tag of the given +name+ using an URL created by the set of +options+, unless the current) + comment(# request uri is the same as the link's, in which case only the name is returned (or the) + comment(# given block is yielded, if one exists\). This is useful for creating link bars where you don't want to link) + comment(# to the page currently being viewed.) + reserved(def) method(link_to_unless_current)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(,) operator(&)ident(block)operator(\)) + ident(link_to_unless) ident(current_page?)operator(()ident(options)operator(\))operator(,) ident(name)operator(,) ident(options)operator(,) ident(html_options)operator(,) operator(*)ident(parameters_for_method_reference)operator(,) operator(&)ident(block) + reserved(end) + + comment(# Create a link tag of the given +name+ using an URL created by the set of +options+, unless +condition+) + comment(# is true, in which case only the name is returned (or the given block is yielded, if one exists\). ) + reserved(def) method(link_to_unless)operator(()ident(condition)operator(,) ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(,) operator(&)ident(block)operator(\)) + reserved(if) ident(condition) + reserved(if) ident(block_given?) + ident(block)operator(.)ident(arity) operator(<=) integer(1) operator(?) reserved(yield)operator(()ident(name)operator(\)) operator(:) reserved(yield)operator(()ident(name)operator(,) ident(options)operator(,) ident(html_options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + reserved(else) + ident(name) + reserved(end) + reserved(else) + ident(link_to)operator(()ident(name)operator(,) ident(options)operator(,) ident(html_options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + reserved(end) + reserved(end) + + comment(# Create a link tag of the given +name+ using an URL created by the set of +options+, if +condition+) + comment(# is true, in which case only the name is returned (or the given block is yielded, if one exists\). ) + reserved(def) method(link_to_if)operator(()ident(condition)operator(,) ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(,) ident(html_options) operator(=) operator({)operator(})operator(,) operator(*)ident(parameters_for_method_reference)operator(,) operator(&)ident(block)operator(\)) + ident(link_to_unless) operator(!)ident(condition)operator(,) ident(name)operator(,) ident(options)operator(,) ident(html_options)operator(,) operator(*)ident(parameters_for_method_reference)operator(,) operator(&)ident(block) + reserved(end) + + comment(# Creates a link tag for starting an email to the specified <tt>email_address</tt>, which is also used as the name of the) + comment(# link unless +name+ is specified. Additional HTML options, such as class or id, can be passed in the <tt>html_options</tt> hash.) + comment(#) + comment(# You can also make it difficult for spiders to harvest email address by obfuscating them.) + comment(# Examples:) + comment(# mail_to "me@domain.com", "My email", :encode => "javascript" # =>) + comment(# <script type="text/javascript" language="javascript">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'\)\)</script>) + comment(#) + comment(# mail_to "me@domain.com", "My email", :encode => "hex" # =>) + comment(# <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>) + comment(#) + comment(# You can also specify the cc address, bcc address, subject, and body parts of the message header to create a complex e-mail using the) + comment(# corresponding +cc+, +bcc+, +subject+, and +body+ <tt>html_options</tt> keys. Each of these options are URI escaped and then appended to) + comment(# the <tt>email_address</tt> before being output. <b>Be aware that javascript keywords will not be escaped and may break this feature) + comment(# when encoding with javascript.</b>) + comment(# Examples:) + comment(# mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com", :bcc => "bccaddress@domain.com", :subject => "This is an example email", :body => "This is the body of the message." # =>) + comment(# <a href="mailto:me@domain.com?cc="ccaddress@domain.com"&bcc="bccaddress@domain.com"&body="This%20is%20the%20body%20of%20the%20message."&subject="This%20is%20an%20example%20email">My email</a>) + reserved(def) method(mail_to)operator(()ident(email_address)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(html_options) operator(=) operator({)operator(})operator(\)) + ident(html_options) operator(=) ident(html_options)operator(.)ident(stringify_keys) + ident(encode) operator(=) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(encode)delimiter(")>operator(\)) + ident(cc)operator(,) ident(bcc)operator(,) ident(subject)operator(,) ident(body) operator(=) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(cc)delimiter(")>operator(\))operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(bcc)delimiter(")>operator(\))operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(subject)delimiter(")>operator(\))operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(body)delimiter(")>operator(\)) + + ident(string) operator(=) string<delimiter(')delimiter(')> + ident(extras) operator(=) string<delimiter(')delimiter(')> + ident(extras) operator(<<) string<delimiter(")content(cc=)inline<inline_delimiter(#{)constant(CGI)operator(.)ident(escape)operator(()ident(cc)operator(\))operator(.)ident(gsub)operator(()string<delimiter(")content(+)delimiter(")>operator(,) string<delimiter(")content(%20)delimiter(")>operator(\))inline_delimiter(})>content(&)delimiter(")> reserved(unless) ident(cc)operator(.)ident(nil?) + ident(extras) operator(<<) string<delimiter(")content(bcc=)inline<inline_delimiter(#{)constant(CGI)operator(.)ident(escape)operator(()ident(bcc)operator(\))operator(.)ident(gsub)operator(()string<delimiter(")content(+)delimiter(")>operator(,) string<delimiter(")content(%20)delimiter(")>operator(\))inline_delimiter(})>content(&)delimiter(")> reserved(unless) ident(bcc)operator(.)ident(nil?) + ident(extras) operator(<<) string<delimiter(")content(body=)inline<inline_delimiter(#{)constant(CGI)operator(.)ident(escape)operator(()ident(body)operator(\))operator(.)ident(gsub)operator(()string<delimiter(")content(+)delimiter(")>operator(,) string<delimiter(")content(%20)delimiter(")>operator(\))inline_delimiter(})>content(&)delimiter(")> reserved(unless) ident(body)operator(.)ident(nil?) + ident(extras) operator(<<) string<delimiter(")content(subject=)inline<inline_delimiter(#{)constant(CGI)operator(.)ident(escape)operator(()ident(subject)operator(\))operator(.)ident(gsub)operator(()string<delimiter(")content(+)delimiter(")>operator(,) string<delimiter(")content(%20)delimiter(")>operator(\))inline_delimiter(})>content(&)delimiter(")> reserved(unless) ident(subject)operator(.)ident(nil?) + ident(extras) operator(=) string<delimiter(")content(?)delimiter(")> operator(<<) ident(extras)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(&?$)delimiter(/)>operator(,)string<delimiter(")delimiter(")>operator(\)) reserved(unless) ident(extras)operator(.)ident(empty?) + + ident(email_address_obfuscated) operator(=) ident(email_address)operator(.)ident(dup) + ident(email_address_obfuscated)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(@)delimiter(/)>operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(replace_at)delimiter(")>operator(\))operator(\)) reserved(if) ident(html_options)operator(.)ident(has_key?)operator(()string<delimiter(")content(replace_at)delimiter(")>operator(\)) + ident(email_address_obfuscated)operator(.)ident(gsub!)operator(()regexp<delimiter(/)char(\\.)delimiter(/)>operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(replace_dot)delimiter(")>operator(\))operator(\)) reserved(if) ident(html_options)operator(.)ident(has_key?)operator(()string<delimiter(")content(replace_dot)delimiter(")>operator(\)) + + reserved(if) ident(encode) operator(==) string<delimiter(')content(javascript)delimiter(')> + ident(tmp) operator(=) string<delimiter(")content(document.write(')inline<inline_delimiter(#{)ident(content_tag)operator(()string<delimiter(")content(a)delimiter(")>operator(,) ident(name) operator(||) ident(email_address)operator(,) ident(html_options)operator(.)ident(merge)operator(()operator({) string<delimiter(")content(href)delimiter(")> operator(=)operator(>) string<delimiter(")content(mailto:)delimiter(")>operator(+)ident(email_address)operator(.)ident(to_s)operator(+)ident(extras) operator(})operator(\))operator(\))inline_delimiter(})>content('\);)delimiter(")> + reserved(for) ident(i) reserved(in) integer(0)operator(...)ident(tmp)operator(.)ident(length) + ident(string) operator(<<) ident(sprintf)operator(()string<delimiter(")content(%%%x)delimiter(")>operator(,)ident(tmp)operator([)ident(i)operator(])operator(\)) + reserved(end) + string<delimiter(")content(<script type=)char(\\")content(text/javascript)char(\\")content(>eval(unescape(')inline<inline_delimiter(#{)ident(string)inline_delimiter(})>content('\)\)</script>)delimiter(")> + reserved(elsif) ident(encode) operator(==) string<delimiter(')content(hex)delimiter(')> + reserved(for) ident(i) reserved(in) integer(0)operator(...)ident(email_address)operator(.)ident(length) + reserved(if) ident(email_address)operator([)ident(i)operator(,)integer(1)operator(]) operator(=)operator(~) regexp<delimiter(/)char(\\w)delimiter(/)> + ident(string) operator(<<) ident(sprintf)operator(()string<delimiter(")content(%%%x)delimiter(")>operator(,)ident(email_address)operator([)ident(i)operator(])operator(\)) + reserved(else) + ident(string) operator(<<) ident(email_address)operator([)ident(i)operator(,)integer(1)operator(]) + reserved(end) + reserved(end) + ident(content_tag) string<delimiter(")content(a)delimiter(")>operator(,) ident(name) operator(||) ident(email_address_obfuscated)operator(,) ident(html_options)operator(.)ident(merge)operator(()operator({) string<delimiter(")content(href)delimiter(")> operator(=)operator(>) string<delimiter(")content(mailto:)inline<inline_delimiter(#{)ident(string)inline_delimiter(})>inline<inline_delimiter(#{)ident(extras)inline_delimiter(})>delimiter(")> operator(})operator(\)) + reserved(else) + ident(content_tag) string<delimiter(")content(a)delimiter(")>operator(,) ident(name) operator(||) ident(email_address_obfuscated)operator(,) ident(html_options)operator(.)ident(merge)operator(()operator({) string<delimiter(")content(href)delimiter(")> operator(=)operator(>) string<delimiter(")content(mailto:)inline<inline_delimiter(#{)ident(email_address)inline_delimiter(})>inline<inline_delimiter(#{)ident(extras)inline_delimiter(})>delimiter(")> operator(})operator(\)) + reserved(end) + reserved(end) + + comment(# Returns true if the current page uri is generated by the options passed (in url_for format\).) + reserved(def) method(current_page?)operator(()ident(options)operator(\)) + constant(CGI)operator(.)ident(escapeHTML)operator(()ident(url_for)operator(()ident(options)operator(\))operator(\)) operator(==) instance_variable(@controller)operator(.)ident(request)operator(.)ident(request_uri) + reserved(end) + + ident(private) + reserved(def) method(convert_options_to_javascript!)operator(()ident(html_options)operator(\)) + ident(confirm)operator(,) ident(popup)operator(,) ident(post) operator(=) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(confirm)delimiter(")>operator(\))operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(popup)delimiter(")>operator(\))operator(,) ident(html_options)operator(.)ident(delete)operator(()string<delimiter(")content(post)delimiter(")>operator(\)) + + ident(html_options)operator([)string<delimiter(")content(onclick)delimiter(")>operator(]) operator(=) reserved(case) + reserved(when) ident(popup) operator(&&) ident(post) + ident(raise) constant(ActionView)operator(::)constant(ActionViewError)operator(,) string<delimiter(")content(You can't use :popup and :post in the same link)delimiter(")> + reserved(when) ident(confirm) operator(&&) ident(popup) + string<delimiter(")content(if ()inline<inline_delimiter(#{)ident(confirm_javascript_function)operator(()ident(confirm)operator(\))inline_delimiter(})>content(\) { )inline<inline_delimiter(#{)ident(popup_javascript_function)operator(()ident(popup)operator(\))inline_delimiter(})>content( };return false;)delimiter(")> + reserved(when) ident(confirm) operator(&&) ident(post) + string<delimiter(")content(if ()inline<inline_delimiter(#{)ident(confirm_javascript_function)operator(()ident(confirm)operator(\))inline_delimiter(})>content(\) { )inline<inline_delimiter(#{)ident(post_javascript_function)inline_delimiter(})>content( };return false;)delimiter(")> + reserved(when) ident(confirm) + string<delimiter(")content(return )inline<inline_delimiter(#{)ident(confirm_javascript_function)operator(()ident(confirm)operator(\))inline_delimiter(})>content(;)delimiter(")> + reserved(when) ident(post) + string<delimiter(")inline<inline_delimiter(#{)ident(post_javascript_function)inline_delimiter(})>content(return false;)delimiter(")> + reserved(when) ident(popup) + ident(popup_javascript_function)operator(()ident(popup)operator(\)) operator(+) string<delimiter(')content(return false;)delimiter(')> + reserved(else) + ident(html_options)operator([)string<delimiter(")content(onclick)delimiter(")>operator(]) + reserved(end) + reserved(end) + + reserved(def) method(confirm_javascript_function)operator(()ident(confirm)operator(\)) + string<delimiter(")content(confirm(')inline<inline_delimiter(#{)ident(escape_javascript)operator(()ident(confirm)operator(\))inline_delimiter(})>content('\))delimiter(")> + reserved(end) + + reserved(def) method(popup_javascript_function)operator(()ident(popup)operator(\)) + ident(popup)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(?) string<delimiter(")content(window.open(this.href,')inline<inline_delimiter(#{)ident(popup)operator(.)ident(first)inline_delimiter(})>content(',')inline<inline_delimiter(#{)ident(popup)operator(.)ident(last)inline_delimiter(})>content('\);)delimiter(")> operator(:) string<delimiter(")content(window.open(this.href\);)delimiter(")> + reserved(end) + + reserved(def) method(post_javascript_function) + string<delimiter(")content(var f = document.createElement('form'\); this.parentNode.appendChild(f\); f.method = 'POST'; f.action = this.href; f.submit(\);)delimiter(")> + reserved(end) + + comment(# Processes the _html_options_ hash, converting the boolean) + comment(# attributes from true/false form into the form required by) + comment(# HTML/XHTML. (An attribute is considered to be boolean if) + comment(# its name is listed in the given _bool_attrs_ array.\)) + comment(#) + comment(# More specifically, for each boolean attribute in _html_options_) + comment(# given as:) + comment(#) + comment(# "attr" => bool_value) + comment(#) + comment(# if the associated _bool_value_ evaluates to true, it is) + comment(# replaced with the attribute's name; otherwise the attribute is) + comment(# removed from the _html_options_ hash. (See the XHTML 1.0 spec,) + comment(# section 4.5 "Attribute Minimization" for more:) + comment(# http://www.w3.org/TR/xhtml1/#h-4.5\)) + comment(#) + comment(# Returns the updated _html_options_ hash, which is also modified) + comment(# in place.) + comment(#) + comment(# Example:) + comment(#) + comment(# convert_boolean_attributes!( html_options,) + comment(# %w( checked disabled readonly \) \)) + reserved(def) method(convert_boolean_attributes!)operator(()ident(html_options)operator(,) ident(bool_attrs)operator(\)) + ident(bool_attrs)operator(.)ident(each) operator({) operator(|)ident(x)operator(|) ident(html_options)operator([)ident(x)operator(]) operator(=) ident(x) reserved(if) ident(html_options)operator(.)ident(delete)operator(()ident(x)operator(\)) operator(}) + ident(html_options) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + comment(# There's also a convenience method for rendering sub templates within the current controller that depends on a single object ) + comment(# (we call this kind of sub templates for partials\). It relies on the fact that partials should follow the naming convention of being ) + comment(# prefixed with an underscore -- as to separate them from regular templates that could be rendered on their own. ) + comment(#) + comment(# In a template for Advertiser#account:) + comment(#) + comment(# <%= render :partial => "account" %>) + comment(#) + comment(# This would render "advertiser/_account.rhtml" and pass the instance variable @account in as a local variable +account+ to ) + comment(# the template for display.) + comment(#) + comment(# In another template for Advertiser#buy, we could have:) + comment(#) + comment(# <%= render :partial => "account", :locals => { :account => @buyer } %>) + comment(#) + comment(# <% for ad in @advertisements %>) + comment(# <%= render :partial => "ad", :locals => { :ad => ad } %>) + comment(# <% end %>) + comment(#) + comment(# This would first render "advertiser/_account.rhtml" with @buyer passed in as the local variable +account+, then render ) + comment(# "advertiser/_ad.rhtml" and pass the local variable +ad+ to the template for display.) + comment(#) + comment(# == Rendering a collection of partials) + comment(#) + comment(# The example of partial use describes a familiar pattern where a template needs to iterate over an array and render a sub) + comment(# template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders) + comment(# a partial by the same name as the elements contained within. So the three-lined example in "Using partials" can be rewritten) + comment(# with a single line:) + comment(#) + comment(# <%= render :partial => "ad", :collection => @advertisements %>) + comment(#) + comment(# This will render "advertiser/_ad.rhtml" and pass the local variable +ad+ to the template for display. An iteration counter) + comment(# will automatically be made available to the template with a name of the form +partial_name_counter+. In the case of the ) + comment(# example above, the template would be fed +ad_counter+.) + comment(#) + comment(# NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also just keep domain objects,) + comment(# like Active Records, in there.) + comment(# ) + comment(# == Rendering shared partials) + comment(#) + comment(# Two controllers can share a set of partials and render them like this:) + comment(#) + comment(# <%= render :partial => "advertisement/ad", :locals => { :ad => @advertisement } %>) + comment(#) + comment(# This will render the partial "advertisement/_ad.rhtml" regardless of which controller this is being called from.) + reserved(module) class(Partials) + comment(# Deprecated, use render :partial) + reserved(def) method(render_partial)operator(()ident(partial_path)operator(,) ident(local_assigns) operator(=) pre_constant(nil)operator(,) ident(deprecated_local_assigns) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(path)operator(,) ident(partial_name) operator(=) ident(partial_pieces)operator(()ident(partial_path)operator(\)) + ident(object) operator(=) ident(extracting_object)operator(()ident(partial_name)operator(,) ident(local_assigns)operator(,) ident(deprecated_local_assigns)operator(\)) + ident(local_assigns) operator(=) ident(extract_local_assigns)operator(()ident(local_assigns)operator(,) ident(deprecated_local_assigns)operator(\)) + ident(local_assigns) operator(=) ident(local_assigns) operator(?) ident(local_assigns)operator(.)ident(clone) operator(:) operator({)operator(}) + ident(add_counter_to_local_assigns!)operator(()ident(partial_name)operator(,) ident(local_assigns)operator(\)) + ident(add_object_to_local_assigns!)operator(()ident(partial_name)operator(,) ident(local_assigns)operator(,) ident(object)operator(\)) + + reserved(if) ident(logger) + constant(ActionController)operator(::)constant(Base)operator(.)ident(benchmark)operator(()string<delimiter(")content(Rendered )inline<inline_delimiter(#{)ident(path)inline_delimiter(})>content(/_)inline<inline_delimiter(#{)ident(partial_name)inline_delimiter(})>delimiter(")>operator(,) constant(Logger)operator(::)constant(DEBUG)operator(,) pre_constant(false)operator(\)) reserved(do) + ident(render)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(path)inline_delimiter(})>content(/_)inline<inline_delimiter(#{)ident(partial_name)inline_delimiter(})>delimiter(")>operator(,) ident(local_assigns)operator(\)) + reserved(end) + reserved(else) + ident(render)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(path)inline_delimiter(})>content(/_)inline<inline_delimiter(#{)ident(partial_name)inline_delimiter(})>delimiter(")>operator(,) ident(local_assigns)operator(\)) + reserved(end) + reserved(end) + + comment(# Deprecated, use render :partial, :collection) + reserved(def) method(render_partial_collection)operator(()ident(partial_name)operator(,) ident(collection)operator(,) ident(partial_spacer_template) operator(=) pre_constant(nil)operator(,) ident(local_assigns) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(collection_of_partials) operator(=) constant(Array)operator(.)ident(new) + ident(counter_name) operator(=) ident(partial_counter_name)operator(()ident(partial_name)operator(\)) + ident(local_assigns) operator(=) ident(local_assigns) operator(?) ident(local_assigns)operator(.)ident(clone) operator(:) operator({)operator(}) + ident(collection)operator(.)ident(each_with_index) reserved(do) operator(|)ident(element)operator(,) ident(counter)operator(|) + ident(local_assigns)operator([)ident(counter_name)operator(]) operator(=) ident(counter) + ident(collection_of_partials)operator(.)ident(push)operator(()ident(render_partial)operator(()ident(partial_name)operator(,) ident(element)operator(,) ident(local_assigns)operator(\))operator(\)) + reserved(end) + + reserved(return) string<delimiter(")content( )delimiter(")> reserved(if) ident(collection_of_partials)operator(.)ident(empty?) + + reserved(if) ident(partial_spacer_template) + ident(spacer_path)operator(,) ident(spacer_name) operator(=) ident(partial_pieces)operator(()ident(partial_spacer_template)operator(\)) + ident(collection_of_partials)operator(.)ident(join)operator(()ident(render)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(spacer_path)inline_delimiter(})>content(/_)inline<inline_delimiter(#{)ident(spacer_name)inline_delimiter(})>delimiter(")>operator(\))operator(\)) + reserved(else) + ident(collection_of_partials)operator(.)ident(join) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:render_collection_of_partials)operator(,) symbol(:render_partial_collection) + + ident(private) + reserved(def) method(partial_pieces)operator(()ident(partial_path)operator(\)) + reserved(if) ident(partial_path)operator(.)ident(include?)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) + reserved(return) constant(File)operator(.)ident(dirname)operator(()ident(partial_path)operator(\))operator(,) constant(File)operator(.)ident(basename)operator(()ident(partial_path)operator(\)) + reserved(else) + reserved(return) ident(controller)operator(.)ident(class)operator(.)ident(controller_path)operator(,) ident(partial_path) + reserved(end) + reserved(end) + + reserved(def) method(partial_counter_name)operator(()ident(partial_name)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(partial_name)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\))operator(.)ident(last)inline_delimiter(})>content(_counter)delimiter(")>operator(.)ident(intern) + reserved(end) + + reserved(def) method(extracting_object)operator(()ident(partial_name)operator(,) ident(local_assigns)operator(,) ident(deprecated_local_assigns)operator(\)) + reserved(if) ident(local_assigns)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(||) ident(local_assigns)operator(.)ident(nil?) + ident(controller)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(partial_name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(else) + comment(# deprecated form where object could be passed in as second parameter) + ident(local_assigns) + reserved(end) + reserved(end) + + reserved(def) method(extract_local_assigns)operator(()ident(local_assigns)operator(,) ident(deprecated_local_assigns)operator(\)) + ident(local_assigns)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(local_assigns) operator(:) ident(deprecated_local_assigns) + reserved(end) + + reserved(def) method(add_counter_to_local_assigns!)operator(()ident(partial_name)operator(,) ident(local_assigns)operator(\)) + ident(counter_name) operator(=) ident(partial_counter_name)operator(()ident(partial_name)operator(\)) + ident(local_assigns)operator([)ident(counter_name)operator(]) operator(=) integer(1) reserved(unless) ident(local_assigns)operator(.)ident(has_key?)operator(()ident(counter_name)operator(\)) + reserved(end) + + reserved(def) method(add_object_to_local_assigns!)operator(()ident(partial_name)operator(,) ident(local_assigns)operator(,) ident(object)operator(\)) + ident(local_assigns)operator([)ident(partial_name)operator(.)ident(intern)operator(]) operator(||=) + reserved(if) ident(object)operator(.)ident(is_a?)operator(()constant(ActionView)operator(::)constant(Base)operator(::)constant(ObjectWrapper)operator(\)) + ident(object)operator(.)ident(value) + reserved(else) + ident(object) + reserved(end) operator(||) ident(controller)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(partial_name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionView) + comment(# The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a) + comment(# bunch of intimate details and uses it to report a very precise exception message.) + reserved(class) class(TemplateError) operator(<) constant(ActionViewError) comment(#:nodoc:) + constant(SOURCE_CODE_RADIUS) operator(=) integer(3) + + ident(attr_reader) symbol(:original_exception) + + reserved(def) method(initialize)operator(()ident(base_path)operator(,) ident(file_name)operator(,) ident(assigns)operator(,) ident(source)operator(,) ident(original_exception)operator(\)) + instance_variable(@base_path)operator(,) instance_variable(@assigns)operator(,) instance_variable(@source)operator(,) instance_variable(@original_exception) operator(=) + ident(base_path)operator(,) ident(assigns)operator(,) ident(source)operator(,) ident(original_exception) + instance_variable(@file_name) operator(=) ident(file_name) + reserved(end) + + reserved(def) method(message) + ident(original_exception)operator(.)ident(message) + reserved(end) + + reserved(def) method(sub_template_message) + reserved(if) instance_variable(@sub_templates) + string<delimiter(")content(Trace of template inclusion: )delimiter(")> operator(+) + instance_variable(@sub_templates)operator(.)ident(collect) operator({) operator(|)ident(template)operator(|) ident(strip_base_path)operator(()ident(template)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(else) + string<delimiter(")delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(source_extract)operator(()ident(indention) operator(=) integer(0)operator(\)) + ident(source_code) operator(=) constant(IO)operator(.)ident(readlines)operator(()instance_variable(@file_name)operator(\)) + + ident(start_on_line) operator(=) operator([) ident(line_number) operator(-) constant(SOURCE_CODE_RADIUS) operator(-) integer(1)operator(,) integer(0) operator(])operator(.)ident(max) + ident(end_on_line) operator(=) operator([) ident(line_number) operator(+) constant(SOURCE_CODE_RADIUS) operator(-) integer(1)operator(,) ident(source_code)operator(.)ident(length)operator(])operator(.)ident(min) + + ident(line_counter) operator(=) ident(start_on_line) + ident(extract) operator(=) ident(source_code)operator([)ident(start_on_line)operator(..)ident(end_on_line)operator(])operator(.)ident(collect) reserved(do) operator(|)ident(line)operator(|) + ident(line_counter) operator(+=) integer(1) + string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content( )delimiter(')> operator(*) ident(indention)inline_delimiter(})>inline<inline_delimiter(#{)ident(line_counter)inline_delimiter(})>content(: )delimiter(")> operator(+) ident(line) + reserved(end) + + ident(extract)operator(.)ident(join) + reserved(end) + + reserved(def) method(sub_template_of)operator(()ident(file_name)operator(\)) + instance_variable(@sub_templates) operator(||=) operator([)operator(]) + instance_variable(@sub_templates) operator(<<) ident(file_name) + reserved(end) + + reserved(def) method(line_number) + reserved(if) ident(file_name) + ident(regexp) operator(=) regexp<delimiter(/)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(escape) constant(File)operator(.)ident(basename)operator(()ident(file_name)operator(\))inline_delimiter(})>content(:()char(\\d)content(+\))delimiter(/)> + operator([)instance_variable(@original_exception)operator(.)ident(message)operator(,) instance_variable(@original_exception)operator(.)ident(clean_backtrace)operator(])operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(line)operator(|) + reserved(return) global_variable($1)operator(.)ident(to_i) reserved(if) ident(regexp) operator(=)operator(~) ident(line) + reserved(end) + reserved(end) + integer(0) + reserved(end) + + reserved(def) method(file_name) + ident(stripped) operator(=) ident(strip_base_path)operator(()instance_variable(@file_name)operator(\)) + ident(stripped)operator([)integer(0)operator(]) operator(==) integer(?/) operator(?) ident(stripped)operator([)integer(1)operator(..)integer(-1)operator(]) operator(:) ident(stripped) + reserved(end) + + reserved(def) method(to_s) + string<delimiter(")char(\\n)char(\\n)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(message)inline_delimiter(})>content(\) on line #)inline<inline_delimiter(#{)ident(line_number)inline_delimiter(})>content( of )inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>content(:)char(\\n)delimiter(")> operator(+) + ident(source_extract) operator(+) string<delimiter(")char(\\n)content( )delimiter(")> operator(+) + ident(original_exception)operator(.)ident(clean_backtrace)operator(.)ident(join)operator(()string<delimiter(")char(\\n)content( )delimiter(")>operator(\)) operator(+) + string<delimiter(")char(\\n)char(\\n)delimiter(")> + reserved(end) + + reserved(def) method(backtrace) + operator([) + string<delimiter(")content(On line #)inline<inline_delimiter(#{)ident(line_number)inline_delimiter(})>content( of )inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>char(\\n)char(\\n)inline<inline_delimiter(#{)ident(source_extract)operator(()integer(4)operator(\))inline_delimiter(})>char(\\n)content( )delimiter(")> operator(+) + ident(original_exception)operator(.)ident(clean_backtrace)operator(.)ident(join)operator(()string<delimiter(")char(\\n)content( )delimiter(")>operator(\)) + operator(]) + reserved(end) + + ident(private) + reserved(def) method(strip_base_path)operator(()ident(file_name)operator(\)) + ident(file_name) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(file_name)operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)content(^)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(escape) constant(File)operator(.)ident(expand_path)operator(()constant(RAILS_ROOT)operator(\))inline_delimiter(})>delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(file_name)operator(.)ident(gsub)operator(()instance_variable(@base_path)operator(,) string<delimiter(")delimiter(")>operator(\)) + reserved(end) + reserved(end) +reserved(end) + +constant(Exception)operator(::)constant(TraceSubstitutions) operator(<<) operator([)regexp<delimiter(/)content(:in)char(\\s)content(+`_run_(html|xml\).*')char(\\s)content(*$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(]) reserved(if) reserved(defined?)operator(()constant(Exception)operator(::)constant(TraceSubstitutions)operator(\)) +constant(Exception)operator(::)constant(TraceSubstitutions) operator(<<) operator([)regexp<delimiter(%r{)content(^)char(\\s)content(*)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(escape) constant(RAILS_ROOT)inline_delimiter(})>delimiter(})>operator(,) string<delimiter(')content(#{RAILS_ROOT})delimiter(')>operator(]) reserved(if) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) +comment(#--) +comment(# Copyright (c\) 2004 David Heinemeier Hansson) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/action_view/vendor)delimiter(")>operator(\)) +ident(require) string<delimiter(')content(action_view/base)delimiter(')> +ident(require) string<delimiter(')content(action_view/partials)delimiter(')> + +constant(ActionView)operator(::)constant(Base)operator(.)ident(class_eval) reserved(do) + ident(include) constant(ActionView)operator(::)constant(Partials) +reserved(end) + +constant(ActionView)operator(::)constant(Base)operator(.)ident(load_helpers)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/action_view/helpers/)delimiter(")>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../lib)delimiter(')>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../activesupport/lib/active_support)delimiter(')>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/helpers)delimiter(')>operator(\)) + +ident(require) string<delimiter(')content(yaml)delimiter(')> +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(action_controller)delimiter(')> +ident(require) string<delimiter(')content(breakpoint)delimiter(')> + +ident(require) string<delimiter(')content(action_controller/test_process)delimiter(')> + +constant(ActionController)operator(::)constant(Base)operator(.)ident(logger) operator(=) pre_constant(nil) +constant(ActionController)operator(::)constant(Base)operator(.)ident(ignore_missing_templates) operator(=) pre_constant(false) +constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(reload) reserved(rescue) ident(nilrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +comment(# Define the essentials) +reserved(class) class(ActiveRecordTestConnector) + ident(cattr_accessor) symbol(:able_to_connect) + ident(cattr_accessor) symbol(:connected) + + comment(# Set our defaults) + pre_constant(self)operator(.)ident(connected) operator(=) pre_constant(false) + pre_constant(self)operator(.)ident(able_to_connect) operator(=) pre_constant(true) +reserved(end) + +comment(# Try to grab AR) +reserved(begin) + constant(PATH_TO_AR) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../activerecord)delimiter(')> + ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(PATH_TO_AR)inline_delimiter(})>content(/lib/active_record)delimiter(")> reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) + ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(PATH_TO_AR)inline_delimiter(})>content(/lib/active_record/fixtures)delimiter(")> reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:Fixtures)operator(\)) +reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")char(\\n)content(Skipping ActiveRecord assertion tests: )inline<inline_delimiter(#{)ident(e)inline_delimiter(})>delimiter(")> + constant(ActiveRecordTestConnector)operator(.)ident(able_to_connect) operator(=) pre_constant(false) +reserved(end) + +comment(# Define the rest of the connector) +reserved(class) class(ActiveRecordTestConnector) + reserved(def) pre_constant(self)operator(.)ident(setup) + reserved(unless) pre_constant(self)operator(.)ident(connected) operator(||) operator(!)pre_constant(self)operator(.)ident(able_to_connect) + ident(setup_connection) + ident(load_schema) + pre_constant(self)operator(.)ident(connected) operator(=) pre_constant(true) + reserved(end) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")char(\\n)content(Skipping ActiveRecord assertion tests: )inline<inline_delimiter(#{)ident(e)inline_delimiter(})>delimiter(")> + comment(#$stderr.puts " #{e.backtrace.join("\\n "\)}\\n") + pre_constant(self)operator(.)ident(able_to_connect) operator(=) pre_constant(false) + reserved(end) + + ident(private) + + reserved(def) pre_constant(self)operator(.)ident(setup_connection) + reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) + + reserved(begin) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(()symbol(:adapter) operator(=)operator(>) string<delimiter(')content(sqlite3)delimiter(')>operator(,) symbol(:dbfile) operator(=)operator(>) string<delimiter(')content(:memory:)delimiter(')>operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + reserved(rescue) constant(Object) + global_variable($stderr)operator(.)ident(puts) string<delimiter(')content(SQLite 3 unavailable; falling to SQLite 2.)delimiter(')> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(()symbol(:adapter) operator(=)operator(>) string<delimiter(')content(sqlite)delimiter(')>operator(,) symbol(:dbfile) operator(=)operator(>) string<delimiter(')content(:memory:)delimiter(')>operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + reserved(end) + + constant(Object)operator(.)ident(send)operator(()symbol(:const_set)operator(,) symbol(:QUOTED_TYPE)operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(quote_column_name)operator(()string<delimiter(')content(type)delimiter(')>operator(\))operator(\)) reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:QUOTED_TYPE)operator(\)) + reserved(else) + ident(raise) string<delimiter(")content(Couldn't locate ActiveRecord.)delimiter(")> + reserved(end) + reserved(end) + + comment(# Load actionpack sqlite tables) + reserved(def) pre_constant(self)operator(.)ident(load_schema) + constant(File)operator(.)ident(read)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/db_definitions/sqlite.sql)delimiter(")>operator(\))operator(.)ident(split)operator(()string<delimiter(')content(;)delimiter(')>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(sql)operator(|) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) reserved(unless) ident(sql)operator(.)ident(blank?) + reserved(end) + reserved(end) +reserved(end) + +comment(# Test case for inheiritance ) +reserved(class) class(ActiveRecordTestCase) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + comment(# Set our fixture path) + pre_constant(self)operator(.)ident(fixture_path) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/)delimiter(")> + + reserved(def) method(setup) + ident(abort_tests) reserved(unless) constant(ActiveRecordTestConnector)operator(.)ident(connected) operator(=) pre_constant(true) + reserved(end) + + comment(# Default so Test::Unit::TestCase doesn't complain) + reserved(def) method(test_truth) + reserved(end) + + ident(private) + + comment(# If things go wrong, we don't want to run our test cases. We'll just define them to test nothing.) + reserved(def) method(abort_tests) + pre_constant(self)operator(.)ident(class)operator(.)ident(public_instance_methods)operator(.)ident(grep)operator(()regexp<delimiter(/)content(^test.)delimiter(/)>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + pre_constant(self)operator(.)ident(class)operator(.)ident(class_eval) operator({) ident(define_method)operator(()ident(method)operator(.)ident(to_sym)operator(\))operator({)operator(}) operator(}) + reserved(end) + reserved(end) +reserved(end) + +constant(ActiveRecordTestConnector)operator(.)ident(setuprequire) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../active_record_unit)delimiter(")> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> + +reserved(class) class(ActiveRecordAssertionsController) operator(<) constant(ActionController)operator(::)constant(Base) + pre_constant(self)operator(.)ident(template_root) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../fixtures/)delimiter(")> + + comment(# fail with 1 bad column) + reserved(def) method(nasty_columns_1) + instance_variable(@company) operator(=) constant(Company)operator(.)ident(new) + instance_variable(@company)operator(.)ident(name) operator(=) string<delimiter(")content(B)delimiter(")> + instance_variable(@company)operator(.)ident(rating) operator(=) integer(2) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(snicker....)delimiter(")> + reserved(end) + + comment(# fail with 2 bad columns) + reserved(def) method(nasty_columns_2) + instance_variable(@company) operator(=) constant(Company)operator(.)ident(new) + instance_variable(@company)operator(.)ident(name) operator(=) string<delimiter(")delimiter(")> + instance_variable(@company)operator(.)ident(rating) operator(=) integer(2) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(double snicker....)delimiter(")> + reserved(end) + + comment(# this will pass validation) + reserved(def) method(good_company) + instance_variable(@company) operator(=) constant(Company)operator(.)ident(new) + instance_variable(@company)operator(.)ident(name) operator(=) string<delimiter(")content(A)delimiter(")> + instance_variable(@company)operator(.)ident(rating) operator(=) integer(69) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(Goodness Gracious!)delimiter(")> + reserved(end) + + comment(# this will fail validation) + reserved(def) method(bad_company) + instance_variable(@company) operator(=) constant(Company)operator(.)ident(new) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(Who's Bad?)delimiter(")> + reserved(end) + + comment(# the safety dance......) + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise)operator(;) reserved(end) +reserved(end) + +reserved(class) class(ActiveRecordAssertionsControllerTest) operator(<) constant(ActiveRecordTestCase) + ident(fixtures) symbol(:companies) + + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@controller) operator(=) constant(ActiveRecordAssertionsController)operator(.)ident(new) + reserved(super) + reserved(end) + + comment(# test for 1 bad apple column) + reserved(def) method(test_some_invalid_columns) + ident(process) symbol(:nasty_columns_1) + ident(assert_success) + ident(assert_invalid_record) string<delimiter(')content(company)delimiter(')> + ident(assert_invalid_column_on_record) string<delimiter(')content(company)delimiter(')>operator(,) string<delimiter(')content(rating)delimiter(')> + ident(assert_valid_column_on_record) string<delimiter(')content(company)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')> + ident(assert_valid_column_on_record) string<delimiter(')content(company)delimiter(')>operator(,) string<delimiter(%w()content(name id)delimiter(\))> + reserved(end) + + comment(# test for 2 bad apples columns) + reserved(def) method(test_all_invalid_columns) + ident(process) symbol(:nasty_columns_2) + ident(assert_success) + ident(assert_invalid_record) string<delimiter(')content(company)delimiter(')> + ident(assert_invalid_column_on_record) string<delimiter(')content(company)delimiter(')>operator(,) string<delimiter(')content(rating)delimiter(')> + ident(assert_invalid_column_on_record) string<delimiter(')content(company)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')> + ident(assert_invalid_column_on_record) string<delimiter(')content(company)delimiter(')>operator(,) string<delimiter(%w()content(name rating)delimiter(\))> + reserved(end) + + comment(# ensure we have no problems with an ActiveRecord) + reserved(def) method(test_valid_record) + ident(process) symbol(:good_company) + ident(assert_success) + ident(assert_valid_record) string<delimiter(')content(company)delimiter(')> + reserved(end) + + comment(# ensure we have problems with an ActiveRecord) + reserved(def) method(test_invalid_record) + ident(process) symbol(:bad_company) + ident(assert_success) + ident(assert_invalid_record) string<delimiter(')content(company)delimiter(')> + reserved(end) +reserved(end)comment(# Unfurl the safety net.) +ident(path_to_ar) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../../activerecord)delimiter(')> +reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) reserved(or) constant(File)operator(.)ident(exist?)operator(()ident(path_to_ar)operator(\)) + reserved(begin) + +comment(# These tests exercise CGI::Session::ActiveRecordStore, so you're going to) +comment(# need AR in a sibling directory to AP and have SQLite installed.) + +reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) + ident(require) constant(File)operator(.)ident(join)operator(()ident(path_to_ar)operator(,) string<delimiter(')content(lib)delimiter(')>operator(,) string<delimiter(')content(active_record)delimiter(')>operator(\)) +reserved(end) + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(action_controller/session/active_record_store)delimiter(')> + +comment(#ActiveRecord::Base.logger = Logger.new($stdout\)) +reserved(begin) + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session)operator(.)ident(establish_connection)operator(()symbol(:adapter) operator(=)operator(>) string<delimiter(')content(sqlite3)delimiter(')>operator(,) symbol(:database) operator(=)operator(>) string<delimiter(')content(:memory:)delimiter(')>operator(\)) + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session)operator(.)ident(connection) +reserved(rescue) constant(Object) + global_variable($stderr)operator(.)ident(puts) string<delimiter(')content(SQLite 3 unavailable; falling back to SQLite 2.)delimiter(')> + reserved(begin) + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session)operator(.)ident(establish_connection)operator(()symbol(:adapter) operator(=)operator(>) string<delimiter(')content(sqlite)delimiter(')>operator(,) symbol(:database) operator(=)operator(>) string<delimiter(')content(:memory:)delimiter(')>operator(\)) + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session)operator(.)ident(connection) + reserved(rescue) constant(Object) + global_variable($stderr)operator(.)ident(puts) string<delimiter(')content(SQLite 2 unavailable; skipping ActiveRecordStore test suite.)delimiter(')> + ident(raise) constant(SystemExit) + reserved(end) +reserved(end) + + +reserved(module) class(CommonActiveRecordStoreTests) + reserved(def) method(test_basics) + ident(s) operator(=) ident(session_class)operator(.)ident(new)operator(()symbol(:session_id) operator(=)operator(>) string<delimiter(')content(1234)delimiter(')>operator(,) symbol(:data) operator(=)operator(>) operator({) string<delimiter(')content(foo)delimiter(')> operator(=)operator(>) string<delimiter(')content(bar)delimiter(')> operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(s)operator(.)ident(data)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + ident(assert) ident(s)operator(.)ident(save) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(s)operator(.)ident(data)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + + ident(assert_not_nil) ident(t) operator(=) ident(session_class)operator(.)ident(find_by_session_id)operator(()string<delimiter(')content(1234)delimiter(')>operator(\)) + ident(assert_not_nil) ident(t)operator(.)ident(data) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(t)operator(.)ident(data)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_reload_same_session) + instance_variable(@new_session)operator(.)ident(update) + ident(reloaded) operator(=) constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()constant(CGI)operator(.)ident(new)operator(,) string<delimiter(')content(session_id)delimiter(')> operator(=)operator(>) instance_variable(@new_session)operator(.)ident(session_id)operator(,) string<delimiter(')content(database_manager)delimiter(')> operator(=)operator(>) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(\)) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(reloaded)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_tolerates_close_close) + ident(assert_nothing_raised) reserved(do) + instance_variable(@new_session)operator(.)ident(close) + instance_variable(@new_session)operator(.)ident(close) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(ActiveRecordStoreTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(CommonActiveRecordStoreTests) + + reserved(def) method(session_class) + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session) + reserved(end) + + reserved(def) method(session_id_column) + string<delimiter(")content(session_id)delimiter(")> + reserved(end) + + reserved(def) method(setup) + ident(session_class)operator(.)ident(create_table!) + + constant(ENV)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(GET)delimiter(')> + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(.)ident(session_class) operator(=) ident(session_class) + + instance_variable(@cgi) operator(=) constant(CGI)operator(.)ident(new) + instance_variable(@new_session) operator(=) constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()instance_variable(@cgi)operator(,) string<delimiter(')content(database_manager)delimiter(')> operator(=)operator(>) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(,) string<delimiter(')content(new_session)delimiter(')> operator(=)operator(>) pre_constant(true)operator(\)) + instance_variable(@new_session)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) operator(=) string<delimiter(')content(bar)delimiter(')> + reserved(end) + +comment(# this test only applies for eager sesssion saving) +comment(# def test_another_instance) +comment(# @another = CGI::Session.new(@cgi, 'session_id' => @new_session.session_id, 'database_manager' => CGI::Session::ActiveRecordStore\)) +comment(# assert_equal @new_session.session_id, @another.session_id) +comment(# end) + + reserved(def) method(test_model_attribute) + ident(assert_kind_of) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session)operator(,) instance_variable(@new_session)operator(.)ident(model) + ident(assert_equal)operator(()operator({) string<delimiter(')content(foo)delimiter(')> operator(=)operator(>) string<delimiter(')content(bar)delimiter(')> operator(})operator(,) instance_variable(@new_session)operator(.)ident(model)operator(.)ident(data)operator(\)) + reserved(end) + + reserved(def) method(test_save_unloaded_session) + ident(c) operator(=) ident(session_class)operator(.)ident(connection) + ident(bogus_class) operator(=) ident(c)operator(.)ident(quote)operator(()constant(Base64)operator(.)ident(encode64)operator(()string<delimiter(")char(\\004)char(\\010)content(o:)char(\\v)content(Blammo)char(\\000)delimiter(")>operator(\))operator(\)) + ident(c)operator(.)ident(insert)operator(()string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)ident(session_class)operator(.)ident(table_name)inline_delimiter(})>content( (')inline<inline_delimiter(#{)ident(session_id_column)inline_delimiter(})>content(', 'data'\) VALUES ('abcdefghijklmnop', )inline<inline_delimiter(#{)ident(bogus_class)inline_delimiter(})>content(\))delimiter(")>operator(\)) + + ident(sess) operator(=) ident(session_class)operator(.)ident(find_by_session_id)operator(()string<delimiter(')content(abcdefghijklmnop)delimiter(')>operator(\)) + ident(assert_not_nil) ident(sess) + ident(assert) operator(!)ident(sess)operator(.)ident(loaded?) + + comment(# because the session is not loaded, the save should be a no-op. If it) + comment(# isn't, this'll try and unmarshall the bogus class, and should get an error.) + ident(assert_nothing_raised) operator({) ident(sess)operator(.)ident(save) operator(}) + reserved(end) + + reserved(def) method(teardown) + ident(session_class)operator(.)ident(drop_table!) + reserved(end) +reserved(end) + +reserved(class) class(ColumnLimitTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@session_class) operator(=) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session) + instance_variable(@session_class)operator(.)ident(create_table!) + reserved(end) + + reserved(def) method(teardown) + instance_variable(@session_class)operator(.)ident(drop_table!) + reserved(end) + + reserved(def) method(test_protection_from_data_larger_than_column) + comment(# Can't test this unless there is a limit) + reserved(return) reserved(unless) ident(limit) operator(=) instance_variable(@session_class)operator(.)ident(data_column_size_limit) + ident(too_big) operator(=) string<delimiter(')content(:()delimiter(')> operator(*) ident(limit) + ident(s) operator(=) instance_variable(@session_class)operator(.)ident(new)operator(()symbol(:session_id) operator(=)operator(>) string<delimiter(')content(666)delimiter(')>operator(,) symbol(:data) operator(=)operator(>) operator({)string<delimiter(')content(foo)delimiter(')> operator(=)operator(>) ident(too_big)operator(})operator(\)) + ident(s)operator(.)ident(data) + ident(assert_raise)operator(()constant(ActionController)operator(::)constant(SessionOverflowError)operator(\)) operator({) ident(s)operator(.)ident(save) operator(}) + reserved(end) +reserved(end) + +reserved(class) class(DeprecatedActiveRecordStoreTest) operator(<) constant(ActiveRecordStoreTest) + reserved(def) method(session_id_column) + string<delimiter(")content(sessid)delimiter(")> + reserved(end) + + reserved(def) method(setup) + ident(session_class)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(')content(create table old_sessions (id integer primary key, sessid text unique, data text\))delimiter(')> + ident(session_class)operator(.)ident(table_name) operator(=) string<delimiter(')content(old_sessions)delimiter(')> + ident(session_class)operator(.)ident(send) symbol(:setup_sessid_compatibility!) + + constant(ENV)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(GET)delimiter(')> + constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(.)ident(session_class) operator(=) ident(session_class) + + instance_variable(@new_session) operator(=) constant(CGI)operator(::)constant(Session)operator(.)ident(new)operator(()constant(CGI)operator(.)ident(new)operator(,) string<delimiter(')content(database_manager)delimiter(')> operator(=)operator(>) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(,) string<delimiter(')content(new_session)delimiter(')> operator(=)operator(>) pre_constant(true)operator(\)) + instance_variable(@new_session)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) operator(=) string<delimiter(')content(bar)delimiter(')> + reserved(end) + + reserved(def) method(teardown) + ident(session_class)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(')content(drop table old_sessions)delimiter(')> + ident(session_class)operator(.)ident(table_name) operator(=) string<delimiter(')content(sessions)delimiter(')> + reserved(end) +reserved(end) + +reserved(class) class(SqlBypassActiveRecordStoreTest) operator(<) constant(ActiveRecordStoreTest) + reserved(def) method(session_class) + reserved(unless) instance_variable(@session_class) + instance_variable(@session_class) operator(=) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(SqlBypass) + instance_variable(@session_class)operator(.)ident(connection) operator(=) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(Session)operator(.)ident(connection) + reserved(end) + instance_variable(@session_class) + reserved(end) + + reserved(def) method(test_model_attribute) + ident(assert_kind_of) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(::)constant(SqlBypass)operator(,) instance_variable(@new_session)operator(.)ident(model) + ident(assert_equal)operator(()operator({) string<delimiter(')content(foo)delimiter(')> operator(=)operator(>) string<delimiter(')content(bar)delimiter(')> operator(})operator(,) instance_variable(@new_session)operator(.)ident(model)operator(.)ident(data)operator(\)) + reserved(end) +reserved(end) + + +comment(# End of safety net.) + reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(Skipping CGI::Session::ActiveRecordStore tests: )inline<inline_delimiter(#{)ident(e)inline_delimiter(})>delimiter(")> + comment(#$stderr.puts " #{e.backtrace.join("\\n "\)}") + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../active_record_unit)delimiter(')> + +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> + +reserved(class) class(PaginationTest) operator(<) constant(ActiveRecordTestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:replies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:developers_projects) + + reserved(class) class(PaginationController) operator(<) constant(ActionController)operator(::)constant(Base) + pre_constant(self)operator(.)ident(template_root) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../fixtures/)delimiter(")> + + reserved(def) method(simple_paginate) + instance_variable(@topic_pages)operator(,) instance_variable(@topics) operator(=) ident(paginate)operator(()symbol(:topics)operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_per_page) + instance_variable(@topic_pages)operator(,) instance_variable(@topics) operator(=) ident(paginate)operator(()symbol(:topics)operator(,) symbol(:per_page) operator(=)operator(>) integer(1)operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_order) + instance_variable(@topic_pages)operator(,) instance_variable(@topics) operator(=) ident(paginate)operator(()symbol(:topics)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(created_at asc)delimiter(')>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_order_by) + instance_variable(@topic_pages)operator(,) instance_variable(@topics) operator(=) ident(paginate)operator(()symbol(:topics)operator(,) symbol(:order_by) operator(=)operator(>) string<delimiter(')content(created_at asc)delimiter(')>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_include_and_order) + instance_variable(@topic_pages)operator(,) instance_variable(@topics) operator(=) ident(paginate)operator(()symbol(:topics)operator(,) symbol(:include) operator(=)operator(>) symbol(:replies)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(replies.created_at asc, topics.created_at asc)delimiter(')>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_conditions) + instance_variable(@topic_pages)operator(,) instance_variable(@topics) operator(=) ident(paginate)operator(()symbol(:topics)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(created_at > ?)delimiter(")>operator(,) integer(30)operator(.)ident(minutes)operator(.)ident(ago)operator(])operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_class_name) + instance_variable(@developer_pages)operator(,) instance_variable(@developers) operator(=) ident(paginate)operator(()symbol(:developers)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(DeVeLoPeR)delimiter(")>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_singular_name) + instance_variable(@developer_pages)operator(,) instance_variable(@developers) operator(=) ident(paginate)operator(()operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_joins) + instance_variable(@developer_pages)operator(,) instance_variable(@developers) operator(=) ident(paginate)operator(()symbol(:developers)operator(,) + symbol(:joins) operator(=)operator(>) string<delimiter(')content(LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id)delimiter(')>operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(')content(project_id=1)delimiter(')>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_join) + instance_variable(@developer_pages)operator(,) instance_variable(@developers) operator(=) ident(paginate)operator(()symbol(:developers)operator(,) + symbol(:join) operator(=)operator(>) string<delimiter(')content(LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id)delimiter(')>operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(')content(project_id=1)delimiter(')>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(paginate_with_join_and_count) + instance_variable(@developer_pages)operator(,) instance_variable(@developers) operator(=) ident(paginate)operator(()symbol(:developers)operator(,) + symbol(:join) operator(=)operator(>) string<delimiter(')content(d LEFT JOIN developers_projects ON d.id = developers_projects.developer_id)delimiter(')>operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(')content(project_id=1)delimiter(')>operator(,) + symbol(:count) operator(=)operator(>) string<delimiter(")content(d.id)delimiter(")>operator(\)) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(rescue_errors)operator(()ident(e)operator(\)) ident(raise) ident(e) reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + + reserved(end) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(PaginationController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(super) + reserved(end) + + comment(# Single Action Pagination Tests) + + reserved(def) method(test_simple_paginate) + ident(get) symbol(:simple_paginate) + ident(assert_equal) integer(1)operator(,) ident(assigns)operator(()symbol(:topic_pages)operator(\))operator(.)ident(page_count) + ident(assert_equal) integer(3)operator(,) ident(assigns)operator(()symbol(:topics)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_paginate_with_per_page) + ident(get) symbol(:paginate_with_per_page) + ident(assert_equal) integer(1)operator(,) ident(assigns)operator(()symbol(:topics)operator(\))operator(.)ident(size) + ident(assert_equal) integer(3)operator(,) ident(assigns)operator(()symbol(:topic_pages)operator(\))operator(.)ident(page_count) + reserved(end) + + reserved(def) method(test_paginate_with_order) + ident(get) symbol(:paginate_with_order) + ident(expected) operator(=) operator([)ident(topics)operator(()symbol(:futurama)operator(\))operator(,) + ident(topics)operator(()symbol(:harvey_birdman)operator(\))operator(,) + ident(topics)operator(()symbol(:rails)operator(\))operator(]) + ident(assert_equal) ident(expected)operator(,) ident(assigns)operator(()symbol(:topics)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(assigns)operator(()symbol(:topic_pages)operator(\))operator(.)ident(page_count) + reserved(end) + + reserved(def) method(test_paginate_with_order_by) + ident(get) symbol(:paginate_with_order) + ident(expected) operator(=) ident(assigns)operator(()symbol(:topics)operator(\)) + ident(get) symbol(:paginate_with_order_by) + ident(assert_equal) ident(expected)operator(,) ident(assigns)operator(()symbol(:topics)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(assigns)operator(()symbol(:topic_pages)operator(\))operator(.)ident(page_count) + reserved(end) + + reserved(def) method(test_paginate_with_conditions) + ident(get) symbol(:paginate_with_conditions) + ident(expected) operator(=) operator([)ident(topics)operator(()symbol(:rails)operator(\))operator(]) + ident(assert_equal) ident(expected)operator(,) ident(assigns)operator(()symbol(:topics)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(assigns)operator(()symbol(:topic_pages)operator(\))operator(.)ident(page_count) + reserved(end) + + reserved(def) method(test_paginate_with_class_name) + ident(get) symbol(:paginate_with_class_name) + + ident(assert) ident(assigns)operator(()symbol(:developers)operator(\))operator(.)ident(size) operator(>) integer(0) + ident(assert_equal) constant(DeVeLoPeR)operator(,) ident(assigns)operator(()symbol(:developers)operator(\))operator(.)ident(first)operator(.)ident(class) + reserved(end) + + reserved(def) method(test_paginate_with_joins) + ident(get) symbol(:paginate_with_joins) + ident(assert_equal) integer(2)operator(,) ident(assigns)operator(()symbol(:developers)operator(\))operator(.)ident(size) + ident(developer_names) operator(=) ident(assigns)operator(()symbol(:developers)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + ident(assert) ident(developer_names)operator(.)ident(include?)operator(()string<delimiter(')content(David)delimiter(')>operator(\)) + ident(assert) ident(developer_names)operator(.)ident(include?)operator(()string<delimiter(')content(Jamis)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_paginate_with_join_and_conditions) + ident(get) symbol(:paginate_with_joins) + ident(expected) operator(=) ident(assigns)operator(()symbol(:developers)operator(\)) + ident(get) symbol(:paginate_with_join) + ident(assert_equal) ident(expected)operator(,) ident(assigns)operator(()symbol(:developers)operator(\)) + reserved(end) + + reserved(def) method(test_paginate_with_join_and_count) + ident(get) symbol(:paginate_with_joins) + ident(expected) operator(=) ident(assigns)operator(()symbol(:developers)operator(\)) + ident(get) symbol(:paginate_with_join_and_count) + ident(assert_equal) ident(expected)operator(,) ident(assigns)operator(()symbol(:developers)operator(\)) + reserved(end) + + reserved(def) method(test_paginate_with_include_and_order) + ident(get) symbol(:paginate_with_include_and_order) + ident(expected) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) string<delimiter(')content(replies)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(replies.created_at asc, topics.created_at asc)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(10)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(assigns)operator(()symbol(:topics)operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +comment(# a controller class to facilitate the tests) +reserved(class) class(ActionPackAssertionsController) operator(<) constant(ActionController)operator(::)constant(Base) + + comment(# this does absolutely nothing) + reserved(def) method(nothing)operator(()operator(\)) ident(render_text) string<delimiter(")delimiter(")>operator(;) reserved(end) + + comment(# a standard template) + reserved(def) method(hello_world)operator(()operator(\)) ident(render) string<delimiter(")content(test/hello_world)delimiter(")>operator(;) reserved(end) + + comment(# a standard template) + reserved(def) method(hello_xml_world)operator(()operator(\)) ident(render) string<delimiter(")content(test/hello_xml_world)delimiter(")>operator(;) reserved(end) + + comment(# a redirect to an internal location) + reserved(def) method(redirect_internal)operator(()operator(\)) ident(redirect_to) string<delimiter(")content(/nothing)delimiter(")>operator(;) reserved(end) + + reserved(def) method(redirect_to_action)operator(()operator(\)) ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(flash_me)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(,) symbol(:params) operator(=)operator(>) operator({) string<delimiter(")content(panda)delimiter(")> operator(=)operator(>) string<delimiter(")content(fun)delimiter(")> operator(})operator(;) reserved(end) + + reserved(def) method(redirect_to_controller)operator(()operator(\)) ident(redirect_to) symbol(:controller) operator(=)operator(>) string<delimiter(")content(elsewhere)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(flash_me)delimiter(")>operator(;) reserved(end) + + reserved(def) method(redirect_to_path)operator(()operator(\)) ident(redirect_to) string<delimiter(')content(/some/path)delimiter(')> reserved(end) + + reserved(def) method(redirect_to_named_route)operator(()operator(\)) ident(redirect_to) ident(route_one_url) reserved(end) + + comment(# a redirect to an external location) + reserved(def) method(redirect_external)operator(()operator(\)) ident(redirect_to_url) string<delimiter(")content(http://www.rubyonrails.org)delimiter(")>operator(;) reserved(end) + + comment(# a 404) + reserved(def) method(response404)operator(()operator(\)) ident(render_text) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(404 AWOL)delimiter(")>operator(;) reserved(end) + + comment(# a 500) + reserved(def) method(response500)operator(()operator(\)) ident(render_text) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(500 Sorry)delimiter(")>operator(;) reserved(end) + + comment(# a fictional 599) + reserved(def) method(response599)operator(()operator(\)) ident(render_text) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(599 Whoah!)delimiter(")>operator(;) reserved(end) + + comment(# putting stuff in the flash) + reserved(def) method(flash_me) + ident(flash)operator([)string<delimiter(')content(hello)delimiter(')>operator(]) operator(=) string<delimiter(')content(my name is inigo montoya...)delimiter(')> + ident(render_text) string<delimiter(")content(Inconceivable!)delimiter(")> + reserved(end) + + comment(# we have a flash, but nothing is in it) + reserved(def) method(flash_me_naked) + ident(flash)operator(.)ident(clear) + ident(render_text) string<delimiter(")content(wow!)delimiter(")> + reserved(end) + + comment(# assign some template instance variables) + reserved(def) method(assign_this) + instance_variable(@howdy) operator(=) string<delimiter(")content(ho)delimiter(")> + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(Mr. Henke)delimiter(")> + reserved(end) + + reserved(def) method(render_based_on_parameters) + ident(render_text) string<delimiter(")content(Mr. )inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(name)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(render_url) + ident(render_text) string<delimiter(")content(<div>)inline<inline_delimiter(#{)ident(url_for)operator(()symbol(:action) operator(=)operator(>) string<delimiter(')content(flash_me)delimiter(')>operator(,) symbol(:only_path) operator(=)operator(>) pre_constant(true)operator(\))inline_delimiter(})>content(</div>)delimiter(")> + reserved(end) + + comment(# puts something in the session) + reserved(def) method(session_stuffing) + ident(session)operator([)string<delimiter(')content(xmas)delimiter(')>operator(]) operator(=) string<delimiter(')content(turkey)delimiter(')> + ident(render_text) string<delimiter(")content(ho ho ho)delimiter(")> + reserved(end) + + comment(# raises exception on get requests) + reserved(def) method(raise_on_get) + ident(raise) string<delimiter(")content(get)delimiter(")> reserved(if) instance_variable(@request)operator(.)ident(get?) + ident(render_text) string<delimiter(")content(request method: )inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# raises exception on post requests) + reserved(def) method(raise_on_post) + ident(raise) string<delimiter(")content(post)delimiter(")> reserved(if) instance_variable(@request)operator(.)ident(post?) + ident(render_text) string<delimiter(")content(request method: )inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(get_valid_record) + instance_variable(@record) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(valid?) + pre_constant(true) + reserved(end) + + reserved(def) method(errors) + constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(full_messages)operator(;) operator([)operator(])operator(;) reserved(end) + reserved(end)operator(.)ident(new) + reserved(end) + + reserved(end)operator(.)ident(new) + + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + + reserved(def) method(get_invalid_record) + instance_variable(@record) operator(=) constant(Class)operator(.)ident(new) reserved(do) + + reserved(def) method(valid?) + pre_constant(false) + reserved(end) + + reserved(def) method(errors) + constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(full_messages)operator(;) operator([)string<delimiter(')content(...stuff...)delimiter(')>operator(])operator(;) reserved(end) + reserved(end)operator(.)ident(new) + reserved(end) + reserved(end)operator(.)ident(new) + + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + comment(# 911) + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise)operator(;) reserved(end) +reserved(end) + +reserved(module) class(Admin) + reserved(class) class(InnerModuleController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(redirect_to_absolute_controller) + ident(redirect_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(/content)delimiter(')> + reserved(end) + reserved(def) method(redirect_to_fellow_controller) + ident(redirect_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(user)delimiter(')> + reserved(end) + reserved(end) +reserved(end) + +comment(# ---------------------------------------------------------------------------) + + +comment(# tell the controller where to find its templates but start from parent ) +comment(# directory of test_request_response to simulate the behaviour of a ) +comment(# production environment) +constant(ActionPackAssertionsController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + + +comment(# a test case to exercise the new capabilities TestRequest & TestResponse) +reserved(class) class(ActionPackAssertionsControllerTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + comment(# let's get this party started ) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(ActionPackAssertionsController)operator(.)ident(new) + instance_variable(@request)operator(,) instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(,) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + comment(# -- assertion-based testing ------------------------------------------------) + + reserved(def) method(test_assert_tag_and_url_for) + ident(get) symbol(:render_url) + ident(assert_tag) symbol(:content) operator(=)operator(>) string<delimiter(")content(/action_pack_assertions/flash_me)delimiter(")> + reserved(end) + + comment(# test the session assertion to make sure something is there.) + reserved(def) method(test_assert_session_has) + ident(process) symbol(:session_stuffing) + ident(assert_session_has) string<delimiter(')content(xmas)delimiter(')> + ident(assert_session_has_no) string<delimiter(')content(halloween)delimiter(')> + reserved(end) + + comment(# test the get method, make sure the request really was a get) + reserved(def) method(test_get) + ident(assert_raise)operator(()constant(RuntimeError)operator(\)) operator({) ident(get) symbol(:raise_on_get) operator(}) + ident(get) symbol(:raise_on_post) + ident(assert_equal) instance_variable(@response)operator(.)ident(body)operator(,) string<delimiter(')content(request method: GET)delimiter(')> + reserved(end) + + comment(# test the get method, make sure the request really was a get) + reserved(def) method(test_post) + ident(assert_raise)operator(()constant(RuntimeError)operator(\)) operator({) ident(post) symbol(:raise_on_post) operator(}) + ident(post) symbol(:raise_on_get) + ident(assert_equal) instance_variable(@response)operator(.)ident(body)operator(,) string<delimiter(')content(request method: POST)delimiter(')> + reserved(end) + +comment(# the following test fails because the request_method is now cached on the request instance) +comment(# test the get/post switch within one test action) +comment(# def test_get_post_switch) +comment(# post :raise_on_get) +comment(# assert_equal @response.body, 'request method: POST') +comment(# get :raise_on_post) +comment(# assert_equal @response.body, 'request method: GET') +comment(# post :raise_on_get) +comment(# assert_equal @response.body, 'request method: POST') +comment(# get :raise_on_post) +comment(# assert_equal @response.body, 'request method: GET') +comment(# end) + + comment(# test the assertion of goodies in the template) + reserved(def) method(test_assert_template_has) + ident(process) symbol(:assign_this) + ident(assert_template_has) string<delimiter(')content(howdy)delimiter(')> + reserved(end) + + comment(# test the assertion for goodies that shouldn't exist in the template) + reserved(def) method(test_assert_template_has_no) + ident(process) symbol(:nothing) + ident(assert_template_has_no) string<delimiter(')content(maple syrup)delimiter(')> + ident(assert_template_has_no) string<delimiter(')content(howdy)delimiter(')> + reserved(end) + + comment(# test the redirection assertions) + reserved(def) method(test_assert_redirect) + ident(process) symbol(:redirect_internal) + ident(assert_redirect) + reserved(end) + + comment(# test the redirect url string) + reserved(def) method(test_assert_redirect_url) + ident(process) symbol(:redirect_external) + ident(assert_redirect_url) string<delimiter(')content(http://www.rubyonrails.org)delimiter(')> + reserved(end) + + comment(# test the redirection pattern matching on a string) + reserved(def) method(test_assert_redirect_url_match_string) + ident(process) symbol(:redirect_external) + ident(assert_redirect_url_match) string<delimiter(')content(rails.org)delimiter(')> + reserved(end) + + comment(# test the redirection pattern matching on a pattern) + reserved(def) method(test_assert_redirect_url_match_pattern) + ident(process) symbol(:redirect_external) + ident(assert_redirect_url_match) regexp<delimiter(/)content(ruby)delimiter(/)> + reserved(end) + + comment(# test the redirection to a named route) + reserved(def) method(test_assert_redirect_to_named_route) + ident(process) symbol(:redirect_to_named_route) + ident(assert_raise)operator(()constant(Test)operator(::)constant(Unit)operator(::)constant(AssertionFailedError)operator(\)) reserved(do) + ident(assert_redirected_to) string<delimiter(')content(http://test.host/route_two)delimiter(')> + reserved(end) + reserved(end) + + comment(# test the flash-based assertions with something is in the flash) + reserved(def) method(test_flash_assertions_full) + ident(process) symbol(:flash_me) + ident(assert) instance_variable(@response)operator(.)ident(has_flash_with_contents?) + ident(assert_flash_exists) + ident(assert_flash_not_empty) + ident(assert_flash_has) string<delimiter(')content(hello)delimiter(')> + ident(assert_flash_has_no) string<delimiter(')content(stds)delimiter(')> + reserved(end) + + comment(# test the flash-based assertions with no flash at all) + reserved(def) method(test_flash_assertions_negative) + ident(process) symbol(:nothing) + ident(assert_flash_empty) + ident(assert_flash_has_no) string<delimiter(')content(hello)delimiter(')> + ident(assert_flash_has_no) string<delimiter(')content(qwerty)delimiter(')> + reserved(end) + + comment(# test the assert_rendered_file ) + reserved(def) method(test_assert_rendered_file) + ident(process) symbol(:hello_world) + ident(assert_rendered_file) string<delimiter(')content(test/hello_world)delimiter(')> + ident(assert_rendered_file) string<delimiter(')content(hello_world)delimiter(')> + reserved(end) + + comment(# test the assert_success assertion) + reserved(def) method(test_assert_success) + ident(process) symbol(:nothing) + ident(assert_success) + ident(assert_rendered_file) + reserved(end) + + comment(# -- standard request/response object testing --------------------------------) + + comment(# ensure our session is working properly) + reserved(def) method(test_session_objects) + ident(process) symbol(:session_stuffing) + ident(assert) instance_variable(@response)operator(.)ident(has_session_object?)operator(()string<delimiter(')content(xmas)delimiter(')>operator(\)) + ident(assert_session_equal) string<delimiter(')content(turkey)delimiter(')>operator(,) string<delimiter(')content(xmas)delimiter(')> + ident(assert) operator(!)instance_variable(@response)operator(.)ident(has_session_object?)operator(()string<delimiter(')content(easter)delimiter(')>operator(\)) + reserved(end) + + comment(# make sure that the template objects exist) + reserved(def) method(test_template_objects_alive) + ident(process) symbol(:assign_this) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(has_template_object?)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert) instance_variable(@response)operator(.)ident(has_template_object?)operator(()string<delimiter(')content(howdy)delimiter(')>operator(\)) + reserved(end) + + comment(# make sure we don't have template objects when we shouldn't) + reserved(def) method(test_template_object_missing) + ident(process) symbol(:nothing) + ident(assert_nil) instance_variable(@response)operator(.)ident(template_objects)operator([)string<delimiter(')content(howdy)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_assigned_equal) + ident(process) symbol(:assign_this) + ident(assert_assigned_equal) string<delimiter(")content(ho)delimiter(")>operator(,) symbol(:howdy) + reserved(end) + + comment(# check the empty flashing) + reserved(def) method(test_flash_me_naked) + ident(process) symbol(:flash_me_naked) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(has_flash?) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(has_flash_with_contents?) + reserved(end) + + comment(# check if we have flash objects) + reserved(def) method(test_flash_haves) + ident(process) symbol(:flash_me) + ident(assert) instance_variable(@response)operator(.)ident(has_flash?) + ident(assert) instance_variable(@response)operator(.)ident(has_flash_with_contents?) + ident(assert) instance_variable(@response)operator(.)ident(has_flash_object?)operator(()string<delimiter(')content(hello)delimiter(')>operator(\)) + reserved(end) + + comment(# ensure we don't have flash objects) + reserved(def) method(test_flash_have_nots) + ident(process) symbol(:nothing) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(has_flash?) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(has_flash_with_contents?) + ident(assert_nil) instance_variable(@response)operator(.)ident(flash)operator([)string<delimiter(')content(hello)delimiter(')>operator(]) + reserved(end) + + comment(# examine that the flash objects are what we expect) + reserved(def) method(test_flash_equals) + ident(process) symbol(:flash_me) + ident(assert_flash_equal) string<delimiter(')content(my name is inigo montoya...)delimiter(')>operator(,) string<delimiter(')content(hello)delimiter(')> + reserved(end) + + + comment(# check if we were rendered by a file-based template? ) + reserved(def) method(test_rendered_action) + ident(process) symbol(:nothing) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(rendered_with_file?) + + ident(process) symbol(:hello_world) + ident(assert) instance_variable(@response)operator(.)ident(rendered_with_file?) + ident(assert) string<delimiter(')content(hello_world)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(rendered_file) + reserved(end) + + comment(# check the redirection location) + reserved(def) method(test_redirection_location) + ident(process) symbol(:redirect_internal) + ident(assert_equal) string<delimiter(')content(http://test.host/nothing)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(redirect_url) + + ident(process) symbol(:redirect_external) + ident(assert_equal) string<delimiter(')content(http://www.rubyonrails.org)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(redirect_url) + + ident(process) symbol(:nothing) + ident(assert_nil) instance_variable(@response)operator(.)ident(redirect_url) + reserved(end) + + + comment(# check server errors ) + reserved(def) method(test_server_error_response_code) + ident(process) symbol(:response500) + ident(assert) instance_variable(@response)operator(.)ident(server_error?) + + ident(process) symbol(:response599) + ident(assert) instance_variable(@response)operator(.)ident(server_error?) + + ident(process) symbol(:response404) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(server_error?) + reserved(end) + + comment(# check a 404 response code) + reserved(def) method(test_missing_response_code) + ident(process) symbol(:response404) + ident(assert) instance_variable(@response)operator(.)ident(missing?) + reserved(end) + + comment(# check to see if our redirection matches a pattern) + reserved(def) method(test_redirect_url_match) + ident(process) symbol(:redirect_external) + ident(assert) instance_variable(@response)operator(.)ident(redirect?) + ident(assert) instance_variable(@response)operator(.)ident(redirect_url_match?)operator(()string<delimiter(")content(rubyonrails)delimiter(")>operator(\)) + ident(assert) instance_variable(@response)operator(.)ident(redirect_url_match?)operator(()regexp<delimiter(/)content(rubyonrails)delimiter(/)>operator(\)) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(redirect_url_match?)operator(()string<delimiter(")content(phpoffrails)delimiter(")>operator(\)) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(redirect_url_match?)operator(()regexp<delimiter(/)content(perloffrails)delimiter(/)>operator(\)) + reserved(end) + + comment(# check for a redirection) + reserved(def) method(test_redirection) + ident(process) symbol(:redirect_internal) + ident(assert) instance_variable(@response)operator(.)ident(redirect?) + + ident(process) symbol(:redirect_external) + ident(assert) instance_variable(@response)operator(.)ident(redirect?) + + ident(process) symbol(:nothing) + ident(assert) operator(!)instance_variable(@response)operator(.)ident(redirect?) + reserved(end) + + comment(# check a successful response code) + reserved(def) method(test_successful_response_code) + ident(process) symbol(:nothing) + ident(assert) instance_variable(@response)operator(.)ident(success?) + reserved(end) + + comment(# a basic check to make sure we have a TestResponse object) + reserved(def) method(test_has_response) + ident(process) symbol(:nothing) + ident(assert_kind_of) constant(ActionController)operator(::)constant(TestResponse)operator(,) instance_variable(@response) + reserved(end) + + reserved(def) method(test_render_based_on_parameters) + ident(process) symbol(:render_based_on_parameters)operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David)delimiter(")> + ident(assert_equal) string<delimiter(")content(Mr. David)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_assert_template_xpath_match_no_matches) + ident(process) symbol(:hello_xml_world) + ident(assert_raises) constant(Test)operator(::)constant(Unit)operator(::)constant(AssertionFailedError) reserved(do) + ident(assert_template_xpath_match)operator(()string<delimiter(')content(/no/such/node/in/document)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_simple_one_element_xpath_match) + ident(process) symbol(:hello_xml_world) + ident(assert_template_xpath_match)operator(()string<delimiter(')content(//title)delimiter(')>operator(,) string<delimiter(")content(Hello World)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_array_of_elements_in_xpath_match) + ident(process) symbol(:hello_xml_world) + ident(assert_template_xpath_match)operator(()string<delimiter(')content(//p)delimiter(')>operator(,) string<delimiter(%w()content( abes monks wiseguys )delimiter(\))>operator(\)) + reserved(end) + + reserved(def) method(test_follow_redirect) + ident(process) symbol(:redirect_to_action) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(flash_me)delimiter(")> + + ident(follow_redirect) + ident(assert_equal) integer(1)operator(,) instance_variable(@request)operator(.)ident(parameters)operator([)string<delimiter(")content(id)delimiter(")>operator(])operator(.)ident(to_i) + + ident(assert) string<delimiter(")content(Inconceivable!)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_follow_redirect_outside_current_action) + ident(process) symbol(:redirect_to_controller) + ident(assert_redirected_to) symbol(:controller) operator(=)operator(>) string<delimiter(")content(elsewhere)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(flash_me)delimiter(")> + + ident(assert_raises)operator(()constant(RuntimeError)operator(,) string<delimiter(")content(Can't follow redirects outside of current controller (elsewhere\))delimiter(")>operator(\)) operator({) ident(follow_redirect) operator(}) + reserved(end) + + reserved(def) method(test_redirected_to_url_leadling_slash) + ident(process) symbol(:redirect_to_path) + ident(assert_redirected_to) string<delimiter(')content(/some/path)delimiter(')> + reserved(end) + reserved(def) method(test_redirected_to_url_no_leadling_slash) + ident(process) symbol(:redirect_to_path) + ident(assert_redirected_to) string<delimiter(')content(some/path)delimiter(')> + reserved(end) + reserved(def) method(test_redirected_to_url_full_url) + ident(process) symbol(:redirect_to_path) + ident(assert_redirected_to) string<delimiter(')content(http://test.host/some/path)delimiter(')> + reserved(end) + + reserved(def) method(test_redirected_to_with_nested_controller) + instance_variable(@controller) operator(=) constant(Admin)operator(::)constant(InnerModuleController)operator(.)ident(new) + ident(get) symbol(:redirect_to_absolute_controller) + ident(assert_redirected_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')> + + ident(get) symbol(:redirect_to_fellow_controller) + ident(assert_redirected_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')> + reserved(end) + + reserved(def) method(test_assert_valid) + ident(get) symbol(:get_valid_record) + ident(assert_valid) ident(assigns)operator(()string<delimiter(')content(record)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_assert_valid_failing) + ident(get) symbol(:get_invalid_record) + + reserved(begin) + ident(assert_valid) ident(assigns)operator(()string<delimiter(')content(record)delimiter(')>operator(\)) + ident(assert) pre_constant(false) + reserved(rescue) constant(Test)operator(::)constant(Unit)operator(::)constant(AssertionFailedError) operator(=)operator(>) ident(e) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(ActionPackHeaderTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(ActionPackAssertionsController)operator(.)ident(new) + instance_variable(@request)operator(,) instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(,) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_rendering_xml_sets_content_type) + ident(process) symbol(:hello_xml_world) + ident(assert_equal)operator(()string<delimiter(')content(application/xml)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_rendering_xml_respects_content_type) + instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(]) operator(=) string<delimiter(')content(application/pdf)delimiter(')> + ident(process) symbol(:hello_xml_world) + ident(assert_equal)operator(()string<delimiter(')content(application/pdf)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(])operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(Address) + + reserved(def) constant(Address)operator(.)ident(count)operator(()ident(conditions) operator(=) pre_constant(nil)operator(,) ident(join) operator(=) pre_constant(nil)operator(\)) + pre_constant(nil) + reserved(end) + + reserved(def) constant(Address)operator(.)ident(find_all)operator(()ident(arg1)operator(,) ident(arg2)operator(,) ident(arg3)operator(,) ident(arg4)operator(\)) + operator([)operator(]) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(find)operator(()operator(*)ident(args)operator(\)) + operator([)operator(]) + reserved(end) +reserved(end) + +reserved(class) class(AddressesTestController) operator(<) constant(ActionController)operator(::)constant(Base) + + ident(scaffold) symbol(:address) + + reserved(def) pre_constant(self)operator(.)ident(controller_name)operator(;) string<delimiter(")content(addresses)delimiter(")>operator(;) reserved(end) + reserved(def) pre_constant(self)operator(.)ident(controller_path)operator(;) string<delimiter(")content(addresses)delimiter(")>operator(;) reserved(end) + +reserved(end) + +constant(AddressesTestController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + +reserved(class) class(AddressesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(AddressesTestController)operator(.)ident(new) + + comment(# enable a logger so that (e.g.\) the benchmarking stuff runs, so we can get) + comment(# a more accurate simulation of what happens in "real life".) + instance_variable(@controller)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()pre_constant(nil)operator(\)) + + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.nextangle.com)delimiter(")> + reserved(end) + + reserved(def) method(test_list) + ident(get) symbol(:list) + ident(assert_equal) string<delimiter(")content(We only need to get this far!)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body)operator(.)ident(chomp) + reserved(end) + + +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(pp)delimiter(')> comment(# require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late) + +comment(# Provide some controller to run the tests on.) +reserved(module) class(Submodule) + reserved(class) class(ContainedEmptyController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(end) + reserved(class) class(ContainedNonEmptyController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(public_action) + reserved(end) + + ident(hide_action) symbol(:hidden_action) + reserved(def) method(hidden_action) + reserved(end) + + reserved(def) method(another_hidden_action) + reserved(end) + ident(hide_action) symbol(:another_hidden_action) + reserved(end) + reserved(class) class(SubclassedController) operator(<) constant(ContainedNonEmptyController) + ident(hide_action) symbol(:public_action) comment(# Hiding it here should not affect the superclass.) + reserved(end) +reserved(end) +reserved(class) class(EmptyController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(include) constant(ActionController)operator(::)constant(Caching) +reserved(end) +reserved(class) class(NonEmptyController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(public_action) + reserved(end) + + ident(hide_action) symbol(:hidden_action) + reserved(def) method(hidden_action) + reserved(end) +reserved(end) + +reserved(class) class(ControllerClassTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_controller_path) + ident(assert_equal) string<delimiter(')content(empty)delimiter(')>operator(,) constant(EmptyController)operator(.)ident(controller_path) + ident(assert_equal) string<delimiter(')content(submodule/contained_empty)delimiter(')>operator(,) constant(Submodule)operator(::)constant(ContainedEmptyController)operator(.)ident(controller_path) + reserved(end) + reserved(def) method(test_controller_name) + ident(assert_equal) string<delimiter(')content(empty)delimiter(')>operator(,) constant(EmptyController)operator(.)ident(controller_name) + ident(assert_equal) string<delimiter(')content(contained_empty)delimiter(')>operator(,) constant(Submodule)operator(::)constant(ContainedEmptyController)operator(.)ident(controller_name) + reserved(end) +reserved(end) + +reserved(class) class(ControllerInstanceTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@empty) operator(=) constant(EmptyController)operator(.)ident(new) + instance_variable(@contained) operator(=) constant(Submodule)operator(::)constant(ContainedEmptyController)operator(.)ident(new) + instance_variable(@empty_controllers) operator(=) operator([)instance_variable(@empty)operator(,) instance_variable(@contained)operator(,) constant(Submodule)operator(::)constant(SubclassedController)operator(.)ident(new)operator(]) + + instance_variable(@non_empty_controllers) operator(=) operator([)constant(NonEmptyController)operator(.)ident(new)operator(,) + constant(Submodule)operator(::)constant(ContainedNonEmptyController)operator(.)ident(new)operator(]) + reserved(end) + + reserved(def) method(test_action_methods) + instance_variable(@empty_controllers)operator(.)ident(each) reserved(do) operator(|)ident(c)operator(|) + ident(assert_equal) constant(Set)operator(.)ident(new)operator(,) ident(c)operator(.)ident(send)operator(()symbol(:action_methods)operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(c)operator(.)ident(class)operator(.)ident(controller_path)inline_delimiter(})>content( should be empty!)delimiter(")> + reserved(end) + instance_variable(@non_empty_controllers)operator(.)ident(each) reserved(do) operator(|)ident(c)operator(|) + ident(assert_equal) constant(Set)operator(.)ident(new)operator(()string<delimiter(')content(public_action)delimiter(')>operator(\))operator(,) ident(c)operator(.)ident(send)operator(()symbol(:action_methods)operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(c)operator(.)ident(class)operator(.)ident(controller_path)inline_delimiter(})>content( should not be empty!)delimiter(")> + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(test/unit)delimiter(')> + +comment(# Provide some static controllers.) +reserved(class) class(BenchmarkedController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(public_action) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) + ident(raise) ident(e) + reserved(end) +reserved(end) + +reserved(class) class(BenchmarkTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(MockLogger) + reserved(def) method(method_missing)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(BenchmarkedController)operator(.)ident(new) + comment(# benchmark doesn't do anything unless a logger is set) + instance_variable(@controller)operator(.)ident(logger) operator(=) constant(MockLogger)operator(.)ident(new) + instance_variable(@request)operator(,) instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(,) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(test.actioncontroller.i)delimiter(")> + reserved(end) + + reserved(def) method(test_with_http_1_0_request) + instance_variable(@request)operator(.)ident(host) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(get) symbol(:public_action) operator(}) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(fileutils)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(TestLogDevice) operator(<) constant(Logger)operator(::)constant(LogDevice) + ident(attr) symbol(:last_message)operator(,) pre_constant(true) + + reserved(def) method(initialize) + instance_variable(@last_message)operator(=)constant(String)operator(.)ident(new) + reserved(end) + + reserved(def) method(write)operator(()ident(message)operator(\)) + instance_variable(@last_message) operator(<<) ident(message) + reserved(end) + + reserved(def) method(clear) + instance_variable(@last_message) operator(=) constant(String)operator(.)ident(new) + reserved(end) +reserved(end) + +comment(#setup our really sophisticated logger) +constant(TestLog) operator(=) constant(TestLogDevice)operator(.)ident(new) +constant(RAILS_DEFAULT_LOGGER) operator(=) constant(Logger)operator(.)ident(new)operator(()constant(TestLog)operator(\)) +constant(ActionController)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(RAILS_DEFAULT_LOGGER) + +reserved(def) method(use_store) + comment(#generate a random key to ensure the cache is always in a different location) + constant(RANDOM_KEY) operator(=) ident(rand)operator(()integer(99999999)operator(\))operator(.)ident(to_s) + constant(FILE_STORE_PATH) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../temp/)delimiter(')> operator(+) constant(RANDOM_KEY) + constant(ActionController)operator(::)constant(Base)operator(.)ident(perform_caching) operator(=) pre_constant(true) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) operator(=) symbol(:file_store)operator(,) constant(FILE_STORE_PATH) +reserved(end) + +reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(caches_action) symbol(:render_to_cache)operator(,) symbol(:index) + + reserved(def) method(render_to_cache) + ident(render_text) string<delimiter(")content(Render Cached)delimiter(")> + reserved(end) + reserved(alias) symbol(:index) symbol(:render_to_cache) +reserved(end) + +reserved(class) class(FileStoreTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(hostname.com)delimiter(")> + reserved(end) + + reserved(def) method(teardown) + constant(FileUtils)operator(.)ident(rm_rf)operator(()constant(FILE_STORE_PATH)operator(\)) + reserved(end) + + reserved(def) method(test_render_cached) + ident(assert_fragment_cached) operator({) ident(get) symbol(:render_to_cache) operator(}) + ident(assert_fragment_hit) operator({) ident(get) symbol(:render_to_cache) operator(}) + reserved(end) + + + ident(private) + reserved(def) method(assert_fragment_cached) + reserved(yield) + ident(assert)operator(()constant(TestLog)operator(.)ident(last_message)operator(.)ident(include?)operator(()string<delimiter(")content(Cached fragment:)delimiter(")>operator(\))operator(,) string<delimiter(")content(--ERROR-- FileStore write failed ----)delimiter(")>operator(\)) + ident(assert)operator(()operator(!)constant(TestLog)operator(.)ident(last_message)operator(.)ident(include?)operator(()string<delimiter(")content(Couldn't create cache directory:)delimiter(")>operator(\))operator(,) string<delimiter(")content(--ERROR-- FileStore create directory failed ----)delimiter(")>operator(\)) + constant(TestLog)operator(.)ident(clear) + reserved(end) + + reserved(def) method(assert_fragment_hit) + reserved(yield) + ident(assert)operator(()constant(TestLog)operator(.)ident(last_message)operator(.)ident(include?)operator(()string<delimiter(")content(Fragment read:)delimiter(")>operator(\))operator(,) string<delimiter(")content(--ERROR-- Fragment not found in FileStore ----)delimiter(")>operator(\)) + ident(assert)operator(()operator(!)constant(TestLog)operator(.)ident(last_message)operator(.)ident(include?)operator(()string<delimiter(")content(Cached fragment:)delimiter(")>operator(\))operator(,) string<delimiter(")content(--ERROR-- Did cache ----)delimiter(")>operator(\)) + constant(TestLog)operator(.)ident(clear) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(CaptureController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) pre_constant(self)operator(.)ident(controller_name)operator(;) string<delimiter(")content(test)delimiter(")>operator(;) reserved(end) + reserved(def) pre_constant(self)operator(.)ident(controller_path)operator(;) string<delimiter(")content(test)delimiter(")>operator(;) reserved(end) + + reserved(def) method(content_for) + ident(render) symbol(:layout) operator(=)operator(>) string<delimiter(")content(talk_from_action)delimiter(")> + reserved(end) + + reserved(def) method(erb_content_for) + ident(render) symbol(:layout) operator(=)operator(>) string<delimiter(")content(talk_from_action)delimiter(")> + reserved(end) + + reserved(def) method(block_content_for) + ident(render) symbol(:layout) operator(=)operator(>) string<delimiter(")content(talk_from_action)delimiter(")> + reserved(end) + + reserved(def) method(non_erb_block_content_for) + ident(render) symbol(:layout) operator(=)operator(>) string<delimiter(")content(talk_from_action)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) +reserved(end) + +constant(CaptureController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + +reserved(class) class(CaptureTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(CaptureController)operator(.)ident(new) + + comment(# enable a logger so that (e.g.\) the benchmarking stuff runs, so we can get) + comment(# a more accurate simulation of what happens in "real life".) + instance_variable(@controller)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()pre_constant(nil)operator(\)) + + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.nextangle.com)delimiter(")> + reserved(end) + + reserved(def) method(test_simple_capture) + ident(get) symbol(:capturing) + ident(assert_equal) string<delimiter(")content(Dreamy days)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body)operator(.)ident(strip) + reserved(end) + + reserved(def) method(test_content_for) + ident(get) symbol(:content_for) + ident(assert_equal) ident(expected_content_for_output)operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_erb_content_for) + ident(get) symbol(:content_for) + ident(assert_equal) ident(expected_content_for_output)operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_block_content_for) + ident(get) symbol(:block_content_for) + ident(assert_equal) ident(expected_content_for_output)operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_non_erb_block_content_for) + ident(get) symbol(:non_erb_block_content_for) + ident(assert_equal) ident(expected_content_for_output)operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_update_element_with_capture) + ident(get) symbol(:update_element_with_capture) + ident(assert_equal)operator(() + string<delimiter(")content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content($('products'\).innerHTML = ')char(\\\\)content(n <p>Product 1</p>)char(\\\\)content(n <p>Product 2</p>)char(\\\\)content(n';)char(\\n)char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(")> operator(+) + string<delimiter(")char(\\n)char(\\n)content($('status'\).innerHTML = ')char(\\\\)content(n <b>You bought something!</b>)char(\\\\)content(n';)delimiter(")>operator(,) + instance_variable(@response)operator(.)ident(body)operator(.)ident(strip) + operator(\)) + reserved(end) + + ident(private) + reserved(def) method(expected_content_for_output) + string<delimiter(")content(<title>Putting stuff in the title!</title>)char(\\n)char(\\n)content(Great stuff!)delimiter(")> + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cgi_process)delimiter(')> +ident(require) string<delimiter(')content(action_controller/cgi_ext/cgi_ext)delimiter(')> + + +ident(require) string<delimiter(')content(stringio)delimiter(')> + +reserved(class) class(CGITest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@query_string) operator(=) string<delimiter(")content(action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1)delimiter(")> + instance_variable(@query_string_with_nil) operator(=) string<delimiter(")content(action=create_customer&full_name=)delimiter(")> + instance_variable(@query_string_with_array) operator(=) string<delimiter(")content(action=create_customer&selected[]=1&selected[]=2&selected[]=3)delimiter(")> + instance_variable(@query_string_with_amps) operator(=) string<delimiter(")content(action=create_customer&name=Don%27t+%26+Does)delimiter(")> + instance_variable(@query_string_with_multiple_of_same_name) operator(=) + string<delimiter(")content(action=update_order&full_name=Lau%20Taarnskov&products=4&products=2&products=3)delimiter(")> + instance_variable(@query_string_with_many_equal) operator(=) string<delimiter(")content(action=create_customer&full_name=abc=def=ghi)delimiter(")> + instance_variable(@query_string_without_equal) operator(=) string<delimiter(")content(action)delimiter(")> + instance_variable(@query_string_with_many_ampersands) operator(=) + string<delimiter(")content(&action=create_customer&&&full_name=David%20Heinemeier%20Hansson)delimiter(")> + reserved(end) + + reserved(def) method(test_query_string) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(create_customer)delimiter(")>operator(,) string<delimiter(")content(full_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(,) string<delimiter(")content(customerId)delimiter(")> operator(=)operator(>) string<delimiter(")content(1)delimiter(")>operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_deep_query_string) + ident(assert_equal)operator(()operator({)string<delimiter(')content(x)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(y)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(z)delimiter(')> operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(})operator(})operator(,) constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()string<delimiter(')content(x[y][z]=10)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_deep_query_string_with_array) + ident(assert_equal)operator(()operator({)string<delimiter(')content(x)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(y)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(z)delimiter(')> operator(=)operator(>) operator([)string<delimiter(')content(10)delimiter(')>operator(])operator(})operator(})operator(})operator(,) constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()string<delimiter(')content(x[y][z][]=10)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)string<delimiter(')content(x)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(y)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(z)delimiter(')> operator(=)operator(>) operator([)string<delimiter(')content(10)delimiter(')>operator(,) string<delimiter(')content(5)delimiter(')>operator(])operator(})operator(})operator(})operator(,) constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()string<delimiter(')content(x[y][z][]=10&x[y][z][]=5)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_query_string_with_nil) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(create_customer)delimiter(")>operator(,) string<delimiter(")content(full_name)delimiter(")> operator(=)operator(>) pre_constant(nil)operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string_with_nil)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_query_string_with_array) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(create_customer)delimiter(")>operator(,) string<delimiter(")content(selected)delimiter(")> operator(=)operator(>) operator([)string<delimiter(")content(1)delimiter(")>operator(,) string<delimiter(")content(2)delimiter(")>operator(,) string<delimiter(")content(3)delimiter(")>operator(])operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string_with_array)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_query_string_with_amps) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(create_customer)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Don't & Does)delimiter(")>operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string_with_amps)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_query_string_with_many_equal) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(create_customer)delimiter(")>operator(,) string<delimiter(")content(full_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc=def=ghi)delimiter(")>operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string_with_many_equal)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_query_string_without_equal) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) pre_constant(nil) operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string_without_equal)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_query_string_with_many_ampersands) + ident(assert_equal)operator(() + operator({) string<delimiter(")content(action)delimiter(")> operator(=)operator(>) string<delimiter(")content(create_customer)delimiter(")>operator(,) string<delimiter(")content(full_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(})operator(,) + constant(CGIMethods)operator(.)ident(parse_query_parameters)operator(()instance_variable(@query_string_with_many_ampersands)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_parse_params) + ident(input) operator(=) operator({) + string<delimiter(")content(customers[boston][first][name])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(David)delimiter(")> operator(])operator(,) + string<delimiter(")content(customers[boston][first][url])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(http://David)delimiter(")> operator(])operator(,) + string<delimiter(")content(customers[boston][second][name])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(Allan)delimiter(")> operator(])operator(,) + string<delimiter(")content(customers[boston][second][url])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(http://Allan)delimiter(")> operator(])operator(,) + string<delimiter(")content(something_else)delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(blah)delimiter(")> operator(])operator(,) + string<delimiter(")content(something_nil)delimiter(")> operator(=)operator(>) operator([) pre_constant(nil) operator(])operator(,) + string<delimiter(")content(something_empty)delimiter(")> operator(=)operator(>) operator([) string<delimiter(")delimiter(")> operator(])operator(,) + string<delimiter(")content(products[first])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(Apple Computer)delimiter(")> operator(])operator(,) + string<delimiter(")content(products[second])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(Pc)delimiter(")> operator(]) + operator(}) + + ident(expected_output) operator(=) operator({) + string<delimiter(")content(customers)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(boston)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(first)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David)delimiter(")>operator(,) + string<delimiter(")content(url)delimiter(")> operator(=)operator(>) string<delimiter(")content(http://David)delimiter(")> + operator(})operator(,) + string<delimiter(")content(second)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Allan)delimiter(")>operator(,) + string<delimiter(")content(url)delimiter(")> operator(=)operator(>) string<delimiter(")content(http://Allan)delimiter(")> + operator(}) + operator(}) + operator(})operator(,) + string<delimiter(")content(something_else)delimiter(")> operator(=)operator(>) string<delimiter(")content(blah)delimiter(")>operator(,) + string<delimiter(")content(something_empty)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + string<delimiter(")content(something_nil)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + string<delimiter(")content(products)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(first)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple Computer)delimiter(")>operator(,) + string<delimiter(")content(second)delimiter(")> operator(=)operator(>) string<delimiter(")content(Pc)delimiter(")> + operator(}) + operator(}) + + ident(assert_equal) ident(expected_output)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_from_multipart_upload) + ident(mockup) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:content_type)operator(,) symbol(:original_filename)operator(\)) + ident(file) operator(=) ident(mockup)operator(.)ident(new)operator(()string<delimiter(')content(img/jpeg)delimiter(')>operator(,) string<delimiter(')content(foo.jpg)delimiter(')>operator(\)) + ident(ie_file) operator(=) ident(mockup)operator(.)ident(new)operator(()string<delimiter(')content(img/jpeg)delimiter(')>operator(,) string<delimiter(')content(c:)char(\\\\)content(Documents and Settings)char(\\\\)content(foo)char(\\\\)content(Desktop)char(\\\\)content(bar.jpg)delimiter(')>operator(\)) + + ident(input) operator(=) operator({) + string<delimiter(")content(something)delimiter(")> operator(=)operator(>) operator([) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")delimiter(")>operator(\)) operator(])operator(,) + string<delimiter(")content(array_of_stringios)delimiter(")> operator(=)operator(>) operator([)operator([) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(One)delimiter(")>operator(\))operator(,) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(Two)delimiter(")>operator(\)) operator(])operator(])operator(,) + string<delimiter(")content(mixed_types_array)delimiter(")> operator(=)operator(>) operator([)operator([) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(Three)delimiter(")>operator(\))operator(,) string<delimiter(")content(NotStringIO)delimiter(")> operator(])operator(])operator(,) + string<delimiter(")content(mixed_types_as_checkboxes[strings][nested])delimiter(")> operator(=)operator(>) operator([)operator([) ident(file)operator(,) string<delimiter(")content(String)delimiter(")>operator(,) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(StringIO)delimiter(")>operator(\))operator(])operator(])operator(,) + string<delimiter(")content(ie_mixed_types_as_checkboxes[strings][nested])delimiter(")> operator(=)operator(>) operator([)operator([) ident(ie_file)operator(,) string<delimiter(")content(String)delimiter(")>operator(,) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(StringIO)delimiter(")>operator(\))operator(])operator(])operator(,) + string<delimiter(")content(products[string])delimiter(")> operator(=)operator(>) operator([) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(Apple Computer)delimiter(")>operator(\)) operator(])operator(,) + string<delimiter(")content(products[file])delimiter(")> operator(=)operator(>) operator([) ident(file) operator(])operator(,) + string<delimiter(")content(ie_products[string])delimiter(")> operator(=)operator(>) operator([) constant(StringIO)operator(.)ident(new)operator(()string<delimiter(")content(Microsoft)delimiter(")>operator(\)) operator(])operator(,) + string<delimiter(")content(ie_products[file])delimiter(")> operator(=)operator(>) operator([) ident(ie_file) operator(]) + operator(}) + + ident(expected_output) operator(=) operator({) + string<delimiter(")content(something)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + string<delimiter(")content(array_of_stringios)delimiter(")> operator(=)operator(>) operator([)string<delimiter(")content(One)delimiter(")>operator(,) string<delimiter(")content(Two)delimiter(")>operator(])operator(,) + string<delimiter(")content(mixed_types_array)delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(Three)delimiter(")>operator(,) string<delimiter(")content(NotStringIO)delimiter(")> operator(])operator(,) + string<delimiter(")content(mixed_types_as_checkboxes)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(strings)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(nested)delimiter(")> operator(=)operator(>) operator([) ident(file)operator(,) string<delimiter(")content(String)delimiter(")>operator(,) string<delimiter(")content(StringIO)delimiter(")> operator(]) + operator(})operator(,) + operator(})operator(,) + string<delimiter(")content(ie_mixed_types_as_checkboxes)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(strings)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(nested)delimiter(")> operator(=)operator(>) operator([) ident(ie_file)operator(,) string<delimiter(")content(String)delimiter(")>operator(,) string<delimiter(")content(StringIO)delimiter(")> operator(]) + operator(})operator(,) + operator(})operator(,) + string<delimiter(")content(products)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(string)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple Computer)delimiter(")>operator(,) + string<delimiter(")content(file)delimiter(")> operator(=)operator(>) ident(file) + operator(})operator(,) + string<delimiter(")content(ie_products)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(string)delimiter(")> operator(=)operator(>) string<delimiter(")content(Microsoft)delimiter(")>operator(,) + string<delimiter(")content(file)delimiter(")> operator(=)operator(>) ident(ie_file) + operator(}) + operator(}) + + ident(params) operator(=) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + ident(assert_equal) ident(expected_output)operator(,) ident(params) + + comment(# Lone filenames are preserved.) + ident(assert_equal) string<delimiter(')content(foo.jpg)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(mixed_types_as_checkboxes)delimiter(')>operator(])operator([)string<delimiter(')content(strings)delimiter(')>operator(])operator([)string<delimiter(')content(nested)delimiter(')>operator(])operator(.)ident(first)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(')content(foo.jpg)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(products)delimiter(')>operator(])operator([)string<delimiter(')content(file)delimiter(')>operator(])operator(.)ident(original_filename) + + comment(# But full Windows paths are reduced to their basename.) + ident(assert_equal) string<delimiter(')content(bar.jpg)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(ie_mixed_types_as_checkboxes)delimiter(')>operator(])operator([)string<delimiter(')content(strings)delimiter(')>operator(])operator([)string<delimiter(')content(nested)delimiter(')>operator(])operator(.)ident(first)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(')content(bar.jpg)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(ie_products)delimiter(')>operator(])operator([)string<delimiter(')content(file)delimiter(')>operator(])operator(.)ident(original_filename) + reserved(end) + + reserved(def) method(test_parse_params_with_file) + ident(input) operator(=) operator({) + string<delimiter(")content(customers[boston][first][name])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(David)delimiter(")> operator(])operator(,) + string<delimiter(")content(something_else)delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(blah)delimiter(")> operator(])operator(,) + string<delimiter(")content(logo)delimiter(")> operator(=)operator(>) operator([) constant(File)operator(.)ident(new)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/cgi_test.rb)delimiter(")>operator(\))operator(.)ident(path) operator(]) + operator(}) + + ident(expected_output) operator(=) operator({) + string<delimiter(")content(customers)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(boston)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(first)delimiter(")> operator(=)operator(>) operator({) + string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David)delimiter(")> + operator(}) + operator(}) + operator(})operator(,) + string<delimiter(")content(something_else)delimiter(")> operator(=)operator(>) string<delimiter(")content(blah)delimiter(")>operator(,) + string<delimiter(")content(logo)delimiter(")> operator(=)operator(>) constant(File)operator(.)ident(new)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/cgi_test.rb)delimiter(")>operator(\))operator(.)ident(path)operator(,) + operator(}) + + ident(assert_equal) ident(expected_output)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_with_array) + ident(input) operator(=) operator({) string<delimiter(")content(selected[])delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(1)delimiter(")>operator(,) string<delimiter(")content(2)delimiter(")>operator(,) string<delimiter(")content(3)delimiter(")> operator(]) operator(}) + + ident(expected_output) operator(=) operator({) string<delimiter(")content(selected)delimiter(")> operator(=)operator(>) operator([) string<delimiter(")content(1)delimiter(")>operator(,) string<delimiter(")content(2)delimiter(")>operator(,) string<delimiter(")content(3)delimiter(")> operator(]) operator(}) + + ident(assert_equal) ident(expected_output)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_with_non_alphanumeric_name) + ident(input) operator(=) operator({) string<delimiter(")content(a/b[c])delimiter(")> operator(=)operator(>) string<delimiter(%w()content(d)delimiter(\))> operator(}) + ident(expected) operator(=) operator({) string<delimiter(")content(a/b)delimiter(")> operator(=)operator(>) operator({) string<delimiter(")content(c)delimiter(")> operator(=)operator(>) string<delimiter(")content(d)delimiter(")> operator(})operator(}) + ident(assert_equal) ident(expected)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_with_single_brackets_in_middle) + ident(input) operator(=) operator({) string<delimiter(")content(a/b[c]d)delimiter(")> operator(=)operator(>) string<delimiter(%w()content(e)delimiter(\))> operator(}) + ident(expected) operator(=) operator({) string<delimiter(")content(a/b[c]d)delimiter(")> operator(=)operator(>) string<delimiter(")content(e)delimiter(")> operator(}) + ident(assert_equal) ident(expected)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_with_separated_brackets) + ident(input) operator(=) operator({) string<delimiter(")content(a/b@[c]d[e])delimiter(")> operator(=)operator(>) string<delimiter(%w()content(f)delimiter(\))> operator(}) + ident(expected) operator(=) operator({) string<delimiter(")content(a/b@)delimiter(")> operator(=)operator(>) operator({) string<delimiter(")content(c]d[e)delimiter(")> operator(=)operator(>) string<delimiter(")content(f)delimiter(")> operator(})operator(}) + ident(assert_equal) ident(expected)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_with_separated_brackets_and_array) + ident(input) operator(=) operator({) string<delimiter(")content(a/b@[c]d[e][])delimiter(")> operator(=)operator(>) string<delimiter(%w()content(f)delimiter(\))> operator(}) + ident(expected) operator(=) operator({) string<delimiter(")content(a/b@)delimiter(")> operator(=)operator(>) operator({) string<delimiter(")content(c]d[e)delimiter(")> operator(=)operator(>) operator([)string<delimiter(")content(f)delimiter(")>operator(]) operator(})operator(}) + ident(assert_equal) ident(expected) operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) + + reserved(def) method(test_parse_params_with_unmatched_brackets_and_array) + ident(input) operator(=) operator({) string<delimiter(")content(a/b@[c][d[e][])delimiter(")> operator(=)operator(>) string<delimiter(%w()content(f)delimiter(\))> operator(}) + ident(expected) operator(=) operator({) string<delimiter(")content(a/b@)delimiter(")> operator(=)operator(>) operator({) string<delimiter(")content(c)delimiter(")> operator(=)operator(>) operator({) string<delimiter(")content(d[e)delimiter(")> operator(=)operator(>) operator([)string<delimiter(")content(f)delimiter(")>operator(]) operator(})operator(})operator(}) + ident(assert_equal) ident(expected)operator(,) constant(CGIMethods)operator(.)ident(parse_request_parameters)operator(()ident(input)operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(MultipartCGITest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + constant(FIXTURE_PATH) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../fixtures/multipart)delimiter(')> + + reserved(def) method(setup) + constant(ENV)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(POST)delimiter(')> + constant(ENV)operator([)string<delimiter(')content(CONTENT_LENGTH)delimiter(')>operator(]) operator(=) string<delimiter(')content(0)delimiter(')> + constant(ENV)operator([)string<delimiter(')content(CONTENT_TYPE)delimiter(')>operator(]) operator(=) string<delimiter(')content(multipart/form-data, boundary=AaB03x)delimiter(')> + reserved(end) + + reserved(def) method(test_single_parameter) + ident(params) operator(=) ident(process)operator(()string<delimiter(')content(single_parameter)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({) string<delimiter(')content(foo)delimiter(')> operator(=)operator(>) string<delimiter(')content(bar)delimiter(')> operator(})operator(,) ident(params)operator(\)) + reserved(end) + + reserved(def) method(test_text_file) + ident(params) operator(=) ident(process)operator(()string<delimiter(')content(text_file)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%w()content(file foo)delimiter(\))>operator(,) ident(params)operator(.)ident(keys)operator(.)ident(sort) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + + ident(file) operator(=) ident(params)operator([)string<delimiter(')content(file)delimiter(')>operator(]) + ident(assert_kind_of) constant(StringIO)operator(,) ident(file) + ident(assert_equal) string<delimiter(')content(file.txt)delimiter(')>operator(,) ident(file)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(")content(text/plain)char(\\r)delimiter(")>operator(,) ident(file)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(')content(contents)delimiter(')>operator(,) ident(file)operator(.)ident(read) + reserved(end) + + reserved(def) method(test_large_text_file) + ident(params) operator(=) ident(process)operator(()string<delimiter(')content(large_text_file)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%w()content(file foo)delimiter(\))>operator(,) ident(params)operator(.)ident(keys)operator(.)ident(sort) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + + ident(file) operator(=) ident(params)operator([)string<delimiter(')content(file)delimiter(')>operator(]) + ident(assert_kind_of) constant(Tempfile)operator(,) ident(file) + ident(assert_equal) string<delimiter(')content(file.txt)delimiter(')>operator(,) ident(file)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(")content(text/plain)char(\\r)delimiter(")>operator(,) ident(file)operator(.)ident(content_type) + ident(assert) operator(()string<delimiter(')content(a)delimiter(')> operator(*) integer(20480)operator(\)) operator(==) ident(file)operator(.)ident(read) + reserved(end) + + reserved(def) method(test_binary_file) + ident(params) operator(=) ident(process)operator(()string<delimiter(')content(binary_file)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%w()content(file flowers foo)delimiter(\))>operator(,) ident(params)operator(.)ident(keys)operator(.)ident(sort) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + + ident(file) operator(=) ident(params)operator([)string<delimiter(')content(file)delimiter(')>operator(]) + ident(assert_kind_of) constant(StringIO)operator(,) ident(file) + ident(assert_equal) string<delimiter(')content(file.txt)delimiter(')>operator(,) ident(file)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(")content(text/plain)char(\\r)delimiter(")>operator(,) ident(file)operator(.)ident(content_type) + ident(assert_equal) string<delimiter(')content(contents)delimiter(')>operator(,) ident(file)operator(.)ident(read) + + ident(file) operator(=) ident(params)operator([)string<delimiter(')content(flowers)delimiter(')>operator(]) + ident(assert_kind_of) constant(StringIO)operator(,) ident(file) + ident(assert_equal) string<delimiter(')content(flowers.jpg)delimiter(')>operator(,) ident(file)operator(.)ident(original_filename) + ident(assert_equal) string<delimiter(")content(image/jpeg)char(\\r)delimiter(")>operator(,) ident(file)operator(.)ident(content_type) + ident(assert_equal) integer(19512)operator(,) ident(file)operator(.)ident(size) + comment(#assert_equal File.read(File.dirname(__FILE__\) + '/../../../activerecord/test/fixtures/flowers.jpg'\), file.read) + reserved(end) + + reserved(def) method(test_mixed_files) + ident(params) operator(=) ident(process)operator(()string<delimiter(')content(mixed_files)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%w()content(files foo)delimiter(\))>operator(,) ident(params)operator(.)ident(keys)operator(.)ident(sort) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(params)operator([)string<delimiter(')content(foo)delimiter(')>operator(]) + + comment(# Ruby CGI doesn't handle multipart/mixed for us.) + ident(assert_kind_of) constant(StringIO)operator(,) ident(params)operator([)string<delimiter(')content(files)delimiter(')>operator(]) + ident(assert_equal) integer(19756)operator(,) ident(params)operator([)string<delimiter(')content(files)delimiter(')>operator(])operator(.)ident(size) + reserved(end) + + ident(private) + reserved(def) method(process)operator(()ident(name)operator(\)) + ident(old_stdin) operator(=) global_variable($stdin) + constant(File)operator(.)ident(open)operator(()constant(File)operator(.)ident(join)operator(()constant(FIXTURE_PATH)operator(,) ident(name)operator(\))operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) reserved(do) operator(|)ident(file)operator(|) + constant(ENV)operator([)string<delimiter(')content(CONTENT_LENGTH)delimiter(')>operator(]) operator(=) ident(file)operator(.)ident(stat)operator(.)ident(size)operator(.)ident(to_s) + global_variable($stdin) operator(=) ident(file) + constant(CGIMethods)operator(.)ident(parse_request_parameters) constant(CGI)operator(.)ident(new)operator(.)ident(params) + reserved(end) + reserved(ensure) + global_variable($stdin) operator(=) ident(old_stdin) + reserved(end) +reserved(end) + + +reserved(class) class(CGIRequestTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request_hash) operator(=) operator({)string<delimiter(")content(HTTP_MAX_FORWARDS)delimiter(")>operator(=)operator(>)string<delimiter(")content(10)delimiter(")>operator(,) string<delimiter(")content(SERVER_NAME)delimiter(")>operator(=)operator(>)string<delimiter(")content(glu.ttono.us:8007)delimiter(")>operator(,) string<delimiter(")content(FCGI_ROLE)delimiter(")>operator(=)operator(>)string<delimiter(")content(RESPONDER)delimiter(")>operator(,) string<delimiter(")content(HTTP_X_FORWARDED_HOST)delimiter(")>operator(=)operator(>)string<delimiter(")content(glu.ttono.us)delimiter(")>operator(,) string<delimiter(")content(HTTP_ACCEPT_ENCODING)delimiter(")>operator(=)operator(>)string<delimiter(")content(gzip, deflate)delimiter(")>operator(,) string<delimiter(")content(HTTP_USER_AGENT)delimiter(")>operator(=)operator(>)string<delimiter(")content(Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en\) AppleWebKit/312.5.1 (KHTML, like Gecko\) Safari/312.3.1)delimiter(")>operator(,) string<delimiter(")content(PATH_INFO)delimiter(")>operator(=)operator(>)string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(HTTP_ACCEPT_LANGUAGE)delimiter(")>operator(=)operator(>)string<delimiter(")content(en)delimiter(")>operator(,) string<delimiter(")content(HTTP_HOST)delimiter(")>operator(=)operator(>)string<delimiter(")content(glu.ttono.us:8007)delimiter(")>operator(,) string<delimiter(")content(SERVER_PROTOCOL)delimiter(")>operator(=)operator(>)string<delimiter(")content(HTTP/1.1)delimiter(")>operator(,) string<delimiter(")content(REDIRECT_URI)delimiter(")>operator(=)operator(>)string<delimiter(")content(/dispatch.fcgi)delimiter(")>operator(,) string<delimiter(")content(SCRIPT_NAME)delimiter(")>operator(=)operator(>)string<delimiter(")content(/dispatch.fcgi)delimiter(")>operator(,) string<delimiter(")content(SERVER_ADDR)delimiter(")>operator(=)operator(>)string<delimiter(")content(207.7.108.53)delimiter(")>operator(,) string<delimiter(")content(REMOTE_ADDR)delimiter(")>operator(=)operator(>)string<delimiter(")content(207.7.108.53)delimiter(")>operator(,) string<delimiter(")content(SERVER_SOFTWARE)delimiter(")>operator(=)operator(>)string<delimiter(")content(lighttpd/1.4.5)delimiter(")>operator(,) string<delimiter(")content(HTTP_COOKIE)delimiter(")>operator(=)operator(>)string<delimiter(")content(_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes)delimiter(")>operator(,) string<delimiter(")content(HTTP_X_FORWARDED_SERVER)delimiter(")>operator(=)operator(>)string<delimiter(")content(glu.ttono.us)delimiter(")>operator(,) string<delimiter(")content(REQUEST_URI)delimiter(")>operator(=)operator(>)string<delimiter(")content(/admin)delimiter(")>operator(,) string<delimiter(")content(DOCUMENT_ROOT)delimiter(")>operator(=)operator(>)string<delimiter(")content(/home/kevinc/sites/typo/public)delimiter(")>operator(,) string<delimiter(")content(SERVER_PORT)delimiter(")>operator(=)operator(>)string<delimiter(")content(8007)delimiter(")>operator(,) string<delimiter(")content(QUERY_STRING)delimiter(")>operator(=)operator(>)string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(REMOTE_PORT)delimiter(")>operator(=)operator(>)string<delimiter(")content(63137)delimiter(")>operator(,) string<delimiter(")content(GATEWAY_INTERFACE)delimiter(")>operator(=)operator(>)string<delimiter(")content(CGI/1.1)delimiter(")>operator(,) string<delimiter(")content(HTTP_X_FORWARDED_FOR)delimiter(")>operator(=)operator(>)string<delimiter(")content(65.88.180.234)delimiter(")>operator(,) string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(=)operator(>)string<delimiter(")content(*/*)delimiter(")>operator(,) string<delimiter(")content(SCRIPT_FILENAME)delimiter(")>operator(=)operator(>)string<delimiter(")content(/home/kevinc/sites/typo/public/dispatch.fcgi)delimiter(")>operator(,) string<delimiter(")content(REDIRECT_STATUS)delimiter(")>operator(=)operator(>)string<delimiter(")content(200)delimiter(")>operator(,) string<delimiter(")content(REQUEST_METHOD)delimiter(")>operator(=)operator(>)string<delimiter(")content(GET)delimiter(")>operator(}) + comment(# cookie as returned by some Nokia phone browsers (no space after semicolon separator\)) + instance_variable(@alt_cookie_fmt_request_hash) operator(=) operator({)string<delimiter(")content(HTTP_COOKIE)delimiter(")>operator(=)operator(>)string<delimiter(")content(_session_id=c84ace84796670c052c6ceb2451fb0f2;is_admin=yes)delimiter(")>operator(}) + instance_variable(@fake_cgi) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:env_table)operator(\))operator(.)ident(new)operator(()instance_variable(@request_hash)operator(\)) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(CgiRequest)operator(.)ident(new)operator(()instance_variable(@fake_cgi)operator(\)) + reserved(end) + + reserved(def) method(test_proxy_request) + ident(assert_equal) string<delimiter(')content(glu.ttono.us)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + reserved(end) + + reserved(def) method(test_http_host) + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(HTTP_X_FORWARDED_HOST)delimiter(")> + instance_variable(@request_hash)operator([)string<delimiter(')content(HTTP_HOST)delimiter(')>operator(]) operator(=) string<delimiter(")content(rubyonrails.org:8080)delimiter(")> + ident(assert_equal) string<delimiter(")content(rubyonrails.org:8080)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + + instance_variable(@request_hash)operator([)string<delimiter(')content(HTTP_X_FORWARDED_HOST)delimiter(')>operator(]) operator(=) string<delimiter(")content(www.firsthost.org, www.secondhost.org)delimiter(")> + ident(assert_equal) string<delimiter(")content(www.secondhost.org)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host) + reserved(end) + + reserved(def) method(test_http_host_with_default_port_overrides_server_port) + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(HTTP_X_FORWARDED_HOST)delimiter(")> + instance_variable(@request_hash)operator([)string<delimiter(')content(HTTP_HOST)delimiter(')>operator(]) operator(=) string<delimiter(")content(rubyonrails.org)delimiter(")> + ident(assert_equal) string<delimiter(")content(rubyonrails.org)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + reserved(end) + + reserved(def) method(test_host_with_port_defaults_to_server_name_if_no_host_headers) + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(HTTP_X_FORWARDED_HOST)delimiter(")> + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(HTTP_HOST)delimiter(")> + ident(assert_equal) string<delimiter(")content(glu.ttono.us:8007)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + reserved(end) + + reserved(def) method(test_host_with_port_falls_back_to_server_addr_if_necessary) + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(HTTP_X_FORWARDED_HOST)delimiter(")> + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(HTTP_HOST)delimiter(")> + instance_variable(@request_hash)operator(.)ident(delete) string<delimiter(")content(SERVER_NAME)delimiter(")> + ident(assert_equal) string<delimiter(")content(207.7.108.53:8007)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + reserved(end) + + reserved(def) method(test_cookie_syntax_resilience) + ident(cookies) operator(=) constant(CGI)operator(::)constant(Cookie)operator(::)ident(parse)operator(()instance_variable(@request_hash)operator([)string<delimiter(")content(HTTP_COOKIE)delimiter(")>operator(])operator(\))operator(;) + ident(assert_equal) operator([)string<delimiter(")content(c84ace84796670c052c6ceb2451fb0f2)delimiter(")>operator(])operator(,) ident(cookies)operator([)string<delimiter(")content(_session_id)delimiter(")>operator(]) + ident(assert_equal) operator([)string<delimiter(")content(yes)delimiter(")>operator(])operator(,) ident(cookies)operator([)string<delimiter(")content(is_admin)delimiter(")>operator(]) + + ident(alt_cookies) operator(=) constant(CGI)operator(::)constant(Cookie)operator(::)ident(parse)operator(()instance_variable(@alt_cookie_fmt_request_hash)operator([)string<delimiter(")content(HTTP_COOKIE)delimiter(")>operator(])operator(\))operator(;) + ident(assert_equal) operator([)string<delimiter(")content(c84ace84796670c052c6ceb2451fb0f2)delimiter(")>operator(])operator(,) ident(alt_cookies)operator([)string<delimiter(")content(_session_id)delimiter(")>operator(]) + ident(assert_equal) operator([)string<delimiter(")content(yes)delimiter(")>operator(])operator(,) ident(alt_cookies)operator([)string<delimiter(")content(is_admin)delimiter(")>operator(]) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(CallerController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(calling_from_controller) + ident(render_component)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(being_called)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(calling_from_controller_with_params) + ident(render_component)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(being_called)delimiter(")>operator(,) symbol(:params) operator(=)operator(>) operator({) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(calling_from_controller_with_different_status_code) + ident(render_component)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(blowing_up)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(calling_from_template) + ident(render_template) string<delimiter(")content(Ring, ring: <%= render_component(:controller => 'callee', :action => 'being_called'\) %>)delimiter(")> + reserved(end) + + reserved(def) method(internal_caller) + ident(render_template) string<delimiter(")content(Are you there? <%= render_component(:action => 'internal_callee'\) %>)delimiter(")> + reserved(end) + + reserved(def) method(internal_callee) + ident(render_text) string<delimiter(")content(Yes, ma'am)delimiter(")> + reserved(end) + + reserved(def) method(set_flash) + ident(render_component)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(set_flash)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(use_flash) + ident(render_component)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(use_flash)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(calling_redirected) + ident(render_component)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(redirected)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(calling_redirected_as_string) + ident(render_template) string<delimiter(")content(<%= render_component(:controller => 'callee', :action => 'redirected'\) %>)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) +reserved(end) + +reserved(class) class(CalleeController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(being_called) + ident(render_text) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(name)delimiter(")>operator(]) operator(||) string<delimiter(")content(Lady)delimiter(")>inline_delimiter(})>content( of the House, speaking)delimiter(")> + reserved(end) + + reserved(def) method(blowing_up) + ident(render_text) string<delimiter(")content(It's game over, man, just game over, man!)delimiter(")>operator(,) string<delimiter(")content(500 Internal Server Error)delimiter(")> + reserved(end) + + reserved(def) method(set_flash) + ident(flash)operator([)symbol(:notice)operator(]) operator(=) string<delimiter(')content(My stoney baby)delimiter(')> + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(')content(flash is set)delimiter(')> + reserved(end) + + reserved(def) method(use_flash) + ident(render) symbol(:text) operator(=)operator(>) ident(flash)operator([)symbol(:notice)operator(]) operator(||) string<delimiter(')content(no flash)delimiter(')> + reserved(end) + + reserved(def) method(redirected) + ident(redirect_to) symbol(:controller) operator(=)operator(>) string<delimiter(")content(callee)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(being_called)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) +reserved(end) + +reserved(class) class(ComponentsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(CallerController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_calling_from_controller) + ident(get) symbol(:calling_from_controller) + ident(assert_equal) string<delimiter(")content(Lady of the House, speaking)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_calling_from_controller_with_params) + ident(get) symbol(:calling_from_controller_with_params) + ident(assert_equal) string<delimiter(")content(David of the House, speaking)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_calling_from_controller_with_different_status_code) + ident(get) symbol(:calling_from_controller_with_different_status_code) + ident(assert_equal) integer(500)operator(,) instance_variable(@response)operator(.)ident(response_code) + reserved(end) + + reserved(def) method(test_calling_from_template) + ident(get) symbol(:calling_from_template) + ident(assert_equal) string<delimiter(")content(Ring, ring: Lady of the House, speaking)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_internal_calling) + ident(get) symbol(:internal_caller) + ident(assert_equal) string<delimiter(")content(Are you there? Yes, ma'am)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_flash) + ident(get) symbol(:set_flash) + ident(assert_equal) string<delimiter(')content(My stoney baby)delimiter(')>operator(,) ident(flash)operator([)symbol(:notice)operator(]) + ident(get) symbol(:use_flash) + ident(assert_equal) string<delimiter(')content(My stoney baby)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + ident(get) symbol(:use_flash) + ident(assert_equal) string<delimiter(')content(no flash)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_component_redirect_redirects) + ident(get) symbol(:calling_redirected) + + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(being_called)delimiter(")> + reserved(end) + + reserved(def) method(test_component_multiple_redirect_redirects) + ident(test_component_redirect_redirects) + ident(test_internal_calling) + reserved(end) + + reserved(def) method(test_component_as_string_redirect_renders_redirecte_action) + ident(get) symbol(:calling_redirected_as_string) + + ident(assert_equal) string<delimiter(")content(Lady of the House, speaking)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(CookieTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(authenticate_with_deprecated_writer) + ident(cookie) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(user_name)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")> + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(authenticate) + ident(cookies)operator([)string<delimiter(")content(user_name)delimiter(")>operator(]) operator(=) string<delimiter(")content(david)delimiter(")> + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(authenticate_for_fourten_days) + ident(cookies)operator([)string<delimiter(")content(user_name)delimiter(")>operator(]) operator(=) operator({) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(,) string<delimiter(")content(expires)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(local)operator(()integer(2005)operator(,) integer(10)operator(,) integer(10)operator(\)) operator(}) + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(authenticate_for_fourten_days_with_symbols) + ident(cookies)operator([)symbol(:user_name)operator(]) operator(=) operator({) symbol(:value) operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(,) symbol(:expires) operator(=)operator(>) constant(Time)operator(.)ident(local)operator(()integer(2005)operator(,) integer(10)operator(,) integer(10)operator(\)) operator(}) + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(set_multiple_cookies) + ident(cookies)operator([)string<delimiter(")content(user_name)delimiter(")>operator(]) operator(=) operator({) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(,) string<delimiter(")content(expires)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(local)operator(()integer(2005)operator(,) integer(10)operator(,) integer(10)operator(\)) operator(}) + ident(cookies)operator([)string<delimiter(")content(login)delimiter(")>operator(]) operator(=) string<delimiter(")content(XJ-122)delimiter(")> + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(access_frozen_cookies) + instance_variable(@cookies)operator([)string<delimiter(")content(will)delimiter(")>operator(]) operator(=) string<delimiter(")content(work)delimiter(")> + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.nextangle.com)delimiter(")> + reserved(end) + + reserved(def) method(test_setting_cookie_with_deprecated_writer) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(")content(authenticate_with_deprecated_writer)delimiter(")> + ident(assert_equal) operator([) constant(CGI)operator(::)constant(Cookie)operator(::)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(user_name)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(\)) operator(])operator(,) ident(process_request)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_setting_cookie) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(")content(authenticate)delimiter(")> + ident(assert_equal) operator([) constant(CGI)operator(::)constant(Cookie)operator(::)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(user_name)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(\)) operator(])operator(,) ident(process_request)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_setting_cookie_for_fourteen_days) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(")content(authenticate_for_fourten_days)delimiter(")> + ident(assert_equal) operator([) constant(CGI)operator(::)constant(Cookie)operator(::)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(user_name)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(,) string<delimiter(")content(expires)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(local)operator(()integer(2005)operator(,) integer(10)operator(,) integer(10)operator(\))operator(\)) operator(])operator(,) ident(process_request)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_setting_cookie_for_fourteen_days_with_symbols) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(")content(authenticate_for_fourten_days)delimiter(")> + ident(assert_equal) operator([) constant(CGI)operator(::)constant(Cookie)operator(::)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(user_name)delimiter(")>operator(,) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(david)delimiter(")>operator(,) string<delimiter(")content(expires)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(local)operator(()integer(2005)operator(,) integer(10)operator(,) integer(10)operator(\))operator(\)) operator(])operator(,) ident(process_request)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_multiple_cookies) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(")content(set_multiple_cookies)delimiter(")> + ident(assert_equal) integer(2)operator(,) ident(process_request)operator(.)ident(headers)operator([)string<delimiter(")content(cookie)delimiter(")>operator(])operator(.)ident(size) + reserved(end) + + reserved(def) method(test_setting_test_cookie) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(")content(access_frozen_cookies)delimiter(")> + ident(assert_nothing_raised) operator({) ident(process_request) operator(}) + reserved(end) + + ident(private) + reserved(def) method(process_request) + constant(TestController)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(CustomHandler) + reserved(def) method(initialize)operator(() ident(view) operator(\)) + instance_variable(@view) operator(=) ident(view) + reserved(end) + + reserved(def) method(render)operator(() ident(template)operator(,) ident(local_assigns) operator(\)) + operator([) ident(template)operator(,) + ident(local_assigns)operator(,) + instance_variable(@view) operator(]) + reserved(end) +reserved(end) + +reserved(class) class(CustomHandlerTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + constant(ActionView)operator(::)constant(Base)operator(.)ident(register_template_handler) string<delimiter(")content(foo)delimiter(")>operator(,) constant(CustomHandler) + constant(ActionView)operator(::)constant(Base)operator(.)ident(register_template_handler) symbol(:foo2)operator(,) constant(CustomHandler) + instance_variable(@view) operator(=) constant(ActionView)operator(::)constant(Base)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_custom_render) + ident(result) operator(=) instance_variable(@view)operator(.)ident(render_template)operator(() string<delimiter(")content(foo)delimiter(")>operator(,) string<delimiter(")content(hello <%= one %>)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(two)delimiter(")> operator(\)) + ident(assert_equal)operator(() + operator([) string<delimiter(")content(hello <%= one %>)delimiter(")>operator(,) operator({) symbol(:one) operator(=)operator(>) string<delimiter(")content(two)delimiter(")> operator(})operator(,) instance_variable(@view) operator(])operator(,) + ident(result) operator(\)) + reserved(end) + + reserved(def) method(test_custom_render2) + ident(result) operator(=) instance_variable(@view)operator(.)ident(render_template)operator(() string<delimiter(")content(foo2)delimiter(")>operator(,) string<delimiter(")content(hello <%= one %>)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(two)delimiter(")> operator(\)) + ident(assert_equal)operator(() + operator([) string<delimiter(")content(hello <%= one %>)delimiter(")>operator(,) operator({) symbol(:one) operator(=)operator(>) string<delimiter(")content(two)delimiter(")> operator(})operator(,) instance_variable(@view) operator(])operator(,) + ident(result) operator(\)) + reserved(end) + + reserved(def) method(test_unhandled_extension) + comment(# uses the ERb handler by default if the extension isn't recognized) + ident(result) operator(=) instance_variable(@view)operator(.)ident(render_template)operator(() string<delimiter(")content(bar)delimiter(")>operator(,) string<delimiter(")content(hello <%= one %>)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(two)delimiter(")> operator(\)) + ident(assert_equal) string<delimiter(")content(hello two)delimiter(")>operator(,) ident(result) + reserved(end) +reserved(end) +reserved(class) operator(<<) class(Object)operator(;) ident(alias_method) symbol(:const_available?)operator(,) symbol(:const_defined?)operator(;) reserved(end) + +reserved(class) class(ContentController) operator(<) constant(Class)operator(.)ident(new)operator(()constant(ActionController)operator(::)constant(Base)operator(\)) +reserved(end) +reserved(class) class(NotAController) +reserved(end) +reserved(module) class(Admin) + reserved(class) operator(<<) class(self)operator(;) ident(alias_method) symbol(:const_available?)operator(,) symbol(:const_defined?)operator(;) reserved(end) + constant(SomeConstant) operator(=) integer(10) + reserved(class) class(UserController) operator(<) constant(Class)operator(.)ident(new)operator(()constant(ActionController)operator(::)constant(Base)operator(\))operator(;) reserved(end) + reserved(class) class(NewsFeedController) operator(<) constant(Class)operator(.)ident(new)operator(()constant(ActionController)operator(::)constant(Base)operator(\))operator(;) reserved(end) +reserved(end) + +constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(map)operator(.)ident(route_one) string<delimiter(')content(route_one)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(elsewhere)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(flash_me)delimiter(')> + ident(map)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(FilterParamController) operator(<) constant(ActionController)operator(::)constant(Base) +reserved(end) + +reserved(class) class(FilterParamTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(FilterParamController)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_filter_parameters) + ident(assert) constant(FilterParamController)operator(.)ident(respond_to?)operator(()symbol(:filter_parameter_logging)operator(\)) + ident(assert) operator(!)instance_variable(@controller)operator(.)ident(respond_to?)operator(()symbol(:filter_parameters)operator(\)) + + constant(FilterParamController)operator(.)ident(filter_parameter_logging) + ident(assert) instance_variable(@controller)operator(.)ident(respond_to?)operator(()symbol(:filter_parameters)operator(\)) + + ident(test_hashes) operator(=) operator([)operator([)operator({)operator(})operator(,)operator({)operator(})operator(,)operator([)operator(])operator(])operator(,) + operator([)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(})operator(,)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(})operator(,)operator([)operator(])operator(])operator(,) + operator([)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(})operator(,)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(})operator(,)string<delimiter(%w')content(food)delimiter(')>operator(])operator(,) + operator([)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(})operator(,)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(})operator(,)string<delimiter(%w')content(foo)delimiter(')>operator(])operator(,) + operator([)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(,)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(,)string<delimiter(%w')content(foo baz)delimiter(')>operator(])operator(,) + operator([)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(,) string<delimiter(')content(baz)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(,)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(,) string<delimiter(')content(baz)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(})operator(,)string<delimiter(%w')content(foo baz)delimiter(')>operator(])operator(,) + operator([)operator({)string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(,)string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(})operator(,)operator({)string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(,)string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(})operator(,)string<delimiter(%w')content(fo)delimiter(')>operator(])operator(,) + operator([)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(,)string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(})operator(,)operator({)string<delimiter(')content(foo)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(})operator(,)string<delimiter(%w')content(f banana)delimiter(')>operator(])operator(]) + + ident(test_hashes)operator(.)ident(each) reserved(do) operator(|)ident(before_filter)operator(,) ident(after_filter)operator(,) ident(filter_words)operator(|) + constant(FilterParamController)operator(.)ident(filter_parameter_logging)operator(()operator(*)ident(filter_words)operator(\)) + ident(assert_equal) ident(after_filter)operator(,) instance_variable(@controller)operator(.)ident(filter_parameters)operator(()ident(before_filter)operator(\)) + + ident(filter_words)operator(.)ident(push)operator(()string<delimiter(')content(blah)delimiter(')>operator(\)) + constant(FilterParamController)operator(.)ident(filter_parameter_logging)operator(()operator(*)ident(filter_words)operator(\)) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + ident(value)operator(.)ident(reverse!) reserved(if) ident(key) operator(=)operator(~) regexp<delimiter(/)content(bargain)delimiter(/)> + reserved(end) + + ident(before_filter)operator([)string<delimiter(')content(barg)delimiter(')>operator(]) operator(=) operator({)string<delimiter(')content(bargain)delimiter(')>operator(=)operator(>)string<delimiter(')content(gain)delimiter(')>operator(,) string<delimiter(')content(blah)delimiter(')>operator(=)operator(>)string<delimiter(')content(bar)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(bargain)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(blah)delimiter(')>operator(=)operator(>)string<delimiter(')content(foo)delimiter(')>operator(})operator(})operator(}) + ident(after_filter)operator([)string<delimiter(')content(barg)delimiter(')>operator(]) operator(=) operator({)string<delimiter(')content(bargain)delimiter(')>operator(=)operator(>)string<delimiter(')content(niag)delimiter(')>operator(,) string<delimiter(')content(blah)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(bargain)delimiter(')>operator(=)operator(>)operator({)string<delimiter(')content(blah)delimiter(')>operator(=)operator(>)string<delimiter(')content([FILTERED])delimiter(')>operator(})operator(})operator(}) + + ident(assert_equal) ident(after_filter)operator(,) instance_variable(@controller)operator(.)ident(filter_parameters)operator(()ident(before_filter)operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(FilterTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(before_filter) symbol(:ensure_login) + ident(after_filter) symbol(:clean_up) + + reserved(def) method(show) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action)delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(ensure_login) + instance_variable(@ran_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_filter) operator(<<) string<delimiter(")content(ensure_login)delimiter(")> + reserved(end) + + reserved(def) method(clean_up) + instance_variable(@ran_after_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_after_filter) operator(<<) string<delimiter(")content(clean_up)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(RenderingController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(before_filter) symbol(:render_something_else) + + reserved(def) method(show) + instance_variable(@ran_action) operator(=) pre_constant(true) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action)delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(render_something_else) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(something else)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(ConditionalFilterController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(show) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action)delimiter(")> + reserved(end) + + reserved(def) method(another_action) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action)delimiter(")> + reserved(end) + + reserved(def) method(show_without_filter) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action without filter)delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(ensure_login) + instance_variable(@ran_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_filter) operator(<<) string<delimiter(")content(ensure_login)delimiter(")> + reserved(end) + + reserved(def) method(clean_up_tmp) + instance_variable(@ran_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_filter) operator(<<) string<delimiter(")content(clean_up_tmp)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise)operator(()ident(e)operator(\)) reserved(end) + reserved(end) + + reserved(class) class(ConditionalCollectionFilterController) operator(<) constant(ConditionalFilterController) + ident(before_filter) symbol(:ensure_login)operator(,) symbol(:except) operator(=)operator(>) operator([) symbol(:show_without_filter)operator(,) symbol(:another_action) operator(]) + reserved(end) + + reserved(class) class(OnlyConditionSymController) operator(<) constant(ConditionalFilterController) + ident(before_filter) symbol(:ensure_login)operator(,) symbol(:only) operator(=)operator(>) symbol(:show) + reserved(end) + + reserved(class) class(ExceptConditionSymController) operator(<) constant(ConditionalFilterController) + ident(before_filter) symbol(:ensure_login)operator(,) symbol(:except) operator(=)operator(>) symbol(:show_without_filter) + reserved(end) + + reserved(class) class(BeforeAndAfterConditionController) operator(<) constant(ConditionalFilterController) + ident(before_filter) symbol(:ensure_login)operator(,) symbol(:only) operator(=)operator(>) symbol(:show) + ident(after_filter) symbol(:clean_up_tmp)operator(,) symbol(:only) operator(=)operator(>) symbol(:show) + reserved(end) + + reserved(class) class(OnlyConditionProcController) operator(<) constant(ConditionalFilterController) + ident(before_filter)operator(()symbol(:only) operator(=)operator(>) symbol(:show)operator(\)) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) operator(=) pre_constant(true) operator(}) + reserved(end) + + reserved(class) class(ExceptConditionProcController) operator(<) constant(ConditionalFilterController) + ident(before_filter)operator(()symbol(:except) operator(=)operator(>) symbol(:show_without_filter)operator(\)) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) operator(=) pre_constant(true) operator(}) + reserved(end) + + reserved(class) class(ConditionalClassFilter) + reserved(def) pre_constant(self)operator(.)ident(filter)operator(()ident(controller)operator(\)) ident(controller)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) operator(=) pre_constant(true) reserved(end) + reserved(end) + + reserved(class) class(OnlyConditionClassController) operator(<) constant(ConditionalFilterController) + ident(before_filter) constant(ConditionalClassFilter)operator(,) symbol(:only) operator(=)operator(>) symbol(:show) + reserved(end) + + reserved(class) class(ExceptConditionClassController) operator(<) constant(ConditionalFilterController) + ident(before_filter) constant(ConditionalClassFilter)operator(,) symbol(:except) operator(=)operator(>) symbol(:show_without_filter) + reserved(end) + + reserved(class) class(AnomolousYetValidConditionController) operator(<) constant(ConditionalFilterController) + ident(before_filter)operator(()constant(ConditionalClassFilter)operator(,) symbol(:ensure_login)operator(,) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter1)delimiter(")>operator(]) operator(=) pre_constant(true) operator(})operator(,) symbol(:except) operator(=)operator(>) symbol(:show_without_filter)operator(\)) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter2)delimiter(")>operator(]) operator(=) pre_constant(true)operator(}) + reserved(end) + + reserved(class) class(PrependingController) operator(<) constant(TestController) + ident(prepend_before_filter) symbol(:wonderful_life) + comment(# skip_before_filter :fire_flash) + + ident(private) + reserved(def) method(wonderful_life) + instance_variable(@ran_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_filter) operator(<<) string<delimiter(")content(wonderful_life)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(ConditionalSkippingController) operator(<) constant(TestController) + ident(skip_before_filter) symbol(:ensure_login)operator(,) symbol(:only) operator(=)operator(>) operator([) symbol(:login) operator(]) + ident(skip_after_filter) symbol(:clean_up)operator(,) symbol(:only) operator(=)operator(>) operator([) symbol(:login) operator(]) + + ident(before_filter) symbol(:find_user)operator(,) symbol(:only) operator(=)operator(>) operator([) symbol(:change_password) operator(]) + + reserved(def) method(login) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action)delimiter(")> + reserved(end) + + reserved(def) method(change_password) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(ran action)delimiter(")> + reserved(end) + + ident(protected) + reserved(def) method(find_user) + instance_variable(@ran_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_filter) operator(<<) string<delimiter(")content(find_user)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(ConditionalParentOfConditionalSkippingController) operator(<) constant(ConditionalFilterController) + ident(before_filter) symbol(:conditional_in_parent)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:show)operator(,) symbol(:another_action)operator(]) + ident(after_filter) symbol(:conditional_in_parent)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:show)operator(,) symbol(:another_action)operator(]) + + ident(private) + + reserved(def) method(conditional_in_parent) + instance_variable(@ran_filter) operator(||=) operator([)operator(]) + instance_variable(@ran_filter) operator(<<) string<delimiter(')content(conditional_in_parent)delimiter(')> + reserved(end) + reserved(end) + + reserved(class) class(ChildOfConditionalParentController) operator(<) constant(ConditionalParentOfConditionalSkippingController) + ident(skip_before_filter) symbol(:conditional_in_parent)operator(,) symbol(:only) operator(=)operator(>) symbol(:another_action) + ident(skip_after_filter) symbol(:conditional_in_parent)operator(,) symbol(:only) operator(=)operator(>) symbol(:another_action) + reserved(end) + + reserved(class) class(ProcController) operator(<) constant(PrependingController) + ident(before_filter)operator(()ident(proc) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) operator(=) pre_constant(true) operator(})operator(\)) + reserved(end) + + reserved(class) class(ImplicitProcController) operator(<) constant(PrependingController) + ident(before_filter) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) operator(=) pre_constant(true) operator(}) + reserved(end) + + reserved(class) class(AuditFilter) + reserved(def) pre_constant(self)operator(.)ident(filter)operator(()ident(controller)operator(\)) + ident(controller)operator(.)ident(assigns)operator([)string<delimiter(")content(was_audited)delimiter(")>operator(]) operator(=) pre_constant(true) + reserved(end) + reserved(end) + + reserved(class) class(AroundFilter) + reserved(def) method(before)operator(()ident(controller)operator(\)) + instance_variable(@execution_log) operator(=) string<delimiter(")content(before)delimiter(")> + ident(controller)operator(.)ident(class)operator(.)ident(execution_log) operator(<<) string<delimiter(")content( before aroundfilter )delimiter(")> reserved(if) ident(controller)operator(.)ident(respond_to?) symbol(:execution_log) + ident(controller)operator(.)ident(assigns)operator([)string<delimiter(")content(before_ran)delimiter(")>operator(]) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(after)operator(()ident(controller)operator(\)) + ident(controller)operator(.)ident(assigns)operator([)string<delimiter(")content(execution_log)delimiter(")>operator(]) operator(=) instance_variable(@execution_log) operator(+) string<delimiter(")content( and after)delimiter(")> + ident(controller)operator(.)ident(assigns)operator([)string<delimiter(")content(after_ran)delimiter(")>operator(]) operator(=) pre_constant(true) + ident(controller)operator(.)ident(class)operator(.)ident(execution_log) operator(<<) string<delimiter(")content( after aroundfilter )delimiter(")> reserved(if) ident(controller)operator(.)ident(respond_to?) symbol(:execution_log) + reserved(end) + reserved(end) + + reserved(class) class(AppendedAroundFilter) + reserved(def) method(before)operator(()ident(controller)operator(\)) + ident(controller)operator(.)ident(class)operator(.)ident(execution_log) operator(<<) string<delimiter(")content( before appended aroundfilter )delimiter(")> + reserved(end) + + reserved(def) method(after)operator(()ident(controller)operator(\)) + ident(controller)operator(.)ident(class)operator(.)ident(execution_log) operator(<<) string<delimiter(")content( after appended aroundfilter )delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(AuditController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(before_filter)operator(()constant(AuditFilter)operator(\)) + + reserved(def) method(show) + ident(render_text) string<delimiter(")content(hello)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(BadFilterController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(before_filter) integer(2) + + reserved(def) method(show)operator(()operator(\)) string<delimiter(")content(show)delimiter(")> reserved(end) + + ident(protected) + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise)operator(()ident(e)operator(\)) reserved(end) + reserved(end) + + reserved(class) class(AroundFilterController) operator(<) constant(PrependingController) + ident(around_filter) constant(AroundFilter)operator(.)ident(new) + reserved(end) + + reserved(class) class(MixedFilterController) operator(<) constant(PrependingController) + ident(cattr_accessor) symbol(:execution_log) + + reserved(def) method(initialize) + class_variable(@@execution_log) operator(=) string<delimiter(")delimiter(")> + reserved(end) + + ident(before_filter) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(class)operator(.)ident(execution_log) operator(<<) string<delimiter(")content( before procfilter )delimiter(")> operator(}) + ident(prepend_around_filter) constant(AroundFilter)operator(.)ident(new) + + ident(after_filter) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(class)operator(.)ident(execution_log) operator(<<) string<delimiter(")content( after procfilter )delimiter(")> operator(}) + ident(append_around_filter) constant(AppendedAroundFilter)operator(.)ident(new) + reserved(end) + + reserved(class) class(MixedSpecializationController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(class) class(OutOfOrder) operator(<) constant(StandardError)operator(;) reserved(end) + + ident(before_filter) symbol(:first) + ident(before_filter) symbol(:second)operator(,) symbol(:only) operator(=)operator(>) symbol(:foo) + + reserved(def) method(foo) + ident(render_text) string<delimiter(')content(foo)delimiter(')> + reserved(end) + + reserved(def) method(bar) + ident(render_text) string<delimiter(')content(bar)delimiter(')> + reserved(end) + + ident(protected) + reserved(def) method(first) + instance_variable(@first) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(second) + ident(raise) constant(OutOfOrder) reserved(unless) instance_variable(@first) + reserved(end) + reserved(end) + + reserved(class) class(DynamicDispatchController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(before_filter) symbol(:choose) + + string<delimiter(%w()content(foo bar baz)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(action)operator(|) + ident(define_method)operator(()ident(action)operator(\)) operator({) ident(render) symbol(:text) operator(=)operator(>) ident(action) operator(}) + reserved(end) + + ident(private) + reserved(def) method(choose) + pre_constant(self)operator(.)ident(action_name) operator(=) ident(params)operator([)symbol(:choose)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(test_added_filter_to_inheritance_graph) + ident(assert_equal) operator([) symbol(:ensure_login) operator(])operator(,) constant(TestController)operator(.)ident(before_filters) + reserved(end) + + reserved(def) method(test_base_class_in_isolation) + ident(assert_equal) operator([) operator(])operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(before_filters) + reserved(end) + + reserved(def) method(test_prepending_filter) + ident(assert_equal) operator([) symbol(:wonderful_life)operator(,) symbol(:ensure_login) operator(])operator(,) constant(PrependingController)operator(.)ident(before_filters) + reserved(end) + + reserved(def) method(test_running_filters) + ident(assert_equal) string<delimiter(%w()content( wonderful_life ensure_login )delimiter(\))>operator(,) ident(test_process)operator(()constant(PrependingController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_filters_with_proc) + ident(assert) ident(test_process)operator(()constant(ProcController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_filters_with_implicit_proc) + ident(assert) ident(test_process)operator(()constant(ImplicitProcController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_filters_with_class) + ident(assert) ident(test_process)operator(()constant(AuditController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(was_audited)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_anomolous_yet_valid_condition_filters) + ident(response) operator(=) ident(test_process)operator(()constant(AnomolousYetValidConditionController)operator(\)) + ident(assert_equal) string<delimiter(%w()content( ensure_login )delimiter(\))>operator(,) ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert) ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) + ident(assert) ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter1)delimiter(")>operator(]) + ident(assert) ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter2)delimiter(")>operator(]) + + ident(response) operator(=) ident(test_process)operator(()constant(AnomolousYetValidConditionController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\)) + ident(assert_equal) pre_constant(nil)operator(,) ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert) operator(!)ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) + ident(assert) operator(!)ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter1)delimiter(")>operator(]) + ident(assert) operator(!)ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter2)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_collection_condition_filters) + ident(assert_equal) string<delimiter(%w()content( ensure_login )delimiter(\))>operator(,) ident(test_process)operator(()constant(ConditionalCollectionFilterController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert_equal) pre_constant(nil)operator(,) ident(test_process)operator(()constant(ConditionalCollectionFilterController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert_equal) pre_constant(nil)operator(,) ident(test_process)operator(()constant(ConditionalCollectionFilterController)operator(,) string<delimiter(")content(another_action)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_only_condition_filters) + ident(assert_equal) string<delimiter(%w()content( ensure_login )delimiter(\))>operator(,) ident(test_process)operator(()constant(OnlyConditionSymController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert_equal) pre_constant(nil)operator(,) ident(test_process)operator(()constant(OnlyConditionSymController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + + ident(assert) ident(test_process)operator(()constant(OnlyConditionProcController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) + ident(assert) operator(!)ident(test_process)operator(()constant(OnlyConditionProcController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) + + ident(assert) ident(test_process)operator(()constant(OnlyConditionClassController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) + ident(assert) operator(!)ident(test_process)operator(()constant(OnlyConditionClassController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_except_condition_filters) + ident(assert_equal) string<delimiter(%w()content( ensure_login )delimiter(\))>operator(,) ident(test_process)operator(()constant(ExceptConditionSymController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert_equal) pre_constant(nil)operator(,) ident(test_process)operator(()constant(ExceptConditionSymController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + + ident(assert) ident(test_process)operator(()constant(ExceptConditionProcController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) + ident(assert) operator(!)ident(test_process)operator(()constant(ExceptConditionProcController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_proc_filter)delimiter(")>operator(]) + + ident(assert) ident(test_process)operator(()constant(ExceptConditionClassController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) + ident(assert) operator(!)ident(test_process)operator(()constant(ExceptConditionClassController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_class_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_running_before_and_after_condition_filters) + ident(assert_equal) string<delimiter(%w()content( ensure_login clean_up_tmp)delimiter(\))>operator(,) ident(test_process)operator(()constant(BeforeAndAfterConditionController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert_equal) pre_constant(nil)operator(,) ident(test_process)operator(()constant(BeforeAndAfterConditionController)operator(,) string<delimiter(")content(show_without_filter)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_bad_filter) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(ActionControllerError)operator(\)) operator({) + ident(test_process)operator(()constant(BadFilterController)operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_around_filter) + ident(controller) operator(=) ident(test_process)operator(()constant(AroundFilterController)operator(\)) + ident(assert) ident(controller)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(before_ran)delimiter(")>operator(]) + ident(assert) ident(controller)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(after_ran)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_having_properties_in_around_filter) + ident(controller) operator(=) ident(test_process)operator(()constant(AroundFilterController)operator(\)) + ident(assert_equal) string<delimiter(")content(before and after)delimiter(")>operator(,) ident(controller)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(execution_log)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_prepending_and_appending_around_filter) + ident(controller) operator(=) ident(test_process)operator(()constant(MixedFilterController)operator(\)) + ident(assert_equal) string<delimiter(")content( before aroundfilter before procfilter before appended aroundfilter )delimiter(")> operator(+) + string<delimiter(")content( after appended aroundfilter after aroundfilter after procfilter )delimiter(")>operator(,) + constant(MixedFilterController)operator(.)ident(execution_log) + reserved(end) + + reserved(def) method(test_rendering_breaks_filtering_chain) + ident(response) operator(=) ident(test_process)operator(()constant(RenderingController)operator(\)) + ident(assert_equal) string<delimiter(")content(something else)delimiter(")>operator(,) ident(response)operator(.)ident(body) + ident(assert) operator(!)ident(response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_action)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_filters_with_mixed_specialization_run_in_order) + ident(assert_nothing_raised) reserved(do) + ident(response) operator(=) ident(test_process)operator(()constant(MixedSpecializationController)operator(,) string<delimiter(')content(bar)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(bar)delimiter(')>operator(,) ident(response)operator(.)ident(body) + reserved(end) + + ident(assert_nothing_raised) reserved(do) + ident(response) operator(=) ident(test_process)operator(()constant(MixedSpecializationController)operator(,) string<delimiter(')content(foo)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(foo)delimiter(')>operator(,) ident(response)operator(.)ident(body) + reserved(end) + reserved(end) + + reserved(def) method(test_dynamic_dispatch) + string<delimiter(%w()content(foo bar baz)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(action)operator(|) + ident(request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(request)operator(.)ident(query_parameters)operator([)symbol(:choose)operator(]) operator(=) ident(action) + ident(response) operator(=) constant(DynamicDispatchController)operator(.)ident(process)operator(()ident(request)operator(,) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new)operator(\)) + ident(assert_equal) ident(action)operator(,) ident(response)operator(.)ident(body) + reserved(end) + reserved(end) + + reserved(def) method(test_conditional_skipping_of_filters) + ident(assert_nil) ident(test_process)operator(()constant(ConditionalSkippingController)operator(,) string<delimiter(")content(login)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + ident(assert_equal) string<delimiter(%w()content( ensure_login find_user )delimiter(\))>operator(,) ident(test_process)operator(()constant(ConditionalSkippingController)operator(,) string<delimiter(")content(change_password)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(ran_filter)delimiter(")>operator(]) + + ident(assert_nil) ident(test_process)operator(()constant(ConditionalSkippingController)operator(,) string<delimiter(")content(login)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(controller)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@ran_after_filter)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%w()content( clean_up )delimiter(\))>operator(,) ident(test_process)operator(()constant(ConditionalSkippingController)operator(,) string<delimiter(")content(change_password)delimiter(")>operator(\))operator(.)ident(template)operator(.)ident(controller)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@ran_after_filter)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_conditional_skipping_of_filters_when_parent_filter_is_also_conditional) + ident(assert_equal) string<delimiter(%w()content( conditional_in_parent conditional_in_parent )delimiter(\))>operator(,) ident(test_process)operator(()constant(ChildOfConditionalParentController)operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(')content(ran_filter)delimiter(')>operator(]) + ident(assert_nil) ident(test_process)operator(()constant(ChildOfConditionalParentController)operator(,) string<delimiter(')content(another_action)delimiter(')>operator(\))operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(')content(ran_filter)delimiter(')>operator(]) + reserved(end) + + ident(private) + reserved(def) method(test_process)operator(()ident(controller)operator(,) ident(action) operator(=) string<delimiter(")content(show)delimiter(")>operator(\)) + ident(request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(request)operator(.)ident(action) operator(=) ident(action) + ident(controller)operator(.)ident(process)operator(()ident(request)operator(,) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new)operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(FlashTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(set_flash) + ident(flash)operator([)string<delimiter(")content(that)delimiter(")>operator(]) operator(=) string<delimiter(")content(hello)delimiter(")> + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(set_flash_now) + ident(flash)operator(.)ident(now)operator([)string<delimiter(")content(that)delimiter(")>operator(]) operator(=) string<delimiter(")content(hello)delimiter(")> + ident(flash)operator(.)ident(now)operator([)string<delimiter(")content(foo)delimiter(")>operator(]) operator(||=) string<delimiter(")content(bar)delimiter(")> + ident(flash)operator(.)ident(now)operator([)string<delimiter(")content(foo)delimiter(")>operator(]) operator(||=) string<delimiter(")content(err)delimiter(")> + instance_variable(@flashy) operator(=) ident(flash)operator(.)ident(now)operator([)string<delimiter(")content(that)delimiter(")>operator(]) + instance_variable(@flash_copy) operator(=) operator({)operator(})operator(.)ident(update) ident(flash) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(attempt_to_use_flash_now) + instance_variable(@flash_copy) operator(=) operator({)operator(})operator(.)ident(update) ident(flash) + instance_variable(@flashy) operator(=) ident(flash)operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(use_flash) + instance_variable(@flash_copy) operator(=) operator({)operator(})operator(.)ident(update) ident(flash) + instance_variable(@flashy) operator(=) ident(flash)operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(use_flash_and_keep_it) + instance_variable(@flash_copy) operator(=) operator({)operator(})operator(.)ident(update) ident(flash) + instance_variable(@flashy) operator(=) ident(flash)operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(silence_warnings) operator({) ident(keep_flash) operator(}) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) + ident(raise) reserved(unless) constant(ActionController)operator(::)constant(MissingTemplate) operator(===) ident(e) + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_flash) + ident(get) symbol(:set_flash) + + ident(get) symbol(:use_flash) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flashy)delimiter(")>operator(]) + + ident(get) symbol(:use_flash) + ident(assert_nil) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(])operator(,) string<delimiter(")content(On second flash)delimiter(")> + reserved(end) + + reserved(def) method(test_keep_flash) + ident(get) symbol(:set_flash) + + ident(get) symbol(:use_flash_and_keep_it) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flashy)delimiter(")>operator(]) + + ident(get) symbol(:use_flash) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(])operator(,) string<delimiter(")content(On second flash)delimiter(")> + + ident(get) symbol(:use_flash) + ident(assert_nil) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(])operator(,) string<delimiter(")content(On third flash)delimiter(")> + reserved(end) + + reserved(def) method(test_flash_now) + ident(get) symbol(:set_flash_now) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(assert_equal) string<delimiter(")content(bar)delimiter(")> operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(foo)delimiter(")>operator(]) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flashy)delimiter(")>operator(]) + + ident(get) symbol(:attempt_to_use_flash_now) + ident(assert_nil) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(that)delimiter(")>operator(]) + ident(assert_nil) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flash_copy)delimiter(")>operator(])operator([)string<delimiter(")content(foo)delimiter(")>operator(]) + ident(assert_nil) instance_variable(@response)operator(.)ident(template)operator(.)ident(assigns)operator([)string<delimiter(")content(flashy)delimiter(")>operator(]) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +constant(MemCache) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:MemCache)operator(,) symbol(:address)operator(\)) reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:MemCache)operator(\)) + +reserved(class) class(FragmentCacheStoreSettingTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(teardown) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) operator(=) constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(::)constant(MemoryStore)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_file_fragment_cache_store) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) operator(=) symbol(:file_store)operator(,) string<delimiter(")content(/path/to/cache/directory)delimiter(")> + ident(assert_kind_of)operator(() + constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(::)constant(FileStore)operator(,) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) + operator(\)) + ident(assert_equal) string<delimiter(")content(/path/to/cache/directory)delimiter(")>operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store)operator(.)ident(cache_path) + reserved(end) + + reserved(def) method(test_drb_fragment_cache_store) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) operator(=) symbol(:drb_store)operator(,) string<delimiter(")content(druby://localhost:9192)delimiter(")> + ident(assert_kind_of)operator(() + constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(::)constant(DRbStore)operator(,) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) + operator(\)) + ident(assert_equal) string<delimiter(")content(druby://localhost:9192)delimiter(")>operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store)operator(.)ident(address) + reserved(end) + + reserved(def) method(test_mem_cache_fragment_cache_store) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) operator(=) symbol(:mem_cache_store)operator(,) string<delimiter(")content(localhost)delimiter(")> + ident(assert_kind_of)operator(() + constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(::)constant(MemCacheStore)operator(,) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) + operator(\)) + ident(assert_equal) string<delimiter(%w()content(localhost)delimiter(\))>operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store)operator(.)ident(addresses) + reserved(end) + + reserved(def) method(test_object_assigned_fragment_cache_store) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) operator(=) constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(::)constant(FileStore)operator(.)ident(new)operator(()string<delimiter(")content(/path/to/cache/directory)delimiter(")>operator(\)) + ident(assert_kind_of)operator(() + constant(ActionController)operator(::)constant(Caching)operator(::)constant(Fragments)operator(::)constant(FileStore)operator(,) + constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store) + operator(\)) + ident(assert_equal) string<delimiter(")content(/path/to/cache/directory)delimiter(")>operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(fragment_cache_store)operator(.)ident(cache_path) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(attr_accessor) symbol(:delegate_attr) + reserved(def) method(delegate_method)operator(()operator(\)) reserved(end) + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) +reserved(end) + +reserved(module) class(Fun) + reserved(class) class(GamesController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(render_hello_world) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(hello: <%= stratego %>)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + reserved(end) + + reserved(class) class(PDFController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(test) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(test: <%= foobar %>)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(LocalAbcHelper) + reserved(def) method(a)operator(()operator(\)) reserved(end) + reserved(def) method(b)operator(()operator(\)) reserved(end) + reserved(def) method(c)operator(()operator(\)) reserved(end) +reserved(end) + +reserved(class) class(HelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + comment(# Increment symbol counter.) + instance_variable(@symbol) operator(=) operator(()class_variable(@@counter) operator(||=) string<delimiter(')content(A0)delimiter(')>operator(\))operator(.)ident(succ!)operator(.)ident(dup) + + comment(# Generate new controller class.) + ident(controller_class_name) operator(=) string<delimiter(")content(Helper)inline<inline_delimiter(#{)instance_variable(@symbol)inline_delimiter(})>content(Controller)delimiter(")> + ident(eval)operator(()string<delimiter(")content(class )inline<inline_delimiter(#{)ident(controller_class_name)inline_delimiter(})>content( < TestController; end)delimiter(")>operator(\)) + instance_variable(@controller_class) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(const_get)operator(()ident(controller_class_name)operator(\)) + + comment(# Generate new template class and assign to controller.) + ident(template_class_name) operator(=) string<delimiter(")content(Test)inline<inline_delimiter(#{)instance_variable(@symbol)inline_delimiter(})>content(View)delimiter(")> + ident(eval)operator(()string<delimiter(")content(class )inline<inline_delimiter(#{)ident(template_class_name)inline_delimiter(})>content( < ActionView::Base; end)delimiter(")>operator(\)) + instance_variable(@template_class) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(const_get)operator(()ident(template_class_name)operator(\)) + instance_variable(@controller_class)operator(.)ident(template_class) operator(=) instance_variable(@template_class) + + comment(# Set default test helper.) + pre_constant(self)operator(.)ident(test_helper) operator(=) constant(LocalAbcHelper) + reserved(end) + + reserved(def) method(teardown) + comment(# Reset template class.) + comment(#ActionController::Base.template_class = ActionView::Base) + reserved(end) + + + reserved(def) method(test_deprecated_helper) + ident(assert_equal) ident(expected_helper_methods)operator(,) ident(missing_methods) + ident(assert_nothing_raised) operator({) instance_variable(@controller_class)operator(.)ident(helper) constant(TestHelper) operator(}) + ident(assert_equal) operator([)operator(])operator(,) ident(missing_methods) + reserved(end) + + reserved(def) method(test_declare_helper) + ident(require) string<delimiter(')content(abc_helper)delimiter(')> + pre_constant(self)operator(.)ident(test_helper) operator(=) constant(AbcHelper) + ident(assert_equal) ident(expected_helper_methods)operator(,) ident(missing_methods) + ident(assert_nothing_raised) operator({) instance_variable(@controller_class)operator(.)ident(helper) symbol(:abc) operator(}) + ident(assert_equal) operator([)operator(])operator(,) ident(missing_methods) + reserved(end) + + reserved(def) method(test_declare_missing_helper) + ident(assert_equal) ident(expected_helper_methods)operator(,) ident(missing_methods) + ident(assert_raise)operator(()constant(MissingSourceFile)operator(\)) operator({) instance_variable(@controller_class)operator(.)ident(helper) symbol(:missing) operator(}) + reserved(end) + + reserved(def) method(test_declare_missing_file_from_helper) + ident(require) string<delimiter(')content(broken_helper)delimiter(')> + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(e) + ident(assert_nil) regexp<delimiter(/)char(\\b)content(broken_helper)char(\\b)delimiter(/)>operator(.)ident(match)operator(()ident(e)operator(.)ident(to_s)operator(\))operator([)integer(1)operator(]) + reserved(end) + + reserved(def) method(test_helper_block) + ident(assert_nothing_raised) operator({) + instance_variable(@controller_class)operator(.)ident(helper) operator({) reserved(def) method(block_helper_method)operator(;) reserved(end) operator(}) + operator(}) + ident(assert) ident(master_helper_methods)operator(.)ident(include?)operator(()string<delimiter(')content(block_helper_method)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_helper_block_include) + ident(assert_equal) ident(expected_helper_methods)operator(,) ident(missing_methods) + ident(assert_nothing_raised) operator({) + instance_variable(@controller_class)operator(.)ident(helper) operator({) ident(include) constant(TestHelper) operator(}) + operator(}) + ident(assert) operator([)operator(])operator(,) ident(missing_methods) + reserved(end) + + reserved(def) method(test_helper_method) + ident(assert_nothing_raised) operator({) instance_variable(@controller_class)operator(.)ident(helper_method) symbol(:delegate_method) operator(}) + ident(assert) ident(master_helper_methods)operator(.)ident(include?)operator(()string<delimiter(')content(delegate_method)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_helper_attr) + ident(assert_nothing_raised) operator({) instance_variable(@controller_class)operator(.)ident(helper_attr) symbol(:delegate_attr) operator(}) + ident(assert) ident(master_helper_methods)operator(.)ident(include?)operator(()string<delimiter(')content(delegate_attr)delimiter(')>operator(\)) + ident(assert) ident(master_helper_methods)operator(.)ident(include?)operator(()string<delimiter(')content(delegate_attr=)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_helper_for_nested_controller) + ident(request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + ident(request)operator(.)ident(action) operator(=) string<delimiter(')content(render_hello_world)delimiter(')> + + ident(assert_equal) string<delimiter(')content(hello: Iz guuut!)delimiter(')>operator(,) constant(Fun)operator(::)constant(GamesController)operator(.)ident(process)operator(()ident(request)operator(,) ident(response)operator(\))operator(.)ident(body) + reserved(end) + + reserved(def) method(test_helper_for_acronym_controller) + ident(request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + ident(request)operator(.)ident(action) operator(=) string<delimiter(')content(test)delimiter(')> + + ident(assert_equal) string<delimiter(')content(test: baz)delimiter(')>operator(,) constant(Fun)operator(::)constant(PDFController)operator(.)ident(process)operator(()ident(request)operator(,) ident(response)operator(\))operator(.)ident(body) + reserved(end) + + ident(private) + reserved(def) method(expected_helper_methods) + constant(TestHelper)operator(.)ident(instance_methods) + reserved(end) + + reserved(def) method(master_helper_methods) + instance_variable(@controller_class)operator(.)ident(master_helper_module)operator(.)ident(instance_methods) + reserved(end) + + reserved(def) method(missing_methods) + ident(expected_helper_methods) operator(-) ident(master_helper_methods) + reserved(end) + + reserved(def) method(test_helper=)operator(()ident(helper_module)operator(\)) + ident(silence_warnings) operator({) pre_constant(self)operator(.)ident(class)operator(.)ident(const_set)operator(()string<delimiter(')content(TestHelper)delimiter(')>operator(,) ident(helper_module)operator(\)) operator(}) + reserved(end) +reserved(end) + + +reserved(class) class(IsolatedHelpersTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(A) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(index) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(')content(<%= shout %>)delimiter(')> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + reserved(end) + + reserved(class) class(B) operator(<) constant(A) + ident(helper) operator({) reserved(def) method(shout)operator(;) string<delimiter(')content(B)delimiter(')> reserved(end) operator(}) + + reserved(def) method(index) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(')content(<%= shout %>)delimiter(')> + reserved(end) + reserved(end) + + reserved(class) class(C) operator(<) constant(A) + ident(helper) operator({) reserved(def) method(shout)operator(;) string<delimiter(')content(C)delimiter(')> reserved(end) operator(}) + + reserved(def) method(index) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(')content(<%= shout %>)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@request)operator(.)ident(action) operator(=) string<delimiter(')content(index)delimiter(')> + reserved(end) + + reserved(def) method(test_helper_in_a) + ident(assert_raise)operator(()constant(NameError)operator(\)) operator({) constant(A)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_helper_in_b) + ident(assert_equal) string<delimiter(')content(B)delimiter(')>operator(,) constant(B)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\))operator(.)ident(body) + reserved(end) + + reserved(def) method(test_helper_in_c) + ident(assert_equal) string<delimiter(')content(C)delimiter(')>operator(,) constant(C)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\))operator(.)ident(body) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +comment(# The template_root must be set on Base and not LayoutTest so that LayoutTest's inherited method has access to) +comment(# the template_root when looking for a layout) +constant(ActionController)operator(::)constant(Base)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../fixtures/layout_tests/)delimiter(')> + +reserved(class) class(LayoutTest) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) pre_constant(self)operator(.)ident(controller_path)operator(;) string<delimiter(')content(views)delimiter(')> reserved(end) +reserved(end) + +comment(# Restore template root to be unset) +constant(ActionController)operator(::)constant(Base)operator(.)ident(template_root) operator(=) pre_constant(nil) + +reserved(class) class(ProductController) operator(<) constant(LayoutTest) +reserved(end) + +reserved(class) class(ItemController) operator(<) constant(LayoutTest) +reserved(end) + +reserved(class) class(ThirdPartyTemplateLibraryController) operator(<) constant(LayoutTest) +reserved(end) + +reserved(module) class(ControllerNameSpace) +reserved(end) + +reserved(class) class(ControllerNameSpace::NestedController) operator(<) constant(LayoutTest) +reserved(end) + +reserved(class) class(MabView) + reserved(def) method(initialize)operator(()ident(view)operator(\)) + reserved(end) + + reserved(def) method(render)operator(()ident(text)operator(,) ident(locals) operator(=) operator({)operator(})operator(\)) + ident(text) + reserved(end) +reserved(end) + +constant(ActionView)operator(::)constant(Base)operator(::)ident(register_template_handler) symbol(:mab)operator(,) constant(MabView) + +reserved(class) class(LayoutAutoDiscoveryTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.nextangle.com)delimiter(")> + reserved(end) + + reserved(def) method(test_application_layout_is_default_when_no_controller_match) + instance_variable(@controller) operator(=) constant(ProductController)operator(.)ident(new) + ident(get) symbol(:hello) + ident(assert_equal) string<delimiter(')content(layout_test.rhtml hello.rhtml)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_controller_name_layout_name_match) + instance_variable(@controller) operator(=) constant(ItemController)operator(.)ident(new) + ident(get) symbol(:hello) + ident(assert_equal) string<delimiter(')content(item.rhtml hello.rhtml)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_third_party_template_library_auto_discovers_layout) + instance_variable(@controller) operator(=) constant(ThirdPartyTemplateLibraryController)operator(.)ident(new) + ident(get) symbol(:hello) + ident(assert_equal) string<delimiter(')content(layouts/third_party_template_library)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(active_layout) + ident(assert_equal) string<delimiter(')content(Mab)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_namespaced_controllers_auto_detect_layouts) + instance_variable(@controller) operator(=) constant(ControllerNameSpace)operator(::)constant(NestedController)operator(.)ident(new) + ident(get) symbol(:hello) + ident(assert_equal) string<delimiter(')content(layouts/controller_name_space/nested)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(active_layout) + ident(assert_equal) string<delimiter(')content(controller_name_space/nested.rhtml hello.rhtml)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(RespondToController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(layout) symbol(:set_layout) + + reserved(def) method(html_xml_or_rss) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(HTML)delimiter(")> operator(}) + ident(type)operator(.)ident(xml) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(XML)delimiter(")> operator(}) + ident(type)operator(.)ident(rss) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(RSS)delimiter(")> operator(}) + ident(type)operator(.)ident(all) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Nothing)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(js_or_html) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(HTML)delimiter(")> operator(}) + ident(type)operator(.)ident(js) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(JS)delimiter(")> operator(}) + ident(type)operator(.)ident(all) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Nothing)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(html_or_xml) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(HTML)delimiter(")> operator(}) + ident(type)operator(.)ident(xml) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(XML)delimiter(")> operator(}) + ident(type)operator(.)ident(all) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Nothing)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(just_xml) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(xml) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(XML)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(using_defaults) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) + ident(type)operator(.)ident(js) + ident(type)operator(.)ident(xml) + reserved(end) + reserved(end) + + reserved(def) method(using_defaults_with_type_list) + ident(respond_to)operator(()symbol(:html)operator(,) symbol(:js)operator(,) symbol(:xml)operator(\)) + reserved(end) + + reserved(def) method(made_for_content_type) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(rss) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(RSS)delimiter(")> operator(}) + ident(type)operator(.)ident(atom) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(ATOM)delimiter(")> operator(}) + ident(type)operator(.)ident(all) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Nothing)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(custom_type_handling) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(HTML)delimiter(")> operator(}) + ident(type)operator(.)ident(custom)operator(()string<delimiter(")content(application/crazy-xml)delimiter(")>operator(\)) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Crazy XML)delimiter(")> operator(}) + ident(type)operator(.)ident(all) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Nothing)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(handle_any) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(HTML)delimiter(")> operator(}) + ident(type)operator(.)ident(any)operator(()symbol(:js)operator(,) symbol(:xml)operator(\)) operator({) ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Either JS or XML)delimiter(")> operator(}) + reserved(end) + reserved(end) + + reserved(def) method(all_types_with_layout) + ident(respond_to) reserved(do) operator(|)ident(type)operator(|) + ident(type)operator(.)ident(html) + ident(type)operator(.)ident(js) + reserved(end) + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) + ident(raise) + reserved(end) + + ident(protected) + reserved(def) method(set_layout) + reserved(if) ident(action_name) operator(==) string<delimiter(")content(all_types_with_layout)delimiter(")> + string<delimiter(")content(standard)delimiter(")> + reserved(end) + reserved(end) +reserved(end) + +constant(RespondToController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + +reserved(class) class(MimeControllerTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + + instance_variable(@controller) operator(=) constant(RespondToController)operator(.)ident(new) + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.example.com)delimiter(")> + reserved(end) + + reserved(def) method(test_html) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/html)delimiter(")> + ident(get) symbol(:js_or_html) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:html_or_xml) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:just_xml) + ident(assert_response) integer(406) + reserved(end) + + reserved(def) method(test_all) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(*/*)delimiter(")> + ident(get) symbol(:js_or_html) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) comment(# js is not part of all) + + ident(get) symbol(:html_or_xml) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:just_xml) + ident(assert_equal) string<delimiter(')content(XML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_xml) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/xml)delimiter(")> + ident(get) symbol(:html_xml_or_rss) + ident(assert_equal) string<delimiter(')content(XML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_js_or_html) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/javascript, text/html)delimiter(")> + ident(get) symbol(:js_or_html) + ident(assert_equal) string<delimiter(')content(JS)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:html_or_xml) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:just_xml) + ident(assert_response) integer(406) + reserved(end) + + reserved(def) method(test_js_or_anything) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/javascript, */*)delimiter(")> + ident(get) symbol(:js_or_html) + ident(assert_equal) string<delimiter(')content(JS)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:html_or_xml) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:just_xml) + ident(assert_equal) string<delimiter(')content(XML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_using_defaults) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(*/*)delimiter(")> + ident(get) symbol(:using_defaults) + ident(assert_equal) string<delimiter(')content(Hello world!)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/javascript)delimiter(")> + ident(get) symbol(:using_defaults) + ident(assert_equal) string<delimiter(')content($("body"\).visualEffect("highlight"\);)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/xml)delimiter(")> + ident(get) symbol(:using_defaults) + ident(assert_equal) string<delimiter(")content(<p>Hello world!</p>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_using_defaults_with_type_list) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(*/*)delimiter(")> + ident(get) symbol(:using_defaults_with_type_list) + ident(assert_equal) string<delimiter(')content(Hello world!)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/javascript)delimiter(")> + ident(get) symbol(:using_defaults_with_type_list) + ident(assert_equal) string<delimiter(')content($("body"\).visualEffect("highlight"\);)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/xml)delimiter(")> + ident(get) symbol(:using_defaults_with_type_list) + ident(assert_equal) string<delimiter(")content(<p>Hello world!</p>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_with_content_type) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(CONTENT_TYPE)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/atom+xml)delimiter(")> + ident(get) symbol(:made_for_content_type) + ident(assert_equal) string<delimiter(")content(ATOM)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(CONTENT_TYPE)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/rss+xml)delimiter(")> + ident(get) symbol(:made_for_content_type) + ident(assert_equal) string<delimiter(")content(RSS)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_synonyms) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/javascript)delimiter(")> + ident(get) symbol(:js_or_html) + ident(assert_equal) string<delimiter(')content(JS)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/x-xml)delimiter(")> + ident(get) symbol(:html_xml_or_rss) + ident(assert_equal) string<delimiter(")content(XML)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_custom_types) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/crazy-xml)delimiter(")> + ident(get) symbol(:custom_type_handling) + ident(assert_equal) string<delimiter(')content(Crazy XML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/html)delimiter(")> + ident(get) symbol(:custom_type_handling) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_xhtml_alias) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(application/xhtml+xml,application/xml)delimiter(")> + ident(get) symbol(:html_or_xml) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_firefox_simulation) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5)delimiter(")> + ident(get) symbol(:html_or_xml) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_handle_any) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(*/*)delimiter(")> + ident(get) symbol(:handle_any) + ident(assert_equal) string<delimiter(')content(HTML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/javascript)delimiter(")> + ident(get) symbol(:handle_any) + ident(assert_equal) string<delimiter(')content(Either JS or XML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/xml)delimiter(")> + ident(get) symbol(:handle_any) + ident(assert_equal) string<delimiter(')content(Either JS or XML)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_all_types_with_layout) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/javascript)delimiter(")> + ident(get) symbol(:all_types_with_layout) + ident(assert_equal) string<delimiter(')content(RJS for all_types_with_layout)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_ACCEPT)delimiter(")>operator(]) operator(=) string<delimiter(")content(text/html)delimiter(")> + ident(get) symbol(:all_types_with_layout) + ident(assert_equal) string<delimiter(')content(<html>HTML for all_types_with_layout</html>)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_xhr) + ident(xhr) symbol(:get)operator(,) symbol(:js_or_html) + ident(assert_equal) string<delimiter(')content(JS)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(xhr) symbol(:get)operator(,) symbol(:using_defaults) + ident(assert_equal) string<delimiter(')content($("body"\).visualEffect("highlight"\);)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(MimeTypeTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + constant(Mime)operator(::)constant(PNG) operator(=) constant(Mime)operator(::)constant(Type)operator(.)ident(new)operator(()string<delimiter(")content(image/png)delimiter(")>operator(\)) + constant(Mime)operator(::)constant(PLAIN) operator(=) constant(Mime)operator(::)constant(Type)operator(.)ident(new)operator(()string<delimiter(")content(text/plain)delimiter(")>operator(\)) + + reserved(def) method(test_parse_single) + constant(Mime)operator(::)constant(LOOKUP)operator(.)ident(keys)operator(.)ident(each) reserved(do) operator(|)ident(mime_type)operator(|) + ident(assert_equal) operator([)constant(Mime)operator(::)constant(Type)operator(.)ident(lookup)operator(()ident(mime_type)operator(\))operator(])operator(,) constant(Mime)operator(::)constant(Type)operator(.)ident(parse)operator(()ident(mime_type)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_parse_without_q) + ident(accept) operator(=) string<delimiter(")content(text/xml,application/xhtml+xml,text/yaml,application/xml,text/html,image/png,text/plain,*/*)delimiter(")> + ident(expect) operator(=) operator([)constant(Mime)operator(::)constant(HTML)operator(,) constant(Mime)operator(::)constant(XML)operator(,) constant(Mime)operator(::)constant(YAML)operator(,) constant(Mime)operator(::)constant(PNG)operator(,) constant(Mime)operator(::)constant(PLAIN)operator(,) constant(Mime)operator(::)constant(ALL)operator(]) + ident(assert_equal) ident(expect)operator(,) constant(Mime)operator(::)constant(Type)operator(.)ident(parse)operator(()ident(accept)operator(\)) + reserved(end) + + reserved(def) method(test_parse_with_q) + ident(accept) operator(=) string<delimiter(")content(text/xml,application/xhtml+xml,text/yaml; q=0.3,application/xml,text/html; q=0.8,image/png,text/plain; q=0.5,*/*; q=0.2)delimiter(")> + ident(expect) operator(=) operator([)constant(Mime)operator(::)constant(HTML)operator(,) constant(Mime)operator(::)constant(XML)operator(,) constant(Mime)operator(::)constant(PNG)operator(,) constant(Mime)operator(::)constant(PLAIN)operator(,) constant(Mime)operator(::)constant(YAML)operator(,) constant(Mime)operator(::)constant(ALL)operator(]) + ident(assert_equal) ident(expect)operator(,) constant(Mime)operator(::)constant(Type)operator(.)ident(parse)operator(()ident(accept)operator(\)) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +ident(silence_warnings) operator({) constant(Customer) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Customer)delimiter(")>operator(,) symbol(:name)operator(\)) operator(}) + +reserved(module) class(Fun) + reserved(class) class(GamesController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(hello_world) + reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(NewRenderTestHelper) + reserved(def) method(rjs_helper_method_from_module) + ident(page)operator(.)ident(visual_effect) symbol(:highlight) + reserved(end) +reserved(end) + +reserved(class) class(NewRenderTestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(layout) symbol(:determine_layout) + + reserved(def) pre_constant(self)operator(.)ident(controller_name)operator(;) string<delimiter(")content(test)delimiter(")>operator(;) reserved(end) + reserved(def) pre_constant(self)operator(.)ident(controller_path)operator(;) string<delimiter(")content(test)delimiter(")>operator(;) reserved(end) + + reserved(def) method(hello_world) + reserved(end) + + reserved(def) method(render_hello_world) + ident(render) symbol(:template) operator(=)operator(>) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(render_hello_world_from_variable) + instance_variable(@person) operator(=) string<delimiter(")content(david)delimiter(")> + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(hello )inline<inline_delimiter(#{)instance_variable(@person)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(render_action_hello_world) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(render_action_hello_world_as_symbol) + ident(render) symbol(:action) operator(=)operator(>) symbol(:hello_world) + reserved(end) + + reserved(def) method(render_text_hello_world) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(render_text_hello_world_with_layout) + instance_variable(@variable_for_layout) operator(=) string<delimiter(")content(, I'm here!)delimiter(")> + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) symbol(:layout) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(hello_world_with_layout_false) + ident(render) symbol(:layout) operator(=)operator(>) pre_constant(false) + reserved(end) + + reserved(def) method(render_custom_code) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) symbol(:status) operator(=)operator(>) string<delimiter(")content(404 Moved)delimiter(")> + reserved(end) + + reserved(def) method(render_file_with_instance_variables) + instance_variable(@secret) operator(=) string<delimiter(')content(in the sauce)delimiter(')> + ident(path) operator(=) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(')content(../fixtures/test/render_file_with_ivar.rhtml)delimiter(')>operator(\)) + ident(render) symbol(:file) operator(=)operator(>) ident(path) + reserved(end) + + reserved(def) method(render_file_with_locals) + ident(path) operator(=) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(')content(../fixtures/test/render_file_with_locals.rhtml)delimiter(')>operator(\)) + ident(render) symbol(:file) operator(=)operator(>) ident(path)operator(,) symbol(:locals) operator(=)operator(>) operator({)symbol(:secret) operator(=)operator(>) string<delimiter(')content(in the sauce)delimiter(')>operator(}) + reserved(end) + + reserved(def) method(render_file_not_using_full_path) + instance_variable(@secret) operator(=) string<delimiter(')content(in the sauce)delimiter(')> + ident(render) symbol(:file) operator(=)operator(>) string<delimiter(')content(test/render_file_with_ivar)delimiter(')>operator(,) symbol(:use_full_path) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(render_file_not_using_full_path_with_relative_path) + instance_variable(@secret) operator(=) string<delimiter(')content(in the sauce)delimiter(')> + ident(render) symbol(:file) operator(=)operator(>) string<delimiter(')content(test/../test/render_file_with_ivar)delimiter(')>operator(,) symbol(:use_full_path) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(render_file_not_using_full_path_with_dot_in_path) + instance_variable(@secret) operator(=) string<delimiter(')content(in the sauce)delimiter(')> + ident(render) symbol(:file) operator(=)operator(>) string<delimiter(')content(test/dot.directory/render_file_with_ivar)delimiter(')>operator(,) symbol(:use_full_path) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(render_xml_hello) + instance_variable(@name) operator(=) string<delimiter(")content(David)delimiter(")> + ident(render) symbol(:template) operator(=)operator(>) string<delimiter(")content(test/hello)delimiter(")> + reserved(end) + + reserved(def) method(greeting) + comment(# let's just rely on the template) + reserved(end) + + reserved(def) method(layout_test) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(layout_test_with_different_layout) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")>operator(,) symbol(:layout) operator(=)operator(>) string<delimiter(")content(standard)delimiter(")> + reserved(end) + + reserved(def) method(rendering_without_layout) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")>operator(,) symbol(:layout) operator(=)operator(>) pre_constant(false) + reserved(end) + + reserved(def) method(layout_overriding_layout) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")>operator(,) symbol(:layout) operator(=)operator(>) string<delimiter(")content(standard)delimiter(")> + reserved(end) + + reserved(def) method(rendering_nothing_on_layout) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(builder_layout_test) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(partials_list) + instance_variable(@test_unchanged) operator(=) string<delimiter(')content(hello)delimiter(')> + instance_variable(@customers) operator(=) operator([) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\))operator(,) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(mary)delimiter(")>operator(\)) operator(]) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(list)delimiter(")> + reserved(end) + + reserved(def) method(partial_only) + ident(render) symbol(:partial) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(partial_only_with_layout) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(partial_only)delimiter(")>operator(,) symbol(:layout) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(partial_with_locals) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(customer)delimiter(")>operator(,) symbol(:locals) operator(=)operator(>) operator({) symbol(:customer) operator(=)operator(>) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\)) operator(}) + reserved(end) + + reserved(def) method(partial_collection) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(customer)delimiter(")>operator(,) symbol(:collection) operator(=)operator(>) operator([) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\))operator(,) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(mary)delimiter(")>operator(\)) operator(]) + reserved(end) + + reserved(def) method(partial_collection_with_locals) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(customer_greeting)delimiter(")>operator(,) symbol(:collection) operator(=)operator(>) operator([) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\))operator(,) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(mary)delimiter(")>operator(\)) operator(])operator(,) symbol(:locals) operator(=)operator(>) operator({) symbol(:greeting) operator(=)operator(>) string<delimiter(")content(Bonjour)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(empty_partial_collection) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(customer)delimiter(")>operator(,) symbol(:collection) operator(=)operator(>) operator([)operator(]) + reserved(end) + + reserved(def) method(partial_with_hash_object) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(hash_object)delimiter(")>operator(,) symbol(:object) operator(=)operator(>) operator({)symbol(:first_name) operator(=)operator(>) string<delimiter(")content(Sam)delimiter(")>operator(}) + reserved(end) + + reserved(def) method(partial_with_implicit_local_assignment) + instance_variable(@customer) operator(=) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(Marcel)delimiter(")>operator(\)) + ident(render) symbol(:partial) operator(=)operator(>) string<delimiter(")content(customer)delimiter(")> + reserved(end) + + reserved(def) method(hello_in_a_string) + instance_variable(@customers) operator(=) operator([) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\))operator(,) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(mary)delimiter(")>operator(\)) operator(]) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(How's there? )inline<inline_delimiter(#{)ident(render_to_string)operator(()string<delimiter(")content(test/list)delimiter(")>operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(accessing_params_in_template) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(Hello: <%= params[:name] %>)delimiter(")> + reserved(end) + + reserved(def) method(accessing_params_in_template_with_layout) + ident(render) symbol(:layout) operator(=)operator(>) pre_constant(nil)operator(,) symbol(:inline) operator(=)operator(>) string<delimiter(")content(Hello: <%= params[:name] %>)delimiter(")> + reserved(end) + + reserved(def) method(render_with_explicit_template) + ident(render) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(double_render) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(world)delimiter(")> + reserved(end) + + reserved(def) method(double_redirect) + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(double_render)delimiter(")> + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(double_render)delimiter(")> + reserved(end) + + reserved(def) method(render_and_redirect) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(double_render)delimiter(")> + reserved(end) + + reserved(def) method(rendering_with_conflicting_local_vars) + instance_variable(@name) operator(=) string<delimiter(")content(David)delimiter(")> + reserved(def) instance_variable(@template)operator(.)ident(name)operator(()operator(\)) pre_constant(nil) reserved(end) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(potential_conflicts)delimiter(")> + reserved(end) + + reserved(def) method(hello_world_from_rxml_using_action) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world.rxml)delimiter(")> + reserved(end) + + reserved(def) method(hello_world_from_rxml_using_template) + ident(render) symbol(:template) operator(=)operator(>) string<delimiter(")content(test/hello_world.rxml)delimiter(")> + reserved(end) + + ident(helper) constant(NewRenderTestHelper) + ident(helper) reserved(do) + reserved(def) method(rjs_helper_method)operator(()ident(value)operator(\)) + ident(page)operator(.)ident(visual_effect) symbol(:highlight)operator(,) ident(value) + reserved(end) + reserved(end) + + reserved(def) method(enum_rjs_test) + ident(render) symbol(:update) reserved(do) operator(|)ident(page)operator(|) + ident(page)operator(.)ident(select)operator(()string<delimiter(')content(.product)delimiter(')>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(value)operator(|) + ident(page)operator(.)ident(rjs_helper_method_from_module) + ident(page)operator(.)ident(rjs_helper_method)operator(()ident(value)operator(\)) + ident(page)operator(.)ident(sortable)operator(()ident(value)operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + ident(page)operator(.)ident(draggable)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(delete_with_js) + instance_variable(@project_id) operator(=) integer(4) + reserved(end) + + reserved(def) method(render_js_with_explicit_template) + instance_variable(@project_id) operator(=) integer(4) + ident(render) symbol(:template) operator(=)operator(>) string<delimiter(')content(test/delete_with_js)delimiter(')> + reserved(end) + + reserved(def) method(render_js_with_explicit_action_template) + instance_variable(@project_id) operator(=) integer(4) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(')content(delete_with_js)delimiter(')> + reserved(end) + + reserved(def) method(update_page) + ident(render) symbol(:update) reserved(do) operator(|)ident(page)operator(|) + ident(page)operator(.)ident(replace_html) string<delimiter(')content(balance)delimiter(')>operator(,) string<delimiter(')content($37,000,000.00)delimiter(')> + ident(page)operator(.)ident(visual_effect) symbol(:highlight)operator(,) string<delimiter(')content(balance)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(update_page_with_instance_variables) + instance_variable(@money) operator(=) string<delimiter(')content($37,000,000.00)delimiter(')> + instance_variable(@div_id) operator(=) string<delimiter(')content(balance)delimiter(')> + ident(render) symbol(:update) reserved(do) operator(|)ident(page)operator(|) + ident(page)operator(.)ident(replace_html) instance_variable(@div_id)operator(,) instance_variable(@money) + ident(page)operator(.)ident(visual_effect) symbol(:highlight)operator(,) instance_variable(@div_id) + reserved(end) + reserved(end) + + reserved(def) method(action_talk_to_layout) + comment(# Action template sets variable that's picked up by layout) + reserved(end) + + reserved(def) method(render_text_with_assigns) + instance_variable(@hello) operator(=) string<delimiter(")content(world)delimiter(")> + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")> + reserved(end) + + reserved(def) method(yield_content_for) + ident(render) symbol(:action) operator(=)operator(>) string<delimiter(")content(content_for)delimiter(")>operator(,) symbol(:layout) operator(=)operator(>) string<delimiter(")content(yield)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + + ident(private) + reserved(def) method(determine_layout) + reserved(case) ident(action_name) + reserved(when) string<delimiter(")content(hello_world)delimiter(")>operator(,) string<delimiter(")content(layout_test)delimiter(")>operator(,) string<delimiter(")content(rendering_without_layout)delimiter(")>operator(,) + string<delimiter(")content(rendering_nothing_on_layout)delimiter(")>operator(,) string<delimiter(")content(render_text_hello_world)delimiter(")>operator(,) + string<delimiter(")content(render_text_hello_world_with_layout)delimiter(")>operator(,) + string<delimiter(")content(hello_world_with_layout_false)delimiter(")>operator(,) + string<delimiter(")content(partial_only)delimiter(")>operator(,) string<delimiter(")content(partial_only_with_layout)delimiter(")>operator(,) + string<delimiter(")content(accessing_params_in_template)delimiter(")>operator(,) + string<delimiter(")content(accessing_params_in_template_with_layout)delimiter(")>operator(,) + string<delimiter(")content(render_with_explicit_template)delimiter(")>operator(,) + string<delimiter(")content(render_js_with_explicit_template)delimiter(")>operator(,) + string<delimiter(")content(render_js_with_explicit_action_template)delimiter(")>operator(,) + string<delimiter(")content(delete_with_js)delimiter(")>operator(,) string<delimiter(")content(update_page)delimiter(")>operator(,) string<delimiter(")content(update_page_with_instance_variables)delimiter(")> + + string<delimiter(")content(layouts/standard)delimiter(")> + reserved(when) string<delimiter(")content(builder_layout_test)delimiter(")> + string<delimiter(")content(layouts/builder)delimiter(")> + reserved(when) string<delimiter(")content(action_talk_to_layout)delimiter(")>operator(,) string<delimiter(")content(layout_overriding_layout)delimiter(")> + string<delimiter(")content(layouts/talk_from_action)delimiter(")> + reserved(end) + reserved(end) +reserved(end) + +constant(NewRenderTestController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> +constant(Fun)operator(::)constant(GamesController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + +reserved(class) class(NewRenderTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(NewRenderTestController)operator(.)ident(new) + + comment(# enable a logger so that (e.g.\) the benchmarking stuff runs, so we can get) + comment(# a more accurate simulation of what happens in "real life".) + instance_variable(@controller)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()pre_constant(nil)operator(\)) + + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.nextangle.com)delimiter(")> + reserved(end) + + reserved(def) method(test_simple_show) + ident(get) symbol(:hello_world) + ident(assert_response) symbol(:success) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + ident(assert_equal) string<delimiter(")content(<html>Hello world!</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render) + ident(get) symbol(:render_hello_world) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render_from_variable) + ident(get) symbol(:render_hello_world_from_variable) + ident(assert_equal) string<delimiter(")content(hello david)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render_action) + ident(get) symbol(:render_action_hello_world) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render_action_as_symbol) + ident(get) symbol(:render_action_hello_world_as_symbol) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render_text) + ident(get) symbol(:render_text_hello_world) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render_text_and_layout) + ident(get) symbol(:render_text_hello_world_with_layout) + ident(assert_equal) string<delimiter(")content(<html>hello world, I'm here!</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render_action_and_layout_false) + ident(get) symbol(:hello_world_with_layout_false) + ident(assert_equal) string<delimiter(')content(Hello world!)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render_custom_code) + ident(get) symbol(:render_custom_code) + ident(assert_response) symbol(:missing) + reserved(end) + + reserved(def) method(test_render_file_with_instance_variables) + ident(get) symbol(:render_file_with_instance_variables) + ident(assert_equal) string<delimiter(")content(The secret is in the sauce)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_file_not_using_full_path) + ident(get) symbol(:render_file_not_using_full_path) + ident(assert_equal) string<delimiter(")content(The secret is in the sauce)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_file_not_using_full_path_with_relative_path) + ident(get) symbol(:render_file_not_using_full_path_with_relative_path) + ident(assert_equal) string<delimiter(")content(The secret is in the sauce)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_file_not_using_full_path_with_dot_in_path) + ident(get) symbol(:render_file_not_using_full_path_with_dot_in_path) + ident(assert_equal) string<delimiter(")content(The secret is in the sauce)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_file_with_locals) + ident(get) symbol(:render_file_with_locals) + ident(assert_equal) string<delimiter(")content(The secret is in the sauce)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_attempt_to_access_object_method) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(UnknownAction)operator(,) string<delimiter(")content(No action responded to [clone])delimiter(")>operator(\)) operator({) ident(get) symbol(:clone) operator(}) + reserved(end) + + reserved(def) method(test_private_methods) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(UnknownAction)operator(,) string<delimiter(")content(No action responded to [determine_layout])delimiter(")>operator(\)) operator({) ident(get) symbol(:determine_layout) operator(}) + reserved(end) + + reserved(def) method(test_access_to_request_in_view) + ident(view_internals_old_value) operator(=) constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) operator(=) pre_constant(false) + constant(ActionController)operator(::)constant(Base)operator(.)ident(protected_variables_cache) operator(=) pre_constant(nil) + + ident(get) symbol(:hello_world) + ident(assert_nil)operator(()ident(assigns)operator([)string<delimiter(")content(request)delimiter(")>operator(])operator(\)) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) operator(=) pre_constant(true) + constant(ActionController)operator(::)constant(Base)operator(.)ident(protected_variables_cache) operator(=) pre_constant(nil) + + ident(get) symbol(:hello_world) + ident(assert_kind_of) constant(ActionController)operator(::)constant(AbstractRequest)operator(,) ident(assigns)operator([)string<delimiter(")content(request)delimiter(")>operator(]) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) operator(=) ident(view_internals_old_value) + constant(ActionController)operator(::)constant(Base)operator(.)ident(protected_variables_cache) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(test_render_xml) + ident(get) symbol(:render_xml_hello) + ident(assert_equal) string<delimiter(")content(<html>)char(\\n)content( <p>Hello David</p>)char(\\n)content(<p>This is grand!</p>)char(\\n)content(</html>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_enum_rjs_test) + ident(get) symbol(:enum_rjs_test) + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@response)operator(.)ident(body)string<content( +$$(".product"\).each(function(value, index\) { +new Effect.Highlight(element,{}\); +new Effect.Highlight(value,{}\); +Sortable.create(value, {onUpdate:function(\){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value\)}\)}}\); +new Draggable(value, {}\); +}\);)delimiter( +EOS)> + reserved(end) + + reserved(def) method(test_render_xml_with_default) + ident(get) symbol(:greeting) + ident(assert_equal) string<delimiter(")content(<p>This is grand!</p>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_rjs_with_default) + ident(get) symbol(:delete_with_js) + ident(assert_equal) string<delimiter(%!)content(["person"].each(Element.remove\);)char(\\n)content(new Effect.Highlight()char(\\")content(project-4)char(\\")content(,{}\);)delimiter(!)>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_rjs_template_explicitly) + ident(get) symbol(:render_js_with_explicit_template) + ident(assert_equal) string<delimiter(%!)content(["person"].each(Element.remove\);)char(\\n)content(new Effect.Highlight()char(\\")content(project-4)char(\\")content(,{}\);)delimiter(!)>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_rendering_rjs_action_explicitly) + ident(get) symbol(:render_js_with_explicit_action_template) + ident(assert_equal) string<delimiter(%!)content(["person"].each(Element.remove\);)char(\\n)content(new Effect.Highlight()char(\\")content(project-4)char(\\")content(,{}\);)delimiter(!)>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_layout_rendering) + ident(get) symbol(:layout_test) + ident(assert_equal) string<delimiter(")content(<html>Hello world!</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_layout_test_with_different_layout) + ident(get) symbol(:layout_test_with_different_layout) + ident(assert_equal) string<delimiter(")content(<html>Hello world!</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_rendering_without_layout) + ident(get) symbol(:rendering_without_layout) + ident(assert_equal) string<delimiter(")content(Hello world!)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_layout_overriding_layout) + ident(get) symbol(:layout_overriding_layout) + ident(assert_no_match) regexp<delimiter(%r{)content(<title>)delimiter(})>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_rendering_nothing_on_layout) + ident(get) symbol(:rendering_nothing_on_layout) + ident(assert_equal) string<delimiter(")content( )delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_xml_with_layouts) + ident(get) symbol(:builder_layout_test) + ident(assert_equal) string<delimiter(")content(<wrapper>)char(\\n)content(<html>)char(\\n)content( <p>Hello </p>)char(\\n)content(<p>This is grand!</p>)char(\\n)content(</html>)char(\\n)content(</wrapper>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_only) + ident(get) symbol(:partial_only) + ident(assert_equal) string<delimiter(")content(only partial)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_only_with_layout) + ident(get) symbol(:partial_only_with_layout) + ident(assert_equal) string<delimiter(")content(<html>only partial</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_to_string) + ident(get) symbol(:hello_in_a_string) + ident(assert_equal) string<delimiter(")content(How's there? goodbyeHello: davidHello: marygoodbye)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_nested_rendering) + ident(get) symbol(:hello_world) + ident(assert_equal) string<delimiter(")content(Living in a nested world)delimiter(")>operator(,) constant(Fun)operator(::)constant(GamesController)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\))operator(.)ident(body) + reserved(end) + + reserved(def) method(test_accessing_params_in_template) + ident(get) symbol(:accessing_params_in_template)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(David)delimiter(")> + ident(assert_equal) string<delimiter(")content(Hello: David)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_accessing_params_in_template_with_layout) + ident(get) symbol(:accessing_params_in_template_with_layout)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(David)delimiter(")> + ident(assert_equal) string<delimiter(")content(<html>Hello: David</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_with_explicit_template) + ident(get) symbol(:render_with_explicit_template) + ident(assert_response) symbol(:success) + reserved(end) + + reserved(def) method(test_double_render) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(DoubleRenderError)operator(\)) operator({) ident(get) symbol(:double_render) operator(}) + reserved(end) + + reserved(def) method(test_double_redirect) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(DoubleRenderError)operator(\)) operator({) ident(get) symbol(:double_redirect) operator(}) + reserved(end) + + reserved(def) method(test_render_and_redirect) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(DoubleRenderError)operator(\)) operator({) ident(get) symbol(:render_and_redirect) operator(}) + reserved(end) + + reserved(def) method(test_rendering_with_conflicting_local_vars) + ident(get) symbol(:rendering_with_conflicting_local_vars) + ident(assert_equal)operator(()string<delimiter(")content(First: David)char(\\n)content(Second: Stephan)char(\\n)content(Third: David)char(\\n)content(Fourth: David)char(\\n)content(Fifth: )delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body)operator(\)) + reserved(end) + + reserved(def) method(test_action_talk_to_layout) + ident(get) symbol(:action_talk_to_layout) + ident(assert_equal) string<delimiter(")content(<title>Talking to the layout</title>)char(\\n)content(Action was here!)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partials_list) + ident(get) symbol(:partials_list) + ident(assert_equal) string<delimiter(")content(goodbyeHello: davidHello: marygoodbye)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_with_locals) + ident(get) symbol(:partial_with_locals) + ident(assert_equal) string<delimiter(")content(Hello: david)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_collection) + ident(get) symbol(:partial_collection) + ident(assert_equal) string<delimiter(")content(Hello: davidHello: mary)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_collection_with_locals) + ident(get) symbol(:partial_collection_with_locals) + ident(assert_equal) string<delimiter(")content(Bonjour: davidBonjour: mary)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_empty_partial_collection) + ident(get) symbol(:empty_partial_collection) + ident(assert_equal) string<delimiter(")content( )delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_with_hash_object) + ident(get) symbol(:partial_with_hash_object) + ident(assert_equal) string<delimiter(")content(Sam)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_partial_with_implicit_local_assignment) + ident(get) symbol(:partial_with_implicit_local_assignment) + ident(assert_equal) string<delimiter(")content(Hello: Marcel)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_text_with_assigns) + ident(get) symbol(:render_text_with_assigns) + ident(assert_equal) string<delimiter(")content(world)delimiter(")>operator(,) ident(assigns)operator([)string<delimiter(")content(hello)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_update_page) + ident(get) symbol(:update_page) + ident(assert_template) pre_constant(nil) + ident(assert_equal) string<delimiter(')content(text/javascript; charset=UTF-8)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(]) + ident(assert_equal) integer(2)operator(,) instance_variable(@response)operator(.)ident(body)operator(.)ident(split)operator(()global_variable($/)operator(\))operator(.)ident(length) + reserved(end) + + reserved(def) method(test_update_page_with_instance_variables) + ident(get) symbol(:update_page_with_instance_variables) + ident(assert_template) pre_constant(nil) + ident(assert_equal) string<delimiter(')content(text/javascript; charset=UTF-8)delimiter(')>operator(,) instance_variable(@response)operator(.)ident(headers)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(]) + ident(assert_match) regexp<delimiter(/)content(balance)delimiter(/)>operator(,) instance_variable(@response)operator(.)ident(body) + ident(assert_match) regexp<delimiter(/)char(\\$)content(37)delimiter(/)>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_yield_content_for) + ident(get) symbol(:yield_content_for) + ident(assert_equal) string<delimiter(")content(<title>Putting stuff in the title!</title>)char(\\n)char(\\n)content(Great stuff!)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + + reserved(def) method(test_overwritting_rendering_relative_file_with_extension) + ident(get) symbol(:hello_world_from_rxml_using_template) + ident(assert_equal) string<delimiter(")content(<html>)char(\\n)content( <p>Hello</p>)char(\\n)content(</html>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + + ident(get) symbol(:hello_world_from_rxml_using_action) + ident(assert_equal) string<delimiter(")content(<html>)char(\\n)content( <p>Hello</p>)char(\\n)content(</html>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(cgi)delimiter(')> +ident(require) string<delimiter(')content(stringio)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_controller/cgi_ext/raw_post_data_fix)delimiter(')> + +reserved(class) class(RawPostDataTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + constant(ENV)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(POST)delimiter(')> + constant(ENV)operator([)string<delimiter(')content(CONTENT_TYPE)delimiter(')>operator(]) operator(=) string<delimiter(')delimiter(')> + constant(ENV)operator([)string<delimiter(')content(CONTENT_LENGTH)delimiter(')>operator(]) operator(=) string<delimiter(')content(0)delimiter(')> + reserved(end) + + reserved(def) method(test_raw_post_data) + ident(process_raw) string<delimiter(")content(action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1)delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(process_raw)operator(()ident(query_string)operator(\)) + ident(old_stdin) operator(=) global_variable($stdin) + reserved(begin) + global_variable($stdin) operator(=) constant(StringIO)operator(.)ident(new)operator(()ident(query_string)operator(.)ident(dup)operator(\)) + constant(ENV)operator([)string<delimiter(')content(CONTENT_LENGTH)delimiter(')>operator(]) operator(=) global_variable($stdin)operator(.)ident(size)operator(.)ident(to_s) + constant(CGI)operator(.)ident(new) + ident(assert_not_nil) constant(ENV)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) + ident(assert) constant(ENV)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(])operator(.)ident(frozen?) + ident(assert_equal) ident(query_string)operator(,) constant(ENV)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) + reserved(ensure) + global_variable($stdin) operator(=) ident(old_stdin) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(RedirectController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(simple_redirect) + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(method_redirect) + ident(redirect_to) symbol(:dashbord_url)operator(,) integer(1)operator(,) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(host_redirect) + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(other_host)delimiter(")>operator(,) symbol(:only_path) operator(=)operator(>) pre_constant(false)operator(,) symbol(:host) operator(=)operator(>) string<delimiter(')content(other.test.host)delimiter(')> + reserved(end) + + reserved(def) method(module_redirect) + ident(redirect_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(module_test/module_redirect)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(redirect_with_assigns) + instance_variable(@hello) operator(=) string<delimiter(")content(world)delimiter(")> + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(redirect_to_back) + ident(redirect_to) symbol(:back) + reserved(end) + + reserved(def) method(rescue_errors)operator(()ident(e)operator(\)) ident(raise) ident(e) reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + + ident(protected) + reserved(def) method(dashbord_url)operator(()ident(id)operator(,) ident(message)operator(\)) + ident(url_for) symbol(:action) operator(=)operator(>) string<delimiter(")content(dashboard)delimiter(")>operator(,) symbol(:params) operator(=)operator(>) operator({) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) ident(id)operator(,) string<delimiter(")content(message)delimiter(")> operator(=)operator(>) ident(message) operator(}) + reserved(end) +reserved(end) + +reserved(class) class(RedirectTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(RedirectController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_simple_redirect) + ident(get) symbol(:simple_redirect) + ident(assert_redirect_url) string<delimiter(")content(http://test.host/redirect/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_redirect_with_method_reference_and_parameters) + ident(get) symbol(:method_redirect) + ident(assert_redirect_url) string<delimiter(")content(http://test.host/redirect/dashboard/1?message=hello)delimiter(")> + reserved(end) + + reserved(def) method(test_simple_redirect_using_options) + ident(get) symbol(:host_redirect) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(other_host)delimiter(")>operator(,) symbol(:only_path) operator(=)operator(>) pre_constant(false)operator(,) symbol(:host) operator(=)operator(>) string<delimiter(')content(other.test.host)delimiter(')> + reserved(end) + + reserved(def) method(test_redirect_error_with_pretty_diff) + ident(get) symbol(:host_redirect) + reserved(begin) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(other_host)delimiter(")>operator(,) symbol(:only_path) operator(=)operator(>) pre_constant(true) + reserved(rescue) constant(Test)operator(::)constant(Unit)operator(::)constant(AssertionFailedError) operator(=)operator(>) ident(err) + ident(redirection_msg)operator(,) ident(diff_msg) operator(=) ident(err)operator(.)ident(message)operator(.)ident(scan)operator(()regexp<delimiter(/)content(<)char(\\{)content([^)char(\\})content(]+)char(\\})content(>)delimiter(/)>operator(\))operator(.)ident(collect) operator({) operator(|)ident(s)operator(|) ident(s)operator([)integer(2)operator(..)integer(-3)operator(]) operator(}) + ident(assert_match) regexp<delimiter(%r()content(:only_path=>false)delimiter(\))>operator(,) ident(redirection_msg) + ident(assert_match) regexp<delimiter(%r()content(:host=>"other.test.host")delimiter(\))>operator(,) ident(redirection_msg) + ident(assert_match) regexp<delimiter(%r()content(:action=>"other_host")delimiter(\))>operator(,) ident(redirection_msg) + ident(assert_match) regexp<delimiter(%r()content(:only_path=>true)delimiter(\))>operator(,) ident(diff_msg) + ident(assert_match) regexp<delimiter(%r()content(:host=>"other.test.host")delimiter(\))>operator(,) ident(diff_msg) + reserved(end) + reserved(end) + + reserved(def) method(test_module_redirect) + ident(get) symbol(:module_redirect) + ident(assert_redirect_url) string<delimiter(")content(http://test.host/module_test/module_redirect/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_module_redirect_using_options) + ident(get) symbol(:module_redirect) + ident(assert_redirected_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(module_test/module_redirect)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hello_world)delimiter(')> + reserved(end) + + reserved(def) method(test_redirect_with_assigns) + ident(get) symbol(:redirect_with_assigns) + ident(assert_equal) string<delimiter(")content(world)delimiter(")>operator(,) ident(assigns)operator([)string<delimiter(")content(hello)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_redirect_to_back) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_REFERER)delimiter(")>operator(]) operator(=) string<delimiter(")content(http://www.example.com/coming/from)delimiter(")> + ident(get) symbol(:redirect_to_back) + ident(assert_redirect_url) string<delimiter(")content(http://www.example.com/coming/from)delimiter(")> + reserved(end) + + reserved(def) method(test_redirect_to_back_with_no_referer) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(RedirectBackError)operator(\)) operator({) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(")content(HTTP_REFERER)delimiter(")>operator(]) operator(=) pre_constant(nil) + ident(get) symbol(:redirect_to_back) + operator(}) + reserved(end) +reserved(end) + +reserved(module) class(ModuleTest) + reserved(class) class(ModuleRedirectController) operator(<) operator(::)constant(RedirectController) + reserved(def) method(module_redirect) + ident(redirect_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(/redirect)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(ModuleRedirectTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(ModuleRedirectController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_simple_redirect) + ident(get) symbol(:simple_redirect) + ident(assert_redirect_url) string<delimiter(")content(http://test.host/module_test/module_redirect/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_redirect_with_method_reference_and_parameters) + ident(get) symbol(:method_redirect) + ident(assert_redirect_url) string<delimiter(")content(http://test.host/module_test/module_redirect/dashboard/1?message=hello)delimiter(")> + reserved(end) + + reserved(def) method(test_simple_redirect_using_options) + ident(get) symbol(:host_redirect) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(other_host)delimiter(")>operator(,) symbol(:only_path) operator(=)operator(>) pre_constant(false)operator(,) symbol(:host) operator(=)operator(>) string<delimiter(')content(other.test.host)delimiter(')> + reserved(end) + + reserved(def) method(test_module_redirect) + ident(get) symbol(:module_redirect) + ident(assert_redirect_url) string<delimiter(")content(http://test.host/redirect/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_module_redirect_using_options) + ident(get) symbol(:module_redirect) + ident(assert_redirected_to) symbol(:controller) operator(=)operator(>) string<delimiter(')content(redirect)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(unless) reserved(defined?)operator(()constant(Customer)operator(\)) + constant(Customer) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Customer)delimiter(")>operator(,) symbol(:name)operator(\)) +reserved(end) + +reserved(module) class(Fun) + reserved(class) class(GamesController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(hello_world) + reserved(end) + reserved(end) +reserved(end) + + +reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(layout) symbol(:determine_layout) + + reserved(def) method(hello_world) + reserved(end) + + reserved(def) method(render_hello_world) + ident(render) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(render_hello_world_from_variable) + instance_variable(@person) operator(=) string<delimiter(")content(david)delimiter(")> + ident(render_text) string<delimiter(")content(hello )inline<inline_delimiter(#{)instance_variable(@person)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(render_action_hello_world) + ident(render_action) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(render_action_hello_world_with_symbol) + ident(render_action) symbol(:hello_world) + reserved(end) + + reserved(def) method(render_text_hello_world) + ident(render_text) string<delimiter(")content(hello world)delimiter(")> + reserved(end) + + reserved(def) method(render_custom_code) + ident(render_text) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(404 Moved)delimiter(")> + reserved(end) + + reserved(def) method(render_xml_hello) + instance_variable(@name) operator(=) string<delimiter(")content(David)delimiter(")> + ident(render) string<delimiter(")content(test/hello)delimiter(")> + reserved(end) + + reserved(def) method(greeting) + comment(# let's just rely on the template) + reserved(end) + + reserved(def) method(layout_test) + ident(render_action) string<delimiter(")content(hello_world)delimiter(")> + reserved(end) + + reserved(def) method(builder_layout_test) + ident(render_action) string<delimiter(")content(hello)delimiter(")> + reserved(end) + + reserved(def) method(partials_list) + instance_variable(@test_unchanged) operator(=) string<delimiter(')content(hello)delimiter(')> + instance_variable(@customers) operator(=) operator([) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\))operator(,) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(mary)delimiter(")>operator(\)) operator(]) + ident(render_action) string<delimiter(")content(list)delimiter(")> + reserved(end) + + reserved(def) method(partial_only) + ident(render_partial) + reserved(end) + + reserved(def) method(hello_in_a_string) + instance_variable(@customers) operator(=) operator([) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(david)delimiter(")>operator(\))operator(,) constant(Customer)operator(.)ident(new)operator(()string<delimiter(")content(mary)delimiter(")>operator(\)) operator(]) + ident(render_text) string<delimiter(")content(How's there? )inline<inline_delimiter(#{)ident(render_to_string)operator(()string<delimiter(")content(test/list)delimiter(")>operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(accessing_params_in_template) + ident(render_template) string<delimiter(")content(Hello: <%= params[:name] %>)delimiter(")> + reserved(end) + + reserved(def) method(accessing_local_assigns_in_inline_template) + ident(name) operator(=) ident(params)operator([)symbol(:local_name)operator(]) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(<%= 'Goodbye, ' + local_name %>)delimiter(")>operator(,) + symbol(:locals) operator(=)operator(>) operator({) symbol(:local_name) operator(=)operator(>) ident(name) operator(}) + reserved(end) + + reserved(def) method(accessing_local_assigns_in_inline_template_with_string_keys) + ident(name) operator(=) ident(params)operator([)symbol(:local_name)operator(]) + constant(ActionView)operator(::)constant(Base)operator(.)ident(local_assigns_support_string_keys) operator(=) pre_constant(true) + ident(render) symbol(:inline) operator(=)operator(>) string<delimiter(")content(<%= 'Goodbye, ' + local_name %>)delimiter(")>operator(,) + symbol(:locals) operator(=)operator(>) operator({) string<delimiter(")content(local_name)delimiter(")> operator(=)operator(>) ident(name) operator(}) + constant(ActionView)operator(::)constant(Base)operator(.)ident(local_assigns_support_string_keys) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(render_to_string_test) + instance_variable(@foo) operator(=) ident(render_to_string) symbol(:inline) operator(=)operator(>) string<delimiter(")content(this is a test)delimiter(")> + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + + ident(private) + reserved(def) method(determine_layout) + reserved(case) ident(action_name) + reserved(when) string<delimiter(")content(layout_test)delimiter(")>operator(:) string<delimiter(")content(layouts/standard)delimiter(")> + reserved(when) string<delimiter(")content(builder_layout_test)delimiter(")>operator(:) string<delimiter(")content(layouts/builder)delimiter(")> + reserved(end) + reserved(end) +reserved(end) + +constant(TestController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> +constant(Fun)operator(::)constant(GamesController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + +reserved(class) class(RenderTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.nextangle.com)delimiter(")> + reserved(end) + + reserved(def) method(test_simple_show) + ident(get) symbol(:hello_world) + ident(assert_response) integer(200) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render) + ident(get) symbol(:render_hello_world) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render_from_variable) + ident(get) symbol(:render_hello_world_from_variable) + ident(assert_equal) string<delimiter(")content(hello david)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render_action) + ident(get) symbol(:render_action_hello_world) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render_action_with_symbol) + ident(get) symbol(:render_action_hello_world_with_symbol) + ident(assert_template) string<delimiter(")content(test/hello_world)delimiter(")> + reserved(end) + + reserved(def) method(test_do_with_render_text) + ident(get) symbol(:render_text_hello_world) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_do_with_render_custom_code) + ident(get) symbol(:render_custom_code) + ident(assert_response) integer(404) + reserved(end) + + reserved(def) method(test_attempt_to_access_object_method) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(UnknownAction)operator(,) string<delimiter(")content(No action responded to [clone])delimiter(")>operator(\)) operator({) ident(get) symbol(:clone) operator(}) + reserved(end) + + reserved(def) method(test_private_methods) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(UnknownAction)operator(,) string<delimiter(")content(No action responded to [determine_layout])delimiter(")>operator(\)) operator({) ident(get) symbol(:determine_layout) operator(}) + reserved(end) + + reserved(def) method(test_access_to_request_in_view) + ident(view_internals_old_value) operator(=) constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) operator(=) pre_constant(false) + constant(ActionController)operator(::)constant(Base)operator(.)ident(protected_variables_cache) operator(=) pre_constant(nil) + + ident(get) symbol(:hello_world) + ident(assert_nil) ident(assigns)operator([)string<delimiter(")content(request)delimiter(")>operator(]) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) operator(=) pre_constant(true) + constant(ActionController)operator(::)constant(Base)operator(.)ident(protected_variables_cache) operator(=) pre_constant(nil) + + ident(get) symbol(:hello_world) + ident(assert_kind_of) constant(ActionController)operator(::)constant(AbstractRequest)operator(,) ident(assigns)operator([)string<delimiter(")content(request)delimiter(")>operator(]) + + constant(ActionController)operator(::)constant(Base)operator(.)ident(view_controller_internals) operator(=) ident(view_internals_old_value) + constant(ActionController)operator(::)constant(Base)operator(.)ident(protected_variables_cache) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(test_render_xml) + ident(get) symbol(:render_xml_hello) + ident(assert_equal) string<delimiter(")content(<html>)char(\\n)content( <p>Hello David</p>)char(\\n)content(<p>This is grand!</p>)char(\\n)content(</html>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_xml_with_default) + ident(get) symbol(:greeting) + ident(assert_equal) string<delimiter(")content(<p>This is grand!</p>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_layout_rendering) + ident(get) symbol(:layout_test) + ident(assert_equal) string<delimiter(")content(<html>Hello world!</html>)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_xml_with_layouts) + ident(get) symbol(:builder_layout_test) + ident(assert_equal) string<delimiter(")content(<wrapper>)char(\\n)content(<html>)char(\\n)content( <p>Hello </p>)char(\\n)content(<p>This is grand!</p>)char(\\n)content(</html>)char(\\n)content(</wrapper>)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + comment(# def test_partials_list) + comment(# get :partials_list) + comment(# assert_equal "goodbyeHello: davidHello: marygoodbye\\n", process_request.body) + comment(# end) + + reserved(def) method(test_partial_only) + ident(get) symbol(:partial_only) + ident(assert_equal) string<delimiter(")content(only partial)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_to_string) + ident(get) symbol(:hello_in_a_string) + ident(assert_equal) string<delimiter(")content(How's there? goodbyeHello: davidHello: marygoodbye)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_render_to_string_resets_assigns) + ident(get) symbol(:render_to_string_test) + ident(assert_equal) string<delimiter(")content(The value of foo is: ::this is a test::)char(\\n)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_nested_rendering) + instance_variable(@controller) operator(=) constant(Fun)operator(::)constant(GamesController)operator(.)ident(new) + ident(get) symbol(:hello_world) + ident(assert_equal) string<delimiter(")content(Living in a nested world)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_accessing_params_in_template) + ident(get) symbol(:accessing_params_in_template)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(David)delimiter(")> + ident(assert_equal) string<delimiter(")content(Hello: David)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_accessing_local_assigns_in_inline_template) + ident(get) symbol(:accessing_local_assigns_in_inline_template)operator(,) symbol(:local_name) operator(=)operator(>) string<delimiter(")content(Local David)delimiter(")> + ident(assert_equal) string<delimiter(")content(Goodbye, Local David)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_accessing_local_assigns_in_inline_template_with_string_keys) + ident(get) symbol(:accessing_local_assigns_in_inline_template_with_string_keys)operator(,) symbol(:local_name) operator(=)operator(>) string<delimiter(")content(Local David)delimiter(")> + ident(assert_equal) string<delimiter(")content(Goodbye, Local David)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(RequestTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_remote_ip) + ident(assert_equal) string<delimiter(')content(0.0.0.0)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(remote_addr) operator(=) string<delimiter(')content(1.2.3.4)delimiter(')> + ident(assert_equal) string<delimiter(')content(1.2.3.4)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_CLIENT_IP)delimiter(')>operator(]) operator(=) string<delimiter(')content(2.3.4.5)delimiter(')> + ident(assert_equal) string<delimiter(')content(2.3.4.5)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + instance_variable(@request)operator(.)ident(env)operator(.)ident(delete) string<delimiter(')content(HTTP_CLIENT_IP)delimiter(')> + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(3.4.5.6)delimiter(')> + ident(assert_equal) string<delimiter(')content(3.4.5.6)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(unknown,3.4.5.6)delimiter(')> + ident(assert_equal) string<delimiter(')content(3.4.5.6)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(172.16.0.1,3.4.5.6)delimiter(')> + ident(assert_equal) string<delimiter(')content(3.4.5.6)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(192.168.0.1,3.4.5.6)delimiter(')> + ident(assert_equal) string<delimiter(')content(3.4.5.6)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(10.0.0.1,3.4.5.6)delimiter(')> + ident(assert_equal) string<delimiter(')content(3.4.5.6)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(127.0.0.1,3.4.5.6)delimiter(')> + ident(assert_equal) string<delimiter(')content(127.0.0.1)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')>operator(]) operator(=) string<delimiter(')content(unknown,192.168.0.1)delimiter(')> + ident(assert_equal) string<delimiter(')content(1.2.3.4)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(remote_ip) + instance_variable(@request)operator(.)ident(env)operator(.)ident(delete) string<delimiter(')content(HTTP_X_FORWARDED_FOR)delimiter(')> + reserved(end) + + reserved(def) method(test_domains) + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.rubyonrails.org)delimiter(")> + ident(assert_equal) string<delimiter(")content(rubyonrails.org)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(domain) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.rubyonrails.co.uk)delimiter(")> + ident(assert_equal) string<delimiter(")content(rubyonrails.co.uk)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(domain)operator(()integer(2)operator(\)) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(192.168.1.200)delimiter(")> + ident(assert_nil) instance_variable(@request)operator(.)ident(domain) + + instance_variable(@request)operator(.)ident(host) operator(=) pre_constant(nil) + ident(assert_nil) instance_variable(@request)operator(.)ident(domain) + reserved(end) + + reserved(def) method(test_subdomains) + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.rubyonrails.org)delimiter(")> + ident(assert_equal) string<delimiter(%w()content( www )delimiter(\))>operator(,) instance_variable(@request)operator(.)ident(subdomains) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(www.rubyonrails.co.uk)delimiter(")> + ident(assert_equal) string<delimiter(%w()content( www )delimiter(\))>operator(,) instance_variable(@request)operator(.)ident(subdomains)operator(()integer(2)operator(\)) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(dev.www.rubyonrails.co.uk)delimiter(")> + ident(assert_equal) string<delimiter(%w()content( dev www )delimiter(\))>operator(,) instance_variable(@request)operator(.)ident(subdomains)operator(()integer(2)operator(\)) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(foobar.foobar.com)delimiter(")> + ident(assert_equal) string<delimiter(%w()content( foobar )delimiter(\))>operator(,) instance_variable(@request)operator(.)ident(subdomains) + + instance_variable(@request)operator(.)ident(host) operator(=) pre_constant(nil) + ident(assert_equal) operator([)operator(])operator(,) instance_variable(@request)operator(.)ident(subdomains) + reserved(end) + + reserved(def) method(test_port_string) + instance_variable(@request)operator(.)ident(port) operator(=) integer(80) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) instance_variable(@request)operator(.)ident(port_string) + + instance_variable(@request)operator(.)ident(port) operator(=) integer(8080) + ident(assert_equal) string<delimiter(")content(:8080)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(port_string) + reserved(end) + + reserved(def) method(test_relative_url_root) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/dispatch.cgi)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(lighttpd/1.2.3)delimiter(')> + ident(assert_equal) string<delimiter(')delimiter(')>operator(,) instance_variable(@request)operator(.)ident(relative_url_root)operator(,) string<delimiter(")content(relative_url_root should be disabled on lighttpd)delimiter(")> + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(apache/1.2.3 some random text)delimiter(')> + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) pre_constant(nil) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/myapp.rb)delimiter(")> + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/hieraki)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/collaboration/hieraki/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/collaboration/hieraki)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + comment(# apache/scgi case) + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/collaboration/hieraki)delimiter(")> + ident(assert_equal) string<delimiter(")content(/collaboration/hieraki)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/dispatch.cgi)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(lighttpd/1.2.3)delimiter(')> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(RAILS_RELATIVE_URL_ROOT)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki)delimiter(")> + ident(assert_equal) string<delimiter(")content(/hieraki)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + + comment(# @env overrides path guess) + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/dispatch.cgi)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(apache/1.2.3 some random text)delimiter(')> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(RAILS_RELATIVE_URL_ROOT)delimiter(')>operator(]) operator(=) string<delimiter(")content(/real_url)delimiter(")> + ident(assert_equal) string<delimiter(")content(/real_url)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(relative_url_root) + reserved(end) + + reserved(def) method(test_request_uri) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(Apache 42.342.3432)delimiter(')> + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(http://www.rubyonrails.org/path/of/some/uri?mapped=1)delimiter(")> + ident(assert_equal) string<delimiter(")content(/path/of/some/uri?mapped=1)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(http://www.rubyonrails.org/path/of/some/uri)delimiter(")> + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/path/of/some/uri)delimiter(")> + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/)delimiter(")> + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/?m=b)delimiter(")> + ident(assert_equal) string<delimiter(")content(/?m=b)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/hieraki/)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/hieraki/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/collaboration/hieraki/books/edit/2)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/collaboration/hieraki/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/collaboration/hieraki/books/edit/2)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/books/edit/2)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + comment(# The following tests are for when REQUEST_URI is not supplied (as in IIS\)) + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/path/of/some/uri?mapped=1)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) pre_constant(nil) comment(#"/path/dispatch.rb") + ident(assert_equal) string<delimiter(")content(/path/of/some/uri?mapped=1)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/path/of/some/uri?mapped=1)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/path/dispatch.rb)delimiter(")> + ident(assert_equal) string<delimiter(")content(/path/of/some/uri?mapped=1)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/path/of/some/uri)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) pre_constant(nil) + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/path/of/some/uri)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/)delimiter(")> + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/?m=b)delimiter(")> + ident(assert_equal) string<delimiter(")content(/?m=b)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/hieraki/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/hieraki/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + + comment(# This test ensures that Rails uses REQUEST_URI over PATH_INFO) + instance_variable(@request)operator(.)ident(relative_url_root) operator(=) pre_constant(nil) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_URI)delimiter(')>operator(]) operator(=) string<delimiter(")content(/some/path)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(PATH_INFO)delimiter(')>operator(]) operator(=) string<delimiter(")content(/another/path)delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SCRIPT_NAME)delimiter(')>operator(]) operator(=) string<delimiter(")content(/dispatch.cgi)delimiter(")> + ident(assert_equal) string<delimiter(")content(/some/path)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(request_uri) + ident(assert_equal) string<delimiter(")content(/some/path)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(path) + reserved(end) + + + reserved(def) method(test_host_with_port) + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(rubyonrails.org)delimiter(")> + instance_variable(@request)operator(.)ident(port) operator(=) integer(80) + ident(assert_equal) string<delimiter(")content(rubyonrails.org)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + + instance_variable(@request)operator(.)ident(host) operator(=) string<delimiter(")content(rubyonrails.org)delimiter(")> + instance_variable(@request)operator(.)ident(port) operator(=) integer(81) + ident(assert_equal) string<delimiter(")content(rubyonrails.org:81)delimiter(")>operator(,) instance_variable(@request)operator(.)ident(host_with_port) + reserved(end) + + reserved(def) method(test_server_software) + ident(assert_equal) pre_constant(nil)operator(,) instance_variable(@request)operator(.)ident(server_software) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(Apache3.422)delimiter(')> + ident(assert_equal) string<delimiter(')content(apache)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(server_software) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_SOFTWARE)delimiter(')>operator(]) operator(=) string<delimiter(')content(lighttpd(1.1.4\))delimiter(')> + ident(assert_equal) string<delimiter(')content(lighttpd)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(server_software) + reserved(end) + + reserved(def) method(test_xml_http_request) + ident(assert) operator(!)instance_variable(@request)operator(.)ident(xml_http_request?) + ident(assert) operator(!)instance_variable(@request)operator(.)ident(xhr?) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_REQUESTED_WITH)delimiter(')>operator(]) operator(=) string<delimiter(")content(DefinitelyNotAjax1.0)delimiter(")> + ident(assert) operator(!)instance_variable(@request)operator(.)ident(xml_http_request?) + ident(assert) operator(!)instance_variable(@request)operator(.)ident(xhr?) + + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_REQUESTED_WITH)delimiter(')>operator(]) operator(=) string<delimiter(")content(XMLHttpRequest)delimiter(")> + ident(assert) instance_variable(@request)operator(.)ident(xml_http_request?) + ident(assert) instance_variable(@request)operator(.)ident(xhr?) + reserved(end) + + reserved(def) method(test_reports_ssl) + ident(assert) operator(!)instance_variable(@request)operator(.)ident(ssl?) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTPS)delimiter(')>operator(]) operator(=) string<delimiter(')content(on)delimiter(')> + ident(assert) instance_variable(@request)operator(.)ident(ssl?) + reserved(end) + + reserved(def) method(test_reports_ssl_when_proxied_via_lighttpd) + ident(assert) operator(!)instance_variable(@request)operator(.)ident(ssl?) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_FORWARDED_PROTO)delimiter(')>operator(]) operator(=) string<delimiter(')content(https)delimiter(')> + ident(assert) instance_variable(@request)operator(.)ident(ssl?) + reserved(end) + +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fake_controllers)delimiter(')> +ident(require) string<delimiter(')content(stringio)delimiter(')> + +constant(RunTimeTests) operator(=) pre_constant(ARGV)operator(.)ident(include?) string<delimiter(')content(time)delimiter(')> + +reserved(module) class(ActionController::CodeGeneration) + +reserved(class) class(SourceTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(attr_accessor) symbol(:source) + reserved(def) method(setup) + instance_variable(@source) operator(=) constant(Source)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_initial_state) + ident(assert_equal) operator([)operator(])operator(,) ident(source)operator(.)ident(lines) + ident(assert_equal) integer(0)operator(,) ident(source)operator(.)ident(indentation_level) + reserved(end) + + reserved(def) method(test_trivial_operations) + ident(source) operator(<<) string<delimiter(")content(puts 'Hello World')delimiter(")> + ident(assert_equal) operator([)string<delimiter(")content(puts 'Hello World')delimiter(")>operator(])operator(,) ident(source)operator(.)ident(lines) + ident(assert_equal) string<delimiter(")content(puts 'Hello World')delimiter(")>operator(,) ident(source)operator(.)ident(to_s) + + ident(source)operator(.)ident(line) string<delimiter(")content(puts 'Goodbye World')delimiter(")> + ident(assert_equal) operator([)string<delimiter(")content(puts 'Hello World')delimiter(")>operator(,) string<delimiter(")content(puts 'Goodbye World')delimiter(")>operator(])operator(,) ident(source)operator(.)ident(lines) + ident(assert_equal) string<delimiter(")content(puts 'Hello World')char(\\n)content(puts 'Goodbye World')delimiter(")>operator(,) ident(source)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_indentation) + ident(source) operator(<<) string<delimiter(")content(x = gets.to_i)delimiter(")> + ident(source) operator(<<) string<delimiter(')content(if x.odd?)delimiter(')> + ident(source)operator(.)ident(indent) operator({) ident(source) operator(<<) string<delimiter(")content(puts 'x is odd!')delimiter(")> operator(}) + ident(source) operator(<<) string<delimiter(')content(else)delimiter(')> + ident(source)operator(.)ident(indent) operator({) ident(source) operator(<<) string<delimiter(")content(puts 'x is even!')delimiter(")> operator(}) + ident(source) operator(<<) string<delimiter(')content(end)delimiter(')> + + ident(assert_equal) operator([)string<delimiter(")content(x = gets.to_i)delimiter(")>operator(,) string<delimiter(")content(if x.odd?)delimiter(")>operator(,) string<delimiter(")content( puts 'x is odd!')delimiter(")>operator(,) string<delimiter(')content(else)delimiter(')>operator(,) string<delimiter(")content( puts 'x is even!')delimiter(")>operator(,) string<delimiter(')content(end)delimiter(')>operator(])operator(,) ident(source)operator(.)ident(lines) + + ident(text) operator(=) string<delimiter(")content(x = gets.to_i +if x.odd? + puts 'x is odd!' +else + puts 'x is even!' +end)delimiter(")> + + ident(assert_equal) ident(text)operator(,) ident(source)operator(.)ident(to_s) + reserved(end) +reserved(end) + +reserved(class) class(CodeGeneratorTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(attr_accessor) symbol(:generator) + reserved(def) method(setup) + instance_variable(@generator) operator(=) constant(CodeGenerator)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_initial_state) + ident(assert_equal) operator([)operator(])operator(,) ident(generator)operator(.)ident(source)operator(.)ident(lines) + ident(assert_equal) operator([)operator(])operator(,) ident(generator)operator(.)ident(locals) + reserved(end) + + reserved(def) method(test_trivial_operations) + operator([)string<delimiter(")content(puts 'Hello World')delimiter(")>operator(,) string<delimiter(")content(puts 'Goodbye World')delimiter(")>operator(])operator(.)ident(each) operator({)operator(|)ident(l)operator(|) ident(generator) operator(<<) ident(l)operator(}) + ident(assert_equal) operator([)string<delimiter(")content(puts 'Hello World')delimiter(")>operator(,) string<delimiter(")content(puts 'Goodbye World')delimiter(")>operator(])operator(,) ident(generator)operator(.)ident(source)operator(.)ident(lines) + ident(assert_equal) string<delimiter(")content(puts 'Hello World')char(\\n)content(puts 'Goodbye World')delimiter(")>operator(,) ident(generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_if) + ident(generator) operator(<<) string<delimiter(")content(x = gets.to_i)delimiter(")> + ident(generator)operator(.)ident(if)operator(()string<delimiter(")content(x.odd?)delimiter(")>operator(\)) operator({) ident(generator) operator(<<) string<delimiter(")content(puts 'x is odd!')delimiter(")> operator(}) + + ident(assert_equal) string<delimiter(")content(x = gets.to_i)char(\\n)content(if x.odd?)char(\\n)content( puts 'x is odd!')char(\\n)content(end)delimiter(")>operator(,) ident(generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_else) + ident(test_if) + ident(generator)operator(.)ident(else) operator({) ident(generator) operator(<<) string<delimiter(")content(puts 'x is even!')delimiter(")> operator(}) + + ident(assert_equal) string<delimiter(")content(x = gets.to_i)char(\\n)content(if x.odd?)char(\\n)content( puts 'x is odd!')char(\\n)content(else )char(\\n)content( puts 'x is even!')char(\\n)content(end)delimiter(")>operator(,) ident(generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_dup) + ident(generator) operator(<<) string<delimiter(')content(x = 2)delimiter(')> + ident(generator)operator(.)ident(locals) operator(<<) symbol(:x) + + ident(g) operator(=) ident(generator)operator(.)ident(dup) + ident(assert_equal) ident(generator)operator(.)ident(source)operator(,) ident(g)operator(.)ident(source) + ident(assert_equal) ident(generator)operator(.)ident(locals)operator(,) ident(g)operator(.)ident(locals) + + ident(g) operator(<<) string<delimiter(')content(y = 3)delimiter(')> + ident(g)operator(.)ident(locals) operator(<<) symbol(:y) + ident(assert_equal) operator([)symbol(:x)operator(,) symbol(:y)operator(])operator(,) ident(g)operator(.)ident(locals) comment(# Make sure they don't share the same array.) + ident(assert_equal) operator([)symbol(:x)operator(])operator(,) ident(generator)operator(.)ident(locals) + reserved(end) +reserved(end) + +reserved(class) class(RecognitionTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(attr_accessor) symbol(:generator) + reserved(alias) symbol(:g) symbol(:generator) + reserved(def) method(setup) + instance_variable(@generator) operator(=) constant(RecognitionGenerator)operator(.)ident(new) + reserved(end) + + reserved(def) method(go)operator(()ident(components)operator(\)) + ident(g)operator(.)ident(current) operator(=) ident(components)operator(.)ident(first) + ident(g)operator(.)ident(after) operator(=) ident(components)operator([)integer(1)operator(..)integer(-1)operator(]) operator(||) operator([)operator(]) + ident(g)operator(.)ident(go) + reserved(end) + + reserved(def) method(execute)operator(()ident(path)operator(,) ident(show) operator(=) pre_constant(false)operator(\)) + ident(path) operator(=) ident(path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) reserved(if) ident(path)operator(.)ident(is_a?) constant(String) + ident(source) operator(=) string<delimiter(")content(index, path = 0, )inline<inline_delimiter(#{)ident(path)operator(.)ident(inspect)inline_delimiter(})>char(\\n)inline<inline_delimiter(#{)ident(g)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + ident(puts) ident(source) reserved(if) ident(show) + ident(r) operator(=) ident(eval) ident(source) + ident(r) operator(?) ident(r)operator(.)ident(symbolize_keys) operator(:) pre_constant(nil) + reserved(end) + + constant(Static) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(StaticComponent) + constant(Dynamic) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(DynamicComponent) + constant(Path) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(PathComponent) + constant(Controller) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(ControllerComponent) + + reserved(def) method(test_all_static) + ident(c) operator(=) string<delimiter(%w()content(hello world how are you)delimiter(\))>operator(.)ident(collect) operator({)operator(|)ident(str)operator(|) constant(Static)operator(.)ident(new)operator(()ident(str)operator(\))operator(}) + + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(g)operator(.)ident(constant_result) symbol(:action)operator(,) string<delimiter(')content(index)delimiter(')> + + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(x)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hello/world/how)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hello/world/how/are)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hello/world/how/are/you/today)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hello/world/how/are/you)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_basic_dynamic) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(dude)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_basic_dynamic_backwards) + ident(c) operator(=) operator([)constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(\))operator(,) constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(]) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(index/hi)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(show/hi)delimiter(')>operator(\))operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_default) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/index)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(dude)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_string_condition) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:condition) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/index)delimiter(')>operator(\))operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_string_condition_backwards) + ident(c) operator(=) operator([)constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:condition) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(,) constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(dude/what/hi)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(index/what)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(index/hi)delimiter(')>operator(\))operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(dude/hi)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_regexp_condition) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:condition) operator(=)operator(>) regexp<delimiter(/)content(^[a-z]+$)delimiter(/)>operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/FOXY)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/138708jkhdf)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dkjfl8792343dfsf)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/index)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(dude)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_regexp_and_default) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:condition) operator(=)operator(>) regexp<delimiter(/)content(^[a-z]+$)delimiter(/)>operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/FOXY)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/138708jkhdf)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dkjfl8792343dfsf)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/index)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(dude)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\))operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_path) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Path)operator(.)ident(new)operator(()symbol(:file)operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(g)operator(.)ident(constant_result) symbol(:action)operator(,) string<delimiter(")content(download)delimiter(")> + + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(download)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(download)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) string<delimiter(%w()content(books agile_rails_dev.pdf)delimiter(\))>operator(})operator(,) + ident(execute)operator(()string<delimiter(')content(hi/books/agile_rails_dev.pdf)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(download)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)string<delimiter(')content(dude)delimiter(')>operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude)delimiter(')>operator(\))operator(\)) + ident(assert_equal) string<delimiter(')content(dude/what)delimiter(')>operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\))operator([)symbol(:file)operator(])operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_path_with_dynamic) + ident(c) operator(=) operator([)constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(\))operator(,) constant(Path)operator(.)ident(new)operator(()symbol(:file)operator(\))operator(]) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(download)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(download)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(download)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) string<delimiter(%w()content(books agile_rails_dev.pdf)delimiter(\))>operator(})operator(,) + ident(execute)operator(()string<delimiter(')content(download/books/agile_rails_dev.pdf)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(download)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)string<delimiter(')content(dude)delimiter(')>operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(download/dude)delimiter(')>operator(\))operator(\)) + ident(assert_equal) string<delimiter(')content(dude/what)delimiter(')>operator(,) ident(execute)operator(()string<delimiter(')content(hi/dude/what)delimiter(')>operator(\))operator([)symbol(:file)operator(])operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_path_with_dynamic_and_default) + ident(c) operator(=) operator([)constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(,) constant(Path)operator(.)ident(new)operator(()symbol(:file)operator(\))operator(]) + + ident(go) ident(c) + + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(index)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(blarg)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(blarg)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)string<delimiter(')content(content)delimiter(')>operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(index/content)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:file) operator(=)operator(>) operator([)string<delimiter(')content(rails_dev.pdf)delimiter(')>operator(])operator(})operator(,) ident(execute)operator(()string<delimiter(')content(show/rails_dev.pdf)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_controller) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Controller)operator(.)ident(new)operator(()symbol(:controller)operator(\))operator(]) + ident(g)operator(.)ident(constant_result) symbol(:action)operator(,) string<delimiter(")content(hi)delimiter(")> + + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(boo/blah)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/x)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/13870948)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/content/dog)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/admin/user/foo)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/content)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/admin/user)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_controller_with_regexp) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Controller)operator(.)ident(new)operator(()symbol(:controller)operator(,) symbol(:condition) operator(=)operator(>) regexp<delimiter(/)content(^admin)char(\\/)content(.+$)delimiter(/)>operator(\))operator(]) + ident(g)operator(.)ident(constant_result) symbol(:action)operator(,) string<delimiter(")content(hi)delimiter(")> + + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/x)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/content)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/admin/user)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(NewsFeedController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(hi/admin/news_feed)delimiter(')>operator(\))operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hi/admin/user/foo)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_standard_route)operator(()ident(time) operator(=) operator(::)constant(RunTimeTests)operator(\)) + ident(c) operator(=) operator([)constant(Controller)operator(.)ident(new)operator(()symbol(:controller)operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:id)operator(,) symbol(:default) operator(=)operator(>) pre_constant(nil)operator(\))operator(]) + ident(go) ident(c) + + comment(# Make sure we get the right answers) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(content)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(content/list)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(content/show/10)delimiter(')>operator(\))operator(\)) + + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(admin/user)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(admin/user/list)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(nseckar)delimiter(')>operator(})operator(,) ident(execute)operator(()string<delimiter(')content(admin/user/show/nseckar)delimiter(')>operator(\))operator(\)) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(content/show/10/20)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(food)delimiter(')>operator(\)) + + reserved(if) ident(time) + ident(source) operator(=) string<delimiter(")content(def self.execute(path\) + path = path.split('/'\) if path.is_a? String + index = 0 + r = )inline<inline_delimiter(#{)ident(g)operator(.)ident(to_s)inline_delimiter(})>content( + end)delimiter(")> + ident(eval)operator(()ident(source)operator(\)) + + constant(GC)operator(.)ident(start) + ident(n) operator(=) integer(1000) + ident(time) operator(=) constant(Benchmark)operator(.)ident(realtime) reserved(do) ident(n)operator(.)ident(times) operator({) + ident(execute)operator(()string<delimiter(')content(content)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(content/list)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(content/show/10)delimiter(')>operator(\)) + + ident(execute)operator(()string<delimiter(')content(admin/user)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(admin/user/list)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(admin/user/show/nseckar)delimiter(')>operator(\)) + + ident(execute)operator(()string<delimiter(')content(admin/user/show/nseckar/dude)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(admin/why/show/nseckar)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(content/show/10/20)delimiter(')>operator(\)) + ident(execute)operator(()string<delimiter(')content(food)delimiter(')>operator(\)) + operator(}) reserved(end) + ident(time) operator(-=) constant(Benchmark)operator(.)ident(realtime) reserved(do) ident(n)operator(.)ident(times) operator({) operator(}) reserved(end) + + + ident(puts) string<delimiter(")char(\\n)char(\\n)content(Recognition:)delimiter(")> + ident(per_url) operator(=) ident(time) operator(/) operator(()ident(n) operator(*) integer(10)operator(\)) + + ident(puts) string<delimiter(")inline<inline_delimiter(#{)ident(per_url) operator(*) integer(1000)inline_delimiter(})>content( ms/url)delimiter(")> + ident(puts) string<delimiter(")inline<inline_delimiter(#{)integer(1) operator(/) ident(per_url)inline_delimiter(})>content( urls/s)char(\\n)char(\\n)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_default_route) + ident(g)operator(.)ident(result) symbol(:controller)operator(,) string<delimiter(")content(::ContentController)delimiter(")>operator(,) pre_constant(true) + ident(g)operator(.)ident(constant_result) symbol(:action)operator(,) string<delimiter(')content(index)delimiter(')> + + ident(go) operator([)operator(]) + + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(x)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hello/world/how)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hello/world/how/are)delimiter(')>operator(\)) + ident(assert_nil) ident(execute)operator(()string<delimiter(')content(hello/world/how/are/you/today)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(execute)operator(()operator([)operator(])operator(\))operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(GenerationTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(attr_accessor) symbol(:generator) + reserved(alias) symbol(:g) symbol(:generator) + reserved(def) method(setup) + instance_variable(@generator) operator(=) constant(GenerationGenerator)operator(.)ident(new) comment(# ha!) + reserved(end) + + reserved(def) method(go)operator(()ident(components)operator(\)) + ident(g)operator(.)ident(current) operator(=) ident(components)operator(.)ident(first) + ident(g)operator(.)ident(after) operator(=) ident(components)operator([)integer(1)operator(..)integer(-1)operator(]) operator(||) operator([)operator(]) + ident(g)operator(.)ident(go) + reserved(end) + + reserved(def) method(execute)operator(()ident(options)operator(,) ident(recall)operator(,) ident(show) operator(=) pre_constant(false)operator(\)) + ident(source) operator(=) string<delimiter(")char(\\n)content( +expire_on = ::ActionController::Routing.expiry_hash(options, recall\) +hash = merged = recall.merge(options\) +not_expired = true + +)inline<inline_delimiter(#{)ident(g)operator(.)ident(to_s)inline_delimiter(})>char(\\n)char(\\n)delimiter(")> + ident(puts) ident(source) reserved(if) ident(show) + ident(eval)operator(()ident(source)operator(\)) + reserved(end) + + constant(Static) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(StaticComponent) + constant(Dynamic) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(DynamicComponent) + constant(Path) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(PathComponent) + constant(Controller) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(ControllerComponent) + + reserved(def) method(test_all_static_no_requirements) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hello)delimiter(")>operator(\))operator(,) constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(world)delimiter(")>operator(\))operator(]) + ident(go) ident(c) + + ident(assert_equal) string<delimiter(")content(/hello/world)delimiter(")>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_basic_dynamic) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(\))operator(]) + ident(go) ident(c) + + ident(assert_equal) string<delimiter(')content(/hi/index)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/show)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/list+people)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list people)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,)operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_default) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(]) + ident(go) ident(c) + + ident(assert_equal) string<delimiter(')content(/hi)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/show)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/list+people)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list people)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_regexp_condition) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:condition) operator(=)operator(>) regexp<delimiter(/)content(^[a-z]+$)delimiter(/)>operator(\))operator(]) + ident(go) ident(c) + + ident(assert_equal) string<delimiter(')content(/hi/index)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(fox5)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(something_is_up)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list people)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/abunchofcharacter)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(abunchofcharacter)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_dynamic_with_default_and_regexp_condition) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:condition) operator(=)operator(>) regexp<delimiter(/)content(^[a-z]+$)delimiter(/)>operator(\))operator(]) + ident(go) ident(c) + + ident(assert_equal) string<delimiter(')content(/hi)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(fox5)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(something_is_up)delimiter(')>operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list people)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/abunchofcharacter)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(abunchofcharacter)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_path) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Path)operator(.)ident(new)operator(()symbol(:file)operator(\))operator(]) + ident(go) ident(c) + + ident(assert_equal) string<delimiter(')content(/hi)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:file) operator(=)operator(>) operator([)operator(])operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/books/agile_rails_dev.pdf)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:file) operator(=)operator(>) string<delimiter(%w()content(books agile_rails_dev.pdf)delimiter(\))>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/books/development%26whatever/agile_rails_dev.pdf)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:file) operator(=)operator(>) string<delimiter(%w()content(books development&whatever agile_rails_dev.pdf)delimiter(\))>operator(})operator(,) operator({)operator(})operator(\)) + + ident(assert_equal) string<delimiter(')content(/hi)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:file) operator(=)operator(>) string<delimiter(')delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/books/agile_rails_dev.pdf)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:file) operator(=)operator(>) string<delimiter(')content(books/agile_rails_dev.pdf)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/books/development%26whatever/agile_rails_dev.pdf)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:file) operator(=)operator(>) string<delimiter(')content(books/development&whatever/agile_rails_dev.pdf)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_controller) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Controller)operator(.)ident(new)operator(()symbol(:controller)operator(\))operator(]) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/content)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/admin/user)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/content)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/admin/user)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_controller_with_regexp) + ident(c) operator(=) operator([)constant(Static)operator(.)ident(new)operator(()string<delimiter(")content(hi)delimiter(")>operator(\))operator(,) constant(Controller)operator(.)ident(new)operator(()symbol(:controller)operator(,) symbol(:condition) operator(=)operator(>) regexp<delimiter(/)content(^admin)char(\\/)content(.+$)delimiter(/)>operator(\))operator(]) + ident(go) ident(c) + + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/admin/user)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hi/admin/user)delimiter(')>operator(,) ident(execute)operator(()operator({)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_standard_route)operator(()ident(time) operator(=) operator(::)constant(RunTimeTests)operator(\)) + ident(c) operator(=) operator([)constant(Controller)operator(.)ident(new)operator(()symbol(:controller)operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:action)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\))operator(,) constant(Dynamic)operator(.)ident(new)operator(()symbol(:id)operator(,) symbol(:default) operator(=)operator(>) pre_constant(nil)operator(\))operator(]) + ident(go) ident(c) + + comment(# Make sure we get the right answers) + ident(assert_equal)operator(()string<delimiter(')content(/content)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(/content/list)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(/content/show/10)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\))operator(\)) + + ident(assert_equal)operator(()string<delimiter(')content(/admin/user)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(/admin/user/list)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(/admin/user/show/10)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\))operator(\)) + + reserved(if) ident(time) + constant(GC)operator(.)ident(start) + ident(n) operator(=) integer(1000) + ident(time) operator(=) constant(Benchmark)operator(.)ident(realtime) reserved(do) ident(n)operator(.)ident(times) operator({) + ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\)) + ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\)) + + ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\)) + ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(\)) + ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(\)) + operator(}) reserved(end) + ident(time) operator(-=) constant(Benchmark)operator(.)ident(realtime) reserved(do) ident(n)operator(.)ident(times) operator({) operator(}) reserved(end) + + ident(puts) string<delimiter(")char(\\n)char(\\n)content(Generation:)delimiter(")> + ident(per_url) operator(=) ident(time) operator(/) operator(()ident(n) operator(*) integer(6)operator(\)) + + ident(puts) string<delimiter(")inline<inline_delimiter(#{)ident(per_url) operator(*) integer(1000)inline_delimiter(})>content( ms/url)delimiter(")> + ident(puts) string<delimiter(")inline<inline_delimiter(#{)integer(1) operator(/) ident(per_url)inline_delimiter(})>content( urls/s)char(\\n)char(\\n)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_default_route) + ident(g)operator(.)ident(if)operator(()ident(g)operator(.)ident(check_conditions)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(welcome)delimiter(')>operator(\))operator(\)) operator({) ident(go) operator([)operator(]) operator(}) + + ident(assert_nil) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(foo)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(welcome)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(elcome)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_nil) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(elcome)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(\)) + + ident(assert_equal) string<delimiter(')content(/)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(welcome)delimiter(')>operator(})operator(,) operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(welcome)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/)delimiter(')>operator(,) ident(execute)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(welcome)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(RouteTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + + reserved(def) method(route)operator(()operator(*)ident(args)operator(\)) + instance_variable(@route) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(Route)operator(.)ident(new)operator(()operator(*)ident(args)operator(\)) reserved(unless) ident(args)operator(.)ident(empty?) + reserved(return) instance_variable(@route) + reserved(end) + + reserved(def) method(rec)operator(()ident(path)operator(,) ident(show) operator(=) pre_constant(false)operator(\)) + ident(path) operator(=) ident(path)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) reserved(if) ident(path)operator(.)ident(is_a?) constant(String) + ident(index) operator(=) integer(0) + ident(source) operator(=) ident(route)operator(.)ident(write_recognition)operator(.)ident(to_s) + ident(puts) string<delimiter(")char(\\n)char(\\n)inline<inline_delimiter(#{)ident(source)inline_delimiter(})>char(\\n)char(\\n)delimiter(")> reserved(if) ident(show) + ident(r) operator(=) ident(eval)operator(()ident(source)operator(\)) + ident(r) operator(?) ident(r)operator(.)ident(symbolize_keys) operator(:) ident(r) + reserved(end) + reserved(def) method(gen)operator(()ident(options)operator(,) ident(recall) operator(=) pre_constant(nil)operator(,) ident(show) operator(=) pre_constant(false)operator(\)) + ident(recall) operator(||=) ident(options)operator(.)ident(dup) + + ident(expire_on) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(.)ident(expiry_hash)operator(()ident(options)operator(,) ident(recall)operator(\)) + ident(hash) operator(=) ident(merged) operator(=) ident(recall)operator(.)ident(merge)operator(()ident(options)operator(\)) + ident(not_expired) operator(=) pre_constant(true) + + ident(source) operator(=) ident(route)operator(.)ident(write_generation)operator(.)ident(to_s) + ident(puts) string<delimiter(")char(\\n)char(\\n)inline<inline_delimiter(#{)ident(source)inline_delimiter(})>char(\\n)char(\\n)delimiter(")> reserved(if) ident(show) + ident(eval)operator(()ident(source)operator(\)) + + reserved(end) + + reserved(def) method(test_static) + ident(route) string<delimiter(')content(hello/world)delimiter(')>operator(,) symbol(:known) operator(=)operator(>) string<delimiter(')content(known_value)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')> + + ident(assert_nil) ident(rec)operator(()string<delimiter(')content(hello/turn)delimiter(')>operator(\)) + ident(assert_nil) ident(rec)operator(()string<delimiter(')content(turn/world)delimiter(')>operator(\)) + ident(assert_equal)operator(() + operator({)symbol(:known) operator(=)operator(>) string<delimiter(')content(known_value)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) + ident(rec)operator(()string<delimiter(')content(hello/world)delimiter(')>operator(\)) + operator(\)) + + ident(assert_nil) ident(gen)operator(()symbol(:known) operator(=)operator(>) string<delimiter(')content(foo)delimiter(')>operator(\)) + ident(assert_nil) ident(gen)operator(()operator({)operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/hello/world)delimiter(')>operator(,) ident(gen)operator(()symbol(:known) operator(=)operator(>) string<delimiter(')content(known_value)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/hello/world)delimiter(')>operator(,) ident(gen)operator(()symbol(:known) operator(=)operator(>) string<delimiter(')content(known_value)delimiter(')>operator(,) symbol(:extra) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\)) + ident(assert_equal) operator([)symbol(:extra)operator(])operator(,) ident(route)operator(.)ident(extra_keys)operator(()symbol(:known) operator(=)operator(>) string<delimiter(')content(known_value)delimiter(')>operator(,) symbol(:extra) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_dynamic) + ident(route) string<delimiter(')content(hello/:name)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')> + + ident(assert_nil) ident(rec)operator(()string<delimiter(')content(hello)delimiter(')>operator(\)) + ident(assert_nil) ident(rec)operator(()string<delimiter(')content(foo/bar)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(rails)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(hello/rails)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(Nicholas Seckar)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(hello/Nicholas+Seckar)delimiter(')>operator(\))operator(\)) + + ident(assert_nil) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_dude)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(rails)delimiter(')>operator(\)) + ident(assert_nil) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')>operator(\)) + ident(assert_nil) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(rails)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/hello/rails)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(rails)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/hello/Nicholas+Seckar)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_person)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(Nicholas Seckar)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_typical) + ident(route) string<delimiter(')content(:controller/:action/:id)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) pre_constant(nil) + ident(assert_nil) ident(rec)operator(()string<delimiter(')content(hello)delimiter(')>operator(\)) + ident(assert_nil) ident(rec)operator(()string<delimiter(')content(foo bar)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(content)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(admin/user)delimiter(')>operator(\))operator(\)) + + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(admin/user/index)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(admin/user/list)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(admin/user/show/10)delimiter(')>operator(\))operator(\)) + + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(content/list)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) ident(rec)operator(()string<delimiter(')content(content/show/10)delimiter(')>operator(\))operator(\)) + + + ident(assert_equal) string<delimiter(')content(/content)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/content/list)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/content/show/10)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(\)) + + ident(assert_equal) string<delimiter(')content(/admin/user)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/admin/user)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(/admin/user)delimiter(')>operator(,) ident(gen)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(\)) + ident(assert_equal) string<delimiter(')content(/admin/user/show/10)delimiter(')>operator(,) ident(gen)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(RouteSetTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(attr_reader) symbol(:rs) + reserved(def) method(setup) + instance_variable(@rs) operator(=) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(RouteSet)operator(.)ident(new) + instance_variable(@rs)operator(.)ident(draw) operator({)operator(|)ident(m)operator(|) ident(m)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> operator(}) + operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(NamedRoutes)operator(.)ident(clear) + reserved(end) + + reserved(def) method(test_default_setup) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(.)ident(stringify_keys)operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(.)ident(stringify_keys)operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content list)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(.)ident(stringify_keys)operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content show 10)delimiter(\))>operator(\))operator(\)) + + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(.)ident(stringify_keys)operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(admin user show 10)delimiter(\))>operator(\))operator(\)) + + ident(assert_equal) operator([)string<delimiter(')content(/admin/user/show/10)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) integer(10)operator(})operator(\)) + + ident(assert_equal) operator([)string<delimiter(')content(/admin/user/show)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/admin/user/list/10)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(\)) + + ident(assert_equal) operator([)string<delimiter(')content(/admin/stuff)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(stuff)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/stuff)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/stuff)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_ignores_leading_slash) + instance_variable(@rs)operator(.)ident(draw) operator({)operator(|)ident(m)operator(|) ident(m)operator(.)ident(connect) string<delimiter(')content(/:controller/:action/:id)delimiter(')>operator(}) + ident(test_default_setup) + reserved(end) + + reserved(def) method(test_time_recognition) + ident(n) operator(=) integer(10000) + reserved(if) constant(RunTimeTests) + constant(GC)operator(.)ident(start) + ident(rectime) operator(=) constant(Benchmark)operator(.)ident(realtime) reserved(do) + ident(n)operator(.)ident(times) reserved(do) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content)delimiter(\))>operator(\)) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content list)delimiter(\))>operator(\)) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content show 10)delimiter(\))>operator(\)) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(admin user)delimiter(\))>operator(\)) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(admin user list)delimiter(\))>operator(\)) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(admin user show 10)delimiter(\))>operator(\)) + reserved(end) + reserved(end) + ident(puts) string<delimiter(")char(\\n)char(\\n)content(Recognition (RouteSet\):)delimiter(")> + ident(per_url) operator(=) ident(rectime) operator(/) operator(()ident(n) operator(*) integer(6)operator(\)) + ident(puts) string<delimiter(")inline<inline_delimiter(#{)ident(per_url) operator(*) integer(1000)inline_delimiter(})>content( ms/url)delimiter(")> + ident(puts) string<delimiter(")inline<inline_delimiter(#{)integer(1) operator(/) ident(per_url)inline_delimiter(})>content( url/s)char(\\n)char(\\n)delimiter(")> + reserved(end) + reserved(end) + reserved(def) method(test_time_generation) + ident(n) operator(=) integer(5000) + reserved(if) constant(RunTimeTests) + constant(GC)operator(.)ident(start) + ident(pairs) operator(=) operator([) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(])operator(,) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(])operator(,) + operator(]) + ident(p) operator(=) pre_constant(nil) + ident(gentime) operator(=) constant(Benchmark)operator(.)ident(realtime) reserved(do) + ident(n)operator(.)ident(times) reserved(do) + ident(pairs)operator(.)ident(each) operator({)operator(|)operator(()ident(a)operator(,) ident(b)operator(\))operator(|) ident(rs)operator(.)ident(generate)operator(()ident(a)operator(,) ident(b)operator(\))operator(}) + reserved(end) + reserved(end) + + ident(puts) string<delimiter(")char(\\n)char(\\n)content(Generation (RouteSet\): ()inline<inline_delimiter(#{)operator(()ident(n) operator(*) integer(8)operator(\))inline_delimiter(})>content( urls\))delimiter(")> + ident(per_url) operator(=) ident(gentime) operator(/) operator(()ident(n) operator(*) integer(8)operator(\)) + ident(puts) string<delimiter(")inline<inline_delimiter(#{)ident(per_url) operator(*) integer(1000)inline_delimiter(})>content( ms/url)delimiter(")> + ident(puts) string<delimiter(")inline<inline_delimiter(#{)integer(1) operator(/) ident(per_url)inline_delimiter(})>content( url/s)char(\\n)char(\\n)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_route_with_colon_first) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(map)operator(.)ident(connect) string<delimiter(')content(/:controller/:action/:id)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) pre_constant(nil) + ident(map)operator(.)ident(connect) string<delimiter(')content(:url)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(tiny_url)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(translate)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(test_route_generating_string_literal_in_comparison_warning) + ident(old_stderr) operator(=) global_variable($stderr) + global_variable($stderr) operator(=) constant(StringIO)operator(.)ident(new) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(map)operator(.)ident(connect) string<delimiter(')content(subscriptions/:action/:subscription_type)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(subscriptions)delimiter(")> + reserved(end) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) global_variable($stderr)operator(.)ident(string) + reserved(ensure) + global_variable($stderr) operator(=) ident(old_stderr) + reserved(end) + + reserved(def) method(test_route_with_regexp_for_controller) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(map)operator(.)ident(connect) string<delimiter(')content(:controller/:admintoken/:action/:id)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) regexp<delimiter(/)content(admin)char(\\/)content(.+)delimiter(/)> + ident(map)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(UserController)operator(,) symbol(:admintoken) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(index)delimiter(")>operator(})operator(.)ident(stringify_keys)operator(,) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(admin user foo)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) operator(::)constant(ContentController)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")>operator(})operator(.)ident(stringify_keys)operator(,) + ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(content foo)delimiter(\))>operator(\))operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/admin/user/foo)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(admin/user)delimiter(")>operator(,) symbol(:admintoken) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(index)delimiter(")>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/content/foo)delimiter(')>operator(,)operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(")content(content)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_basic_named_route) + ident(rs)operator(.)ident(home) string<delimiter(')delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')> + ident(x) operator(=) ident(setup_for_named_route) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:home_url)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_named_route_with_option) + ident(rs)operator(.)ident(page) string<delimiter(')content(page/:title)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')> + ident(x) operator(=) ident(setup_for_named_route) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(new stuff)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:page_url)operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(new stuff)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_named_route_with_default) + ident(rs)operator(.)ident(page) string<delimiter(')content(page/:title)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(AboutPage)delimiter(')> + ident(x) operator(=) ident(setup_for_named_route) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(AboutPage)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:page_url)operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(AboutRails)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:page_url)operator(,) symbol(:title) operator(=)operator(>) string<delimiter(")content(AboutRails)delimiter(")>operator(\))operator(\)) + + reserved(end) + + reserved(def) method(setup_for_named_route) + ident(x) operator(=) constant(Class)operator(.)ident(new) + ident(x)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:url_for)operator(\)) operator({)operator(|)ident(x)operator(|) ident(x)operator(}) + ident(x)operator(.)ident(send) symbol(:include)operator(,) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(NamedRoutes) + ident(x) + reserved(end) + + reserved(def) method(test_named_route_without_hash) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(normal) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(test_named_route_with_regexps) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(article) string<delimiter(')content(page/:year/:month/:day/:title)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(page)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) + symbol(:year) operator(=)operator(>) regexp<delimiter(/)content(^)char(\\d)content(+$)delimiter(/)>operator(,) symbol(:month) operator(=)operator(>) regexp<delimiter(/)content(^)char(\\d)content(+$)delimiter(/)>operator(,) symbol(:day) operator(=)operator(>) regexp<delimiter(/)content(^)char(\\d)content(+$)delimiter(/)> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + ident(x) operator(=) ident(setup_for_named_route) + ident(assert_equal)operator(() + operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/page)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:article_url)operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(\)) + operator(\)) + ident(assert_equal)operator(() + operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/page)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(,) symbol(:day) operator(=)operator(>) integer(10)operator(,) symbol(:year) operator(=)operator(>) integer(2005)operator(,) symbol(:month) operator(=)operator(>) integer(6)operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:article_url)operator(,) symbol(:title) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(,) symbol(:day) operator(=)operator(>) integer(10)operator(,) symbol(:year) operator(=)operator(>) integer(2005)operator(,) symbol(:month) operator(=)operator(>) integer(6)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_changing_controller) + ident(assert_equal) operator([)string<delimiter(')content(/admin/stuff/show/10)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(() + operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(stuff)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) integer(10)operator(})operator(,) + operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(}) + operator(\)) + reserved(end) + + reserved(def) method(test_paths_escaped) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(path) string<delimiter(')content(file/*path)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_file)delimiter(')> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + ident(results) operator(=) ident(rs)operator(.)ident(recognize_path) string<delimiter(%w()content(file hello+world how+are+you%3F)delimiter(\))> + ident(assert) ident(results)operator(,) string<delimiter(")content(Recognition should have succeeded)delimiter(")> + ident(assert_equal) operator([)string<delimiter(')content(hello world)delimiter(')>operator(,) string<delimiter(')content(how are you?)delimiter(')>operator(])operator(,) ident(results)operator([)string<delimiter(')content(path)delimiter(')>operator(]) + + ident(results) operator(=) ident(rs)operator(.)ident(recognize_path) string<delimiter(%w()content(file)delimiter(\))> + ident(assert) ident(results)operator(,) string<delimiter(")content(Recognition should have succeeded)delimiter(")> + ident(assert_equal) operator([)operator(])operator(,) ident(results)operator([)string<delimiter(')content(path)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_non_controllers_cannot_be_matched) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + ident(assert_nil) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(not_a show 10)delimiter(\))>operator(\))operator(,) string<delimiter(")content(Shouldn't recognize non-controllers as controllers!)delimiter(")> + reserved(end) + + reserved(def) method(test_paths_do_not_accept_defaults) + ident(assert_raises)operator(()constant(ActionController)operator(::)constant(RoutingError)operator(\)) reserved(do) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(path) string<delimiter(')content(file/*path)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_file)delimiter(')>operator(,) symbol(:path) operator(=)operator(>) string<delimiter(%w()content(fake default)delimiter(\))> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + reserved(end) + + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(path) string<delimiter(')content(file/*path)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_file)delimiter(')>operator(,) symbol(:path) operator(=)operator(>) operator([)operator(]) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(test_backwards) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(connect) string<delimiter(')content(page/:id/:action)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(pages)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/page/20)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:id) operator(=)operator(>) integer(20)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(pages)delimiter(')>operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/page/20)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(pages)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) integer(20)operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/pages/boo)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(pages)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(boo)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_route_with_fixnum_default) + ident(rs)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(rs)operator(.)ident(connect) string<delimiter(')content(page/:id)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) integer(1) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/page)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/page)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/page)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/page/10)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) integer(10)operator(\)) + + ident(ctrl) operator(=) operator(::)constant(ContentController) + + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) ident(ctrl)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(1)operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(page)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) ident(ctrl)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(page 1)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) ident(ctrl)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(show_page)delimiter(')>operator(,) string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(page 10)delimiter(\))>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_action_expiry) + ident(assert_equal) operator([)string<delimiter(')content(/content)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_recognition_with_uppercase_controller_name) + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) operator(::)constant(ContentController)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(Content)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) operator(::)constant(ContentController)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(list)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(Content list)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) operator(::)constant(ContentController)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(Content show 10)delimiter(\))>operator(\))operator(\)) + + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(NewsFeedController)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(Admin NewsFeed)delimiter(\))>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) operator(::)constant(Admin)operator(::)constant(NewsFeedController)operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) ident(rs)operator(.)ident(recognize_path)operator(()string<delimiter(%w()content(Admin News_Feed)delimiter(\))>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_both_requirement_and_optional) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(blog)operator(()string<delimiter(')content(test/:year)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(post)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) + symbol(:defaults) operator(=)operator(>) operator({) symbol(:year) operator(=)operator(>) pre_constant(nil) operator(})operator(,) + symbol(:requirements) operator(=)operator(>) operator({) symbol(:year) operator(=)operator(>) regexp<delimiter(/)char(\\d)content({4})delimiter(/)> operator(}) + operator(\)) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/test)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(post)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/test)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(post)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) pre_constant(nil)operator(\)) + + ident(x) operator(=) ident(setup_for_named_route) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/post)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(show)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:blog_url)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_set_to_nil_forgets) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(connect) string<delimiter(')content(pages/:year/:month/:day)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:month) operator(=)operator(>) pre_constant(nil)operator(,) symbol(:day) operator(=)operator(>) pre_constant(nil) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/pages/2005)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) + ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) integer(2005)operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/pages/2005/6)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) + ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) integer(2005)operator(,) symbol(:month) operator(=)operator(>) integer(6)operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/pages/2005/6/12)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) + ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) integer(2005)operator(,) symbol(:month) operator(=)operator(>) integer(6)operator(,) symbol(:day) operator(=)operator(>) integer(12)operator(\)) + + ident(assert_equal) operator([)string<delimiter(')content(/pages/2005/6/4)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) + ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:day) operator(=)operator(>) integer(4)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) string<delimiter(')content(2005)delimiter(')>operator(,) symbol(:month) operator(=)operator(>) string<delimiter(')content(6)delimiter(')>operator(,) symbol(:day) operator(=)operator(>) string<delimiter(')content(12)delimiter(')>operator(})operator(\)) + + ident(assert_equal) operator([)string<delimiter(')content(/pages/2005/6)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) + ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:day) operator(=)operator(>) pre_constant(nil)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) string<delimiter(')content(2005)delimiter(')>operator(,) symbol(:month) operator(=)operator(>) string<delimiter(')content(6)delimiter(')>operator(,) symbol(:day) operator(=)operator(>) string<delimiter(')content(12)delimiter(')>operator(})operator(\)) + + ident(assert_equal) operator([)string<delimiter(')content(/pages/2005)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) + ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:day) operator(=)operator(>) pre_constant(nil)operator(,) symbol(:month) operator(=)operator(>) pre_constant(nil)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_pages)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) string<delimiter(')content(2005)delimiter(')>operator(,) symbol(:month) operator(=)operator(>) string<delimiter(')content(6)delimiter(')>operator(,) symbol(:day) operator(=)operator(>) string<delimiter(')content(12)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_url_with_no_action_specified) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(connect) string<delimiter(')delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_named_url_with_no_action_specified) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(root) string<delimiter(')delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(\)) + + ident(x) operator(=) ident(setup_for_named_route) + ident(assert_equal)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(/content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) + ident(x)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:root_url)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_url_generated_when_forgetting_action) + operator([)operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')>operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(])operator(.)ident(each) reserved(do) operator(|)ident(hash)operator(|) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(root) string<delimiter(')delimiter(')>operator(,) ident(hash) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + ident(assert_equal) operator([)string<delimiter(')content(/)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:action) operator(=)operator(>) pre_constant(nil)operator(})operator(,) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hello)delimiter(')>operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/content/hi)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_named_route_method) + ident(rs)operator(.)ident(draw) reserved(do) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) ident(rs)operator(.)ident(categories) string<delimiter(')content(categories)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(categories)delimiter(')> operator(}) + + ident(rs)operator(.)ident(named_route) symbol(:categories)operator(,) string<delimiter(')content(categories)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(categories)delimiter(')> + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/categories)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(categories)delimiter(')>operator(\)) + ident(assert_equal) operator([)string<delimiter(')content(/content/hi)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_named_route_helper_array) + ident(test_named_route_method) + ident(assert_equal) operator([)symbol(:categories_url)operator(,) symbol(:hash_for_categories_url)operator(])operator(,) operator(::)constant(ActionController)operator(::)constant(Routing)operator(::)constant(NamedRoutes)operator(::)constant(Helpers) + reserved(end) + + reserved(def) method(test_nil_defaults) + ident(rs)operator(.)ident(draw) reserved(do) + ident(rs)operator(.)ident(connect) string<delimiter(')content(journal)delimiter(')>operator(,) + symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) + symbol(:action) operator(=)operator(>) string<delimiter(')content(list_journal)delimiter(')>operator(,) + symbol(:date) operator(=)operator(>) pre_constant(nil)operator(,) symbol(:user_id) operator(=)operator(>) pre_constant(nil) + ident(rs)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(assert_equal) operator([)string<delimiter(')content(/journal)delimiter(')>operator(,) operator([)operator(])operator(])operator(,) ident(rs)operator(.)ident(generate)operator(()symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(list_journal)delimiter(')>operator(,) symbol(:date) operator(=)operator(>) pre_constant(nil)operator(,) symbol(:user_id) operator(=)operator(>) pre_constant(nil)operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(ControllerComponentTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + + reserved(def) method(test_traverse_to_controller_should_not_load_arbitrary_files) + ident(load_path) operator(=) global_variable($:)operator(.)ident(dup) + ident(base) operator(=) constant(File)operator(.)ident(dirname)operator(()constant(File)operator(.)ident(dirname)operator(()constant(File)operator(.)ident(expand_path)operator(()pre_constant(__FILE__)operator(\))operator(\))operator(\)) + global_variable($:) operator(<<) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures)delimiter(')>operator(\)) + constant(Object)operator(.)ident(send) symbol(:const_set)operator(,) symbol(:RAILS_ROOT)operator(,) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures/application_root)delimiter(')>operator(\)) + ident(assert_equal) pre_constant(nil)operator(,) constant(ActionController)operator(::)constant(Routing)operator(::)constant(ControllerComponent)operator(.)ident(traverse_to_controller)operator(()string<delimiter(%w()content(dont_load pretty please)delimiter(\))>operator(\)) + reserved(ensure) + global_variable($:)operator([)integer(0)operator(..)integer(-1)operator(]) operator(=) ident(load_path) + constant(Object)operator(.)ident(send) symbol(:remove_const)operator(,) symbol(:RAILS_ROOT) + reserved(end) + + reserved(def) method(test_traverse_should_not_trip_on_non_module_constants) + ident(assert_equal) pre_constant(nil)operator(,) constant(ActionController)operator(::)constant(Routing)operator(::)constant(ControllerComponent)operator(.)ident(traverse_to_controller)operator(()string<delimiter(%w()content(admin some_constant a)delimiter(\))>operator(\)) + reserved(end) + + comment(# This is evil, but people do it.) + reserved(def) method(test_traverse_to_controller_should_pass_thru_classes) + ident(load_path) operator(=) global_variable($:)operator(.)ident(dup) + ident(base) operator(=) constant(File)operator(.)ident(dirname)operator(()constant(File)operator(.)ident(dirname)operator(()constant(File)operator(.)ident(expand_path)operator(()pre_constant(__FILE__)operator(\))operator(\))operator(\)) + global_variable($:) operator(<<) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures)delimiter(')>operator(\)) + global_variable($:) operator(<<) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures/application_root/app/controllers)delimiter(')>operator(\)) + global_variable($:) operator(<<) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures/application_root/app/models)delimiter(')>operator(\)) + constant(Object)operator(.)ident(send) symbol(:const_set)operator(,) symbol(:RAILS_ROOT)operator(,) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures/application_root)delimiter(')>operator(\)) + ident(pair) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(ControllerComponent)operator(.)ident(traverse_to_controller)operator(()string<delimiter(%w()content(a_class_that_contains_a_controller poorly_placed)delimiter(\))>operator(\)) + + comment(# Make sure the container class was loaded properly) + ident(assert) reserved(defined?)operator(()constant(AClassThatContainsAController)operator(\)) + ident(assert_kind_of) constant(Class)operator(,) constant(AClassThatContainsAController) + ident(assert_equal) symbol(:you_know_it)operator(,) constant(AClassThatContainsAController)operator(.)ident(is_special?) + + comment(# Make sure the controller was too) + ident(assert_kind_of) constant(Array)operator(,) ident(pair) + ident(assert_equal) integer(2)operator(,) ident(pair)operator([)integer(1)operator(]) + ident(klass) operator(=) ident(pair)operator(.)ident(first) + ident(assert_kind_of) constant(Class)operator(,) ident(klass) + ident(assert_equal) symbol(:decidedly_so)operator(,) ident(klass)operator(.)ident(is_evil?) + ident(assert) ident(klass)operator(.)ident(ancestors)operator(.)ident(include?)operator(()constant(ActionController)operator(::)constant(Base)operator(\)) + ident(assert) reserved(defined?)operator(()constant(AClassThatContainsAController)operator(::)constant(PoorlyPlacedController)operator(\)) + ident(assert_equal) ident(klass)operator(,) constant(AClassThatContainsAController)operator(::)constant(PoorlyPlacedController) + reserved(ensure) + global_variable($:)operator([)integer(0)operator(..)integer(-1)operator(]) operator(=) ident(load_path) + constant(Object)operator(.)ident(send) symbol(:remove_const)operator(,) symbol(:RAILS_ROOT) + reserved(end) + + reserved(def) method(test_traverse_to_nested_controller) + ident(load_path) operator(=) global_variable($:)operator(.)ident(dup) + ident(base) operator(=) constant(File)operator(.)ident(dirname)operator(()constant(File)operator(.)ident(dirname)operator(()constant(File)operator(.)ident(expand_path)operator(()pre_constant(__FILE__)operator(\))operator(\))operator(\)) + global_variable($:) operator(<<) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures)delimiter(')>operator(\)) + global_variable($:) operator(<<) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures/application_root/app/controllers)delimiter(')>operator(\)) + constant(Object)operator(.)ident(send) symbol(:const_set)operator(,) symbol(:RAILS_ROOT)operator(,) constant(File)operator(.)ident(join)operator(()ident(base)operator(,) string<delimiter(')content(fixtures/application_root)delimiter(')>operator(\)) + ident(pair) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(ControllerComponent)operator(.)ident(traverse_to_controller)operator(()string<delimiter(%w()content(module_that_holds_controllers nested)delimiter(\))>operator(\)) + + ident(assert_not_equal) pre_constant(nil)operator(,) ident(pair) + + comment(# Make sure that we created a module for the dir) + ident(assert) reserved(defined?)operator(()constant(ModuleThatHoldsControllers)operator(\)) + ident(assert_kind_of) constant(Module)operator(,) constant(ModuleThatHoldsControllers) + + comment(# Make sure the controller is ok) + ident(assert_kind_of) constant(Array)operator(,) ident(pair) + ident(assert_equal) integer(2)operator(,) ident(pair)operator([)integer(1)operator(]) + ident(klass) operator(=) ident(pair)operator(.)ident(first) + ident(assert_kind_of) constant(Class)operator(,) ident(klass) + ident(assert) ident(klass)operator(.)ident(ancestors)operator(.)ident(include?)operator(()constant(ActionController)operator(::)constant(Base)operator(\)) + ident(assert) reserved(defined?)operator(()constant(ModuleThatHoldsControllers)operator(::)constant(NestedController)operator(\)) + ident(assert_equal) ident(klass)operator(,) constant(ModuleThatHoldsControllers)operator(::)constant(NestedController) + reserved(ensure) + global_variable($:)operator([)integer(0)operator(..)integer(-1)operator(]) operator(=) ident(load_path) + constant(Object)operator(.)ident(send) symbol(:remove_const)operator(,) symbol(:RAILS_ROOT) + reserved(end) + +reserved(end) + +reserved(end) +ident(require) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(')content(..)delimiter(')>operator(,) string<delimiter(')content(abstract_unit)delimiter(')>operator(\)) + + +reserved(module) class(TestFileUtils) + reserved(def) method(file_name)operator(()operator(\)) constant(File)operator(.)ident(basename)operator(()pre_constant(__FILE__)operator(\)) reserved(end) + reserved(def) method(file_path)operator(()operator(\)) constant(File)operator(.)ident(expand_path)operator(()pre_constant(__FILE__)operator(\)) reserved(end) + reserved(def) method(file_data)operator(()operator(\)) constant(File)operator(.)ident(open)operator(()ident(file_path)operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) operator({) operator(|)ident(f)operator(|) ident(f)operator(.)ident(read) operator(}) reserved(end) +reserved(end) + + +reserved(class) class(SendFileController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(include) constant(TestFileUtils) + ident(layout) string<delimiter(")content(layouts/standard)delimiter(")> comment(# to make sure layouts don't interfere) + + ident(attr_writer) symbol(:options) + reserved(def) method(options)operator(()operator(\)) instance_variable(@options) operator(||=) operator({)operator(}) reserved(end) + + reserved(def) method(file)operator(()operator(\)) ident(send_file)operator(()ident(file_path)operator(,) ident(options)operator(\)) reserved(end) + reserved(def) method(data)operator(()operator(\)) ident(send_data)operator(()ident(file_data)operator(,) ident(options)operator(\)) reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) +reserved(end) + +constant(SendFileController)operator(.)ident(template_root) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")> + +reserved(class) class(SendFileTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(TestFileUtils) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(SendFileController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_file_nostream) + instance_variable(@controller)operator(.)ident(options) operator(=) operator({) symbol(:stream) operator(=)operator(>) pre_constant(false) operator(}) + ident(response) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(response) operator(=) ident(process)operator(()string<delimiter(')content(file)delimiter(')>operator(\)) operator(}) + ident(assert_not_nil) ident(response) + ident(assert_kind_of) constant(String)operator(,) ident(response)operator(.)ident(body) + ident(assert_equal) ident(file_data)operator(,) ident(response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_file_stream) + ident(response) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(response) operator(=) ident(process)operator(()string<delimiter(')content(file)delimiter(')>operator(\)) operator(}) + ident(assert_not_nil) ident(response) + ident(assert_kind_of) constant(Proc)operator(,) ident(response)operator(.)ident(body) + + ident(require) string<delimiter(')content(stringio)delimiter(')> + ident(output) operator(=) constant(StringIO)operator(.)ident(new) + ident(output)operator(.)ident(binmode) + ident(assert_nothing_raised) operator({) ident(response)operator(.)ident(body)operator(.)ident(call)operator(()ident(response)operator(,) ident(output)operator(\)) operator(}) + ident(assert_equal) ident(file_data)operator(,) ident(output)operator(.)ident(string) + reserved(end) + + reserved(def) method(test_data) + ident(response) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(response) operator(=) ident(process)operator(()string<delimiter(')content(data)delimiter(')>operator(\)) operator(}) + ident(assert_not_nil) ident(response) + + ident(assert_kind_of) constant(String)operator(,) ident(response)operator(.)ident(body) + ident(assert_equal) ident(file_data)operator(,) ident(response)operator(.)ident(body) + reserved(end) + + comment(# Test that send_file_headers! is setting the correct HTTP headers.) + reserved(def) method(test_send_file_headers!) + ident(options) operator(=) operator({) + symbol(:length) operator(=)operator(>) integer(1)operator(,) + symbol(:type) operator(=)operator(>) string<delimiter(')content(type)delimiter(')>operator(,) + symbol(:disposition) operator(=)operator(>) string<delimiter(')content(disposition)delimiter(')>operator(,) + symbol(:filename) operator(=)operator(>) string<delimiter(')content(filename)delimiter(')> + operator(}) + + comment(# Do it a few times: the resulting headers should be identical) + comment(# no matter how many times you send with the same options.) + comment(# Test resolving Ticket #458.) + instance_variable(@controller)operator(.)ident(headers) operator(=) operator({)operator(}) + instance_variable(@controller)operator(.)ident(send)operator(()symbol(:send_file_headers!)operator(,) ident(options)operator(\)) + instance_variable(@controller)operator(.)ident(send)operator(()symbol(:send_file_headers!)operator(,) ident(options)operator(\)) + instance_variable(@controller)operator(.)ident(send)operator(()symbol(:send_file_headers!)operator(,) ident(options)operator(\)) + + ident(h) operator(=) instance_variable(@controller)operator(.)ident(headers) + ident(assert_equal) integer(1)operator(,) ident(h)operator([)string<delimiter(')content(Content-Length)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(type)delimiter(')>operator(,) ident(h)operator([)string<delimiter(')content(Content-Type)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(disposition; filename="filename")delimiter(')>operator(,) ident(h)operator([)string<delimiter(')content(Content-Disposition)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(binary)delimiter(')>operator(,) ident(h)operator([)string<delimiter(')content(Content-Transfer-Encoding)delimiter(')>operator(]) + + comment(# test overriding Cache-Control: no-cache header to fix IE open/save dialog) + instance_variable(@controller)operator(.)ident(headers) operator(=) operator({) string<delimiter(')content(Cache-Control)delimiter(')> operator(=)operator(>) string<delimiter(')content(no-cache)delimiter(')> operator(}) + instance_variable(@controller)operator(.)ident(send)operator(()symbol(:send_file_headers!)operator(,) ident(options)operator(\)) + ident(h) operator(=) instance_variable(@controller)operator(.)ident(headers) + ident(assert_equal) string<delimiter(')content(private)delimiter(')>operator(,) ident(h)operator([)string<delimiter(')content(Cache-Control)delimiter(')>operator(]) + reserved(end) + + string<delimiter(%w()content(file data)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(define_method) string<delimiter(")content(test_send_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(_status)delimiter(")> reserved(do) + instance_variable(@controller)operator(.)ident(options) operator(=) operator({) symbol(:stream) operator(=)operator(>) pre_constant(false)operator(,) symbol(:status) operator(=)operator(>) integer(500) operator(}) + ident(assert_nothing_raised) operator({) ident(assert_not_nil) ident(process)operator(()ident(method)operator(\)) operator(}) + ident(assert_equal) string<delimiter(')content(500)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(]) + reserved(end) + + ident(define_method) string<delimiter(")content(test_default_send_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(_status)delimiter(")> reserved(do) + instance_variable(@controller)operator(.)ident(options) operator(=) operator({) symbol(:stream) operator(=)operator(>) pre_constant(false) operator(}) + ident(assert_nothing_raised) operator({) ident(assert_not_nil) ident(process)operator(()ident(method)operator(\)) operator(}) + ident(assert_equal) constant(ActionController)operator(::)constant(Base)operator(::)constant(DEFAULT_RENDER_STATUS_CODE)operator(,) instance_variable(@controller)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(]) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(SessionManagementTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(SessionOffController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(session) symbol(:off) + + reserved(def) method(show) + ident(render_text) string<delimiter(")content(done)delimiter(")> + reserved(end) + + reserved(def) method(tell) + ident(render_text) string<delimiter(")content(done)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(session) symbol(:off)operator(,) symbol(:only) operator(=)operator(>) symbol(:show) + ident(session) symbol(:session_secure) operator(=)operator(>) pre_constant(true)operator(,) symbol(:except) operator(=)operator(>) symbol(:show) + ident(session) symbol(:off)operator(,) symbol(:only) operator(=)operator(>) symbol(:conditional)operator(,) + symbol(:if) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(r)operator(|) ident(r)operator(.)ident(parameters)operator([)symbol(:ws)operator(]) operator(}) + + reserved(def) method(show) + ident(render_text) string<delimiter(")content(done)delimiter(")> + reserved(end) + + reserved(def) method(tell) + ident(render_text) string<delimiter(")content(done)delimiter(")> + reserved(end) + + reserved(def) method(conditional) + ident(render_text) string<delimiter(")content(>>>)inline<inline_delimiter(#{)ident(params)operator([)symbol(:ws)operator(])inline_delimiter(})>content(<<<)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(SpecializedController) operator(<) constant(SessionOffController) + ident(session) symbol(:disabled) operator(=)operator(>) pre_constant(false)operator(,) symbol(:only) operator(=)operator(>) symbol(:something) + + reserved(def) method(something) + ident(render_text) string<delimiter(")content(done)delimiter(")> + reserved(end) + + reserved(def) method(another) + ident(render_text) string<delimiter(")content(done)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@request)operator(,) instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(,) + constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_session_off_globally) + instance_variable(@controller) operator(=) constant(SessionOffController)operator(.)ident(new) + ident(get) symbol(:show) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@request)operator(.)ident(session_options) + ident(get) symbol(:tell) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@request)operator(.)ident(session_options) + reserved(end) + + reserved(def) method(test_session_off_conditionally) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + ident(get) symbol(:show) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@request)operator(.)ident(session_options) + ident(get) symbol(:tell) + ident(assert_instance_of) constant(Hash)operator(,) instance_variable(@request)operator(.)ident(session_options) + ident(assert) instance_variable(@request)operator(.)ident(session_options)operator([)symbol(:session_secure)operator(]) + reserved(end) + + reserved(def) method(test_controller_specialization_overrides_settings) + instance_variable(@controller) operator(=) constant(SpecializedController)operator(.)ident(new) + ident(get) symbol(:something) + ident(assert_instance_of) constant(Hash)operator(,) instance_variable(@request)operator(.)ident(session_options) + ident(get) symbol(:another) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@request)operator(.)ident(session_options) + reserved(end) + + reserved(def) method(test_session_off_with_if) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + ident(get) symbol(:conditional) + ident(assert_instance_of) constant(Hash)operator(,) instance_variable(@request)operator(.)ident(session_options) + ident(get) symbol(:conditional)operator(,) symbol(:ws) operator(=)operator(>) string<delimiter(")content(ws)delimiter(")> + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@request)operator(.)ident(session_options) + reserved(end) + + reserved(def) method(test_session_store_setting) + constant(ActionController)operator(::)constant(Base)operator(.)ident(session_store) operator(=) symbol(:drb_store) + ident(assert_equal) constant(CGI)operator(::)constant(Session)operator(::)constant(DRbStore)operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(session_store) + + reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) + constant(ActionController)operator(::)constant(Base)operator(.)ident(session_store) operator(=) symbol(:active_record_store) + ident(assert_equal) constant(CGI)operator(::)constant(Session)operator(::)constant(ActiveRecordStore)operator(,) constant(ActionController)operator(::)constant(Base)operator(.)ident(session_store) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fake_controllers)delimiter(')> + +reserved(class) class(TestTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(set_flash) + ident(flash)operator([)string<delimiter(")content(test)delimiter(")>operator(]) operator(=) string<delimiter(")content(>)inline<inline_delimiter(#{)ident(flash)operator([)string<delimiter(")content(test)delimiter(")>operator(])inline_delimiter(})>content(<)delimiter(")> + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(')content(ignore me)delimiter(')> + reserved(end) + + reserved(def) method(render_raw_post) + ident(raise) constant(Test)operator(::)constant(Unit)operator(::)constant(AssertionFailedError)operator(,) string<delimiter(")content(#raw_post is blank)delimiter(")> reserved(if) ident(request)operator(.)ident(raw_post)operator(.)ident(blank?) + ident(render) symbol(:text) operator(=)operator(>) ident(request)operator(.)ident(raw_post) + reserved(end) + + reserved(def) method(test_params) + ident(render) symbol(:text) operator(=)operator(>) ident(params)operator(.)ident(inspect) + reserved(end) + + reserved(def) method(test_uri) + ident(render) symbol(:text) operator(=)operator(>) ident(request)operator(.)ident(request_uri) + reserved(end) + + reserved(def) method(test_html_output) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(<<HTML)>string<content( +<html> + <body> + <a href="/"><img src="/images/button.png" /></a> + <div id="foo"> + <ul> + <li class="item">hello</li> + <li class="item">goodbye</li> + </ul> + </div> + <div id="bar"> + <form action="/somewhere"> + Name: <input type="text" name="person[name]" id="person_name" /> + </form> + </div> + </body> +</html>)delimiter( +HTML)> + reserved(end) + + reserved(def) method(test_only_one_param) + ident(render) symbol(:text) operator(=)operator(>) operator(()ident(params)operator([)symbol(:left)operator(]) operator(&&) ident(params)operator([)symbol(:right)operator(])operator(\)) operator(?) string<delimiter(")content(EEP, Both here!)delimiter(")> operator(:) string<delimiter(")content(OK)delimiter(")> + reserved(end) + + reserved(def) method(test_remote_addr) + ident(render) symbol(:text) operator(=)operator(>) operator(()ident(request)operator(.)ident(remote_addr) operator(||) string<delimiter(")content(not specified)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_file_upload) + ident(render) symbol(:text) operator(=)operator(>) ident(params)operator([)symbol(:file)operator(])operator(.)ident(size) + reserved(end) + + reserved(def) method(redirect_to_symbol) + ident(redirect_to) symbol(:generate_url)operator(,) symbol(:id) operator(=)operator(>) integer(5) + reserved(end) + + ident(private) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) + ident(raise) ident(e) + reserved(end) + + reserved(def) method(generate_url)operator(()ident(opts)operator(\)) + ident(url_for)operator(()ident(opts)operator(.)ident(merge)operator(()symbol(:action) operator(=)operator(>) string<delimiter(")content(test_uri)delimiter(")>operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(reload) + reserved(end) + + reserved(def) method(teardown) + constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(reload) + reserved(end) + + reserved(def) method(test_raw_post_handling) + ident(params) operator(=) operator({)symbol(:page) operator(=)operator(>) operator({)symbol(:name) operator(=)operator(>) string<delimiter(')content(page name)delimiter(')>operator(})operator(,) string<delimiter(')content(some key)delimiter(')> operator(=)operator(>) integer(123)operator(}) + ident(get) symbol(:render_raw_post)operator(,) ident(params)operator(.)ident(dup) + + ident(raw_post) operator(=) ident(params)operator(.)ident(map) operator({)operator(|)ident(k)operator(,)ident(v)operator(|) operator([)constant(CGI)operator(::)ident(escape)operator(()ident(k)operator(.)ident(to_s)operator(\))operator(,) constant(CGI)operator(::)ident(escape)operator(()ident(v)operator(.)ident(to_s)operator(\))operator(])operator(.)ident(join)operator(()string<delimiter(')content(=)delimiter(')>operator(\))operator(})operator(.)ident(sort)operator(.)ident(join)operator(()string<delimiter(')content(&)delimiter(')>operator(\)) + ident(assert_equal) ident(raw_post)operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_process_without_flash) + ident(process) symbol(:set_flash) + ident(assert_equal) string<delimiter(')content(><)delimiter(')>operator(,) ident(flash)operator([)string<delimiter(')content(test)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_process_with_flash) + ident(process) symbol(:set_flash)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) operator({) string<delimiter(")content(test)delimiter(")> operator(=)operator(>) string<delimiter(")content(value)delimiter(")> operator(}) + ident(assert_equal) string<delimiter(')content(>value<)delimiter(')>operator(,) ident(flash)operator([)string<delimiter(')content(test)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_process_with_request_uri_with_no_params) + ident(process) symbol(:test_uri) + ident(assert_equal) string<delimiter(")content(/test_test/test/test_uri)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_process_with_request_uri_with_params) + ident(process) symbol(:test_uri)operator(,) symbol(:id) operator(=)operator(>) integer(7) + ident(assert_equal) string<delimiter(")content(/test_test/test/test_uri/7)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_process_with_request_uri_with_params_with_explicit_uri) + instance_variable(@request)operator(.)ident(set_REQUEST_URI) string<delimiter(")content(/explicit/uri)delimiter(")> + ident(process) symbol(:test_uri)operator(,) symbol(:id) operator(=)operator(>) integer(7) + ident(assert_equal) string<delimiter(")content(/explicit/uri)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_multiple_calls) + ident(process) symbol(:test_only_one_param)operator(,) symbol(:left) operator(=)operator(>) pre_constant(true) + ident(assert_equal) string<delimiter(")content(OK)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + ident(process) symbol(:test_only_one_param)operator(,) symbol(:right) operator(=)operator(>) pre_constant(true) + ident(assert_equal) string<delimiter(")content(OK)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_assert_tag_tag) + ident(process) symbol(:test_html_output) + + comment(# there is a 'form' tag) + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(')content(form)delimiter(')> + comment(# there is not an 'hr' tag) + ident(assert_no_tag) symbol(:tag) operator(=)operator(>) string<delimiter(')content(hr)delimiter(')> + reserved(end) + + reserved(def) method(test_assert_tag_attributes) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with an 'id' of 'bar') + ident(assert_tag) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(bar)delimiter(")> operator(}) + comment(# there is no tag with a 'name' of 'baz') + ident(assert_no_tag) symbol(:attributes) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(baz)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_parent) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with a parent 'form' tag) + ident(assert_tag) symbol(:parent) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(form)delimiter(")> operator(}) + comment(# there is no tag with a parent of 'input') + ident(assert_no_tag) symbol(:parent) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(input)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_child) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with a child 'input' tag) + ident(assert_tag) symbol(:child) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(input)delimiter(")> operator(}) + comment(# there is no tag with a child 'strong' tag) + ident(assert_no_tag) symbol(:child) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(strong)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_ancestor) + ident(process) symbol(:test_html_output) + + comment(# there is a 'li' tag with an ancestor having an id of 'foo') + ident(assert_tag) symbol(:ancestor) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")> operator(}) operator(})operator(,) symbol(:tag) operator(=)operator(>) string<delimiter(")content(li)delimiter(")> + comment(# there is no tag of any kind with an ancestor having an href matching 'foo') + ident(assert_no_tag) symbol(:ancestor) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:href) operator(=)operator(>) regexp<delimiter(/)content(foo)delimiter(/)> operator(}) operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_descendant) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with a decendant 'li' tag) + ident(assert_tag) symbol(:descendant) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(li)delimiter(")> operator(}) + comment(# there is no tag with a descendant 'html' tag) + ident(assert_no_tag) symbol(:descendant) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(html)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_sibling) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with a sibling of class 'item') + ident(assert_tag) symbol(:sibling) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:class) operator(=)operator(>) string<delimiter(")content(item)delimiter(")> operator(}) operator(}) + comment(# there is no tag with a sibling 'ul' tag) + ident(assert_no_tag) symbol(:sibling) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(ul)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_after) + ident(process) symbol(:test_html_output) + + comment(# there is a tag following a sibling 'div' tag) + ident(assert_tag) symbol(:after) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(div)delimiter(")> operator(}) + comment(# there is no tag following a sibling tag with id 'bar') + ident(assert_no_tag) symbol(:after) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(bar)delimiter(")> operator(}) operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_before) + ident(process) symbol(:test_html_output) + + comment(# there is a tag preceeding a tag with id 'bar') + ident(assert_tag) symbol(:before) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(bar)delimiter(")> operator(}) operator(}) + comment(# there is no tag preceeding a 'form' tag) + ident(assert_no_tag) symbol(:before) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(form)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_children_count) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with 2 children) + ident(assert_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(2) operator(}) + comment(# there is no tag with 4 children) + ident(assert_no_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(4) operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_children_less_than) + ident(process) symbol(:test_html_output) + + comment(# there is a tag with less than 5 children) + ident(assert_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:less_than) operator(=)operator(>) integer(5) operator(}) + comment(# there is no 'ul' tag with less than 2 children) + ident(assert_no_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:less_than) operator(=)operator(>) integer(2) operator(})operator(,) symbol(:tag) operator(=)operator(>) string<delimiter(")content(ul)delimiter(")> + reserved(end) + + reserved(def) method(test_assert_tag_children_greater_than) + ident(process) symbol(:test_html_output) + + comment(# there is a 'body' tag with more than 1 children) + ident(assert_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:greater_than) operator(=)operator(>) integer(1) operator(})operator(,) symbol(:tag) operator(=)operator(>) string<delimiter(")content(body)delimiter(")> + comment(# there is no tag with more than 10 children) + ident(assert_no_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:greater_than) operator(=)operator(>) integer(10) operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_children_only) + ident(process) symbol(:test_html_output) + + comment(# there is a tag containing only one child with an id of 'foo') + ident(assert_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(1)operator(,) + symbol(:only) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")> operator(}) operator(}) operator(}) + comment(# there is no tag containing only one 'li' child) + ident(assert_no_tag) symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(1)operator(,) symbol(:only) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(li)delimiter(")> operator(}) operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_content) + ident(process) symbol(:test_html_output) + + comment(# the output contains the string "Name") + ident(assert_tag) symbol(:content) operator(=)operator(>) string<delimiter(")content(Name)delimiter(")> + comment(# the output does not contain the string "test") + ident(assert_no_tag) symbol(:content) operator(=)operator(>) string<delimiter(")content(test)delimiter(")> + reserved(end) + + reserved(def) method(test_assert_tag_multiple) + ident(process) symbol(:test_html_output) + + comment(# there is a 'div', id='bar', with an immediate child whose 'action') + comment(# attribute matches the regexp /somewhere/.) + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(")content(div)delimiter(")>operator(,) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(bar)delimiter(")> operator(})operator(,) + symbol(:child) operator(=)operator(>) operator({) symbol(:attributes) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) regexp<delimiter(/)content(somewhere)delimiter(/)> operator(}) operator(}) + + comment(# there is no 'div', id='foo', with a 'ul' child with more than) + comment(# 2 "li" children.) + ident(assert_no_tag) symbol(:tag) operator(=)operator(>) string<delimiter(")content(div)delimiter(")>operator(,) symbol(:attributes) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(")content(foo)delimiter(")> operator(})operator(,) + symbol(:child) operator(=)operator(>) operator({) + symbol(:tag) operator(=)operator(>) string<delimiter(")content(ul)delimiter(")>operator(,) + symbol(:children) operator(=)operator(>) operator({) symbol(:greater_than) operator(=)operator(>) integer(2)operator(,) + symbol(:only) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(li)delimiter(")> operator(}) operator(}) operator(}) + reserved(end) + + reserved(def) method(test_assert_tag_children_without_content) + ident(process) symbol(:test_html_output) + + comment(# there is a form tag with an 'input' child which is a self closing tag) + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(")content(form)delimiter(")>operator(,) + symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(1)operator(,) + symbol(:only) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(input)delimiter(")> operator(}) operator(}) + + comment(# the body tag has an 'a' child which in turn has an 'img' child) + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(")content(body)delimiter(")>operator(,) + symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(1)operator(,) + symbol(:only) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(a)delimiter(")>operator(,) + symbol(:children) operator(=)operator(>) operator({) symbol(:count) operator(=)operator(>) integer(1)operator(,) + symbol(:only) operator(=)operator(>) operator({) symbol(:tag) operator(=)operator(>) string<delimiter(")content(img)delimiter(")> operator(}) operator(}) operator(}) operator(}) + reserved(end) + + reserved(def) method(test_assert_generates) + ident(assert_generates) string<delimiter(')content(controller/action/5)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(controller)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(action)delimiter(')>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(')content(5)delimiter(')> + reserved(end) + + reserved(def) method(test_assert_routing) + ident(assert_routing) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(content)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')> + reserved(end) + + reserved(def) method(test_assert_routing_in_module) + ident(assert_routing) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(admin/user)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(index)delimiter(')> + reserved(end) + + reserved(def) method(test_params_passing) + ident(get) symbol(:test_params)operator(,) symbol(:page) operator(=)operator(>) operator({)symbol(:name) operator(=)operator(>) string<delimiter(")content(Page name)delimiter(")>operator(,) symbol(:month) operator(=)operator(>) string<delimiter(')content(4)delimiter(')>operator(,) symbol(:year) operator(=)operator(>) string<delimiter(')content(2004)delimiter(')>operator(,) symbol(:day) operator(=)operator(>) string<delimiter(')content(6)delimiter(')>operator(}) + ident(parsed_params) operator(=) ident(eval)operator(()instance_variable(@response)operator(.)ident(body)operator(\)) + ident(assert_equal)operator(() + operator({)string<delimiter(')content(controller)delimiter(')> operator(=)operator(>) string<delimiter(')content(test_test/test)delimiter(')>operator(,) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(test_params)delimiter(')>operator(,) + string<delimiter(')content(page)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(")content(Page name)delimiter(")>operator(,) string<delimiter(')content(month)delimiter(')> operator(=)operator(>) string<delimiter(')content(4)delimiter(')>operator(,) string<delimiter(')content(year)delimiter(')> operator(=)operator(>) string<delimiter(')content(2004)delimiter(')>operator(,) string<delimiter(')content(day)delimiter(')> operator(=)operator(>) string<delimiter(')content(6)delimiter(')>operator(})operator(})operator(,) + ident(parsed_params) + operator(\)) + reserved(end) + + reserved(def) method(test_id_converted_to_string) + ident(get) symbol(:test_params)operator(,) symbol(:id) operator(=)operator(>) integer(20)operator(,) symbol(:foo) operator(=)operator(>) constant(Object)operator(.)ident(new) + ident(assert_kind_of) constant(String)operator(,) instance_variable(@request)operator(.)ident(path_parameters)operator([)string<delimiter(')content(id)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_array_path_parameter_handled_properly) + ident(with_routing) reserved(do) operator(|)ident(set)operator(|) + ident(set)operator(.)ident(draw) reserved(do) + ident(set)operator(.)ident(connect) string<delimiter(')content(file/*path)delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(test_test/test)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(test_params)delimiter(')> + ident(set)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> + reserved(end) + + ident(get) symbol(:test_params)operator(,) symbol(:path) operator(=)operator(>) operator([)string<delimiter(')content(hello)delimiter(')>operator(,) string<delimiter(')content(world)delimiter(')>operator(]) + ident(assert_equal) operator([)string<delimiter(')content(hello)delimiter(')>operator(,) string<delimiter(')content(world)delimiter(')>operator(])operator(,) instance_variable(@request)operator(.)ident(path_parameters)operator([)string<delimiter(')content(path)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(hello/world)delimiter(')>operator(,) instance_variable(@request)operator(.)ident(path_parameters)operator([)string<delimiter(')content(path)delimiter(')>operator(])operator(.)ident(to_s) + reserved(end) + reserved(end) + + reserved(def) method(test_assert_realistic_path_parameters) + ident(get) symbol(:test_params)operator(,) symbol(:id) operator(=)operator(>) integer(20)operator(,) symbol(:foo) operator(=)operator(>) constant(Object)operator(.)ident(new) + + comment(# All elements of path_parameters should use string keys) + instance_variable(@request)operator(.)ident(path_parameters)operator(.)ident(keys)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + ident(assert_kind_of) constant(String)operator(,) ident(key) + reserved(end) + reserved(end) + + reserved(def) method(test_with_routing_places_routes_back) + ident(assert) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes) + ident(routes_id) operator(=) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(object_id) + + reserved(begin) + ident(with_routing) operator({) ident(raise) string<delimiter(')content(fail)delimiter(')> operator(}) + ident(fail) string<delimiter(')content(Should not be here.)delimiter(')> + reserved(rescue) constant(RuntimeError) + reserved(end) + + ident(assert) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes) + ident(assert_equal) ident(routes_id)operator(,) constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(object_id) + reserved(end) + + reserved(def) method(test_remote_addr) + ident(get) symbol(:test_remote_addr) + ident(assert_equal) string<delimiter(")content(0.0.0.0)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + + instance_variable(@request)operator(.)ident(remote_addr) operator(=) string<delimiter(")content(192.0.0.1)delimiter(")> + ident(get) symbol(:test_remote_addr) + ident(assert_equal) string<delimiter(")content(192.0.0.1)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_header_properly_reset_after_remote_http_request) + ident(xhr) symbol(:get)operator(,) symbol(:test_params) + ident(assert_nil) instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_X_REQUESTED_WITH)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_header_properly_reset_after_get_request) + ident(get) symbol(:test_params) + instance_variable(@request)operator(.)ident(recycle!) + ident(assert_nil) instance_variable(@request)operator(.)ident(instance_variable_get)operator(()string<delimiter(")content(@request_method)delimiter(")>operator(\)) + reserved(end) + + string<delimiter(%w()content(controller response request)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(variable)operator(|) + string<delimiter(%w()content(get post put delete head process)delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(define_method)operator(()string<delimiter(")content(test_)inline<inline_delimiter(#{)ident(variable)inline_delimiter(})>content(_missing_for_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(_raises_error)delimiter(")>operator(\)) reserved(do) + ident(remove_instance_variable) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(variable)inline_delimiter(})>delimiter(")> + reserved(begin) + ident(send)operator(()ident(method)operator(,) symbol(:test_remote_addr)operator(\)) + ident(assert) pre_constant(false)operator(,) string<delimiter(")content(expected RuntimeError, got nothing)delimiter(")> + reserved(rescue) constant(RuntimeError) operator(=)operator(>) ident(error) + ident(assert) pre_constant(true) + ident(assert_match) regexp<delimiter(%r{)content(@)inline<inline_delimiter(#{)ident(variable)inline_delimiter(})>content( is nil)delimiter(})>operator(,) ident(error)operator(.)ident(message) + reserved(rescue) operator(=)operator(>) ident(error) + ident(assert) pre_constant(false)operator(,) string<delimiter(")content(expected RuntimeError, got )inline<inline_delimiter(#{)ident(error)operator(.)ident(class)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + constant(FILES_DIR) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../fixtures/multipart)delimiter(')> + + reserved(def) method(test_test_uploaded_file) + ident(filename) operator(=) string<delimiter(')content(mona_lisa.jpg)delimiter(')> + ident(path) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(FILES_DIR)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(filename)inline_delimiter(})>delimiter(")> + ident(content_type) operator(=) string<delimiter(')content(image/png)delimiter(')> + + ident(file) operator(=) constant(ActionController)operator(::)constant(TestUploadedFile)operator(.)ident(new)operator(()ident(path)operator(,) ident(content_type)operator(\)) + ident(assert_equal) ident(filename)operator(,) ident(file)operator(.)ident(original_filename) + ident(assert_equal) ident(content_type)operator(,) ident(file)operator(.)ident(content_type) + ident(assert_equal) ident(file)operator(.)ident(path)operator(,) ident(file)operator(.)ident(local_path) + ident(assert_equal) constant(File)operator(.)ident(read)operator(()ident(path)operator(\))operator(,) ident(file)operator(.)ident(read) + reserved(end) + + reserved(def) method(test_fixture_file_upload) + ident(post) symbol(:test_file_upload)operator(,) symbol(:file) operator(=)operator(>) ident(fixture_file_upload)operator(()constant(FILES_DIR) operator(+) string<delimiter(")content(/mona_lisa.jpg)delimiter(")>operator(,) string<delimiter(")content(image/jpg)delimiter(")>operator(\)) + ident(assert_equal) integer(159528)operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_test_uploaded_file_exception_when_file_doesnt_exist) + ident(assert_raise)operator(()constant(RuntimeError)operator(\)) operator({) constant(ActionController)operator(::)constant(TestUploadedFile)operator(.)ident(new)operator(()string<delimiter(')content(non_existent_file)delimiter(')>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_assert_redirected_to_symbol) + ident(get) symbol(:redirect_to_symbol) + ident(assert_redirected_to) symbol(:generate_url) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(UrlRewriterTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@params) operator(=) operator({)operator(}) + instance_variable(@rewriter) operator(=) constant(ActionController)operator(::)constant(UrlRewriter)operator(.)ident(new)operator(()instance_variable(@request)operator(,) instance_variable(@params)operator(\)) + reserved(end) + + reserved(def) method(test_simple_build_query_string) + ident(assert_query_equal) string<delimiter(')content(?x=1&y=2)delimiter(')>operator(,) instance_variable(@rewriter)operator(.)ident(send)operator(()symbol(:build_query_string)operator(,) symbol(:x) operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) symbol(:y) operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(\)) + reserved(end) + reserved(def) method(test_convert_ints_build_query_string) + ident(assert_query_equal) string<delimiter(')content(?x=1&y=2)delimiter(')>operator(,) instance_variable(@rewriter)operator(.)ident(send)operator(()symbol(:build_query_string)operator(,) symbol(:x) operator(=)operator(>) integer(1)operator(,) symbol(:y) operator(=)operator(>) integer(2)operator(\)) + reserved(end) + reserved(def) method(test_escape_spaces_build_query_string) + ident(assert_query_equal) string<delimiter(')content(?x=hello+world&y=goodbye+world)delimiter(')>operator(,) instance_variable(@rewriter)operator(.)ident(send)operator(()symbol(:build_query_string)operator(,) symbol(:x) operator(=)operator(>) string<delimiter(')content(hello world)delimiter(')>operator(,) symbol(:y) operator(=)operator(>) string<delimiter(')content(goodbye world)delimiter(')>operator(\)) + reserved(end) + reserved(def) method(test_expand_array_build_query_string) + ident(assert_query_equal) string<delimiter(')content(?x[]=1&x[]=2)delimiter(')>operator(,) instance_variable(@rewriter)operator(.)ident(send)operator(()symbol(:build_query_string)operator(,) symbol(:x) operator(=)operator(>) operator([)integer(1)operator(,) integer(2)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_escape_spaces_build_query_string_selected_keys) + ident(assert_query_equal) string<delimiter(')content(?x=hello+world)delimiter(')>operator(,) instance_variable(@rewriter)operator(.)ident(send)operator(()symbol(:build_query_string)operator(,) operator({)symbol(:x) operator(=)operator(>) string<delimiter(')content(hello world)delimiter(')>operator(,) symbol(:y) operator(=)operator(>) string<delimiter(')content(goodbye world)delimiter(')>operator(})operator(,) operator([)symbol(:x)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_overwrite_params) + instance_variable(@params)operator([)symbol(:controller)operator(]) operator(=) string<delimiter(')content(hi)delimiter(')> + instance_variable(@params)operator([)symbol(:action)operator(]) operator(=) string<delimiter(')content(bye)delimiter(')> + instance_variable(@params)operator([)symbol(:id)operator(]) operator(=) string<delimiter(')content(2)delimiter(')> + + ident(assert_equal) string<delimiter(')content(/hi/hi/2)delimiter(')>operator(,) instance_variable(@rewriter)operator(.)ident(rewrite)operator(()symbol(:only_path) operator(=)operator(>) pre_constant(true)operator(,) symbol(:overwrite_params) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(\)) + ident(u) operator(=) instance_variable(@rewriter)operator(.)ident(rewrite)operator(()symbol(:only_path) operator(=)operator(>) pre_constant(false)operator(,) symbol(:overwrite_params) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(hi)delimiter(')>operator(})operator(\)) + ident(assert_match) regexp<delimiter(%r()content(/hi/hi/2$)delimiter(\))>operator(,) ident(u) + reserved(end) + + + ident(private) + reserved(def) method(split_query_string)operator(()ident(str)operator(\)) + operator([)ident(str)operator([)integer(0)operator(])operator(.)ident(chr)operator(]) operator(+) ident(str)operator([)integer(1)operator(..)integer(-1)operator(])operator(.)ident(split)operator(()regexp<delimiter(/)content(&)delimiter(/)>operator(\))operator(.)ident(sort) + reserved(end) + + reserved(def) method(assert_query_equal)operator(()ident(q1)operator(,) ident(q2)operator(\)) + ident(assert_equal)operator(()ident(split_query_string)operator(()ident(q1)operator(\))operator(,) ident(split_query_string)operator(()ident(q2)operator(\))operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(VerificationTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_one)operator(,) symbol(:params) operator(=)operator(>) string<delimiter(")content(one)delimiter(")>operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_two)operator(,) symbol(:params) operator(=)operator(>) string<delimiter(%w()content( one two )delimiter(\))>operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_with_flash)operator(,) symbol(:params) operator(=)operator(>) string<delimiter(")content(one)delimiter(")>operator(,) + symbol(:add_flash) operator(=)operator(>) operator({) string<delimiter(")content(notice)delimiter(")> operator(=)operator(>) string<delimiter(")content(prereqs failed)delimiter(")> operator(})operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_in_session)operator(,) symbol(:session) operator(=)operator(>) string<delimiter(")content(one)delimiter(")>operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) operator([)symbol(:multi_one)operator(,) symbol(:multi_two)operator(])operator(,) symbol(:session) operator(=)operator(>) string<delimiter(%w()content( one two )delimiter(\))>operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_by_method)operator(,) symbol(:method) operator(=)operator(>) symbol(:post)operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_by_xhr)operator(,) symbol(:xhr) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:guarded_by_not_xhr)operator(,) symbol(:xhr) operator(=)operator(>) pre_constant(false)operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(before_filter) symbol(:unconditional_redirect)operator(,) symbol(:only) operator(=)operator(>) symbol(:two_redirects) + ident(verify) symbol(:only) operator(=)operator(>) symbol(:two_redirects)operator(,) symbol(:method) operator(=)operator(>) symbol(:post)operator(,) + symbol(:redirect_to) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> operator(}) + + ident(verify) symbol(:only) operator(=)operator(>) symbol(:must_be_post)operator(,) symbol(:method) operator(=)operator(>) symbol(:post)operator(,) symbol(:render) operator(=)operator(>) operator({) symbol(:status) operator(=)operator(>) integer(500)operator(,) symbol(:text) operator(=)operator(>) string<delimiter(")content(Must be post)delimiter(")>operator(}) + + reserved(def) method(guarded_one) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(guarded_with_flash) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(guarded_two) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(two)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(guarded_in_session) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@session)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(multi_one) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@session)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@session)operator([)string<delimiter(")content(two)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(multi_two) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@session)operator([)string<delimiter(")content(two)delimiter(")>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@session)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(guarded_by_method) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(method)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(guarded_by_xhr) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(xhr?)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(guarded_by_not_xhr) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@request)operator(.)ident(xhr?)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(unguarded) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@params)operator([)string<delimiter(")content(one)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(two_redirects) + ident(render) symbol(:nothing) operator(=)operator(>) pre_constant(true) + reserved(end) + + reserved(def) method(must_be_post) + ident(render) symbol(:text) operator(=)operator(>) string<delimiter(")content(Was a post!)delimiter(")> + reserved(end) + + ident(protected) + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + + reserved(def) method(unconditional_redirect) + ident(redirect_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_guarded_one_with_prereqs) + ident(get) symbol(:guarded_one)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(here)delimiter(")> + ident(assert_equal) string<delimiter(")content(here)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_one_without_prereqs) + ident(get) symbol(:guarded_one) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_with_flash_with_prereqs) + ident(get) symbol(:guarded_with_flash)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(here)delimiter(")> + ident(assert_equal) string<delimiter(")content(here)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + ident(assert_flash_empty) + reserved(end) + + reserved(def) method(test_guarded_with_flash_without_prereqs) + ident(get) symbol(:guarded_with_flash) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + ident(assert_flash_equal) string<delimiter(")content(prereqs failed)delimiter(")>operator(,) string<delimiter(")content(notice)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_two_with_prereqs) + ident(get) symbol(:guarded_two)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(here)delimiter(")>operator(,) symbol(:two) operator(=)operator(>) string<delimiter(")content(there)delimiter(")> + ident(assert_equal) string<delimiter(")content(here:there)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_two_without_prereqs_one) + ident(get) symbol(:guarded_two)operator(,) symbol(:two) operator(=)operator(>) string<delimiter(")content(there)delimiter(")> + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_two_without_prereqs_two) + ident(get) symbol(:guarded_two)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(here)delimiter(")> + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_two_without_prereqs_both) + ident(get) symbol(:guarded_two) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_unguarded_with_params) + ident(get) symbol(:unguarded)operator(,) symbol(:one) operator(=)operator(>) string<delimiter(")content(here)delimiter(")> + ident(assert_equal) string<delimiter(")content(here)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_unguarded_without_params) + ident(get) symbol(:unguarded) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_in_session_with_prereqs) + ident(get) symbol(:guarded_in_session)operator(,) operator({)operator(})operator(,) string<delimiter(")content(one)delimiter(")> operator(=)operator(>) string<delimiter(")content(here)delimiter(")> + ident(assert_equal) string<delimiter(")content(here)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_in_session_without_prereqs) + ident(get) symbol(:guarded_in_session) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_multi_one_with_prereqs) + ident(get) symbol(:multi_one)operator(,) operator({)operator(})operator(,) string<delimiter(")content(one)delimiter(")> operator(=)operator(>) string<delimiter(")content(here)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")> operator(=)operator(>) string<delimiter(")content(there)delimiter(")> + ident(assert_equal) string<delimiter(")content(here:there)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_multi_one_without_prereqs) + ident(get) symbol(:multi_one) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_multi_two_with_prereqs) + ident(get) symbol(:multi_two)operator(,) operator({)operator(})operator(,) string<delimiter(")content(one)delimiter(")> operator(=)operator(>) string<delimiter(")content(here)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")> operator(=)operator(>) string<delimiter(")content(there)delimiter(")> + ident(assert_equal) string<delimiter(")content(there:here)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_multi_two_without_prereqs) + ident(get) symbol(:multi_two) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_by_method_with_prereqs) + ident(post) symbol(:guarded_by_method) + ident(assert_equal) string<delimiter(")content(post)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_by_method_without_prereqs) + ident(get) symbol(:guarded_by_method) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_by_xhr_with_prereqs) + ident(xhr) symbol(:post)operator(,) symbol(:guarded_by_xhr) + ident(assert_equal) string<delimiter(")content(true)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_by_xhr_without_prereqs) + ident(get) symbol(:guarded_by_xhr) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_by_not_xhr_with_prereqs) + ident(get) symbol(:guarded_by_not_xhr) + ident(assert_equal) string<delimiter(")content(false)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_by_not_xhr_without_prereqs) + ident(xhr) symbol(:post)operator(,) symbol(:guarded_by_not_xhr) + ident(assert_redirected_to) symbol(:action) operator(=)operator(>) string<delimiter(")content(unguarded)delimiter(")> + reserved(end) + + reserved(def) method(test_guarded_post_and_calls_render_succeeds) + ident(post) symbol(:must_be_post) + ident(assert_equal) string<delimiter(")content(Was a post!)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_guarded_post_and_calls_render_fails) + ident(get) symbol(:must_be_post) + ident(assert_response) integer(500) + ident(assert_equal) string<delimiter(")content(Must be post)delimiter(")>operator(,) instance_variable(@response)operator(.)ident(body) + reserved(end) + + + reserved(def) method(test_second_redirect) + ident(assert_nothing_raised) operator({) ident(get) symbol(:two_redirects) operator(}) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(stringio)delimiter(')> + +reserved(class) class(WebServiceTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + + reserved(class) class(MockCGI) operator(<) constant(CGI) comment(#:nodoc:) + ident(attr_accessor) symbol(:stdinput)operator(,) symbol(:stdoutput)operator(,) symbol(:env_table) + + reserved(def) method(initialize)operator(()ident(env)operator(,) ident(data) operator(=) string<delimiter(')delimiter(')>operator(\)) + pre_constant(self)operator(.)ident(env_table) operator(=) ident(env) + pre_constant(self)operator(.)ident(stdinput) operator(=) constant(StringIO)operator(.)ident(new)operator(()ident(data)operator(\)) + pre_constant(self)operator(.)ident(stdoutput) operator(=) constant(StringIO)operator(.)ident(new) + reserved(super)operator(()operator(\)) + reserved(end) + reserved(end) + + + reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(session) symbol(:off) + + reserved(def) method(assign_parameters) + reserved(if) ident(params)operator([)symbol(:full)operator(]) + ident(render) symbol(:text) operator(=)operator(>) ident(dump_params_keys) + reserved(else) + ident(render) symbol(:text) operator(=)operator(>) operator(()ident(params)operator(.)ident(keys) operator(-) operator([)string<delimiter(')content(controller)delimiter(')>operator(,) string<delimiter(')content(action)delimiter(')>operator(])operator(\))operator(.)ident(sort)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(dump_params_keys)operator(()ident(hash)operator(=)ident(params)operator(\)) + ident(hash)operator(.)ident(keys)operator(.)ident(sort)operator(.)ident(inject)operator(()string<delimiter(")delimiter(")>operator(\)) reserved(do) operator(|)ident(s)operator(,) ident(k)operator(|) + ident(value) operator(=) ident(hash)operator([)ident(k)operator(]) + ident(value) operator(=) constant(Hash) operator(===) ident(value) operator(?) string<delimiter(")content(()inline<inline_delimiter(#{)ident(dump_params_keys)operator(()ident(value)operator(\))inline_delimiter(})>content(\))delimiter(")> operator(:) string<delimiter(")delimiter(")> + ident(s) operator(<<) string<delimiter(")content(, )delimiter(")> reserved(unless) ident(s)operator(.)ident(empty?) + ident(s) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(k)inline_delimiter(})>inline<inline_delimiter(#{)ident(value)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(TestController)operator(.)ident(new) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator(.)ident(clear) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(XML)operator(]) operator(=) symbol(:xml_node) + reserved(end) + + reserved(def) method(test_check_parameters) + ident(process)operator(()string<delimiter(')content(GET)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_post_xml) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(')content(<entry attributed="true"><summary>content...</summary></entry>)delimiter(')>operator(\)) + + ident(assert_equal) string<delimiter(')content(entry)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert) instance_variable(@controller)operator(.)ident(params)operator(.)ident(has_key?)operator(()symbol(:entry)operator(\)) + ident(assert_equal) string<delimiter(')content(content...)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(entry)delimiter(")>operator(])operator(.)ident(summary)operator(.)ident(node_value) + ident(assert_equal) string<delimiter(')content(true)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(entry)delimiter(")>operator(])operator([)string<delimiter(')content(attributed)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_put_xml) + ident(process)operator(()string<delimiter(')content(PUT)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(')content(<entry attributed="true"><summary>content...</summary></entry>)delimiter(')>operator(\)) + + ident(assert_equal) string<delimiter(')content(entry)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert) instance_variable(@controller)operator(.)ident(params)operator(.)ident(has_key?)operator(()symbol(:entry)operator(\)) + ident(assert_equal) string<delimiter(')content(content...)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(entry)delimiter(")>operator(])operator(.)ident(summary)operator(.)ident(node_value) + ident(assert_equal) string<delimiter(')content(true)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(entry)delimiter(")>operator(])operator([)string<delimiter(')content(attributed)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_register_and_use_yaml) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(YAML)operator(]) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(d)operator(|) constant(YAML)operator(.)ident(load)operator(()ident(d)operator(\)) operator(}) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/x-yaml)delimiter(')>operator(,) operator({)string<delimiter(")content(entry)delimiter(")> operator(=)operator(>) string<delimiter(")content(loaded from yaml)delimiter(")>operator(})operator(.)ident(to_yaml)operator(\)) + ident(assert_equal) string<delimiter(')content(entry)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert) instance_variable(@controller)operator(.)ident(params)operator(.)ident(has_key?)operator(()symbol(:entry)operator(\)) + ident(assert_equal) string<delimiter(')content(loaded from yaml)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(entry)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_register_and_use_yaml_as_symbol) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(YAML)operator(]) operator(=) symbol(:yaml) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/x-yaml)delimiter(')>operator(,) operator({)string<delimiter(")content(entry)delimiter(")> operator(=)operator(>) string<delimiter(")content(loaded from yaml)delimiter(")>operator(})operator(.)ident(to_yaml)operator(\)) + ident(assert_equal) string<delimiter(')content(entry)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert) instance_variable(@controller)operator(.)ident(params)operator(.)ident(has_key?)operator(()symbol(:entry)operator(\)) + ident(assert_equal) string<delimiter(')content(loaded from yaml)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(entry)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_register_and_use_xml_simple) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(XML)operator(]) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(data)operator(|) constant(XmlSimple)operator(.)ident(xml_in)operator(()ident(data)operator(,) string<delimiter(')content(ForceArray)delimiter(')> operator(=)operator(>) pre_constant(false)operator(\)) operator(}) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(')content(<request><summary>content...</summary><title>SimpleXml</title></request>)delimiter(')> operator(\)) + ident(assert_equal) string<delimiter(')content(summary, title)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert) instance_variable(@controller)operator(.)ident(params)operator(.)ident(has_key?)operator(()symbol(:summary)operator(\)) + ident(assert) instance_variable(@controller)operator(.)ident(params)operator(.)ident(has_key?)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(')content(content...)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(summary)delimiter(")>operator(]) + ident(assert_equal) string<delimiter(')content(SimpleXml)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_use_xml_ximple_with_empty_request) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(XML)operator(]) operator(=) symbol(:xml_simple) + ident(assert_nothing_raised) operator({) ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(")delimiter(")>operator(\)) operator(}) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + reserved(end) + + reserved(def) method(test_deprecated_request_methods) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/x-yaml)delimiter(')>operator(\)) + ident(assert_equal) constant(Mime)operator(::)constant(YAML)operator(,) instance_variable(@controller)operator(.)ident(request)operator(.)ident(content_type) + ident(assert_equal) pre_constant(true)operator(,) instance_variable(@controller)operator(.)ident(request)operator(.)ident(post?) + ident(assert_equal) symbol(:yaml)operator(,) instance_variable(@controller)operator(.)ident(request)operator(.)ident(post_format) + ident(assert_equal) pre_constant(true)operator(,) instance_variable(@controller)operator(.)ident(request)operator(.)ident(yaml_post?) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@controller)operator(.)ident(request)operator(.)ident(xml_post?) + reserved(end) + + reserved(def) method(test_dasherized_keys_as_xml) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(XML)operator(]) operator(=) symbol(:xml_simple) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(")content(<first-key>)char(\\n)content(<sub-key>...</sub-key>)char(\\n)content(</first-key>)delimiter(")>operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(')content(action, controller, first_key(sub_key\), full)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert_equal) string<delimiter(")content(...)delimiter(")>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)symbol(:first_key)operator(])operator([)symbol(:sub_key)operator(]) + reserved(end) + + reserved(def) method(test_typecast_as_xml) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(XML)operator(]) operator(=) symbol(:xml_simple) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(<<-XML)>operator(\))string<content( + <data> + <a type="integer">15</a> + <b type="boolean">false</b> + <c type="boolean">true</c> + <d type="date">2005-03-17</d> + <e type="datetime">2005-03-17T21:41:07Z</e> + <f>unparsed</f> + <g type="integer">1</g> + <g>hello</g> + <g type="date">1974-07-25</g> + </data>)delimiter( + XML)> + ident(params) operator(=) instance_variable(@controller)operator(.)ident(params) + ident(assert_equal) integer(15)operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:a)operator(]) + ident(assert_equal) pre_constant(false)operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:b)operator(]) + ident(assert_equal) pre_constant(true)operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:c)operator(]) + ident(assert_equal) constant(Date)operator(.)ident(new)operator(()integer(2005)operator(,)integer(3)operator(,)integer(17)operator(\))operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:d)operator(]) + ident(assert_equal) constant(Time)operator(.)ident(utc)operator(()integer(2005)operator(,)integer(3)operator(,)integer(17)operator(,)integer(21)operator(,)integer(41)operator(,)integer(7)operator(\))operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:e)operator(]) + ident(assert_equal) string<delimiter(")content(unparsed)delimiter(")>operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:f)operator(]) + ident(assert_equal) operator([)integer(1)operator(,) string<delimiter(")content(hello)delimiter(")>operator(,) constant(Date)operator(.)ident(new)operator(()integer(1974)operator(,)integer(7)operator(,)integer(25)operator(\))operator(])operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:g)operator(]) + reserved(end) + + reserved(def) method(test_entities_unescaped_as_xml_simple) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(XML)operator(]) operator(=) symbol(:xml_simple) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/xml)delimiter(')>operator(,) string<delimiter(<<-XML)>operator(\))string<content( + <data><foo "bar's" & friends></data>)delimiter( + XML)> + ident(assert_equal) string<delimiter(%()content(<foo "bar's" & friends>)delimiter(\))>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)symbol(:data)operator(]) + reserved(end) + + reserved(def) method(test_dasherized_keys_as_yaml) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(YAML)operator(]) operator(=) symbol(:yaml) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/x-yaml)delimiter(')>operator(,) string<delimiter(")content(---)char(\\n)content(first-key:)char(\\n)content( sub-key: ...)char(\\n)delimiter(")>operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(')content(action, controller, first_key(sub_key\), full)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(response)operator(.)ident(body) + ident(assert_equal) string<delimiter(")content(...)delimiter(")>operator(,) instance_variable(@controller)operator(.)ident(params)operator([)symbol(:first_key)operator(])operator([)symbol(:sub_key)operator(]) + reserved(end) + + reserved(def) method(test_typecast_as_yaml) + constant(ActionController)operator(::)constant(Base)operator(.)ident(param_parsers)operator([)constant(Mime)operator(::)constant(YAML)operator(]) operator(=) symbol(:yaml) + ident(process)operator(()string<delimiter(')content(POST)delimiter(')>operator(,) string<delimiter(')content(application/x-yaml)delimiter(')>operator(,) string<delimiter(<<-YAML)>operator(\))string<content( + --- + data: + a: 15 + b: false + c: true + d: 2005-03-17 + e: 2005-03-17T21:41:07Z + f: unparsed + g: + - 1 + - hello + - 1974-07-25)delimiter( + YAML)> + ident(params) operator(=) instance_variable(@controller)operator(.)ident(params) + ident(assert_equal) integer(15)operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:a)operator(]) + ident(assert_equal) pre_constant(false)operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:b)operator(]) + ident(assert_equal) pre_constant(true)operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:c)operator(]) + ident(assert_equal) constant(Date)operator(.)ident(new)operator(()integer(2005)operator(,)integer(3)operator(,)integer(17)operator(\))operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:d)operator(]) + ident(assert_equal) constant(Time)operator(.)ident(utc)operator(()integer(2005)operator(,)integer(3)operator(,)integer(17)operator(,)integer(21)operator(,)integer(41)operator(,)integer(7)operator(\))operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:e)operator(]) + ident(assert_equal) string<delimiter(")content(unparsed)delimiter(")>operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:f)operator(]) + ident(assert_equal) operator([)integer(1)operator(,) string<delimiter(")content(hello)delimiter(")>operator(,) constant(Date)operator(.)ident(new)operator(()integer(1974)operator(,)integer(7)operator(,)integer(25)operator(\))operator(])operator(,) ident(params)operator([)symbol(:data)operator(])operator([)symbol(:g)operator(]) + reserved(end) + + ident(private) + + reserved(def) method(process)operator(()ident(verb)operator(,) ident(content_type) operator(=) string<delimiter(')content(application/x-www-form-urlencoded)delimiter(')>operator(,) ident(data) operator(=) string<delimiter(')delimiter(')>operator(,) ident(full)operator(=)pre_constant(false)operator(\)) + + ident(cgi) operator(=) constant(MockCGI)operator(.)ident(new)operator(()operator({) + string<delimiter(')content(REQUEST_METHOD)delimiter(')> operator(=)operator(>) ident(verb)operator(,) + string<delimiter(')content(CONTENT_TYPE)delimiter(')> operator(=)operator(>) ident(content_type)operator(,) + string<delimiter(')content(QUERY_STRING)delimiter(')> operator(=)operator(>) string<delimiter(")content(action=assign_parameters&controller=webservicetest/test)inline<inline_delimiter(#{)string<delimiter(")content(&full=1)delimiter(")> reserved(if) ident(full)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(REQUEST_URI)delimiter(")> operator(=)operator(>) string<delimiter(")content(/)delimiter(")>operator(,) + string<delimiter(")content(HTTP_HOST)delimiter(")> operator(=)operator(>) string<delimiter(')content(testdomain.com)delimiter(')>operator(,) + string<delimiter(")content(CONTENT_LENGTH)delimiter(")> operator(=)operator(>) ident(data)operator(.)ident(size)operator(,) + string<delimiter(")content(SERVER_PORT)delimiter(")> operator(=)operator(>) string<delimiter(")content(80)delimiter(")>operator(,) + string<delimiter(")content(HTTPS)delimiter(")> operator(=)operator(>) string<delimiter(")content(off)delimiter(")>operator(})operator(,) ident(data)operator(\)) + + instance_variable(@controller)operator(.)ident(send)operator(()symbol(:process)operator(,) constant(ActionController)operator(::)constant(CgiRequest)operator(.)ident(new)operator(()ident(cgi)operator(,) operator({)operator(})operator(\))operator(,) constant(ActionController)operator(::)constant(CgiResponse)operator(.)ident(new)operator(()ident(cgi)operator(\))operator(\)) + reserved(end) + +reserved(end) + + +reserved(class) class(XmlNodeTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_all) + ident(xn) operator(=) constant(XmlNode)operator(.)ident(from_xml)operator(()string<delimiter(%{)content(<?xml version="1.0" encoding="UTF-8"?> + <response success='true'> + <page title='Ajax Summit' id='1133' email_address='ry87ib@backpackit.com'> + <description>With O'Reilly and Adaptive Path</description> + <notes> + <note title='Hotel' id='1020' created_at='2005-05-14 16:41:11'> + Staying at the Savoy + </note> + </notes> + <tags> + <tag name='Technology' id='4' /> + <tag name='Travel' id='5' /> + </tags> + </page> + </response> + )delimiter(})> + operator(\)) + ident(assert_equal) string<delimiter(')content(UTF-8)delimiter(')>operator(,) ident(xn)operator(.)ident(node)operator(.)ident(document)operator(.)ident(encoding) + ident(assert_equal) string<delimiter(')content(1.0)delimiter(')>operator(,) ident(xn)operator(.)ident(node)operator(.)ident(document)operator(.)ident(version) + ident(assert_equal) string<delimiter(')content(true)delimiter(')>operator(,) ident(xn)operator([)string<delimiter(')content(success)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(response)delimiter(')>operator(,) ident(xn)operator(.)ident(node_name) + ident(assert_equal) string<delimiter(')content(Ajax Summit)delimiter(')>operator(,) ident(xn)operator(.)ident(page)operator([)string<delimiter(')content(title)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(1133)delimiter(')>operator(,) ident(xn)operator(.)ident(page)operator([)string<delimiter(')content(id)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(")content(With O'Reilly and Adaptive Path)delimiter(")>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(description)operator(.)ident(node_value) + ident(assert_equal) pre_constant(nil)operator(,) ident(xn)operator(.)ident(nonexistent) + ident(assert_equal) string<delimiter(")content(Staying at the Savoy)delimiter(")>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(notes)operator(.)ident(note)operator(.)ident(node_value)operator(.)ident(strip) + ident(assert_equal) string<delimiter(')content(Technology)delimiter(')>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(tags)operator(.)ident(tag)operator([)integer(0)operator(])operator([)string<delimiter(')content(name)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(')content(Travel)delimiter(')>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(tags)operator(.)ident(tag)operator([)integer(1)operator(])operator([)symbol(:name)operator(]) + ident(matches) operator(=) ident(xn)operator(.)ident(xpath)operator(()string<delimiter(')content(//@id)delimiter(')>operator(\))operator(.)ident(map)operator({) operator(|)ident(id)operator(|) ident(id)operator(.)ident(to_i) operator(}) + ident(assert_equal) operator([)integer(4)operator(,) integer(5)operator(,) integer(1020)operator(,) integer(1133)operator(])operator(,) ident(matches)operator(.)ident(sort) + ident(matches) operator(=) ident(xn)operator(.)ident(xpath)operator(()string<delimiter(')content(//tag)delimiter(')>operator(\))operator(.)ident(map)operator({) operator(|)ident(tag)operator(|) ident(tag)operator([)string<delimiter(')content(name)delimiter(')>operator(]) operator(}) + ident(assert_equal) operator([)string<delimiter(')content(Technology)delimiter(')>operator(,) string<delimiter(')content(Travel)delimiter(')>operator(])operator(,) ident(matches)operator(.)ident(sort) + ident(assert_equal) string<delimiter(")content(Ajax Summit)delimiter(")>operator(,) ident(xn)operator(.)ident(page)operator([)string<delimiter(')content(title)delimiter(')>operator(]) + ident(xn)operator(.)ident(page)operator([)string<delimiter(')content(title)delimiter(')>operator(]) operator(=) string<delimiter(')content(Ajax Summit V2)delimiter(')> + ident(assert_equal) string<delimiter(")content(Ajax Summit V2)delimiter(")>operator(,) ident(xn)operator(.)ident(page)operator([)string<delimiter(')content(title)delimiter(')>operator(]) + ident(assert_equal) string<delimiter(")content(Staying at the Savoy)delimiter(")>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(notes)operator(.)ident(note)operator(.)ident(node_value)operator(.)ident(strip) + ident(xn)operator(.)ident(page)operator(.)ident(notes)operator(.)ident(note)operator(.)ident(node_value) operator(=) string<delimiter(")content(Staying at the Ritz)delimiter(")> + ident(assert_equal) string<delimiter(")content(Staying at the Ritz)delimiter(")>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(notes)operator(.)ident(note)operator(.)ident(node_value)operator(.)ident(strip) + ident(assert_equal) string<delimiter(')content(5)delimiter(')>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(tags)operator(.)ident(tag)operator([)integer(1)operator(])operator([)symbol(:id)operator(]) + ident(xn)operator(.)ident(page)operator(.)ident(tags)operator(.)ident(tag)operator([)integer(1)operator(])operator([)string<delimiter(')content(id)delimiter(')>operator(]) operator(=) string<delimiter(')content(7)delimiter(')> + ident(assert_equal) string<delimiter(')content(7)delimiter(')>operator(,) ident(xn)operator(.)ident(page)operator(.)ident(tags)operator(.)ident(tag)operator([)integer(1)operator(])operator([)string<delimiter(')content(id)delimiter(')>operator(]) + reserved(end) + + + reserved(def) method(test_small_entry) + ident(node) operator(=) constant(XmlNode)operator(.)ident(from_xml)operator(()string<delimiter(')content(<entry>hi</entry>)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(hi)delimiter(')>operator(,) ident(node)operator(.)ident(node_value) + reserved(end) + +reserved(end) +reserved(class) class(AClassThatContainsAController::PoorlyPlacedController) operator(<) constant(ActionController)operator(::)constant(Base) + + reserved(def) pre_constant(self)operator(.)ident(is_evil?) + symbol(:decidedly_so) + reserved(end) + +ident(endclass) constant(ModuleThatHoldsControllers)operator(::)constant(NestedController) operator(<) constant(ActionController)operator(::)constant(Base) + +ident(endclass) constant(AClassThatContainsAController) comment(#often < ActiveRecord::Base) + + reserved(def) pre_constant(self)operator(.)ident(is_special?) + symbol(:you_know_it) + reserved(end) + +ident(endclass) constant(Company) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(attr_protected) symbol(:rating) + ident(set_sequence_name) symbol(:companies_nonstd_seq) + + ident(validates_presence_of) symbol(:name) + reserved(def) method(validate) + ident(errors)operator(.)ident(add)operator(()string<delimiter(')content(rating)delimiter(')>operator(,) string<delimiter(')content(rating should not be 2)delimiter(')>operator(\)) reserved(if) ident(rating) operator(==) integer(2) + reserved(end) +ident(endclass) constant(Developer) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:projects) +reserved(end) + +reserved(class) class(DeVeLoPeR) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(")content(developers)delimiter(")> +reserved(end) +comment(# see routing/controller component tests) + +ident(raise) constant(Exception)operator(,) string<delimiter(")content(I should never be loaded)delimiter(")>reserved(module) class(AbcHelper) + reserved(def) method(bare_a)operator(()operator(\)) reserved(end) + reserved(def) method(bare_b)operator(()operator(\)) reserved(end) + reserved(def) method(bare_c)operator(()operator(\)) reserved(end) +reserved(end) +reserved(module) class(Fun::GamesHelper) + reserved(def) method(stratego)operator(()operator(\)) string<delimiter(")content(Iz guuut!)delimiter(")> reserved(end) +ident(endmodule) constant(Fun)operator(::)constant(PDFHelper) + reserved(def) method(foobar)operator(()operator(\)) string<delimiter(')content(baz)delimiter(')> reserved(end) +reserved(end) +reserved(class) class(Project) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:developers)operator(,) symbol(:uniq) operator(=)operator(>) pre_constant(true) +reserved(end) +reserved(class) class(Reply) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:topic)operator(,) symbol(:include) operator(=)operator(>) operator([)symbol(:replies)operator(]) + + ident(validates_presence_of) symbol(:content) +reserved(end) +reserved(class) class(Topic) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_many) symbol(:replies)operator(,) symbol(:include) operator(=)operator(>) operator([)symbol(:user)operator(])operator(,) symbol(:dependent) operator(=)operator(>) pre_constant(true) +ident(endrequire) string<delimiter(')content(test/unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/date_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/form_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/text_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/tag_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/url_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/form_tag_helper)delimiter(')> +comment(# require File.dirname(__FILE__\) + '/../../lib/action_view/helpers/active_record_helper') + +reserved(class) class(ActiveRecordHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(ActiveRecordHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormTagHelper) + + ident(silence_warnings) reserved(do) + constant(Post) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:title)operator(,) symbol(:author_name)operator(,) symbol(:body)operator(,) symbol(:secret)operator(,) symbol(:written_on)operator(\)) + constant(Post)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:title_before_type_cast)operator(,) symbol(:title) reserved(unless) ident(respond_to?)operator(()symbol(:title_before_type_cast)operator(\)) + ident(alias_method) symbol(:body_before_type_cast)operator(,) symbol(:body) reserved(unless) ident(respond_to?)operator(()symbol(:body_before_type_cast)operator(\)) + ident(alias_method) symbol(:author_name_before_type_cast)operator(,) symbol(:author_name) reserved(unless) ident(respond_to?)operator(()symbol(:author_name_before_type_cast)operator(\)) + reserved(end) + constant(Column) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Column)delimiter(")>operator(,) symbol(:type)operator(,) symbol(:name)operator(,) symbol(:human_name)operator(\)) + reserved(end) + + reserved(def) method(setup) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + reserved(def) instance_variable(@post)operator(.)ident(errors) + constant(Class)operator(.)ident(new) operator({) + reserved(def) method(on)operator(()ident(field)operator(\)) ident(field) operator(==) string<delimiter(")content(author_name)delimiter(")> operator(||) ident(field) operator(==) string<delimiter(")content(body)delimiter(")> reserved(end) + reserved(def) method(empty?)operator(()operator(\)) pre_constant(false) reserved(end) + reserved(def) method(count)operator(()operator(\)) integer(1) reserved(end) + reserved(def) method(full_messages)operator(()operator(\)) operator([) string<delimiter(")content(Author name can't be empty)delimiter(")> operator(]) reserved(end) + operator(})operator(.)ident(new) + reserved(end) + + reserved(def) instance_variable(@post)operator(.)ident(new_record?)operator(()operator(\)) pre_constant(true) reserved(end) + reserved(def) instance_variable(@post)operator(.)ident(to_param)operator(()operator(\)) pre_constant(nil) reserved(end) + + reserved(def) instance_variable(@post)operator(.)ident(column_for_attribute)operator(()ident(attr_name)operator(\)) + constant(Post)operator(.)ident(content_columns)operator(.)ident(select) operator({) operator(|)ident(column)operator(|) ident(column)operator(.)ident(name) operator(==) ident(attr_name) operator(})operator(.)ident(first) + reserved(end) + + reserved(def) constant(Post)operator(.)ident(content_columns)operator(()operator(\)) operator([) constant(Column)operator(.)ident(new)operator(()symbol(:string)operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Title)delimiter(")>operator(\))operator(,) constant(Column)operator(.)ident(new)operator(()symbol(:text)operator(,) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(Body)delimiter(")>operator(\)) operator(]) reserved(end) + + instance_variable(@post)operator(.)ident(title) operator(=) string<delimiter(")content(Hello World)delimiter(")> + instance_variable(@post)operator(.)ident(author_name) operator(=) string<delimiter(")delimiter(")> + instance_variable(@post)operator(.)ident(body) operator(=) string<delimiter(")content(Back to the hill and over it again!)delimiter(")> + instance_variable(@post)operator(.)ident(secret) operator(=) integer(1) + instance_variable(@post)operator(.)ident(written_on) operator(=) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(6)operator(,) integer(15)operator(\)) + + instance_variable(@controller) operator(=) constant(Object)operator(.)ident(new) + reserved(def) instance_variable(@controller)operator(.)ident(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(options) operator(=) ident(options)operator(.)ident(symbolize_keys) + + operator([)ident(options)operator([)symbol(:action)operator(])operator(,) ident(options)operator([)symbol(:id)operator(])operator(.)ident(to_param)operator(])operator(.)ident(compact)operator(.)ident(join)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_generic_input_tag) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />)delimiter(\))>operator(,) ident(input)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_area_with_errors) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div>)delimiter(\))>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_field_with_errors) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<div class="fieldWithErrors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>)delimiter(\))>operator(,) + ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(author_name)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_form_with_string) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<form action="create" method="post"><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>)char(\\n)content(<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>)delimiter(\))>operator(,) + ident(form)operator(()string<delimiter(")content(post)delimiter(")>operator(\)) + operator(\)) + + reserved(class) operator(<<) instance_variable(@post) + reserved(def) method(new_record?)operator(()operator(\)) pre_constant(false) reserved(end) + reserved(def) method(to_param)operator(()operator(\)) ident(id) reserved(end) + reserved(def) method(id)operator(()operator(\)) integer(1) reserved(end) + reserved(end) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<form action="update/1" method="post"><input id="post_id" name="post[id]" type="hidden" value="1" /><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>)char(\\n)content(<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Update" /></form>)delimiter(\))>operator(,) + ident(form)operator(()string<delimiter(")content(post)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_form_with_date) + reserved(def) constant(Post)operator(.)ident(content_columns)operator(()operator(\)) operator([) constant(Column)operator(.)ident(new)operator(()symbol(:date)operator(,) string<delimiter(")content(written_on)delimiter(")>operator(,) string<delimiter(")content(Written on)delimiter(")>operator(\)) operator(]) reserved(end) + + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<form action="create" method="post"><p><label for="post_written_on">Written on</label><br /><select name="post[written_on)nesting_delimiter(()content(1i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="1999">1999</option>)char(\\n)content(<option value="2000">2000</option>)char(\\n)content(<option value="2001">2001</option>)char(\\n)content(<option value="2002">2002</option>)char(\\n)content(<option value="2003">2003</option>)char(\\n)content(<option value="2004" selected="selected">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)content(<option value="2006">2006</option>)char(\\n)content(<option value="2007">2007</option>)char(\\n)content(<option value="2008">2008</option>)char(\\n)content(<option value="2009">2009</option>)char(\\n)content(</select>)char(\\n)content(<select name="post[written_on)nesting_delimiter(()content(2i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6" selected="selected">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)content(</select>)char(\\n)content(<select name="post[written_on)nesting_delimiter(()content(3i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15" selected="selected">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(</select>)char(\\n)content(</p><input name="commit" type="submit" value="Create" /></form>)delimiter(\))>operator(,) + ident(form)operator(()string<delimiter(")content(post)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_form_with_datetime) + reserved(def) constant(Post)operator(.)ident(content_columns)operator(()operator(\)) operator([) constant(Column)operator(.)ident(new)operator(()symbol(:datetime)operator(,) string<delimiter(")content(written_on)delimiter(")>operator(,) string<delimiter(")content(Written on)delimiter(")>operator(\)) operator(]) reserved(end) + instance_variable(@post)operator(.)ident(written_on) operator(=) constant(Time)operator(.)ident(gm)operator(()integer(2004)operator(,) integer(6)operator(,) integer(15)operator(,) integer(16)operator(,) integer(30)operator(\)) + + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<form action="create" method="post"><p><label for="post_written_on">Written on</label><br /><select name="post[written_on)nesting_delimiter(()content(1i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="1999">1999</option>)char(\\n)content(<option value="2000">2000</option>)char(\\n)content(<option value="2001">2001</option>)char(\\n)content(<option value="2002">2002</option>)char(\\n)content(<option value="2003">2003</option>)char(\\n)content(<option value="2004" selected="selected">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)content(<option value="2006">2006</option>)char(\\n)content(<option value="2007">2007</option>)char(\\n)content(<option value="2008">2008</option>)char(\\n)content(<option value="2009">2009</option>)char(\\n)content(</select>)char(\\n)content(<select name="post[written_on)nesting_delimiter(()content(2i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6" selected="selected">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)content(</select>)char(\\n)content(<select name="post[written_on)nesting_delimiter(()content(3i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15" selected="selected">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(</select>)char(\\n)content( — <select name="post[written_on)nesting_delimiter(()content(4i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(</select>)char(\\n)content( : <select name="post[written_on)nesting_delimiter(()content(5i)nesting_delimiter(\))content(]">)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30" selected="selected">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)content(</select>)char(\\n)content(</p><input name="commit" type="submit" value="Create" /></form>)delimiter(\))>operator(,) + ident(form)operator(()string<delimiter(")content(post)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_error_for_block) + ident(assert_dom_equal) string<delimiter(%()content(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>)delimiter(\))>operator(,) ident(error_messages_for)operator(()string<delimiter(")content(post)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<div class="errorDeathByClass" id="errorDeathById"><h1>1 error prohibited this post from being saved</h1><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>)delimiter(\))>operator(,) ident(error_messages_for)operator(()string<delimiter(")content(post)delimiter(")>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(")content(errorDeathByClass)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")content(errorDeathById)delimiter(")>operator(,) symbol(:header_tag) operator(=)operator(>) string<delimiter(")content(h1)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_error_messages_for_handles_nil) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) ident(error_messages_for)operator(()string<delimiter(")content(notthere)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_form_with_string_multipart) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<form action="create" enctype="multipart/form-data" method="post"><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>)char(\\n)content(<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>)delimiter(\))>operator(,) + ident(form)operator(()string<delimiter(")content(post)delimiter(")>operator(,) symbol(:multipart) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(AssetTagHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + + ident(attr_accessor) symbol(:request) + + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + string<delimiter(")content(http://www.example.com)delimiter(")> + reserved(end) + + reserved(end)operator(.)ident(new) + + instance_variable(@request) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(relative_url_root) + string<delimiter(")delimiter(")> + reserved(end) + reserved(end)operator(.)ident(new) + + instance_variable(@controller)operator(.)ident(request) operator(=) instance_variable(@request) + + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper)operator(::)ident(reset_javascript_include_default) + reserved(end) + + reserved(def) method(teardown) + constant(Object)operator(.)ident(send)operator(()symbol(:remove_const)operator(,) symbol(:RAILS_ROOT)operator(\)) reserved(if) reserved(defined?)operator(()constant(RAILS_ROOT)operator(\)) + constant(ENV)operator([)string<delimiter(")content(RAILS_ASSET_ID)delimiter(")>operator(]) operator(=) pre_constant(nil) + reserved(end) + + constant(AutoDiscoveryToTag) operator(=) operator({) + string<delimiter(%()content(auto_discovery_link_tag)delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:atom)nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="ATOM" type="application/atom+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:rss, :action => "feed")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:rss, "http://localhost/feed")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://localhost/feed" rel="alternate" title="RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:rss, {:action => "feed"}, {:title => "My RSS"})nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="My RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:rss, {}, {:title => "My RSS"})nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="My RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(nil, {}, {:type => "text/html"})nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="" type="text/html" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(nil, {}, {:title => "No stream.. really", :type => "text/html"})nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="No stream.. really" type="text/html" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:rss, {}, {:title => "My RSS", :type => "text/html"})nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="alternate" title="My RSS" type="text/html" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:atom, {}, {:rel => "Not so alternate"})nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com" rel="Not so alternate" title="ATOM" type="application/atom+xml" />)delimiter(\))>operator(,) + operator(}) + + constant(JavascriptPathToTag) operator(=) operator({) + string<delimiter(%()content(javascript_path)nesting_delimiter(()content("xmlhr")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/javascripts/xmlhr.js)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_path)nesting_delimiter(()content("super/xmlhr")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/javascripts/super/xmlhr.js)delimiter(\))> + operator(}) + + constant(JavascriptIncludeToTag) operator(=) operator({) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content("xmlhr")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/javascripts/xmlhr.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content("xmlhr", :lang => "vbscript")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script lang="vbscript" src="/javascripts/xmlhr.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content("common.javascript", "/elsewhere/cools")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/javascripts/common.javascript" type="text/javascript"></script>)char(\\n)content(<script src="/elsewhere/cools.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content(:defaults)nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/controls.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content(:defaults, "test")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/controls.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/test.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content("test", :defaults)nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/javascripts/test.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/controls.js" type="text/javascript"></script>)delimiter(\))> + operator(}) + + constant(StylePathToTag) operator(=) operator({) + string<delimiter(%()content(stylesheet_path)nesting_delimiter(()content("style")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/stylesheets/style.css)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_path)nesting_delimiter(()content('dir/file')nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/stylesheets/dir/file.css)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_path)nesting_delimiter(()content('/dir/file')nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/dir/file.css)delimiter(\))> + operator(}) + + constant(StyleLinkToTag) operator(=) operator({) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("style")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("/dir/file")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/dir/file.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("dir/file")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/stylesheets/dir/file.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("style", :media => "all")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("random.styles", "/css/stylish")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />)char(\\n)content(<link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))> + operator(}) + + constant(ImagePathToTag) operator(=) operator({) + string<delimiter(%()content(image_path)nesting_delimiter(()content("xml")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/images/xml.png)delimiter(\))>operator(,) + operator(}) + + constant(ImageLinkToTag) operator(=) operator({) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("xml")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Xml" src="/images/xml.png" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("rss", :alt => "rss syndication")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="rss syndication" src="/images/rss.png" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("gold", :size => "45x70")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Gold" height="70" src="/images/gold.png" width="45" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("symbolize", "size" => "45x70")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Symbolize" height="70" src="/images/symbolize.png" width="45" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("http://www.rubyonrails.com/images/rails")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Rails" src="http://www.rubyonrails.com/images/rails.png" />)delimiter(\))> + operator(}) + + reserved(def) method(test_auto_discovery) + constant(AutoDiscoveryToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_javascript_path) + constant(JavascriptPathToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_javascript_include) + constant(JavascriptIncludeToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_register_javascript_include_default) + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper)operator(::)ident(register_javascript_include_default) string<delimiter(')content(slider)delimiter(')> + ident(assert_dom_equal) string<delimiter(%()content(<script src="/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/controls.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/slider.js" type="text/javascript"></script>)delimiter(\))>operator(,) ident(javascript_include_tag)operator(()symbol(:defaults)operator(\)) + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper)operator(::)ident(register_javascript_include_default) string<delimiter(')content(lib1)delimiter(')>operator(,) string<delimiter(')content(/elsewhere/blub/lib2)delimiter(')> + ident(assert_dom_equal) string<delimiter(%()content(<script src="/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/controls.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/slider.js" type="text/javascript"></script>)char(\\n)content(<script src="/javascripts/lib1.js" type="text/javascript"></script>)char(\\n)content(<script src="/elsewhere/blub/lib2.js" type="text/javascript"></script>)delimiter(\))>operator(,) ident(javascript_include_tag)operator(()symbol(:defaults)operator(\)) + reserved(end) + + reserved(def) method(test_style_path) + constant(StylePathToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_style_link) + constant(StyleLinkToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_image_path) + constant(ImagePathToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_image_tag) + constant(ImageLinkToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_timebased_asset_id) + constant(Object)operator(.)ident(send)operator(()symbol(:const_set)operator(,) symbol(:RAILS_ROOT)operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")>operator(\)) + ident(expected_time) operator(=) constant(File)operator(.)ident(stat)operator(()constant(File)operator(.)ident(expand_path)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/public/images/rails.png)delimiter(")>operator(\))operator(\))operator(.)ident(mtime)operator(.)ident(to_i)operator(.)ident(to_s) + ident(assert_equal) string<delimiter(%()content(<img alt="Rails" src="/images/rails.png?)inline<inline_delimiter(#{)ident(expected_time)inline_delimiter(})>content(" />)delimiter(\))>operator(,) ident(image_tag)operator(()string<delimiter(")content(rails.png)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_skipping_asset_id_on_complete_url) + constant(Object)operator(.)ident(send)operator(()symbol(:const_set)operator(,) symbol(:RAILS_ROOT)operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<img alt="Rails" src="http://www.example.com/rails.png" />)delimiter(\))>operator(,) ident(image_tag)operator(()string<delimiter(")content(http://www.example.com/rails.png)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_preset_asset_id) + constant(Object)operator(.)ident(send)operator(()symbol(:const_set)operator(,) symbol(:RAILS_ROOT)operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../fixtures/)delimiter(")>operator(\)) + constant(ENV)operator([)string<delimiter(")content(RAILS_ASSET_ID)delimiter(")>operator(]) operator(=) string<delimiter(")content(4500)delimiter(")> + ident(assert_equal) string<delimiter(%()content(<img alt="Rails" src="/images/rails.png?4500" />)delimiter(\))>operator(,) ident(image_tag)operator(()string<delimiter(")content(rails.png)delimiter(")>operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(AssetTagHelperNonVhostTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + + ident(attr_accessor) symbol(:request) + + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + string<delimiter(")content(http://www.example.com/calloboration/hieraki)delimiter(")> + reserved(end) + + reserved(end)operator(.)ident(new) + + instance_variable(@request) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(relative_url_root) + string<delimiter(")content(/calloboration/hieraki)delimiter(")> + reserved(end) + reserved(end)operator(.)ident(new) + + instance_variable(@controller)operator(.)ident(request) operator(=) instance_variable(@request) + + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper)operator(::)ident(reset_javascript_include_default) + reserved(end) + + constant(AutoDiscoveryToTag) operator(=) operator({) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:rss, :action => "feed")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com/calloboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)nesting_delimiter(()content(:atom)nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com/calloboration/hieraki" rel="alternate" title="ATOM" type="application/atom+xml" />)delimiter(\))>operator(,) + string<delimiter(%()content(auto_discovery_link_tag)delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="http://www.example.com/calloboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />)delimiter(\))>operator(,) + operator(}) + + constant(JavascriptPathToTag) operator(=) operator({) + string<delimiter(%()content(javascript_path)nesting_delimiter(()content("xmlhr")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/calloboration/hieraki/javascripts/xmlhr.js)delimiter(\))>operator(,) + operator(}) + + constant(JavascriptIncludeToTag) operator(=) operator({) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content("xmlhr")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/calloboration/hieraki/javascripts/xmlhr.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content("common.javascript", "/elsewhere/cools")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/calloboration/hieraki/javascripts/common.javascript" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/elsewhere/cools.js" type="text/javascript"></script>)delimiter(\))>operator(,) + string<delimiter(%()content(javascript_include_tag)nesting_delimiter(()content(:defaults)nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<script src="/calloboration/hieraki/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/controls.js" type="text/javascript"></script>)delimiter(\))> + operator(}) + + constant(StylePathToTag) operator(=) operator({) + string<delimiter(%()content(stylesheet_path)nesting_delimiter(()content("style")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/calloboration/hieraki/stylesheets/style.css)delimiter(\))>operator(,) + operator(}) + + constant(StyleLinkToTag) operator(=) operator({) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("style")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/calloboration/hieraki/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))>operator(,) + string<delimiter(%()content(stylesheet_link_tag)nesting_delimiter(()content("random.styles", "/css/stylish")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<link href="/calloboration/hieraki/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />)char(\\n)content(<link href="/calloboration/hieraki/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))> + operator(}) + + constant(ImagePathToTag) operator(=) operator({) + string<delimiter(%()content(image_path)nesting_delimiter(()content("xml")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(/calloboration/hieraki/images/xml.png)delimiter(\))>operator(,) + operator(}) + + constant(ImageLinkToTag) operator(=) operator({) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("xml")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Xml" src="/calloboration/hieraki/images/xml.png" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("rss", :alt => "rss syndication")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="rss syndication" src="/calloboration/hieraki/images/rss.png" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("gold", :size => "45x70")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Gold" height="70" src="/calloboration/hieraki/images/gold.png" width="45" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("http://www.example.com/images/icon.gif")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Icon" src="http://www.example.com/images/icon.gif" />)delimiter(\))>operator(,) + string<delimiter(%()content(image_tag)nesting_delimiter(()content("symbolize", "size" => "45x70")nesting_delimiter(\))delimiter(\))> operator(=)operator(>) string<delimiter(%()content(<img alt="Symbolize" height="70" src="/calloboration/hieraki/images/symbolize.png" width="45" />)delimiter(\))> + operator(}) + + reserved(def) method(test_auto_discovery) + constant(AutoDiscoveryToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_javascript_path) + constant(JavascriptPathToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_javascript_include) + constant(JavascriptIncludeToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_register_javascript_include_default) + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper)operator(::)ident(register_javascript_include_default) string<delimiter(')content(slider)delimiter(')> + ident(assert_dom_equal) string<delimiter(%()content(<script src="/calloboration/hieraki/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/controls.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/slider.js" type="text/javascript"></script>)delimiter(\))>operator(,) ident(javascript_include_tag)operator(()symbol(:defaults)operator(\)) + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper)operator(::)ident(register_javascript_include_default) string<delimiter(')content(lib1)delimiter(')>operator(,) string<delimiter(')content(/elsewhere/blub/lib2)delimiter(')> + ident(assert_dom_equal) string<delimiter(%()content(<script src="/calloboration/hieraki/javascripts/prototype.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/effects.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/dragdrop.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/controls.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/slider.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/javascripts/lib1.js" type="text/javascript"></script>)char(\\n)content(<script src="/calloboration/hieraki/elsewhere/blub/lib2.js" type="text/javascript"></script>)delimiter(\))>operator(,) ident(javascript_include_tag)operator(()symbol(:defaults)operator(\)) + reserved(end) + + reserved(def) method(test_style_path) + constant(StylePathToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_style_link) + constant(StyleLinkToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_image_path) + constant(ImagePathToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_image_tag) + constant(ImageLinkToTag)operator(.)ident(each) operator({) operator(|)ident(method)operator(,) ident(tag)operator(|) ident(assert_dom_equal)operator(()ident(tag)operator(,) ident(eval)operator(()ident(method)operator(\))operator(\)) operator(}) + comment(# Assigning a default alt tag should not cause an exception to be raised) + ident(assert_nothing_raised) operator({) ident(image_tag)operator(()string<delimiter(')delimiter(')>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_stylesheet_with_asset_host_already_encoded) + constant(ActionController)operator(::)constant(Base)operator(.)ident(asset_host) operator(=) string<delimiter(")content(http://foo.example.com)delimiter(")> + ident(result) operator(=) ident(stylesheet_link_tag)operator(()string<delimiter(")content(http://bar.example.com/stylesheets/style.css)delimiter(")>operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />)delimiter(\))>operator(,) + ident(result)operator(\)) + reserved(ensure) + constant(ActionController)operator(::)constant(Base)operator(.)ident(asset_host) operator(=) string<delimiter(")delimiter(")> + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/benchmark_helper)delimiter(')> + +reserved(class) class(BenchmarkHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(BenchmarkHelper) + + reserved(class) class(MockLogger) + ident(attr_reader) symbol(:logged) + + reserved(def) method(initialize) + instance_variable(@logged) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(\)) + instance_variable(@logged) operator(<<) operator([)ident(method)operator(,) ident(args)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@logger) operator(=) constant(MockLogger)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_without_logger_or_block) + instance_variable(@logger) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(benchmark) operator(}) + reserved(end) + + reserved(def) method(test_without_block) + ident(assert_raise)operator(()constant(LocalJumpError)operator(\)) operator({) ident(benchmark) operator(}) + ident(assert) instance_variable(@logger)operator(.)ident(logged)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(test_without_logger) + instance_variable(@logger) operator(=) pre_constant(nil) + ident(i_was_run) operator(=) pre_constant(false) + ident(benchmark) operator({) ident(i_was_run) operator(=) pre_constant(true) operator(}) + ident(assert) operator(!)ident(i_was_run) + reserved(end) + + reserved(def) method(test_defaults) + ident(i_was_run) operator(=) pre_constant(false) + ident(benchmark) operator({) ident(i_was_run) operator(=) pre_constant(true) operator(}) + ident(assert) ident(i_was_run) + ident(assert) integer(1)operator(,) instance_variable(@logger)operator(.)ident(logged)operator(.)ident(size) + ident(assert_last_logged) + reserved(end) + + reserved(def) method(test_with_message) + ident(i_was_run) operator(=) pre_constant(false) + ident(benchmark)operator(()string<delimiter(')content(test_run)delimiter(')>operator(\)) operator({) ident(i_was_run) operator(=) pre_constant(true) operator(}) + ident(assert) ident(i_was_run) + ident(assert) integer(1)operator(,) instance_variable(@logger)operator(.)ident(logged)operator(.)ident(size) + ident(assert_last_logged) string<delimiter(')content(test_run)delimiter(')> + reserved(end) + + reserved(def) method(test_with_message_and_level) + ident(i_was_run) operator(=) pre_constant(false) + ident(benchmark)operator(()string<delimiter(')content(debug_run)delimiter(')>operator(,) symbol(:debug)operator(\)) operator({) ident(i_was_run) operator(=) pre_constant(true) operator(}) + ident(assert) ident(i_was_run) + ident(assert) integer(1)operator(,) instance_variable(@logger)operator(.)ident(logged)operator(.)ident(size) + ident(assert_last_logged) string<delimiter(')content(debug_run)delimiter(')>operator(,) symbol(:debug) + reserved(end) + + ident(private) + reserved(def) method(assert_last_logged)operator(()ident(message) operator(=) string<delimiter(')content(Benchmarking)delimiter(')>operator(,) ident(level) operator(=) symbol(:info)operator(\)) + ident(last) operator(=) instance_variable(@logger)operator(.)ident(logged)operator(.)ident(last) + ident(assert) integer(2)operator(,) ident(last)operator(.)ident(size) + ident(assert_equal) ident(level)operator(,) ident(last)operator(.)ident(first) + ident(assert) integer(1)operator(,) ident(last)operator([)integer(1)operator(])operator(.)ident(size) + ident(assert) ident(last)operator([)integer(1)operator(])operator([)integer(0)operator(]) operator(=)operator(~) regexp<delimiter(/)content(^)inline<inline_delimiter(#{)ident(message)inline_delimiter(})>content( )char(\\()content(.*)char(\\\))content($)delimiter(/)> + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/date_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../abstract_unit)delimiter(")> + +reserved(class) class(CompiledTemplateTests) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + + reserved(def) method(setup) + instance_variable(@ct) operator(=) constant(ActionView)operator(::)constant(CompiledTemplates)operator(.)ident(new) + instance_variable(@v) operator(=) constant(Class)operator(.)ident(new) + instance_variable(@v)operator(.)ident(send) symbol(:include)operator(,) instance_variable(@ct) + instance_variable(@a) operator(=) string<delimiter(')content(./test_compile_template_a.rhtml)delimiter(')> + instance_variable(@b) operator(=) string<delimiter(')content(./test_compile_template_b.rhtml)delimiter(')> + instance_variable(@s) operator(=) string<delimiter(')content(./test_compile_template_link.rhtml)delimiter(')> + reserved(end) + reserved(def) method(teardown) + operator([)instance_variable(@a)operator(,) instance_variable(@b)operator(,) instance_variable(@s)operator(])operator(.)ident(each) reserved(do) operator(|)ident(f)operator(|) + shell<delimiter(`)content(rm )inline<inline_delimiter(#{)ident(f)inline_delimiter(})>delimiter(`)> reserved(if) constant(File)operator(.)ident(exist?)operator(()ident(f)operator(\)) operator(||) constant(File)operator(.)ident(symlink?)operator(()ident(f)operator(\)) + reserved(end) + reserved(end) + ident(attr_reader) symbol(:ct)operator(,) symbol(:v) + + reserved(def) method(test_name_allocation) + ident(hi_world) operator(=) ident(ct)operator(.)ident(method_names)operator([)string<delimiter(')content(hi world)delimiter(')>operator(]) + ident(hi_sexy) operator(=) ident(ct)operator(.)ident(method_names)operator([)string<delimiter(')content(hi sexy)delimiter(')>operator(]) + ident(wish_upon_a_star) operator(=) ident(ct)operator(.)ident(method_names)operator([)string<delimiter(')content(I love seeing decent error messages)delimiter(')>operator(]) + + ident(assert_equal) ident(hi_world)operator(,) ident(ct)operator(.)ident(method_names)operator([)string<delimiter(')content(hi world)delimiter(')>operator(]) + ident(assert_equal) ident(hi_sexy)operator(,) ident(ct)operator(.)ident(method_names)operator([)string<delimiter(')content(hi sexy)delimiter(')>operator(]) + ident(assert_equal) ident(wish_upon_a_star)operator(,) ident(ct)operator(.)ident(method_names)operator([)string<delimiter(')content(I love seeing decent error messages)delimiter(')>operator(]) + ident(assert_equal) integer(3)operator(,) operator([)ident(hi_world)operator(,) ident(hi_sexy)operator(,) ident(wish_upon_a_star)operator(])operator(.)ident(uniq)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_wrap_source) + ident(assert_equal)operator(() + string<delimiter(")content(def aliased_assignment(value\))char(\\n)content(self.value = value)char(\\n)content(end)delimiter(")>operator(,) + instance_variable(@ct)operator(.)ident(wrap_source)operator(()symbol(:aliased_assignment)operator(,) operator([)symbol(:value)operator(])operator(,) string<delimiter(')content(self.value = value)delimiter(')>operator(\)) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(")content(def simple(\))char(\\n)content(nil)char(\\n)content(end)delimiter(")>operator(,) + instance_variable(@ct)operator(.)ident(wrap_source)operator(()symbol(:simple)operator(,) operator([)operator(])operator(,) string<delimiter(')content(nil)delimiter(')>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_compile_source_single_method) + ident(selector) operator(=) ident(ct)operator(.)ident(compile_source)operator(()string<delimiter(')content(doubling method)delimiter(')>operator(,) operator([)symbol(:a)operator(])operator(,) string<delimiter(')content(a + a)delimiter(')>operator(\)) + ident(assert_equal) integer(2)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(selector)operator(,) integer(1)operator(\)) + ident(assert_equal) integer(4)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(selector)operator(,) integer(2)operator(\)) + ident(assert_equal) integer(-4)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(selector)operator(,) integer(-2)operator(\)) + ident(assert_equal) integer(0)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(selector)operator(,) integer(0)operator(\)) + ident(selector) + reserved(end) + + reserved(def) method(test_compile_source_two_method) + ident(sel1) operator(=) ident(test_compile_source_single_method) comment(# compile the method in the other test) + ident(sel2) operator(=) ident(ct)operator(.)ident(compile_source)operator(()string<delimiter(')content(doubling method)delimiter(')>operator(,) operator([)symbol(:a)operator(,) symbol(:b)operator(])operator(,) string<delimiter(')content(a + b + a + b)delimiter(')>operator(\)) + ident(assert_not_equal) ident(sel1)operator(,) ident(sel2) + + ident(assert_equal) integer(2)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(sel1)operator(,) integer(1)operator(\)) + ident(assert_equal) integer(4)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(sel1)operator(,) integer(2)operator(\)) + + ident(assert_equal) integer(6)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(sel2)operator(,) integer(1)operator(,) integer(2)operator(\)) + ident(assert_equal) integer(32)operator(,) instance_variable(@v)operator(.)ident(new)operator(.)ident(send)operator(()ident(sel2)operator(,) integer(15)operator(,) integer(1)operator(\)) + reserved(end) + + reserved(def) method(test_mtime) + ident(t1) operator(=) constant(Time)operator(.)ident(now) + ident(test_compile_source_single_method) + ident(assert) operator(()ident(t1)operator(..)constant(Time)operator(.)ident(now)operator(\))operator(.)ident(include?)operator(()ident(ct)operator(.)ident(mtime)operator(()string<delimiter(')content(doubling method)delimiter(')>operator(,) operator([)symbol(:a)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_compile_time) + shell<delimiter(`)content(echo ')inline<inline_delimiter(#{)instance_variable(@a)inline_delimiter(})>content(' > )inline<inline_delimiter(#{)instance_variable(@a)inline_delimiter(})>content(; echo ')inline<inline_delimiter(#{)instance_variable(@b)inline_delimiter(})>content(' > )inline<inline_delimiter(#{)instance_variable(@b)inline_delimiter(})>content(; ln -s )inline<inline_delimiter(#{)instance_variable(@a)inline_delimiter(})>content( )inline<inline_delimiter(#{)instance_variable(@s)inline_delimiter(})>delimiter(`)> + + ident(v) operator(=) constant(ActionView)operator(::)constant(Base)operator(.)ident(new) + ident(v)operator(.)ident(base_path) operator(=) string<delimiter(')content(.)delimiter(')> + ident(v)operator(.)ident(cache_template_loading) operator(=) pre_constant(false)operator(;) + + ident(sleep) integer(1) + ident(t) operator(=) constant(Time)operator(.)ident(now) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@a)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@b)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@s)operator(\)) + ident(a_n) operator(=) ident(v)operator(.)ident(method_names)operator([)instance_variable(@a)operator(]) + ident(b_n) operator(=) ident(v)operator(.)ident(method_names)operator([)instance_variable(@b)operator(]) + ident(s_n) operator(=) ident(v)operator(.)ident(method_names)operator([)instance_variable(@s)operator(]) + comment(# all of the files have changed since last compile) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(a_n)operator(]) operator(>) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(b_n)operator(]) operator(>) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(s_n)operator(]) operator(>) ident(t) + + ident(sleep) integer(1) + ident(t) operator(=) constant(Time)operator(.)ident(now) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@a)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@b)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@s)operator(\)) + comment(# none of the files have changed since last compile) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(a_n)operator(]) operator(<) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(b_n)operator(]) operator(<) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(s_n)operator(]) operator(<) ident(t) + + shell<delimiter(`)content(rm )inline<inline_delimiter(#{)instance_variable(@s)inline_delimiter(})>content(; ln -s )inline<inline_delimiter(#{)instance_variable(@b)inline_delimiter(})>content( )inline<inline_delimiter(#{)instance_variable(@s)inline_delimiter(})>delimiter(`)> + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@a)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@b)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@s)operator(\)) + comment(# the symlink has changed since last compile) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(a_n)operator(]) operator(<) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(b_n)operator(]) operator(<) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(s_n)operator(]) operator(>) ident(t) + + ident(sleep) integer(1) + shell<delimiter(`)content(touch )inline<inline_delimiter(#{)instance_variable(@b)inline_delimiter(})>delimiter(`)> + ident(t) operator(=) constant(Time)operator(.)ident(now) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@a)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@b)operator(\)) + ident(v)operator(.)ident(compile_and_render_template)operator(()symbol(:rhtml)operator(,) string<delimiter(')delimiter(')>operator(,) instance_variable(@s)operator(\)) + comment(# the file at the end of the symlink has changed since last compile) + comment(# both the symlink and the file at the end of it should be recompiled) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(a_n)operator(]) operator(<) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(b_n)operator(]) operator(>) ident(t) + ident(assert) ident(v)operator(.)ident(compile_time)operator([)ident(s_n)operator(]) operator(>) ident(t) + reserved(end) +reserved(end) + +reserved(module) class(ActionView) + reserved(class) class(Base) + reserved(def) method(compile_time) + class_variable(@@compile_time) + reserved(end) + reserved(def) method(method_names) + class_variable(@@method_names) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../abstract_unit)delimiter(")> + +reserved(class) class(DateHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(DateHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + + ident(silence_warnings) reserved(do) + constant(Post) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:written_on)operator(,) symbol(:updated_at)operator(\)) + reserved(end) + + reserved(def) method(test_distance_in_words) + ident(from) operator(=) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(18)operator(\)) + + ident(assert_equal) string<delimiter(")content(less than a minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(25)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(5 minutes)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(46)operator(,) integer(25)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(about 1 hour)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(22)operator(,) integer(47)operator(,) integer(25)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(about 3 hours)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(7)operator(,) integer(0)operator(,) integer(41)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(about 4 hours)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(7)operator(,) integer(1)operator(,) integer(20)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(2 days)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(9)operator(,) integer(15)operator(,) integer(40)operator(\))operator(\)) + + comment(# include seconds ) + ident(assert_equal) string<delimiter(")content(less than a minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(19)operator(\))operator(,) pre_constant(false)operator(\)) + ident(assert_equal) string<delimiter(")content(less than 5 seconds)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(19)operator(\))operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(less than 10 seconds)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(28)operator(\))operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(less than 20 seconds)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(38)operator(\))operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(half a minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(48)operator(\))operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(less than a minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(42)operator(,) integer(17)operator(\))operator(,) pre_constant(true)operator(\)) + + ident(assert_equal) string<delimiter(")content(1 minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(42)operator(,) integer(18)operator(\))operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(1 minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(42)operator(,) integer(28)operator(\))operator(,) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(2 minutes)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()ident(from)operator(,) constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(42)operator(,) integer(48)operator(\))operator(,) pre_constant(true)operator(\)) + + comment(# test to < from) + ident(assert_equal) string<delimiter(")content(about 4 hours)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(7)operator(,) integer(1)operator(,) integer(20)operator(\))operator(,) ident(from)operator(\)) + ident(assert_equal) string<delimiter(")content(less than 20 seconds)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2004)operator(,) integer(3)operator(,) integer(6)operator(,) integer(21)operator(,) integer(41)operator(,) integer(38)operator(\))operator(,) ident(from)operator(,) pre_constant(true)operator(\)) + + comment(# test with integers) + ident(assert_equal) string<delimiter(")content(less than a minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()integer(50)operator(\)) + ident(assert_equal) string<delimiter(")content(about 1 hour)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()integer(60)operator(*)integer(60)operator(\)) + + comment(# more cumbersome test with integers) + ident(assert_equal) string<delimiter(")content(less than a minute)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()integer(0)operator(,) integer(50)operator(\)) + ident(assert_equal) string<delimiter(")content(about 1 hour)delimiter(")>operator(,) ident(distance_of_time_in_words)operator(()integer(60)operator(*)integer(60)operator(,) integer(0)operator(\)) + + reserved(end) + + reserved(def) method(test_distance_in_words_date) + ident(start_date) operator(=) constant(Date)operator(.)ident(new) integer(1975)operator(,) integer(1)operator(,) integer(31) + ident(end_date) operator(=) constant(Date)operator(.)ident(new) integer(1977)operator(,) integer(4)operator(,) integer(17) + ident(assert_not_equal)operator(()string<delimiter(")content(13 minutes)delimiter(")>operator(,) + ident(distance_of_time_in_words)operator(()ident(start_date)operator(,) ident(end_date)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_select_day) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_day)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_day)operator(()integer(16)operator(\)) + reserved(end) + + reserved(def) method(test_select_day_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_day)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_day)operator(()integer(16)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_day_nil_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_day)operator(()pre_constant(nil)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_disabled) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_field_name_override) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[mois]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(mois)delimiter(')>operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(mois)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_nil_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()pre_constant(nil)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_numbers) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8" selected="selected">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:use_month_numbers) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:use_month_numbers) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_numbers_and_names) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">1 - January</option>)char(\\n)content(<option value="2">2 - February</option>)char(\\n)content(<option value="3">3 - March</option>)char(\\n)content(<option value="4">4 - April</option>)char(\\n)content(<option value="5">5 - May</option>)char(\\n)content(<option value="6">6 - June</option>)char(\\n)content(<option value="7">7 - July</option>)char(\\n)content(<option value="8" selected="selected">8 - August</option>)char(\\n)content(<option value="9">9 - September</option>)char(\\n)content(<option value="10">10 - October</option>)char(\\n)content(<option value="11">11 - November</option>)char(\\n)content(<option value="12">12 - December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:add_month_numbers) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:add_month_numbers) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_numbers_and_names_with_abbv) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">1 - Jan</option>)char(\\n)content(<option value="2">2 - Feb</option>)char(\\n)content(<option value="3">3 - Mar</option>)char(\\n)content(<option value="4">4 - Apr</option>)char(\\n)content(<option value="5">5 - May</option>)char(\\n)content(<option value="6">6 - Jun</option>)char(\\n)content(<option value="7">7 - Jul</option>)char(\\n)content(<option value="8" selected="selected">8 - Aug</option>)char(\\n)content(<option value="9">9 - Sep</option>)char(\\n)content(<option value="10">10 - Oct</option>)char(\\n)content(<option value="11">11 - Nov</option>)char(\\n)content(<option value="12">12 - Dec</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:add_month_numbers) operator(=)operator(>) pre_constant(true)operator(,) symbol(:use_short_month) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:add_month_numbers) operator(=)operator(>) pre_constant(true)operator(,) symbol(:use_short_month) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_month_with_abbv) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">Jan</option>)char(\\n)content(<option value="2">Feb</option>)char(\\n)content(<option value="3">Mar</option>)char(\\n)content(<option value="4">Apr</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">Jun</option>)char(\\n)content(<option value="7">Jul</option>)char(\\n)content(<option value="8" selected="selected">Aug</option>)char(\\n)content(<option value="9">Sep</option>)char(\\n)content(<option value="10">Oct</option>)char(\\n)content(<option value="11">Nov</option>)char(\\n)content(<option value="12">Dec</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:use_short_month) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_month)operator(()integer(8)operator(,) symbol(:use_short_month) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[year]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003" selected="selected">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()integer(2003)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(\)) + reserved(end) + + reserved(def) method(test_select_year_with_disabled) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[year]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003" selected="selected">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()integer(2003)operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(\)) + reserved(end) + + reserved(def) method(test_select_year_with_field_name_override) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[annee]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003" selected="selected">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(annee)delimiter(')>operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()integer(2003)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(annee)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_select_year_with_type_discarding) + ident(expected) operator(=) string<delimiter(%()content(<select name="date_year">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003" selected="selected">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(() + constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date_year)delimiter(")>operator(,) symbol(:discard_type) operator(=)operator(>) pre_constant(true)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(() + integer(2003)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date_year)delimiter(")>operator(,) symbol(:discard_type) operator(=)operator(>) pre_constant(true)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(\)) + reserved(end) + + reserved(def) method(test_select_year_descending) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[year]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2005" selected="selected">2005</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2003">2003</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2005)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:start_year) operator(=)operator(>) integer(2005)operator(,) symbol(:end_year) operator(=)operator(>) integer(2003)operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_year)operator(()integer(2005)operator(,) symbol(:start_year) operator(=)operator(>) integer(2005)operator(,) symbol(:end_year) operator(=)operator(>) integer(2003)operator(\)) + reserved(end) + + reserved(def) method(test_select_hour) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[hour]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08" selected="selected">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_hour)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_select_hour_with_disabled) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[hour]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08" selected="selected">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_hour)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_hour_with_field_name_override) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[heure]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08" selected="selected">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_hour)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(heure)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_select_hour_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[hour]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08" selected="selected">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_hour)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_hour_nil_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[hour]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_hour)operator(()pre_constant(nil)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_minute) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04" selected="selected">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_select_minute_with_disabled) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minute]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04" selected="selected">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_minute_with_field_name_override) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minuto]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04" selected="selected">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(minuto)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_select_minute_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04" selected="selected">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_minute_with_blank_and_step) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="45">45</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) operator({) symbol(:include_blank) operator(=)operator(>) pre_constant(true) operator(,) symbol(:minute_step) operator(=)operator(>) integer(15) operator(})operator(\)) + reserved(end) + + reserved(def) method(test_select_minute_nil_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()pre_constant(nil)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_minute_nil_with_blank_and_step) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="45">45</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_minute)operator(()pre_constant(nil)operator(,) operator({) symbol(:include_blank) operator(=)operator(>) pre_constant(true) operator(,) symbol(:minute_step) operator(=)operator(>) integer(15) operator(})operator(\)) + reserved(end) + + reserved(def) method(test_select_second) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[second]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18" selected="selected">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_second)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_select_second_with_disabled) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[second]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18" selected="selected">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_second)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_second_with_field_name_override) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[segundo]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18" selected="selected">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_second)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:field_name) operator(=)operator(>) string<delimiter(')content(segundo)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_select_second_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[second]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18" selected="selected">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_second)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_second_nil_with_blank) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[second]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value=""></option>)char(\\n)content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_second)operator(()pre_constant(nil)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_date) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003" selected="selected">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(() + constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(test_select_date_with_disabled) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003" selected="selected">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]" disabled="disabled">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + + reserved(def) method(test_select_date_with_no_start_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(-)integer(5)operator(\))operator(.)ident(upto)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(1)operator(\)) reserved(do) operator(|)ident(y)operator(|) + reserved(if) ident(y) operator(==) constant(Date)operator(.)ident(today)operator(.)ident(year) + ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + reserved(else) + ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + reserved(end) + reserved(end) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(() + constant(Time)operator(.)ident(mktime)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:end_year) operator(=)operator(>) constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(1)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(test_select_date_with_no_end_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + integer(2003)operator(.)ident(upto)operator(()integer(2008)operator(\)) reserved(do) operator(|)ident(y)operator(|) + reserved(if) ident(y) operator(==) integer(2003) + ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + reserved(else) + ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + reserved(end) + reserved(end) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(() + constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(test_select_date_with_no_start_or_end_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(-)integer(5)operator(\))operator(.)ident(upto)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(5)operator(\)) reserved(do) operator(|)ident(y)operator(|) + reserved(if) ident(y) operator(==) constant(Date)operator(.)ident(today)operator(.)ident(year) + ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(" selected="selected">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + reserved(else) + ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> + reserved(end) + reserved(end) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8" selected="selected">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16" selected="selected">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(() + constant(Time)operator(.)ident(mktime)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(,) integer(8)operator(,) integer(16)operator(\))operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(test_select_time_with_seconds) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[hour]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08" selected="selected">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04" selected="selected">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[second]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18" selected="selected">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_time)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:include_seconds) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_select_time_without_seconds) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[hour]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08" selected="selected">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04" selected="selected">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_time)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(\)) + ident(assert_equal) ident(expected)operator(,) ident(select_time)operator(()constant(Time)operator(.)ident(mktime)operator(()integer(2003)operator(,) integer(8)operator(,) integer(16)operator(,) integer(8)operator(,) integer(4)operator(,) integer(18)operator(\))operator(,) symbol(:include_seconds) operator(=)operator(>) pre_constant(false)operator(\)) + reserved(end) + + reserved(def) method(test_date_select_with_zero_value) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="2003">2003</option>)char(\\n)content(<option value="2004">2004</option>)char(\\n)content(<option value="2005">2005</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(()integer(0)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:end_year) operator(=)operator(>) integer(2005)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_date_select_within_fields_for) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(written_on) operator(=) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(6)operator(,) integer(15)operator(\)) + + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for) symbol(:post)operator(,) instance_variable(@post) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(date_select)operator(()symbol(:written_on)operator(\)) + reserved(end) + + ident(expected) operator(=) string<delimiter(")content(<select name='post[written_on(1i\)]'>)char(\\n)content(<option value='1999'>1999</option>)char(\\n)content(<option value='2000'>2000</option>)char(\\n)content(<option value='2001'>2001</option>)char(\\n)content(<option value='2002'>2002</option>)char(\\n)content(<option value='2003'>2003</option>)char(\\n)content(<option selected='selected' value='2004'>2004</option>)char(\\n)content(<option value='2005'>2005</option>)char(\\n)content(<option value='2006'>2006</option>)char(\\n)content(<option value='2007'>2007</option>)char(\\n)content(<option value='2008'>2008</option>)char(\\n)content(<option value='2009'>2009</option>)char(\\n)content(</select>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<select name='post[written_on(2i\)]'>)char(\\n)content(<option value='1'>January</option>)char(\\n)content(<option value='2'>February</option>)char(\\n)content(<option value='3'>March</option>)char(\\n)content(<option value='4'>April</option>)char(\\n)content(<option value='5'>May</option>)char(\\n)content(<option selected='selected' value='6'>June</option>)char(\\n)content(<option value='7'>July</option>)char(\\n)content(<option value='8'>August</option>)char(\\n)content(<option value='9'>September</option>)char(\\n)content(<option value='10'>October</option>)char(\\n)content(<option value='11'>November</option>)char(\\n)content(<option value='12'>December</option>)char(\\n)content(</select>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<select name='post[written_on(3i\)]'>)char(\\n)content(<option value='1'>1</option>)char(\\n)content(<option value='2'>2</option>)char(\\n)content(<option value='3'>3</option>)char(\\n)content(<option value='4'>4</option>)char(\\n)content(<option value='5'>5</option>)char(\\n)content(<option value='6'>6</option>)char(\\n)content(<option value='7'>7</option>)char(\\n)content(<option value='8'>8</option>)char(\\n)content(<option value='9'>9</option>)char(\\n)content(<option value='10'>10</option>)char(\\n)content(<option value='11'>11</option>)char(\\n)content(<option value='12'>12</option>)char(\\n)content(<option value='13'>13</option>)char(\\n)content(<option value='14'>14</option>)char(\\n)content(<option selected='selected' value='15'>15</option>)char(\\n)content(<option value='16'>16</option>)char(\\n)content(<option value='17'>17</option>)char(\\n)content(<option value='18'>18</option>)char(\\n)content(<option value='19'>19</option>)char(\\n)content(<option value='20'>20</option>)char(\\n)content(<option value='21'>21</option>)char(\\n)content(<option value='22'>22</option>)char(\\n)content(<option value='23'>23</option>)char(\\n)content(<option value='24'>24</option>)char(\\n)content(<option value='25'>25</option>)char(\\n)content(<option value='26'>26</option>)char(\\n)content(<option value='27'>27</option>)char(\\n)content(<option value='28'>28</option>)char(\\n)content(<option value='29'>29</option>)char(\\n)content(<option value='30'>30</option>)char(\\n)content(<option value='31'>31</option>)char(\\n)content(</select>)char(\\n)delimiter(")> + + ident(assert_dom_equal)operator(()ident(expected)operator(,) ident(_erbout)operator(\)) + reserved(end) + + reserved(def) method(test_datetime_select_within_fields_for) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(updated_at) operator(=) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(6)operator(,) integer(15)operator(,) integer(16)operator(,) integer(35)operator(\)) + + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for) symbol(:post)operator(,) instance_variable(@post) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(datetime_select)operator(()symbol(:updated_at)operator(\)) + reserved(end) + + ident(expected) operator(=) string<delimiter(")content(<select name='post[updated_at(1i\)]'>)char(\\n)content(<option value='1999'>1999</option>)char(\\n)content(<option value='2000'>2000</option>)char(\\n)content(<option value='2001'>2001</option>)char(\\n)content(<option value='2002'>2002</option>)char(\\n)content(<option value='2003'>2003</option>)char(\\n)content(<option selected='selected' value='2004'>2004</option>)char(\\n)content(<option value='2005'>2005</option>)char(\\n)content(<option value='2006'>2006</option>)char(\\n)content(<option value='2007'>2007</option>)char(\\n)content(<option value='2008'>2008</option>)char(\\n)content(<option value='2009'>2009</option>)char(\\n)content(</select>)char(\\n)content(<select name='post[updated_at(2i\)]'>)char(\\n)content(<option value='1'>January</option>)char(\\n)content(<option value='2'>February</option>)char(\\n)content(<option value='3'>March</option>)char(\\n)content(<option value='4'>April</option>)char(\\n)content(<option value='5'>May</option>)char(\\n)content(<option selected='selected' value='6'>June</option>)char(\\n)content(<option value='7'>July</option>)char(\\n)content(<option value='8'>August</option>)char(\\n)content(<option value='9'>September</option>)char(\\n)content(<option value='10'>October</option>)char(\\n)content(<option value='11'>November</option>)char(\\n)content(<option value='12'>December</option>)char(\\n)content(</select>)char(\\n)content(<select name='post[updated_at(3i\)]'>)char(\\n)content(<option value='1'>1</option>)char(\\n)content(<option value='2'>2</option>)char(\\n)content(<option value='3'>3</option>)char(\\n)content(<option value='4'>4</option>)char(\\n)content(<option value='5'>5</option>)char(\\n)content(<option value='6'>6</option>)char(\\n)content(<option value='7'>7</option>)char(\\n)content(<option value='8'>8</option>)char(\\n)content(<option value='9'>9</option>)char(\\n)content(<option value='10'>10</option>)char(\\n)content(<option value='11'>11</option>)char(\\n)content(<option value='12'>12</option>)char(\\n)content(<option value='13'>13</option>)char(\\n)content(<option value='14'>14</option>)char(\\n)content(<option selected='selected' value='15'>15</option>)char(\\n)content(<option value='16'>16</option>)char(\\n)content(<option value='17'>17</option>)char(\\n)content(<option value='18'>18</option>)char(\\n)content(<option value='19'>19</option>)char(\\n)content(<option value='20'>20</option>)char(\\n)content(<option value='21'>21</option>)char(\\n)content(<option value='22'>22</option>)char(\\n)content(<option value='23'>23</option>)char(\\n)content(<option value='24'>24</option>)char(\\n)content(<option value='25'>25</option>)char(\\n)content(<option value='26'>26</option>)char(\\n)content(<option value='27'>27</option>)char(\\n)content(<option value='28'>28</option>)char(\\n)content(<option value='29'>29</option>)char(\\n)content(<option value='30'>30</option>)char(\\n)content(<option value='31'>31</option>)char(\\n)content(</select>)char(\\n)content( — <select name='post[updated_at(4i\)]'>)char(\\n)content(<option value='00'>00</option>)char(\\n)content(<option value='01'>01</option>)char(\\n)content(<option value='02'>02</option>)char(\\n)content(<option value='03'>03</option>)char(\\n)content(<option value='04'>04</option>)char(\\n)content(<option value='05'>05</option>)char(\\n)content(<option value='06'>06</option>)char(\\n)content(<option value='07'>07</option>)char(\\n)content(<option value='08'>08</option>)char(\\n)content(<option value='09'>09</option>)char(\\n)content(<option value='10'>10</option>)char(\\n)content(<option value='11'>11</option>)char(\\n)content(<option value='12'>12</option>)char(\\n)content(<option value='13'>13</option>)char(\\n)content(<option value='14'>14</option>)char(\\n)content(<option value='15'>15</option>)char(\\n)content(<option selected='selected' value='16'>16</option>)char(\\n)content(<option value='17'>17</option>)char(\\n)content(<option value='18'>18</option>)char(\\n)content(<option value='19'>19</option>)char(\\n)content(<option value='20'>20</option>)char(\\n)content(<option value='21'>21</option>)char(\\n)content(<option value='22'>22</option>)char(\\n)content(<option value='23'>23</option>)char(\\n)content(</select>)char(\\n)content( : <select name='post[updated_at(5i\)]'>)char(\\n)content(<option value='00'>00</option>)char(\\n)content(<option value='01'>01</option>)char(\\n)content(<option value='02'>02</option>)char(\\n)content(<option value='03'>03</option>)char(\\n)content(<option value='04'>04</option>)char(\\n)content(<option value='05'>05</option>)char(\\n)content(<option value='06'>06</option>)char(\\n)content(<option value='07'>07</option>)char(\\n)content(<option value='08'>08</option>)char(\\n)content(<option value='09'>09</option>)char(\\n)content(<option value='10'>10</option>)char(\\n)content(<option value='11'>11</option>)char(\\n)content(<option value='12'>12</option>)char(\\n)content(<option value='13'>13</option>)char(\\n)content(<option value='14'>14</option>)char(\\n)content(<option value='15'>15</option>)char(\\n)content(<option value='16'>16</option>)char(\\n)content(<option value='17'>17</option>)char(\\n)content(<option value='18'>18</option>)char(\\n)content(<option value='19'>19</option>)char(\\n)content(<option value='20'>20</option>)char(\\n)content(<option value='21'>21</option>)char(\\n)content(<option value='22'>22</option>)char(\\n)content(<option value='23'>23</option>)char(\\n)content(<option value='24'>24</option>)char(\\n)content(<option value='25'>25</option>)char(\\n)content(<option value='26'>26</option>)char(\\n)content(<option value='27'>27</option>)char(\\n)content(<option value='28'>28</option>)char(\\n)content(<option value='29'>29</option>)char(\\n)content(<option value='30'>30</option>)char(\\n)content(<option value='31'>31</option>)char(\\n)content(<option value='32'>32</option>)char(\\n)content(<option value='33'>33</option>)char(\\n)content(<option value='34'>34</option>)char(\\n)content(<option selected='selected' value='35'>35</option>)char(\\n)content(<option value='36'>36</option>)char(\\n)content(<option value='37'>37</option>)char(\\n)content(<option value='38'>38</option>)char(\\n)content(<option value='39'>39</option>)char(\\n)content(<option value='40'>40</option>)char(\\n)content(<option value='41'>41</option>)char(\\n)content(<option value='42'>42</option>)char(\\n)content(<option value='43'>43</option>)char(\\n)content(<option value='44'>44</option>)char(\\n)content(<option value='45'>45</option>)char(\\n)content(<option value='46'>46</option>)char(\\n)content(<option value='47'>47</option>)char(\\n)content(<option value='48'>48</option>)char(\\n)content(<option value='49'>49</option>)char(\\n)content(<option value='50'>50</option>)char(\\n)content(<option value='51'>51</option>)char(\\n)content(<option value='52'>52</option>)char(\\n)content(<option value='53'>53</option>)char(\\n)content(<option value='54'>54</option>)char(\\n)content(<option value='55'>55</option>)char(\\n)content(<option value='56'>56</option>)char(\\n)content(<option value='57'>57</option>)char(\\n)content(<option value='58'>58</option>)char(\\n)content(<option value='59'>59</option>)char(\\n)content(</select>)char(\\n)delimiter(")> + + ident(assert_dom_equal)operator(()ident(expected)operator(,) ident(_erbout)operator(\)) + reserved(end) + + reserved(def) method(test_date_select_with_zero_value_and_no_start_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(-)integer(5)operator(\))operator(.)ident(upto)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(1)operator(\)) operator({) operator(|)ident(y)operator(|) ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(}) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(()integer(0)operator(,) symbol(:end_year) operator(=)operator(>) constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(1)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_date_select_with_zero_value_and_no_end_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + ident(last_year) operator(=) constant(Time)operator(.)ident(now)operator(.)ident(year) operator(+) integer(5) + integer(2003)operator(.)ident(upto)operator(()ident(last_year)operator(\)) operator({) operator(|)ident(y)operator(|) ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(}) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(()integer(0)operator(,) symbol(:start_year) operator(=)operator(>) integer(2003)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_date_select_with_zero_value_and_no_start_and_end_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(-)integer(5)operator(\))operator(.)ident(upto)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(5)operator(\)) operator({) operator(|)ident(y)operator(|) ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(}) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(()integer(0)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_date_select_with_nil_value_and_no_start_and_end_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(-)integer(5)operator(\))operator(.)ident(upto)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(5)operator(\)) operator({) operator(|)ident(y)operator(|) ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(}) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_date)operator(()pre_constant(nil)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_datetime_select_with_nil_value_and_no_start_and_end_year) + ident(expected) operator(=) string<delimiter(%()content(<select name="date[first][year]">)char(\\n)delimiter(\))> + operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(-)integer(5)operator(\))operator(.)ident(upto)operator(()constant(Date)operator(.)ident(today)operator(.)ident(year)operator(+)integer(5)operator(\)) operator({) operator(|)ident(y)operator(|) ident(expected) operator(<<) string<delimiter(%()content(<option value=")inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(y)inline_delimiter(})>content(</option>)char(\\n)delimiter(\))> operator(}) + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][month]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="1">January</option>)char(\\n)content(<option value="2">February</option>)char(\\n)content(<option value="3">March</option>)char(\\n)content(<option value="4">April</option>)char(\\n)content(<option value="5">May</option>)char(\\n)content(<option value="6">June</option>)char(\\n)content(<option value="7">July</option>)char(\\n)content(<option value="8">August</option>)char(\\n)content(<option value="9">September</option>)char(\\n)content(<option value="10">October</option>)char(\\n)content(<option value="11">November</option>)char(\\n)content(<option value="12">December</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][day]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) +string<delimiter(%()content(<option value="1">1</option>)char(\\n)content(<option value="2">2</option>)char(\\n)content(<option value="3">3</option>)char(\\n)content(<option value="4">4</option>)char(\\n)content(<option value="5">5</option>)char(\\n)content(<option value="6">6</option>)char(\\n)content(<option value="7">7</option>)char(\\n)content(<option value="8">8</option>)char(\\n)content(<option value="9">9</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][hour]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(expected) operator(<<) string<delimiter(%()content(<select name="date[first][minute]">)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(%()content(<option value="00">00</option>)char(\\n)content(<option value="01">01</option>)char(\\n)content(<option value="02">02</option>)char(\\n)content(<option value="03">03</option>)char(\\n)content(<option value="04">04</option>)char(\\n)content(<option value="05">05</option>)char(\\n)content(<option value="06">06</option>)char(\\n)content(<option value="07">07</option>)char(\\n)content(<option value="08">08</option>)char(\\n)content(<option value="09">09</option>)char(\\n)content(<option value="10">10</option>)char(\\n)content(<option value="11">11</option>)char(\\n)content(<option value="12">12</option>)char(\\n)content(<option value="13">13</option>)char(\\n)content(<option value="14">14</option>)char(\\n)content(<option value="15">15</option>)char(\\n)content(<option value="16">16</option>)char(\\n)content(<option value="17">17</option>)char(\\n)content(<option value="18">18</option>)char(\\n)content(<option value="19">19</option>)char(\\n)content(<option value="20">20</option>)char(\\n)content(<option value="21">21</option>)char(\\n)content(<option value="22">22</option>)char(\\n)content(<option value="23">23</option>)char(\\n)content(<option value="24">24</option>)char(\\n)content(<option value="25">25</option>)char(\\n)content(<option value="26">26</option>)char(\\n)content(<option value="27">27</option>)char(\\n)content(<option value="28">28</option>)char(\\n)content(<option value="29">29</option>)char(\\n)content(<option value="30">30</option>)char(\\n)content(<option value="31">31</option>)char(\\n)content(<option value="32">32</option>)char(\\n)content(<option value="33">33</option>)char(\\n)content(<option value="34">34</option>)char(\\n)content(<option value="35">35</option>)char(\\n)content(<option value="36">36</option>)char(\\n)content(<option value="37">37</option>)char(\\n)content(<option value="38">38</option>)char(\\n)content(<option value="39">39</option>)char(\\n)content(<option value="40">40</option>)char(\\n)content(<option value="41">41</option>)char(\\n)content(<option value="42">42</option>)char(\\n)content(<option value="43">43</option>)char(\\n)content(<option value="44">44</option>)char(\\n)content(<option value="45">45</option>)char(\\n)content(<option value="46">46</option>)char(\\n)content(<option value="47">47</option>)char(\\n)content(<option value="48">48</option>)char(\\n)content(<option value="49">49</option>)char(\\n)content(<option value="50">50</option>)char(\\n)content(<option value="51">51</option>)char(\\n)content(<option value="52">52</option>)char(\\n)content(<option value="53">53</option>)char(\\n)content(<option value="54">54</option>)char(\\n)content(<option value="55">55</option>)char(\\n)content(<option value="56">56</option>)char(\\n)content(<option value="57">57</option>)char(\\n)content(<option value="58">58</option>)char(\\n)content(<option value="59">59</option>)char(\\n)delimiter(\))> + ident(expected) operator(<<) string<delimiter(")content(</select>)char(\\n)delimiter(")> + + ident(assert_equal) ident(expected)operator(,) ident(select_datetime)operator(()pre_constant(nil)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")content(date[first])delimiter(")>operator(\)) + reserved(end) + +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(FormHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormTagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + + ident(silence_warnings) reserved(do) + constant(Post) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:title)operator(,) symbol(:author_name)operator(,) symbol(:body)operator(,) symbol(:secret)operator(,) symbol(:written_on)operator(,) symbol(:cost)operator(\)) + constant(Post)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:title_before_type_cast)operator(,) symbol(:title) reserved(unless) ident(respond_to?)operator(()symbol(:title_before_type_cast)operator(\)) + ident(alias_method) symbol(:body_before_type_cast)operator(,) symbol(:body) reserved(unless) ident(respond_to?)operator(()symbol(:body_before_type_cast)operator(\)) + ident(alias_method) symbol(:author_name_before_type_cast)operator(,) symbol(:author_name) reserved(unless) ident(respond_to?)operator(()symbol(:author_name_before_type_cast)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(setup) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + reserved(def) instance_variable(@post)operator(.)ident(errors)operator(()operator(\)) constant(Class)operator(.)ident(new)operator({) reserved(def) method(on)operator(()ident(field)operator(\)) ident(field) operator(==) string<delimiter(")content(author_name)delimiter(")> reserved(end) operator(})operator(.)ident(new) reserved(end) + + reserved(def) instance_variable(@post)operator(.)ident(id)operator(;) integer(123)operator(;) reserved(end) + reserved(def) instance_variable(@post)operator(.)ident(id_before_type_cast)operator(;) integer(123)operator(;) reserved(end) + + instance_variable(@post)operator(.)ident(title) operator(=) string<delimiter(")content(Hello World)delimiter(")> + instance_variable(@post)operator(.)ident(author_name) operator(=) string<delimiter(")delimiter(")> + instance_variable(@post)operator(.)ident(body) operator(=) string<delimiter(")content(Back to the hill and over it again!)delimiter(")> + instance_variable(@post)operator(.)ident(secret) operator(=) integer(1) + instance_variable(@post)operator(.)ident(written_on) operator(=) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(6)operator(,) integer(15)operator(\)) + + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + ident(attr_reader) symbol(:url_for_options) + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + instance_variable(@url_for_options) operator(=) ident(options) + string<delimiter(")content(http://www.example.com)delimiter(")> + reserved(end) + reserved(end) + instance_variable(@controller) operator(=) instance_variable(@controller)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_text_field) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />)delimiter(')>operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="post_title" name="post[title]" size="30" type="password" value="Hello World" />)delimiter(')>operator(,) ident(password_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="person_name" name="person[name]" size="30" type="password" />)delimiter(')>operator(,) ident(password_field)operator(()string<delimiter(")content(person)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_field_with_escapes) + instance_variable(@post)operator(.)ident(title) operator(=) string<delimiter(")content(<b>Hello World</b>)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="post_title" name="post[title]" size="30" type="text" value="<b>Hello World</b>" />)delimiter(')>operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_field_with_options) + ident(expected) operator(=) string<delimiter(')content(<input id="post_title" name="post[title]" size="35" type="text" value="Hello World" />)delimiter(')> + ident(assert_dom_equal) ident(expected)operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(size)delimiter(")> operator(=)operator(>) integer(35)operator(\)) + ident(assert_dom_equal) ident(expected)operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) symbol(:size) operator(=)operator(>) integer(35)operator(\)) + reserved(end) + + reserved(def) method(test_text_field_assuming_size) + ident(expected) operator(=) string<delimiter(')content(<input id="post_title" maxlength="35" name="post[title]" size="35" type="text" value="Hello World" />)delimiter(')> + ident(assert_dom_equal) ident(expected)operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(maxlength)delimiter(")> operator(=)operator(>) integer(35)operator(\)) + ident(assert_dom_equal) ident(expected)operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) symbol(:maxlength) operator(=)operator(>) integer(35)operator(\)) + reserved(end) + + reserved(def) method(test_text_field_doesnt_change_param_values) + ident(object_name) operator(=) string<delimiter(')content(post[])delimiter(')> + ident(expected) operator(=) string<delimiter(')content(<input id="post_123_title" name="post[123][title]" size="30" type="text" value="Hello World" />)delimiter(')> + ident(assert_equal) ident(expected)operator(,) ident(text_field)operator(()ident(object_name)operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + ident(assert_equal) ident(object_name)operator(,) string<delimiter(")content(post[])delimiter(")> + reserved(end) + + reserved(def) method(test_check_box) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(\)) + operator(\)) + instance_variable(@post)operator(.)ident(secret) operator(=) integer(0) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")> operator(,)operator({)string<delimiter(")content(checked)delimiter(")>operator(=)operator(>)string<delimiter(")content(checked)delimiter(")>operator(})operator(\)) + operator(\)) + instance_variable(@post)operator(.)ident(secret) operator(=) pre_constant(true) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_check_box_with_explicit_checked_and_unchecked_values) + instance_variable(@post)operator(.)ident(secret) operator(=) string<delimiter(")content(on)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" /><input name="post[secret]" type="hidden" value="off" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) operator({)operator(})operator(,) string<delimiter(")content(on)delimiter(")>operator(,) string<delimiter(")content(off)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_radio_button) + ident(assert_dom_equal)operator(()string<delimiter(')content(<input checked="checked" id="post_title_hello_world" name="post[title]" type="radio" value="Hello World" />)delimiter(')>operator(,) + ident(radio_button)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Hello World)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(()string<delimiter(')content(<input id="post_title_goodbye_world" name="post[title]" type="radio" value="Goodbye World" />)delimiter(')>operator(,) + ident(radio_button)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Goodbye World)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_radio_button_is_checked_with_integers) + ident(assert_dom_equal)operator(()string<delimiter(')content(<input checked="checked" id="post_secret_1" name="post[secret]" type="radio" value="1" />)delimiter(')>operator(,) + ident(radio_button)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) string<delimiter(")content(1)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_area) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>)delimiter(')>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_area_with_escapes) + instance_variable(@post)operator(.)ident(body) operator(=) string<delimiter(")content(Back to <i>the</i> hill and over it again!)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(')content(<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to <i>the</i> hill and over it again!</textarea>)delimiter(')>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_text_area_with_alternate_value) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<textarea cols="40" id="post_body" name="post[body]" rows="20">Testing alternate values.</textarea>)delimiter(')>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) symbol(:value) operator(=)operator(>) string<delimiter(')content(Testing alternate values.)delimiter(')>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_date_selects) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>)delimiter(')>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_explicit_name) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="post_title" name="dont guess" size="30" type="text" value="Hello World" />)delimiter(')>operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(dont guess)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<textarea cols="40" id="post_body" name="really!" rows="20">Back to the hill and over it again!</textarea>)delimiter(')>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(really!)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input checked="checked" id="post_secret" name="i mean it" type="checkbox" value="1" /><input name="i mean it" type="hidden" value="0" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(i mean it)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(dont guess)delimiter(")>operator(\))operator(,) + ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(dont guess)delimiter(")>operator(\)) + ident(assert_dom_equal) ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(really!)delimiter(")>operator(\))operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(really!)delimiter(")>operator(\)) + ident(assert_dom_equal) ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(i mean it)delimiter(")>operator(\))operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(i mean it)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_explicit_id) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input id="dont guess" name="post[title]" size="30" type="text" value="Hello World" />)delimiter(')>operator(,) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) string<delimiter(")content(dont guess)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<textarea cols="40" id="really!" name="post[body]" rows="20">Back to the hill and over it again!</textarea>)delimiter(')>operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) string<delimiter(")content(really!)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(')content(<input checked="checked" id="i mean it" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />)delimiter(')>operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) string<delimiter(")content(i mean it)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal) ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) string<delimiter(")content(dont guess)delimiter(")>operator(\))operator(,) + ident(text_field)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")content(dont guess)delimiter(")>operator(\)) + ident(assert_dom_equal) ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) string<delimiter(")content(really!)delimiter(")>operator(\))operator(,) + ident(text_area)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")content(really!)delimiter(")>operator(\)) + ident(assert_dom_equal) ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) string<delimiter(")content(i mean it)delimiter(")>operator(\))operator(,) + ident(check_box)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")content(i mean it)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_auto_index) + ident(pid) operator(=) instance_variable(@post)operator(.)ident(id) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<input id=)char(\\")content(post_)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(_title)char(\\")content( name=)char(\\")content(post[)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(][title])char(\\")content( size=)char(\\")content(30)char(\\")content( type=)char(\\")content(text)char(\\")content( value=)char(\\")content(Hello World)char(\\")content( />)delimiter(")>operator(,) ident(text_field)operator(()string<delimiter(")content(post[])delimiter(")>operator(,)string<delimiter(")content(title)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<textarea cols=)char(\\")content(40)char(\\")content( id=)char(\\")content(post_)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(_body)char(\\")content( name=)char(\\")content(post[)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(][body])char(\\")content( rows=)char(\\")content(20)char(\\")content(>Back to the hill and over it again!</textarea>)delimiter(")>operator(,) + ident(text_area)operator(()string<delimiter(")content(post[])delimiter(")>operator(,) string<delimiter(")content(body)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<input checked=)char(\\")content(checked)char(\\")content( id=)char(\\")content(post_)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(_secret)char(\\")content( name=)char(\\")content(post[)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(][secret])char(\\")content( type=)char(\\")content(checkbox)char(\\")content( value=)char(\\")content(1)char(\\")content( /><input name=)char(\\")content(post[)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(][secret])char(\\")content( type=)char(\\")content(hidden)char(\\")content( value=)char(\\")content(0)char(\\")content( />)delimiter(")>operator(,) + ident(check_box)operator(()string<delimiter(")content(post[])delimiter(")>operator(,) string<delimiter(")content(secret)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() +string<delimiter(")content(<input checked=)char(\\")content(checked)char(\\")content( id=)char(\\")content(post_)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(_title_hello_world)char(\\")content( name=)char(\\")content(post[)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(][title])char(\\")content( type=)char(\\")content(radio)char(\\")content( value=)char(\\")content(Hello World)char(\\")content( />)delimiter(")>operator(,) + ident(radio_button)operator(()string<delimiter(")content(post[])delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Hello World)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(()string<delimiter(")content(<input id=)char(\\")content(post_)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(_title_goodbye_world)char(\\")content( name=)char(\\")content(post[)inline<inline_delimiter(#{)ident(pid)inline_delimiter(})>content(][title])char(\\")content( type=)char(\\")content(radio)char(\\")content( value=)char(\\")content(Goodbye World)char(\\")content( />)delimiter(")>operator(,) + ident(radio_button)operator(()string<delimiter(")content(post[])delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Goodbye World)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_form_for) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:html) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(')content(create-post)delimiter(')> operator(})operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<form action='http://www.example.com' id='create-post' method='post'>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />)delimiter(")> operator(+) + string<delimiter(")content(<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' />)delimiter(")> operator(+) + string<delimiter(")content(</form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_form_for_without_object) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) symbol(:html) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(')content(create-post)delimiter(')> operator(})operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<form action='http://www.example.com' id='create-post' method='post'>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />)delimiter(")> operator(+) + string<delimiter(")content(<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' />)delimiter(")> operator(+) + string<delimiter(")content(</form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_fields_for) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />)delimiter(")> operator(+) + string<delimiter(")content(<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' />)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_fields_for_without_object) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + ident(fields_for)operator(()symbol(:post)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />)delimiter(")> operator(+) + string<delimiter(")content(<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' />)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_form_builder_does_not_have_form_for_method) + ident(assert) operator(!) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormBuilder)operator(.)ident(instance_methods)operator(.)ident(include?)operator(()string<delimiter(')content(form_for)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_form_for_and_fields_for) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:html) operator(=)operator(>) operator({) symbol(:id) operator(=)operator(>) string<delimiter(')content(create-post)delimiter(')> operator(})operator(\)) reserved(do) operator(|)ident(post_form)operator(|) + ident(_erbout)operator(.)ident(concat) ident(post_form)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(post_form)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + + ident(fields_for)operator(()symbol(:parent_post)operator(,) instance_variable(@post)operator(\)) reserved(do) operator(|)ident(parent_fields)operator(|) + ident(_erbout)operator(.)ident(concat) ident(parent_fields)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<form action='http://www.example.com' id='create-post' method='post'>)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />)delimiter(")> operator(+) + string<delimiter(")content(<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>)delimiter(")> operator(+) + string<delimiter(")content(<input name='parent_post[secret]' checked='checked' type='checkbox' id='parent_post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='parent_post[secret]' type='hidden' value='0' />)delimiter(")> operator(+) + string<delimiter(")content(</form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(class) class(LabelledFormBuilder) operator(<) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormBuilder) + operator(()ident(field_helpers) operator(-) string<delimiter(%w()content(hidden_field)delimiter(\))>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(selector)operator(|) + ident(src) operator(=) string<delimiter(<<-END_SRC)>string<content( + def )inline<inline_delimiter(#{)ident(selector)inline_delimiter(})>content((field, *args, &proc\) + "<label for=')char(\\#)content({field}'>)char(\\#)content({field.to_s.humanize}:</label> " + super + "<br/>" + end)delimiter( + END_SRC)> + ident(class_eval) ident(src)operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__) + reserved(end) + reserved(end) + + reserved(def) method(test_form_for_with_labelled_builder) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:builder) operator(=)operator(>) constant(LabelledFormBuilder)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<form action='http://www.example.com' method='post'>)delimiter(")> operator(+) + string<delimiter(")content(<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>)delimiter(")> operator(+) + string<delimiter(")content(<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>)delimiter(")> operator(+) + string<delimiter(")content(<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' /><br/>)delimiter(")> operator(+) + string<delimiter(")content(</form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + comment(# Perhaps this test should be moved to prototype helper tests.) + reserved(def) method(test_remote_form_for_with_labelled_builder) + pre_constant(self)operator(.)ident(extend) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(PrototypeHelper) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(remote_form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:builder) operator(=)operator(>) constant(LabelledFormBuilder)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(%()content(<form action="http://www.example.com" onsubmit="new Ajax.Request)nesting_delimiter(()content('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;" method="post">)delimiter(\))> operator(+) + string<delimiter(")content(<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>)delimiter(")> operator(+) + string<delimiter(")content(<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>)delimiter(")> operator(+) + string<delimiter(")content(<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' /><br/>)delimiter(")> operator(+) + string<delimiter(")content(</form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_fields_for_with_labelled_builder) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:builder) operator(=)operator(>) constant(LabelledFormBuilder)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_field)operator(()symbol(:title)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(text_area)operator(()symbol(:body)operator(\)) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(check_box)operator(()symbol(:secret)operator(\)) + reserved(end) + + ident(expected) operator(=) + string<delimiter(")content(<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>)delimiter(")> operator(+) + string<delimiter(")content(<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>)delimiter(")> operator(+) + string<delimiter(")content(<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />)delimiter(")> operator(+) + string<delimiter(")content(<input name='post[secret]' type='hidden' value='0' /><br/>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_form_for_with_html_options_adds_options_to_form_tag) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:html) operator(=)operator(>) operator({)symbol(:id) operator(=)operator(>) string<delimiter(')content(some_form)delimiter(')>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(')content(some_class)delimiter(')>operator(})operator(\)) reserved(do) operator(|)ident(f)operator(|) reserved(end) + ident(expected) operator(=) string<delimiter(")content(<form action=)char(\\")content(http://www.example.com)char(\\")content( class=)char(\\")content(some_class)char(\\")content( id=)char(\\")content(some_form)char(\\")content( method=)char(\\")content(post)char(\\")content(></form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) + + reserved(def) method(test_form_for_with_string_url_option) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:url) operator(=)operator(>) string<delimiter(')content(http://www.otherdomain.com)delimiter(')>operator(\)) reserved(do) operator(|)ident(f)operator(|) reserved(end) + + ident(assert_equal) string<delimiter(')content(http://www.otherdomain.com)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(url_for_options) + reserved(end) + + reserved(def) method(test_form_for_with_hash_url_option) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:url) operator(=)operator(>) operator({)symbol(:controller) operator(=)operator(>) string<delimiter(')content(controller)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(')content(action)delimiter(')>operator(})operator(\)) reserved(do) operator(|)ident(f)operator(|) reserved(end) + + ident(assert_equal) string<delimiter(')content(controller)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(url_for_options)operator([)symbol(:controller)operator(]) + ident(assert_equal) string<delimiter(')content(action)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(url_for_options)operator([)symbol(:action)operator(]) + reserved(end) + + reserved(def) method(test_remote_form_for_with_html_options_adds_options_to_form_tag) + pre_constant(self)operator(.)ident(extend) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(PrototypeHelper) + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(remote_form_for)operator(()symbol(:post)operator(,) instance_variable(@post)operator(,) symbol(:html) operator(=)operator(>) operator({)symbol(:id) operator(=)operator(>) string<delimiter(')content(some_form)delimiter(')>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(')content(some_class)delimiter(')>operator(})operator(\)) reserved(do) operator(|)ident(f)operator(|) reserved(end) + ident(expected) operator(=) string<delimiter(")content(<form action=)char(\\")content(http://www.example.com)char(\\")content( class=)char(\\")content(some_class)char(\\")content( id=)char(\\")content(some_form)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this\)}\); return false;)char(\\")content(></form>)delimiter(")> + + ident(assert_dom_equal) ident(expected)operator(,) ident(_erbout) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(MockTimeZone) + ident(attr_reader) symbol(:name) + + reserved(def) method(initialize)operator(() ident(name) operator(\)) + instance_variable(@name) operator(=) ident(name) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(all) + operator([) string<delimiter(")content(A)delimiter(")>operator(,) string<delimiter(")content(B)delimiter(")>operator(,) string<delimiter(")content(C)delimiter(")>operator(,) string<delimiter(")content(D)delimiter(")>operator(,) string<delimiter(")content(E)delimiter(")> operator(])operator(.)ident(map) operator({) operator(|)ident(s)operator(|) ident(new) ident(s) operator(}) + reserved(end) + + reserved(def) method(==)operator(() ident(z) operator(\)) + ident(z) operator(&&) instance_variable(@name) operator(==) ident(z)operator(.)ident(name) + reserved(end) + + reserved(def) method(to_s) + instance_variable(@name) + reserved(end) +reserved(end) + +constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormOptionsHelper)operator(::)constant(TimeZone) operator(=) constant(MockTimeZone) + +reserved(class) class(FormOptionsHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormOptionsHelper) + + ident(silence_warnings) reserved(do) + constant(Post) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(')content(Post)delimiter(')>operator(,) symbol(:title)operator(,) symbol(:author_name)operator(,) symbol(:body)operator(,) symbol(:secret)operator(,) symbol(:written_on)operator(,) symbol(:category)operator(,) symbol(:origin)operator(\)) + constant(Continent) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(')content(Continent)delimiter(')>operator(,) symbol(:continent_name)operator(,) symbol(:countries)operator(\)) + constant(Country) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(')content(Country)delimiter(')>operator(,) symbol(:country_id)operator(,) symbol(:country_name)operator(\)) + constant(Firm) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(')content(Firm)delimiter(')>operator(,) symbol(:time_zone)operator(\)) + reserved(end) + + reserved(def) method(test_collection_options) + instance_variable(@posts) operator(=) operator([) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(<Abe> went home)delimiter(")>operator(,) string<delimiter(")content(<Abe>)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Babe went home)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Cabe went home)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\)) + operator(]) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Abe>)char(\\")content(><Abe> went home</option>)char(\\n)content(<option value=)char(\\")content(Babe)char(\\")content(>Babe went home</option>)char(\\n)content(<option value=)char(\\")content(Cabe)char(\\")content(>Cabe went home</option>)delimiter(")>operator(,) + ident(options_from_collection_for_select)operator(()instance_variable(@posts)operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + + reserved(def) method(test_collection_options_with_preselected_value) + instance_variable(@posts) operator(=) operator([) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(<Abe> went home)delimiter(")>operator(,) string<delimiter(")content(<Abe>)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Babe went home)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Cabe went home)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\)) + operator(]) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Abe>)char(\\")content(><Abe> went home</option>)char(\\n)content(<option value=)char(\\")content(Babe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Babe went home</option>)char(\\n)content(<option value=)char(\\")content(Cabe)char(\\")content(>Cabe went home</option>)delimiter(")>operator(,) + ident(options_from_collection_for_select)operator(()instance_variable(@posts)operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_collection_options_with_preselected_value_array) + instance_variable(@posts) operator(=) operator([) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(<Abe> went home)delimiter(")>operator(,) string<delimiter(")content(<Abe>)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Babe went home)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Cabe went home)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\)) + operator(]) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Abe>)char(\\")content(><Abe> went home</option>)char(\\n)content(<option value=)char(\\")content(Babe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Babe went home</option>)char(\\n)content(<option value=)char(\\")content(Cabe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Cabe went home</option>)delimiter(")>operator(,) + ident(options_from_collection_for_select)operator(()instance_variable(@posts)operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")>operator(,) operator([) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")> operator(])operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_array_options_for_select) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Denmark>)char(\\")content(><Denmark></option>)char(\\n)content(<option value=)char(\\")content(USA)char(\\")content(>USA</option>)char(\\n)content(<option value=)char(\\")content(Sweden)char(\\")content(>Sweden</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([) string<delimiter(")content(<Denmark>)delimiter(")>operator(,) string<delimiter(")content(USA)delimiter(")>operator(,) string<delimiter(")content(Sweden)delimiter(")> operator(])operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_array_options_for_select_with_selection) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(Denmark)char(\\")content(>Denmark</option>)char(\\n)content(<option value=)char(\\")content(<USA>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><USA></option>)char(\\n)content(<option value=)char(\\")content(Sweden)char(\\")content(>Sweden</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([) string<delimiter(")content(Denmark)delimiter(")>operator(,) string<delimiter(")content(<USA>)delimiter(")>operator(,) string<delimiter(")content(Sweden)delimiter(")> operator(])operator(,) string<delimiter(")content(<USA>)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_array_options_for_select_with_selection_array) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(Denmark)char(\\")content(>Denmark</option>)char(\\n)content(<option value=)char(\\")content(<USA>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><USA></option>)char(\\n)content(<option value=)char(\\")content(Sweden)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Sweden</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([) string<delimiter(")content(Denmark)delimiter(")>operator(,) string<delimiter(")content(<USA>)delimiter(")>operator(,) string<delimiter(")content(Sweden)delimiter(")> operator(])operator(,) operator([) string<delimiter(")content(<USA>)delimiter(")>operator(,) string<delimiter(")content(Sweden)delimiter(")> operator(])operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_array_options_for_string_include_in_other_string_bug_fix) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(ruby)char(\\")content(>ruby</option>)char(\\n)content(<option value=)char(\\")content(rubyonrails)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>rubyonrails</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([) string<delimiter(")content(ruby)delimiter(")>operator(,) string<delimiter(")content(rubyonrails)delimiter(")> operator(])operator(,) string<delimiter(")content(rubyonrails)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(ruby)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>ruby</option>)char(\\n)content(<option value=)char(\\")content(rubyonrails)char(\\")content(>rubyonrails</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([) string<delimiter(")content(ruby)delimiter(")>operator(,) string<delimiter(")content(rubyonrails)delimiter(")> operator(])operator(,) string<delimiter(")content(ruby)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_hash_options_for_select) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Kroner>)char(\\")content(><DKR></option>)char(\\n)content(<option value=)char(\\")content(Dollar)char(\\")content(>$</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator({) string<delimiter(")content($)delimiter(")> operator(=)operator(>) string<delimiter(")content(Dollar)delimiter(")>operator(,) string<delimiter(")content(<DKR>)delimiter(")> operator(=)operator(>) string<delimiter(")content(<Kroner>)delimiter(")> operator(})operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Kroner>)char(\\")content(><DKR></option>)char(\\n)content(<option value=)char(\\")content(Dollar)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>$</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator({) string<delimiter(")content($)delimiter(")> operator(=)operator(>) string<delimiter(")content(Dollar)delimiter(")>operator(,) string<delimiter(")content(<DKR>)delimiter(")> operator(=)operator(>) string<delimiter(")content(<Kroner>)delimiter(")> operator(})operator(,) string<delimiter(")content(Dollar)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Kroner>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><DKR></option>)char(\\n)content(<option value=)char(\\")content(Dollar)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>$</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator({) string<delimiter(")content($)delimiter(")> operator(=)operator(>) string<delimiter(")content(Dollar)delimiter(")>operator(,) string<delimiter(")content(<DKR>)delimiter(")> operator(=)operator(>) string<delimiter(")content(<Kroner>)delimiter(")> operator(})operator(,) operator([) string<delimiter(")content(Dollar)delimiter(")>operator(,) string<delimiter(")content(<Kroner>)delimiter(")> operator(])operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_ducktyped_options_for_select) + ident(quack) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:first)operator(,) symbol(:last)operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Kroner>)char(\\")content(><DKR></option>)char(\\n)content(<option value=)char(\\")content(Dollar)char(\\")content(>$</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([)ident(quack)operator(.)ident(new)operator(()string<delimiter(")content(<DKR>)delimiter(")>operator(,) string<delimiter(")content(<Kroner>)delimiter(")>operator(\))operator(,) ident(quack)operator(.)ident(new)operator(()string<delimiter(")content($)delimiter(")>operator(,) string<delimiter(")content(Dollar)delimiter(")>operator(\))operator(])operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Kroner>)char(\\")content(><DKR></option>)char(\\n)content(<option value=)char(\\")content(Dollar)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>$</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([)ident(quack)operator(.)ident(new)operator(()string<delimiter(")content(<DKR>)delimiter(")>operator(,) string<delimiter(")content(<Kroner>)delimiter(")>operator(\))operator(,) ident(quack)operator(.)ident(new)operator(()string<delimiter(")content($)delimiter(")>operator(,) string<delimiter(")content(Dollar)delimiter(")>operator(\))operator(])operator(,) string<delimiter(")content(Dollar)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<option value=)char(\\")content(<Kroner>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><DKR></option>)char(\\n)content(<option value=)char(\\")content(Dollar)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>$</option>)delimiter(")>operator(,) + ident(options_for_select)operator(()operator([)ident(quack)operator(.)ident(new)operator(()string<delimiter(")content(<DKR>)delimiter(")>operator(,) string<delimiter(")content(<Kroner>)delimiter(")>operator(\))operator(,) ident(quack)operator(.)ident(new)operator(()string<delimiter(")content($)delimiter(")>operator(,) string<delimiter(")content(Dollar)delimiter(")>operator(\))operator(])operator(,) operator([)string<delimiter(")content(Dollar)delimiter(")>operator(,) string<delimiter(")content(<Kroner>)delimiter(")>operator(])operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_html_option_groups_from_collection) + instance_variable(@continents) operator(=) operator([) + constant(Continent)operator(.)ident(new)operator(()string<delimiter(")content(<Africa>)delimiter(")>operator(,) operator([)constant(Country)operator(.)ident(new)operator(()string<delimiter(")content(<sa>)delimiter(")>operator(,) string<delimiter(")content(<South Africa>)delimiter(")>operator(\))operator(,) constant(Country)operator(.)ident(new)operator(()string<delimiter(")content(so)delimiter(")>operator(,) string<delimiter(")content(Somalia)delimiter(")>operator(\))operator(]) operator(\))operator(,) + constant(Continent)operator(.)ident(new)operator(()string<delimiter(")content(Europe)delimiter(")>operator(,) operator([)constant(Country)operator(.)ident(new)operator(()string<delimiter(")content(dk)delimiter(")>operator(,) string<delimiter(")content(Denmark)delimiter(")>operator(\))operator(,) constant(Country)operator(.)ident(new)operator(()string<delimiter(")content(ie)delimiter(")>operator(,) string<delimiter(")content(Ireland)delimiter(")>operator(\))operator(]) operator(\)) + operator(]) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<optgroup label=)char(\\")content(<Africa>)char(\\")content(><option value=)char(\\")content(<sa>)char(\\")content(><South Africa></option>)char(\\n)content(<option value=)char(\\")content(so)char(\\")content(>Somalia</option></optgroup><optgroup label=)char(\\")content(Europe)char(\\")content(><option value=)char(\\")content(dk)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Denmark</option>)char(\\n)content(<option value=)char(\\")content(ie)char(\\")content(>Ireland</option></optgroup>)delimiter(")>operator(,) + ident(option_groups_from_collection_for_select)operator(()instance_variable(@continents)operator(,) string<delimiter(")content(countries)delimiter(")>operator(,) string<delimiter(")content(continent_name)delimiter(")>operator(,) string<delimiter(")content(country_id)delimiter(")>operator(,) string<delimiter(")content(country_name)delimiter(")>operator(,) string<delimiter(")content(dk)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_time_zone_options_no_parms) + ident(opts) operator(=) ident(time_zone_options_for_select) + ident(assert_dom_equal) string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")>operator(,) + ident(opts) + reserved(end) + + reserved(def) method(test_time_zone_options_with_selected) + ident(opts) operator(=) ident(time_zone_options_for_select)operator(() string<delimiter(")content(D)delimiter(")> operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")>operator(,) + ident(opts) + reserved(end) + + reserved(def) method(test_time_zone_options_with_unknown_selected) + ident(opts) operator(=) ident(time_zone_options_for_select)operator(() string<delimiter(")content(K)delimiter(")> operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")>operator(,) + ident(opts) + reserved(end) + + reserved(def) method(test_time_zone_options_with_priority_zones) + ident(zones) operator(=) operator([) constant(TimeZone)operator(.)ident(new)operator(() string<delimiter(")content(B)delimiter(")> operator(\))operator(,) constant(TimeZone)operator(.)ident(new)operator(() string<delimiter(")content(E)delimiter(")> operator(\)) operator(]) + ident(opts) operator(=) ident(time_zone_options_for_select)operator(() pre_constant(nil)operator(,) ident(zones) operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")char(\\")content(>-------------</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content(>D</option>)delimiter(")>operator(,) + ident(opts) + reserved(end) + + reserved(def) method(test_time_zone_options_with_selected_priority_zones) + ident(zones) operator(=) operator([) constant(TimeZone)operator(.)ident(new)operator(() string<delimiter(")content(B)delimiter(")> operator(\))operator(,) constant(TimeZone)operator(.)ident(new)operator(() string<delimiter(")content(E)delimiter(")> operator(\)) operator(]) + ident(opts) operator(=) ident(time_zone_options_for_select)operator(() string<delimiter(")content(E)delimiter(")>operator(,) ident(zones) operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")char(\\")content(>-------------</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content(>D</option>)delimiter(")>operator(,) + ident(opts) + reserved(end) + + reserved(def) method(test_time_zone_options_with_unselected_priority_zones) + ident(zones) operator(=) operator([) constant(TimeZone)operator(.)ident(new)operator(() string<delimiter(")content(B)delimiter(")> operator(\))operator(,) constant(TimeZone)operator(.)ident(new)operator(() string<delimiter(")content(E)delimiter(")> operator(\)) operator(]) + ident(opts) operator(=) ident(time_zone_options_for_select)operator(() string<delimiter(")content(C)delimiter(")>operator(,) ident(zones) operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")char(\\")content(>-------------</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content(>D</option>)delimiter(")>operator(,) + ident(opts) + reserved(end) + + reserved(def) method(test_select) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")content(<mus>)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_under_fields_for) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")content(<mus>)delimiter(")> + + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for) symbol(:post)operator(,) instance_variable(@post) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(select)operator(()symbol(:category)operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(\)) + reserved(end) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(_erbout) + operator(\)) + reserved(end) + + reserved(def) method(test_select_with_blank) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")content(<mus>)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")char(\\")content(></option>)char(\\n)content(<option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_with_default_prompt) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")char(\\")content(>Please select</option>)char(\\n)content(<option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(,) symbol(:prompt) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_no_prompt_when_select_has_value) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")content(<mus>)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content( selected=)char(\\")content(selected)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(,) symbol(:prompt) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_with_given_prompt) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")char(\\")content(>The prompt</option>)char(\\n)content(<option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(,) symbol(:prompt) operator(=)operator(>) string<delimiter(')content(The prompt)delimiter(')>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_with_prompt_and_blank) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")char(\\")content(>Please select</option>)char(\\n)content(<option value=)char(\\")char(\\")content(></option>)char(\\n)content(<option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest)delimiter(\))>operator(,) symbol(:prompt) operator(=)operator(>) pre_constant(true)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_with_selected_value) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")content(<mus>)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")content(abe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest )delimiter(\))>operator(,) symbol(:selected) operator(=)operator(>) string<delimiter(')content(abe)delimiter(')>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_select_with_selected_nil) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(category) operator(=) string<delimiter(")content(<mus>)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_category)char(\\")content( name=)char(\\")content(post[category])char(\\")content(><option value=)char(\\")content(abe)char(\\")content(>abe</option>)char(\\n)content(<option value=)char(\\")content(<mus>)char(\\")content(><mus></option>)char(\\n)content(<option value=)char(\\")content(hest)char(\\")content(>hest</option></select>)delimiter(")>operator(,) + ident(select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(category)delimiter(")>operator(,) string<delimiter(%w()content( abe <mus> hest )delimiter(\))>operator(,) symbol(:selected) operator(=)operator(>) pre_constant(nil)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_collection_select) + instance_variable(@posts) operator(=) operator([) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(<Abe> went home)delimiter(")>operator(,) string<delimiter(")content(<Abe>)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Babe went home)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Cabe went home)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\)) + operator(]) + + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(author_name) operator(=) string<delimiter(")content(Babe)delimiter(")> + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_author_name)char(\\")content( name=)char(\\")content(post[author_name])char(\\")content(><option value=)char(\\")content(<Abe>)char(\\")content(><Abe></option>)char(\\n)content(<option value=)char(\\")content(Babe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Babe</option>)char(\\n)content(<option value=)char(\\")content(Cabe)char(\\")content(>Cabe</option></select>)delimiter(")>operator(,) + ident(collection_select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) instance_variable(@posts)operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) string<delimiter(")content(author_name)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_collection_select_under_fields_for) + instance_variable(@posts) operator(=) operator([) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(<Abe> went home)delimiter(")>operator(,) string<delimiter(")content(<Abe>)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Babe went home)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Cabe went home)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\)) + operator(]) + + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(author_name) operator(=) string<delimiter(")content(Babe)delimiter(")> + + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for) symbol(:post)operator(,) instance_variable(@post) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(collection_select)operator(()symbol(:author_name)operator(,) instance_variable(@posts)operator(,) symbol(:author_name)operator(,) symbol(:author_name)operator(\)) + reserved(end) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_author_name)char(\\")content( name=)char(\\")content(post[author_name])char(\\")content(><option value=)char(\\")content(<Abe>)char(\\")content(><Abe></option>)char(\\n)content(<option value=)char(\\")content(Babe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Babe</option>)char(\\n)content(<option value=)char(\\")content(Cabe)char(\\")content(>Cabe</option></select>)delimiter(")>operator(,) + ident(_erbout) + operator(\)) + reserved(end) + + reserved(def) method(test_collection_select_with_blank_and_style) + instance_variable(@posts) operator(=) operator([) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(<Abe> went home)delimiter(")>operator(,) string<delimiter(")content(<Abe>)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Babe went home)delimiter(")>operator(,) string<delimiter(")content(Babe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\))operator(,) + constant(Post)operator(.)ident(new)operator(()string<delimiter(")content(Cabe went home)delimiter(")>operator(,) string<delimiter(")content(Cabe)delimiter(")>operator(,) string<delimiter(")content(To a little house)delimiter(")>operator(,) string<delimiter(")content(shh!)delimiter(")>operator(\)) + operator(]) + + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(author_name) operator(=) string<delimiter(")content(Babe)delimiter(")> + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_author_name)char(\\")content( name=)char(\\")content(post[author_name])char(\\")content( style=)char(\\")content(width: 200px)char(\\")content(><option value=)char(\\")char(\\")content(></option>)char(\\n)content(<option value=)char(\\")content(<Abe>)char(\\")content(><Abe></option>)char(\\n)content(<option value=)char(\\")content(Babe)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Babe</option>)char(\\n)content(<option value=)char(\\")content(Cabe)char(\\")content(>Cabe</option></select>)delimiter(")>operator(,) + ident(collection_select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) instance_variable(@posts)operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) string<delimiter(")content(author_name)delimiter(")>operator(,) operator({) symbol(:include_blank) operator(=)operator(>) pre_constant(true) operator(})operator(,) string<delimiter(")content(style)delimiter(")> operator(=)operator(>) string<delimiter(")content(width: 200px)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_country_select) + instance_variable(@post) operator(=) constant(Post)operator(.)ident(new) + instance_variable(@post)operator(.)ident(origin) operator(=) string<delimiter(")content(Denmark)delimiter(")> + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(post_origin)char(\\")content( name=)char(\\")content(post[origin])char(\\")content(><option value=)char(\\")content(Afghanistan)char(\\")content(>Afghanistan</option>)char(\\n)content(<option value=)char(\\")content(Albania)char(\\")content(>Albania</option>)char(\\n)content(<option value=)char(\\")content(Algeria)char(\\")content(>Algeria</option>)char(\\n)content(<option value=)char(\\")content(American Samoa)char(\\")content(>American Samoa</option>)char(\\n)content(<option value=)char(\\")content(Andorra)char(\\")content(>Andorra</option>)char(\\n)content(<option value=)char(\\")content(Angola)char(\\")content(>Angola</option>)char(\\n)content(<option value=)char(\\")content(Anguilla)char(\\")content(>Anguilla</option>)char(\\n)content(<option value=)char(\\")content(Antarctica)char(\\")content(>Antarctica</option>)char(\\n)content(<option value=)char(\\")content(Antigua And Barbuda)char(\\")content(>Antigua And Barbuda</option>)char(\\n)content(<option value=)char(\\")content(Argentina)char(\\")content(>Argentina</option>)char(\\n)content(<option value=)char(\\")content(Armenia)char(\\")content(>Armenia</option>)char(\\n)content(<option value=)char(\\")content(Aruba)char(\\")content(>Aruba</option>)char(\\n)content(<option value=)char(\\")content(Australia)char(\\")content(>Australia</option>)char(\\n)content(<option value=)char(\\")content(Austria)char(\\")content(>Austria</option>)char(\\n)content(<option value=)char(\\")content(Azerbaijan)char(\\")content(>Azerbaijan</option>)char(\\n)content(<option value=)char(\\")content(Bahamas)char(\\")content(>Bahamas</option>)char(\\n)content(<option value=)char(\\")content(Bahrain)char(\\")content(>Bahrain</option>)char(\\n)content(<option value=)char(\\")content(Bangladesh)char(\\")content(>Bangladesh</option>)char(\\n)content(<option value=)char(\\")content(Barbados)char(\\")content(>Barbados</option>)char(\\n)content(<option value=)char(\\")content(Belarus)char(\\")content(>Belarus</option>)char(\\n)content(<option value=)char(\\")content(Belgium)char(\\")content(>Belgium</option>)char(\\n)content(<option value=)char(\\")content(Belize)char(\\")content(>Belize</option>)char(\\n)content(<option value=)char(\\")content(Benin)char(\\")content(>Benin</option>)char(\\n)content(<option value=)char(\\")content(Bermuda)char(\\")content(>Bermuda</option>)char(\\n)content(<option value=)char(\\")content(Bhutan)char(\\")content(>Bhutan</option>)char(\\n)content(<option value=)char(\\")content(Bolivia)char(\\")content(>Bolivia</option>)char(\\n)content(<option value=)char(\\")content(Bosnia and Herzegowina)char(\\")content(>Bosnia and Herzegowina</option>)char(\\n)content(<option value=)char(\\")content(Botswana)char(\\")content(>Botswana</option>)char(\\n)content(<option value=)char(\\")content(Bouvet Island)char(\\")content(>Bouvet Island</option>)char(\\n)content(<option value=)char(\\")content(Brazil)char(\\")content(>Brazil</option>)char(\\n)content(<option value=)char(\\")content(British Indian Ocean Territory)char(\\")content(>British Indian Ocean Territory</option>)char(\\n)content(<option value=)char(\\")content(Brunei Darussalam)char(\\")content(>Brunei Darussalam</option>)char(\\n)content(<option value=)char(\\")content(Bulgaria)char(\\")content(>Bulgaria</option>)char(\\n)content(<option value=)char(\\")content(Burkina Faso)char(\\")content(>Burkina Faso</option>)char(\\n)content(<option value=)char(\\")content(Burma)char(\\")content(>Burma</option>)char(\\n)content(<option value=)char(\\")content(Burundi)char(\\")content(>Burundi</option>)char(\\n)content(<option value=)char(\\")content(Cambodia)char(\\")content(>Cambodia</option>)char(\\n)content(<option value=)char(\\")content(Cameroon)char(\\")content(>Cameroon</option>)char(\\n)content(<option value=)char(\\")content(Canada)char(\\")content(>Canada</option>)char(\\n)content(<option value=)char(\\")content(Cape Verde)char(\\")content(>Cape Verde</option>)char(\\n)content(<option value=)char(\\")content(Cayman Islands)char(\\")content(>Cayman Islands</option>)char(\\n)content(<option value=)char(\\")content(Central African Republic)char(\\")content(>Central African Republic</option>)char(\\n)content(<option value=)char(\\")content(Chad)char(\\")content(>Chad</option>)char(\\n)content(<option value=)char(\\")content(Chile)char(\\")content(>Chile</option>)char(\\n)content(<option value=)char(\\")content(China)char(\\")content(>China</option>)char(\\n)content(<option value=)char(\\")content(Christmas Island)char(\\")content(>Christmas Island</option>)char(\\n)content(<option value=)char(\\")content(Cocos (Keeling\) Islands)char(\\")content(>Cocos (Keeling\) Islands</option>)char(\\n)content(<option value=)char(\\")content(Colombia)char(\\")content(>Colombia</option>)char(\\n)content(<option value=)char(\\")content(Comoros)char(\\")content(>Comoros</option>)char(\\n)content(<option value=)char(\\")content(Congo)char(\\")content(>Congo</option>)char(\\n)content(<option value=)char(\\")content(Congo, the Democratic Republic of the)char(\\")content(>Congo, the Democratic Republic of the</option>)char(\\n)content(<option value=)char(\\")content(Cook Islands)char(\\")content(>Cook Islands</option>)char(\\n)content(<option value=)char(\\")content(Costa Rica)char(\\")content(>Costa Rica</option>)char(\\n)content(<option value=)char(\\")content(Cote d'Ivoire)char(\\")content(>Cote d'Ivoire</option>)char(\\n)content(<option value=)char(\\")content(Croatia)char(\\")content(>Croatia</option>)char(\\n)content(<option value=)char(\\")content(Cuba)char(\\")content(>Cuba</option>)char(\\n)content(<option value=)char(\\")content(Cyprus)char(\\")content(>Cyprus</option>)char(\\n)content(<option value=)char(\\")content(Czech Republic)char(\\")content(>Czech Republic</option>)char(\\n)content(<option value=)char(\\")content(Denmark)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>Denmark</option>)char(\\n)content(<option value=)char(\\")content(Djibouti)char(\\")content(>Djibouti</option>)char(\\n)content(<option value=)char(\\")content(Dominica)char(\\")content(>Dominica</option>)char(\\n)content(<option value=)char(\\")content(Dominican Republic)char(\\")content(>Dominican Republic</option>)char(\\n)content(<option value=)char(\\")content(East Timor)char(\\")content(>East Timor</option>)char(\\n)content(<option value=)char(\\")content(Ecuador)char(\\")content(>Ecuador</option>)char(\\n)content(<option value=)char(\\")content(Egypt)char(\\")content(>Egypt</option>)char(\\n)content(<option value=)char(\\")content(El Salvador)char(\\")content(>El Salvador</option>)char(\\n)content(<option value=)char(\\")content(England)char(\\")content(>England)delimiter(")> operator(+) + string<delimiter(")content(</option>)char(\\n)content(<option value=)char(\\")content(Equatorial Guinea)char(\\")content(>Equatorial Guinea</option>)char(\\n)content(<option value=)char(\\")content(Eritrea)char(\\")content(>Eritrea</option>)char(\\n)content(<option value=)char(\\")content(Espana)char(\\")content(>Espana</option>)char(\\n)content(<option value=)char(\\")content(Estonia)char(\\")content(>Estonia</option>)char(\\n)content(<option value=)char(\\")content(Ethiopia)char(\\")content(>Ethiopia</option>)char(\\n)content(<option value=)char(\\")content(Falkland Islands)char(\\")content(>Falkland Islands</option>)char(\\n)content(<option value=)char(\\")content(Faroe Islands)char(\\")content(>Faroe Islands</option>)char(\\n)content(<option value=)char(\\")content(Fiji)char(\\")content(>Fiji</option>)char(\\n)content(<option value=)char(\\")content(Finland)char(\\")content(>Finland</option>)char(\\n)content(<option value=)char(\\")content(France)char(\\")content(>France</option>)char(\\n)content(<option value=)char(\\")content(French Guiana)char(\\")content(>French Guiana</option>)char(\\n)content(<option value=)char(\\")content(French Polynesia)char(\\")content(>French Polynesia</option>)char(\\n)content(<option value=)char(\\")content(French Southern Territories)char(\\")content(>French Southern Territories</option>)char(\\n)content(<option value=)char(\\")content(Gabon)char(\\")content(>Gabon</option>)char(\\n)content(<option value=)char(\\")content(Gambia)char(\\")content(>Gambia</option>)char(\\n)content(<option value=)char(\\")content(Georgia)char(\\")content(>Georgia</option>)char(\\n)content(<option value=)char(\\")content(Germany)char(\\")content(>Germany</option>)char(\\n)content(<option value=)char(\\")content(Ghana)char(\\")content(>Ghana</option>)char(\\n)content(<option value=)char(\\")content(Gibraltar)char(\\")content(>Gibraltar</option>)char(\\n)content(<option value=)char(\\")content(Great Britain)char(\\")content(>Great Britain</option>)char(\\n)content(<option value=)char(\\")content(Greece)char(\\")content(>Greece</option>)char(\\n)content(<option value=)char(\\")content(Greenland)char(\\")content(>Greenland</option>)char(\\n)content(<option value=)char(\\")content(Grenada)char(\\")content(>Grenada</option>)char(\\n)content(<option value=)char(\\")content(Guadeloupe)char(\\")content(>Guadeloupe</option>)char(\\n)content(<option value=)char(\\")content(Guam)char(\\")content(>Guam</option>)char(\\n)content(<option value=)char(\\")content(Guatemala)char(\\")content(>Guatemala</option>)char(\\n)content(<option value=)char(\\")content(Guinea)char(\\")content(>Guinea</option>)char(\\n)content(<option value=)char(\\")content(Guinea-Bissau)char(\\")content(>Guinea-Bissau</option>)char(\\n)content(<option value=)char(\\")content(Guyana)char(\\")content(>Guyana</option>)char(\\n)content(<option value=)char(\\")content(Haiti)char(\\")content(>Haiti</option>)char(\\n)content(<option value=)char(\\")content(Heard and Mc Donald Islands)char(\\")content(>Heard and Mc Donald Islands</option>)char(\\n)content(<option value=)char(\\")content(Honduras)char(\\")content(>Honduras</option>)char(\\n)content(<option value=)char(\\")content(Hong Kong)char(\\")content(>Hong Kong</option>)char(\\n)content(<option value=)char(\\")content(Hungary)char(\\")content(>Hungary</option>)char(\\n)content(<option value=)char(\\")content(Iceland)char(\\")content(>Iceland</option>)char(\\n)content(<option value=)char(\\")content(India)char(\\")content(>India</option>)char(\\n)content(<option value=)char(\\")content(Indonesia)char(\\")content(>Indonesia</option>)char(\\n)content(<option value=)char(\\")content(Ireland)char(\\")content(>Ireland</option>)char(\\n)content(<option value=)char(\\")content(Israel)char(\\")content(>Israel</option>)char(\\n)content(<option value=)char(\\")content(Italy)char(\\")content(>Italy</option>)char(\\n)content(<option value=)char(\\")content(Iran)char(\\")content(>Iran</option>)char(\\n)content(<option value=)char(\\")content(Iraq)char(\\")content(>Iraq</option>)char(\\n)content(<option value=)char(\\")content(Jamaica)char(\\")content(>Jamaica</option>)char(\\n)content(<option value=)char(\\")content(Japan)char(\\")content(>Japan</option>)char(\\n)content(<option value=)char(\\")content(Jordan)char(\\")content(>Jordan</option>)char(\\n)content(<option value=)char(\\")content(Kazakhstan)char(\\")content(>Kazakhstan</option>)char(\\n)content(<option value=)char(\\")content(Kenya)char(\\")content(>Kenya</option>)char(\\n)content(<option value=)char(\\")content(Kiribati)char(\\")content(>Kiribati</option>)char(\\n)content(<option value=)char(\\")content(Korea, Republic of)char(\\")content(>Korea, Republic of</option>)char(\\n)content(<option value=)char(\\")content(Korea (South\))char(\\")content(>Korea (South\)</option>)char(\\n)content(<option value=)char(\\")content(Kuwait)char(\\")content(>Kuwait</option>)char(\\n)content(<option value=)char(\\")content(Kyrgyzstan)char(\\")content(>Kyrgyzstan</option>)char(\\n)content(<option value=)char(\\")content(Lao People's Democratic Republic)char(\\")content(>Lao People's Democratic Republic</option>)char(\\n)content(<option value=)char(\\")content(Latvia)char(\\")content(>Latvia</option>)char(\\n)content(<option value=)char(\\")content(Lebanon)char(\\")content(>Lebanon</option>)char(\\n)content(<option value=)char(\\")content(Lesotho)char(\\")content(>Lesotho</option>)char(\\n)content(<option value=)char(\\")content(Liberia)char(\\")content(>Liberia</option>)char(\\n)content(<option value=)char(\\")content(Liechtenstein)char(\\")content(>Liechtenstein</option>)char(\\n)content(<option value=)char(\\")content(Lithuania)char(\\")content(>Lithuania</option>)char(\\n)content(<option value=)char(\\")content(Luxembourg)char(\\")content(>Luxembourg</option>)char(\\n)content(<option value=)char(\\")content(Macau)char(\\")content(>Macau</option>)char(\\n)content(<option value=)char(\\")content(Macedonia)char(\\")content(>Macedonia</option>)char(\\n)content(<option value=)char(\\")content(Madagascar)char(\\")content(>Madagascar</option>)char(\\n)content(<option value=)char(\\")content(Malawi)char(\\")content(>Malawi</option>)char(\\n)content(<option value=)char(\\")content(Malaysia)char(\\")content(>Malaysia</option>)char(\\n)content(<option value=)char(\\")content(Maldives)char(\\")content(>Maldives</option>)char(\\n)content(<option value=)char(\\")content(Mali)char(\\")content(>Mali</option>)char(\\n)content(<option value=)char(\\")content(Malta)char(\\")content(>Malta</option>)char(\\n)content(<option value=)char(\\")content(Marshall Islands)char(\\")content(>Marshall Islands</option>)char(\\n)content(<option value=)char(\\")content(Martinique)char(\\")content(>Martinique</option>)char(\\n)content(<option value=)char(\\")content(Mauritania)char(\\")content(>Mauritania</option>)char(\\n)content(<option value=)char(\\")content(Mauritius)char(\\")content(>Mauritius</option>)char(\\n)content(<option value=)char(\\")content(Mayotte)char(\\")content(>Mayotte</option>)char(\\n)content(<option value=)char(\\")content(Mexico)char(\\")content(>Mexico</option>)char(\\n)content(<option value=)char(\\")content(Micronesia, Federated States of)char(\\")content(>Micronesia, Federated States of</option>)char(\\n)content(<option value=)char(\\")content(Moldova, Republic of)char(\\")content(>Moldova, Republic of</option>)char(\\n)content(<option value=)char(\\")content(Monaco)char(\\")content(>Monaco</option>)char(\\n)content(<option value=)char(\\")content(Mongolia)char(\\")content(>Mongolia</option>)char(\\n)content(<option value=)char(\\")content(Montserrat)char(\\")content(>Montserrat</option>)char(\\n)content(<option value=)char(\\")content(Morocco)char(\\")content(>Morocco</option>)char(\\n)content(<option value=)char(\\")content(Mozambique)char(\\")content(>Mozambique</option>)char(\\n)content(<option value=)char(\\")content(Myanmar)char(\\")content(>Myanmar</option>)char(\\n)content(<option value=)char(\\")content(Namibia)char(\\")content(>Namibia</option>)char(\\n)content(<option value=)char(\\")content(Nauru)char(\\")content(>Nauru</option>)char(\\n)content(<option value=)char(\\")content(Nepal)char(\\")content(>Nepal</option>)char(\\n)content(<option value=)char(\\")content(Netherlands)char(\\")content(>Netherlands</option>)char(\\n)content(<option value=)char(\\")content(Netherlands Antilles)char(\\")content(>Netherlands Antilles</option>)char(\\n)content(<option value=)char(\\")content(New Caledonia)char(\\")content(>New Caledonia</option>)delimiter(")> operator(+) + string<delimiter(")char(\\n)content(<option value=)char(\\")content(New Zealand)char(\\")content(>New Zealand</option>)char(\\n)content(<option value=)char(\\")content(Nicaragua)char(\\")content(>Nicaragua</option>)char(\\n)content(<option value=)char(\\")content(Niger)char(\\")content(>Niger</option>)char(\\n)content(<option value=)char(\\")content(Nigeria)char(\\")content(>Nigeria</option>)char(\\n)content(<option value=)char(\\")content(Niue)char(\\")content(>Niue</option>)char(\\n)content(<option value=)char(\\")content(Norfolk Island)char(\\")content(>Norfolk Island</option>)char(\\n)content(<option value=)char(\\")content(Northern Ireland)char(\\")content(>Northern Ireland</option>)char(\\n)content(<option value=)char(\\")content(Northern Mariana Islands)char(\\")content(>Northern Mariana Islands</option>)char(\\n)content(<option value=)char(\\")content(Norway)char(\\")content(>Norway</option>)char(\\n)content(<option value=)char(\\")content(Oman)char(\\")content(>Oman</option>)char(\\n)content(<option value=)char(\\")content(Pakistan)char(\\")content(>Pakistan</option>)char(\\n)content(<option value=)char(\\")content(Palau)char(\\")content(>Palau</option>)char(\\n)content(<option value=)char(\\")content(Panama)char(\\")content(>Panama</option>)char(\\n)content(<option value=)char(\\")content(Papua New Guinea)char(\\")content(>Papua New Guinea</option>)char(\\n)content(<option value=)char(\\")content(Paraguay)char(\\")content(>Paraguay</option>)char(\\n)content(<option value=)char(\\")content(Peru)char(\\")content(>Peru</option>)char(\\n)content(<option value=)char(\\")content(Philippines)char(\\")content(>Philippines</option>)char(\\n)content(<option value=)char(\\")content(Pitcairn)char(\\")content(>Pitcairn</option>)char(\\n)content(<option value=)char(\\")content(Poland)char(\\")content(>Poland</option>)char(\\n)content(<option value=)char(\\")content(Portugal)char(\\")content(>Portugal</option>)char(\\n)content(<option value=)char(\\")content(Puerto Rico)char(\\")content(>Puerto Rico</option>)char(\\n)content(<option value=)char(\\")content(Qatar)char(\\")content(>Qatar</option>)char(\\n)content(<option value=)char(\\")content(Reunion)char(\\")content(>Reunion</option>)char(\\n)content(<option value=)char(\\")content(Romania)char(\\")content(>Romania</option>)char(\\n)content(<option value=)char(\\")content(Russia)char(\\")content(>Russia</option>)char(\\n)content(<option value=)char(\\")content(Rwanda)char(\\")content(>Rwanda</option>)char(\\n)content(<option value=)char(\\")content(Saint Kitts and Nevis)char(\\")content(>Saint Kitts and Nevis</option>)char(\\n)content(<option value=)char(\\")content(Saint Lucia)char(\\")content(>Saint Lucia</option>)char(\\n)content(<option value=)char(\\")content(Saint Vincent and the Grenadines)char(\\")content(>Saint Vincent and the Grenadines</option>)char(\\n)content(<option value=)char(\\")content(Samoa (Independent\))char(\\")content(>Samoa (Independent\)</option>)char(\\n)content(<option value=)char(\\")content(San Marino)char(\\")content(>San Marino</option>)char(\\n)content(<option value=)char(\\")content(Sao Tome and Principe)char(\\")content(>Sao Tome and Principe</option>)char(\\n)content(<option value=)char(\\")content(Saudi Arabia)char(\\")content(>Saudi Arabia</option>)char(\\n)content(<option value=)char(\\")content(Scotland)char(\\")content(>Scotland</option>)char(\\n)content(<option value=)char(\\")content(Senegal)char(\\")content(>Senegal</option>)char(\\n)content(<option value=)char(\\")content(Serbia and Montenegro)char(\\")content(>Serbia and Montenegro</option>)char(\\n)content(<option value=)char(\\")content(Seychelles)char(\\")content(>Seychelles</option>)char(\\n)content(<option value=)char(\\")content(Sierra Leone)char(\\")content(>Sierra Leone</option>)char(\\n)content(<option value=)char(\\")content(Singapore)char(\\")content(>Singapore</option>)char(\\n)content(<option value=)char(\\")content(Slovakia)char(\\")content(>Slovakia</option>)char(\\n)content(<option value=)char(\\")content(Slovenia)char(\\")content(>Slovenia</option>)char(\\n)content(<option value=)char(\\")content(Solomon Islands)char(\\")content(>Solomon Islands</option>)char(\\n)content(<option value=)char(\\")content(Somalia)char(\\")content(>Somalia</option>)char(\\n)content(<option value=)char(\\")content(South Africa)char(\\")content(>South Africa</option>)char(\\n)content(<option value=)char(\\")content(South Georgia and the South Sandwich Islands)char(\\")content(>South Georgia and the South Sandwich Islands</option>)char(\\n)content(<option value=)char(\\")content(South Korea)char(\\")content(>South Korea</option>)char(\\n)content(<option value=)char(\\")content(Spain)char(\\")content(>Spain</option>)char(\\n)content(<option value=)char(\\")content(Sri Lanka)char(\\")content(>Sri Lanka</option>)char(\\n)content(<option value=)char(\\")content(St. Helena)char(\\")content(>St. Helena</option>)char(\\n)content(<option value=)char(\\")content(St. Pierre and Miquelon)char(\\")content(>St. Pierre and Miquelon</option>)char(\\n)content(<option value=)char(\\")content(Suriname)char(\\")content(>Suriname</option>)char(\\n)content(<option value=)char(\\")content(Svalbard and Jan Mayen Islands)char(\\")content(>Svalbard and Jan Mayen Islands</option>)char(\\n)content(<option value=)char(\\")content(Swaziland)char(\\")content(>Swaziland</option>)char(\\n)content(<option value=)char(\\")content(Sweden)char(\\")content(>Sweden</option>)char(\\n)content(<option value=)char(\\")content(Switzerland)char(\\")content(>Switzerland</option>)char(\\n)content(<option value=)char(\\")content(Taiwan)char(\\")content(>Taiwan</option>)char(\\n)content(<option value=)char(\\")content(Tajikistan)char(\\")content(>Tajikistan</option>)char(\\n)content(<option value=)char(\\")content(Tanzania)char(\\")content(>Tanzania</option>)char(\\n)content(<option value=)char(\\")content(Thailand)char(\\")content(>Thailand</option>)char(\\n)content(<option value=)char(\\")content(Togo)char(\\")content(>Togo</option>)char(\\n)content(<option value=)char(\\")content(Tokelau)char(\\")content(>Tokelau</option>)char(\\n)content(<option value=)char(\\")content(Tonga)char(\\")content(>Tonga</option>)char(\\n)content(<option value=)char(\\")content(Trinidad)char(\\")content(>Trinidad</option>)char(\\n)content(<option value=)char(\\")content(Trinidad and Tobago)char(\\")content(>Trinidad and Tobago</option>)char(\\n)content(<option value=)char(\\")content(Tunisia)char(\\")content(>Tunisia</option>)char(\\n)content(<option value=)char(\\")content(Turkey)char(\\")content(>Turkey</option>)char(\\n)content(<option value=)char(\\")content(Turkmenistan)char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(Turkmenistan</option>)char(\\n)content(<option value=)char(\\")content(Turks and Caicos Islands)char(\\")content(>Turks and Caicos Islands</option>)char(\\n)content(<option value=)char(\\")content(Tuvalu)char(\\")content(>Tuvalu</option>)char(\\n)content(<option value=)char(\\")content(Uganda)char(\\")content(>Uganda</option>)char(\\n)content(<option value=)char(\\")content(Ukraine)char(\\")content(>Ukraine</option>)char(\\n)content(<option value=)char(\\")content(United Arab Emirates)char(\\")content(>United Arab Emirates</option>)char(\\n)content(<option value=)char(\\")content(United Kingdom)char(\\")content(>United Kingdom</option>)char(\\n)content(<option value=)char(\\")content(United States)char(\\")content(>United States</option>)char(\\n)content(<option value=)char(\\")content(United States Minor Outlying Islands)char(\\")content(>United States Minor Outlying Islands</option>)char(\\n)content(<option value=)char(\\")content(Uruguay)char(\\")content(>Uruguay</option>)char(\\n)content(<option value=)char(\\")content(Uzbekistan)char(\\")content(>Uzbekistan</option>)char(\\n)content(<option value=)char(\\")content(Vanuatu)char(\\")content(>Vanuatu</option>)char(\\n)content(<option value=)char(\\")content(Vatican City State (Holy See\))char(\\")content(>Vatican City State (Holy See\)</option>)char(\\n)content(<option value=)char(\\")content(Venezuela)char(\\")content(>Venezuela</option>)char(\\n)content(<option value=)char(\\")content(Viet Nam)char(\\")content(>Viet Nam</option>)char(\\n)content(<option value=)char(\\")content(Virgin Islands (British\))char(\\")content(>Virgin Islands (British\)</option>)char(\\n)content(<option value=)char(\\")content(Virgin Islands (U.S.\))char(\\")content(>Virgin Islands (U.S.\)</option>)char(\\n)content(<option value=)char(\\")content(Wales)char(\\")content(>Wales</option>)char(\\n)content(<option value=)char(\\")content(Wallis and Futuna Islands)char(\\")content(>Wallis and Futuna Islands</option>)char(\\n)content(<option value=)char(\\")content(Western Sahara)char(\\")content(>Western Sahara</option>)char(\\n)content(<option value=)char(\\")content(Yemen)char(\\")content(>Yemen</option>)char(\\n)content(<option value=)char(\\")content(Zambia)char(\\")content(>Zambia</option>)char(\\n)content(<option value=)char(\\")content(Zimbabwe)char(\\")content(>Zimbabwe</option></select>)delimiter(")>operator(,) + ident(country_select)operator(()string<delimiter(")content(post)delimiter(")>operator(,) string<delimiter(")content(origin)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_time_zone_select) + instance_variable(@firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) + ident(html) operator(=) ident(time_zone_select)operator(() string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")> operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<select id=)char(\\")content(firm_time_zone)char(\\")content( name=)char(\\")content(firm[time_zone])char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(</select>)delimiter(")>operator(,) + ident(html) + reserved(end) + + reserved(def) method(test_time_zone_select_under_fields_for) + instance_variable(@firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) + + ident(_erbout) operator(=) string<delimiter(')delimiter(')> + + ident(fields_for) symbol(:firm)operator(,) instance_variable(@firm) reserved(do) operator(|)ident(f)operator(|) + ident(_erbout)operator(.)ident(concat) ident(f)operator(.)ident(time_zone_select)operator(()symbol(:time_zone)operator(\)) + reserved(end) + + ident(assert_dom_equal)operator(() + string<delimiter(")content(<select id=)char(\\")content(firm_time_zone)char(\\")content( name=)char(\\")content(firm[time_zone])char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(</select>)delimiter(")>operator(,) + ident(_erbout) + operator(\)) + reserved(end) + + reserved(def) method(test_time_zone_select_with_blank) + instance_variable(@firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) + ident(html) operator(=) ident(time_zone_select)operator(()string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:include_blank) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<select id=)char(\\")content(firm_time_zone)char(\\")content( name=)char(\\")content(firm[time_zone])char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")char(\\")content(></option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(</select>)delimiter(")>operator(,) + ident(html) + reserved(end) + + reserved(def) method(test_time_zone_select_with_style) + instance_variable(@firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) + ident(html) operator(=) ident(time_zone_select)operator(()string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")>operator(,) pre_constant(nil)operator(,) operator({)operator(})operator(,) + string<delimiter(")content(style)delimiter(")> operator(=)operator(>) string<delimiter(")content(color: red)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<select id=)char(\\")content(firm_time_zone)char(\\")content( name=)char(\\")content(firm[time_zone])char(\\")content( style=)char(\\")content(color: red)char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(</select>)delimiter(")>operator(,) + ident(html) + ident(assert_dom_equal) ident(html)operator(,) ident(time_zone_select)operator(()string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")>operator(,) pre_constant(nil)operator(,) operator({)operator(})operator(,) + symbol(:style) operator(=)operator(>) string<delimiter(")content(color: red)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_time_zone_select_with_blank_and_style) + instance_variable(@firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) + ident(html) operator(=) ident(time_zone_select)operator(()string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")>operator(,) pre_constant(nil)operator(,) + operator({) symbol(:include_blank) operator(=)operator(>) pre_constant(true) operator(})operator(,) string<delimiter(")content(style)delimiter(")> operator(=)operator(>) string<delimiter(")content(color: red)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<select id=)char(\\")content(firm_time_zone)char(\\")content( name=)char(\\")content(firm[time_zone])char(\\")content( style=)char(\\")content(color: red)char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")char(\\")content(></option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(</select>)delimiter(")>operator(,) + ident(html) + ident(assert_dom_equal) ident(html)operator(,) ident(time_zone_select)operator(()string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")>operator(,) pre_constant(nil)operator(,) + operator({) symbol(:include_blank) operator(=)operator(>) pre_constant(true) operator(})operator(,) symbol(:style) operator(=)operator(>) string<delimiter(")content(color: red)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_time_zone_select_with_priority_zones) + instance_variable(@firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) + ident(zones) operator(=) operator([) constant(TimeZone)operator(.)ident(new)operator(()string<delimiter(")content(A)delimiter(")>operator(\))operator(,) constant(TimeZone)operator(.)ident(new)operator(()string<delimiter(")content(D)delimiter(")>operator(\)) operator(]) + ident(html) operator(=) ident(time_zone_select)operator(()string<delimiter(")content(firm)delimiter(")>operator(,) string<delimiter(")content(time_zone)delimiter(")>operator(,) ident(zones) operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<select id=)char(\\")content(firm_time_zone)char(\\")content( name=)char(\\")content(firm[time_zone])char(\\")content(>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(A)char(\\")content(>A</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(D)char(\\")content( selected=)char(\\")content(selected)char(\\")content(>D</option>)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")char(\\")content(>-------------</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(B)char(\\")content(>B</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(C)char(\\")content(>C</option>)char(\\n)delimiter(")> operator(+) + string<delimiter(")content(<option value=)char(\\")content(E)char(\\")content(>E</option>)delimiter(")> operator(+) + string<delimiter(")content(</select>)delimiter(")>operator(,) + ident(html) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(FormTagHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormTagHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + string<delimiter(")content(http://www.example.com)delimiter(")> + reserved(end) + reserved(end) + instance_variable(@controller) operator(=) instance_variable(@controller)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_check_box_tag) + ident(actual) operator(=) ident(check_box_tag) string<delimiter(")content(admin)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<input id="admin" name="admin" type="checkbox" value="1" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_form_tag) + ident(actual) operator(=) ident(form_tag) + ident(expected) operator(=) string<delimiter(%()content(<form action="http://www.example.com" method="post">)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_form_tag_multipart) + ident(actual) operator(=) ident(form_tag)operator(()operator({)operator(})operator(,) operator({) string<delimiter(')content(multipart)delimiter(')> operator(=)operator(>) pre_constant(true) operator(})operator(\)) + ident(expected) operator(=) string<delimiter(%()content(<form action="http://www.example.com" enctype="multipart/form-data" method="post">)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_hidden_field_tag) + ident(actual) operator(=) ident(hidden_field_tag) string<delimiter(")content(id)delimiter(")>operator(,) integer(3) + ident(expected) operator(=) string<delimiter(%()content(<input id="id" name="id" type="hidden" value="3" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_password_field_tag) + ident(actual) operator(=) ident(password_field_tag) + ident(expected) operator(=) string<delimiter(%()content(<input id="password" name="password" type="password" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_radio_button_tag) + ident(actual) operator(=) ident(radio_button_tag) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(david)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<input id="people" name="people" type="radio" value="david" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_select_tag) + ident(actual) operator(=) ident(select_tag) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(<option>david</option>)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<select id="people" name="people"><option>david</option></select>)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_text_area_tag_size_string) + ident(actual) operator(=) ident(text_area_tag) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(size)delimiter(")> operator(=)operator(>) string<delimiter(")content(20x40)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_text_area_tag_size_symbol) + ident(actual) operator(=) ident(text_area_tag) string<delimiter(")content(body)delimiter(")>operator(,) string<delimiter(")content(hello world)delimiter(")>operator(,) symbol(:size) operator(=)operator(>) string<delimiter(")content(20x40)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_text_field_tag) + ident(actual) operator(=) ident(text_field_tag) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Hello!)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<input id="title" name="title" type="text" value="Hello!" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_text_field_tag_class_string) + ident(actual) operator(=) ident(text_field_tag) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Hello!)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) string<delimiter(")content(admin)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<input class="admin" id="title" name="title" type="text" value="Hello!" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_boolean_optios) + ident(assert_dom_equal) string<delimiter(%()content(<input checked="checked" disabled="disabled" id="admin" name="admin" readonly="readonly" type="checkbox" value="1" />)delimiter(\))>operator(,) ident(check_box_tag)operator(()string<delimiter(")content(admin)delimiter(")>operator(,) integer(1)operator(,) pre_constant(true)operator(,) string<delimiter(')content(disabled)delimiter(')> operator(=)operator(>) pre_constant(true)operator(,) symbol(:readonly) operator(=)operator(>) string<delimiter(")content(yes)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<input checked="checked" id="admin" name="admin" type="checkbox" value="1" />)delimiter(\))>operator(,) ident(check_box_tag)operator(()string<delimiter(")content(admin)delimiter(")>operator(,) integer(1)operator(,) pre_constant(true)operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(false)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(nil)operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<select id="people" multiple="multiple" name="people"><option>david</option></select>)delimiter(\))>operator(,) ident(select_tag)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(<option>david</option>)delimiter(")>operator(,) symbol(:multiple) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<select id="people" name="people"><option>david</option></select>)delimiter(\))>operator(,) ident(select_tag)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(<option>david</option>)delimiter(")>operator(,) symbol(:multiple) operator(=)operator(>) pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(test_stringify_symbol_keys) + ident(actual) operator(=) ident(text_field_tag) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Hello!)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) string<delimiter(")content(admin)delimiter(")> + ident(expected) operator(=) string<delimiter(%()content(<input id="admin" name="title" type="text" value="Hello!" />)delimiter(\))> + ident(assert_dom_equal) ident(expected)operator(,) ident(actual) + reserved(end) + + reserved(def) method(test_submit_tag) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<input name='commit' type='submit' value='Save' onclick="this.disabled=true;this.value='Saving...';this.form.submit)nesting_delimiter(()nesting_delimiter(\))content(;alert)nesting_delimiter(()content('hello!')nesting_delimiter(\))content(" />)delimiter(\))>operator(,) + ident(submit_tag)operator(()string<delimiter(")content(Save)delimiter(")>operator(,) symbol(:disable_with) operator(=)operator(>) string<delimiter(")content(Saving...)delimiter(")>operator(,) symbol(:onclick) operator(=)operator(>) string<delimiter(")content(alert('hello!'\))delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_pass) + ident(assert_equal) integer(1)operator(,) integer(1) + reserved(end) +reserved(end) + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(JavaScriptMacrosHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptMacrosHelper) + + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(CaptureHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(url) operator(=) string<delimiter(")content(http://www.example.com/)delimiter(")> + ident(url) operator(<<) ident(options)operator([)symbol(:action)operator(])operator(.)ident(to_s) reserved(if) ident(options) reserved(and) ident(options)operator([)symbol(:action)operator(]) + ident(url) + reserved(end) + reserved(end) + instance_variable(@controller) operator(=) instance_variable(@controller)operator(.)ident(new) + reserved(end) + + + reserved(def) method(test_auto_complete_field) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(\))operator(;) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:','})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(,) symbol(:tokens) operator(=)operator(>) string<delimiter(')content(,)delimiter(')>operator(\))operator(;) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:[',']})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(,) symbol(:tokens) operator(=)operator(>) operator([)string<delimiter(')content(,)delimiter(')>operator(])operator(\))operator(;) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {minChars:3})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(,) symbol(:min_chars) operator(=)operator(>) integer(3)operator(\))operator(;) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {onHide:function)nesting_delimiter(()content(element, update)nesting_delimiter(\))content({alert)nesting_delimiter(()content('me')nesting_delimiter(\))content(;}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(,) symbol(:on_hide) operator(=)operator(>) string<delimiter(")content(function(element, update\){alert('me'\);})delimiter(")>operator(\))operator(;) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {frequency:2})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(,) symbol(:frequency) operator(=)operator(>) integer(2)operator(\))operator(;) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var some_input_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {afterUpdateElement:function)nesting_delimiter(()content(element,value)nesting_delimiter(\))content({alert)nesting_delimiter(()content('You have chosen: '+value)nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(auto_complete_field)operator(()string<delimiter(")content(some_input)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(autocomplete)delimiter(")> operator(})operator(,) + symbol(:after_update_element) operator(=)operator(>) string<delimiter(")content(function(element,value\){alert('You have chosen: '+value\)})delimiter(")>operator(\))operator(;) + reserved(end) + + reserved(def) method(test_auto_complete_result) + ident(result) operator(=) operator([) operator({) symbol(:title) operator(=)operator(>) string<delimiter(')content(test1)delimiter(')> operator(})operator(,) operator({) symbol(:title) operator(=)operator(>) string<delimiter(')content(test2)delimiter(')> operator(}) operator(]) + ident(assert_equal) string<delimiter(%()content(<ul><li>test1</li><li>test2</li></ul>)delimiter(\))>operator(,) + ident(auto_complete_result)operator(()ident(result)operator(,) symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(%()content(<ul><li>t<strong class=)char(\\")content(highlight)char(\\")content(>est</strong>1</li><li>t<strong class=)char(\\")content(highlight)char(\\")content(>est</strong>2</li></ul>)delimiter(\))>operator(,) + ident(auto_complete_result)operator(()ident(result)operator(,) symbol(:title)operator(,) string<delimiter(")content(est)delimiter(")>operator(\)) + + ident(resultuniq) operator(=) operator([) operator({) symbol(:title) operator(=)operator(>) string<delimiter(')content(test1)delimiter(')> operator(})operator(,) operator({) symbol(:title) operator(=)operator(>) string<delimiter(')content(test1)delimiter(')> operator(}) operator(]) + ident(assert_equal) string<delimiter(%()content(<ul><li>t<strong class=)char(\\")content(highlight)char(\\")content(>est</strong>1</li></ul>)delimiter(\))>operator(,) + ident(auto_complete_result)operator(()ident(resultuniq)operator(,) symbol(:title)operator(,) string<delimiter(")content(est)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_text_field_with_auto_complete) + ident(assert_match) string<delimiter(")content(<style>)delimiter(")>operator(,) + ident(text_field_with_auto_complete)operator(()symbol(:message)operator(,) symbol(:recipient)operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<input id=)char(\\")content(message_recipient)char(\\")content( name=)char(\\")content(message[recipient])char(\\")content( size=)char(\\")content(30)char(\\")content( type=)char(\\")content(text)char(\\")content( /><div class=)char(\\")content(auto_complete)char(\\")content( id=)char(\\")content(message_recipient_auto_complete)char(\\")content(></div><script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(var message_recipient_auto_completer = new Ajax.Autocompleter)nesting_delimiter(()content('message_recipient', 'message_recipient_auto_complete', 'http://www.example.com/auto_complete_for_message_recipient', {})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(text_field_with_auto_complete)operator(()symbol(:message)operator(,) symbol(:recipient)operator(,) operator({)operator(})operator(,) symbol(:skip_style) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_external_control) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Ajax.InPlaceEditor)nesting_delimiter(()content('some_input', 'http://www.example.com/inplace_edit', {externalControl:'blah'})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(in_place_editor)operator(()string<delimiter(')content(some_input)delimiter(')>operator(,) operator({)symbol(:url) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(inplace_edit)delimiter(')>operator(})operator(,) symbol(:external_control) operator(=)operator(>) string<delimiter(')content(blah)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_size) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Ajax.InPlaceEditor)nesting_delimiter(()content('some_input', 'http://www.example.com/inplace_edit', {size:4})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(in_place_editor)operator(()string<delimiter(')content(some_input)delimiter(')>operator(,) operator({)symbol(:url) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(inplace_edit)delimiter(')>operator(})operator(,) symbol(:size) operator(=)operator(>) integer(4)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_cols_no_rows) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Ajax.InPlaceEditor)nesting_delimiter(()content('some_input', 'http://www.example.com/inplace_edit', {cols:4})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(in_place_editor)operator(()string<delimiter(')content(some_input)delimiter(')>operator(,) operator({)symbol(:url) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(inplace_edit)delimiter(')>operator(})operator(,) symbol(:cols) operator(=)operator(>) integer(4)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_cols_with_rows) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Ajax.InPlaceEditor)nesting_delimiter(()content('some_input', 'http://www.example.com/inplace_edit', {cols:40, rows:5})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(in_place_editor)operator(()string<delimiter(')content(some_input)delimiter(')>operator(,) operator({)symbol(:url) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(inplace_edit)delimiter(')>operator(})operator(,) symbol(:rows) operator(=)operator(>) integer(5)operator(,) symbol(:cols) operator(=)operator(>) integer(40)operator(})operator(\)) + reserved(end) + + reserved(def) method(test_inplace_editor_loading_text) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Ajax.InPlaceEditor)nesting_delimiter(()content('some_input', 'http://www.example.com/inplace_edit', {loadingText:'Why are we waiting?'})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(in_place_editor)operator(()string<delimiter(')content(some_input)delimiter(')>operator(,) operator({)symbol(:url) operator(=)operator(>) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(inplace_edit)delimiter(')>operator(})operator(,) symbol(:loading_text) operator(=)operator(>) string<delimiter(')content(Why are we waiting?)delimiter(')>operator(})operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_url) + ident(assert_match) string<delimiter(")content(Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value'\))delimiter(")>operator(,) + ident(in_place_editor)operator(() string<delimiter(')content(id-goes-here)delimiter(')>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(action_to_set_value)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_load_text_url) + ident(assert_match) string<delimiter(")content(Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value', {loadTextURL:'http://www.example.com/action_to_get_value'}\))delimiter(")>operator(,) + ident(in_place_editor)operator(() string<delimiter(')content(id-goes-here)delimiter(')>operator(,) + symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(action_to_set_value)delimiter(")> operator(})operator(,) + symbol(:load_text_url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(action_to_get_value)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_in_place_editor_eval_scripts) + ident(assert_match) string<delimiter(")content(Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value', {evalScripts:true}\))delimiter(")>operator(,) + ident(in_place_editor)operator(() string<delimiter(')content(id-goes-here)delimiter(')>operator(,) + symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(action_to_set_value)delimiter(")> operator(})operator(,) + symbol(:script) operator(=)operator(>) pre_constant(true) operator(\)) + reserved(end) + +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(JavaScriptHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptHelper) + + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(CaptureHelper) + + reserved(def) method(test_define_javascript_functions) + comment(# check if prototype.js is included first) + ident(assert_not_nil) ident(define_javascript_functions)operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(1)operator(])operator(.)ident(match)operator(()regexp<delimiter(/)content(Prototype JavaScript framework)delimiter(/)>operator(\)) + + comment(# check that scriptaculous.js is not in here, only needed if loaded remotely) + ident(assert_nil) ident(define_javascript_functions)operator(.)ident(split)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator([)integer(1)operator(])operator(.)ident(match)operator(()regexp<delimiter(/)content(var Scriptaculous = )char(\\{)delimiter(/)>operator(\)) + reserved(end) + + reserved(def) method(test_escape_javascript) + ident(assert_equal) string<delimiter(%()content(This )char(\\\\)content("thing)char(\\\\)content(" is really)char(\\\\)content(n netos)char(\\\\)content(')delimiter(\))>operator(,) ident(escape_javascript)operator(()string<delimiter(%()content(This "thing" is really)char(\\n)content( netos')delimiter(\))>operator(\)) + reserved(end) + + reserved(def) method(test_link_to_function) + ident(assert_dom_equal) string<delimiter(%()content(<a href="#" onclick="alert)nesting_delimiter(()content('Hello world!')nesting_delimiter(\))content(; return false;">Greeting</a>)delimiter(\))>operator(,) + ident(link_to_function)operator(()string<delimiter(")content(Greeting)delimiter(")>operator(,) string<delimiter(")content(alert('Hello world!'\))delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_link_to_function_with_existing_onclick) + ident(assert_dom_equal) string<delimiter(%()content(<a href="#" onclick="confirm)nesting_delimiter(()content('Sanity!')nesting_delimiter(\))content(; alert)nesting_delimiter(()content('Hello world!')nesting_delimiter(\))content(; return false;">Greeting</a>)delimiter(\))>operator(,) + ident(link_to_function)operator(()string<delimiter(")content(Greeting)delimiter(")>operator(,) string<delimiter(")content(alert('Hello world!'\))delimiter(")>operator(,) symbol(:onclick) operator(=)operator(>) string<delimiter(")content(confirm('Sanity!'\))delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_button_to_function) + ident(assert_dom_equal) string<delimiter(%()content(<input type="button" onclick="alert)nesting_delimiter(()content('Hello world!')nesting_delimiter(\))content(;" value="Greeting" />)delimiter(\))>operator(,) + ident(button_to_function)operator(()string<delimiter(")content(Greeting)delimiter(")>operator(,) string<delimiter(")content(alert('Hello world!'\))delimiter(")>operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/number_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../../activesupport/lib/active_support/core_ext/hash)delimiter(')> comment(# for stringify_keys) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../../activesupport/lib/active_support/core_ext/numeric)delimiter(')> comment(# for human_size) + +reserved(class) class(NumberHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(NumberHelper) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Hash) + + reserved(def) method(test_number_to_phone) + ident(assert_equal)operator(()string<delimiter(")content(123-555-1234)delimiter(")>operator(,) ident(number_to_phone)operator(()integer(1235551234)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content((123\) 555-1234)delimiter(")>operator(,) ident(number_to_phone)operator(()integer(1235551234)operator(,) operator({)symbol(:area_code) operator(=)operator(>) pre_constant(true)operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(123 555 1234)delimiter(")>operator(,) ident(number_to_phone)operator(()integer(1235551234)operator(,) operator({)symbol(:delimiter) operator(=)operator(>) string<delimiter(")content( )delimiter(")>operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content((123\) 555-1234 x 555)delimiter(")>operator(,) ident(number_to_phone)operator(()integer(1235551234)operator(,) operator({)symbol(:area_code) operator(=)operator(>) pre_constant(true)operator(,) symbol(:extension) operator(=)operator(>) integer(555)operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(123-555-1234)delimiter(")>operator(,) ident(number_to_phone)operator(()integer(1235551234)operator(,) symbol(:extension) operator(=)operator(>) string<delimiter(")content( )delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_number_to_currency) + ident(assert_equal)operator(()string<delimiter(")content($1,234,567,890.50)delimiter(")>operator(,) ident(number_to_currency)operator(()float(1234567890.50)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content($1,234,567,890.51)delimiter(")>operator(,) ident(number_to_currency)operator(()float(1234567890.506)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content($1,234,567,890)delimiter(")>operator(,) ident(number_to_currency)operator(()float(1234567890.50)operator(,) operator({)symbol(:precision) operator(=)operator(>) integer(0)operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content($1,234,567,890.5)delimiter(")>operator(,) ident(number_to_currency)operator(()float(1234567890.50)operator(,) operator({)symbol(:precision) operator(=)operator(>) integer(1)operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(£1234567890,50)delimiter(")>operator(,) ident(number_to_currency)operator(()float(1234567890.50)operator(,) operator({)symbol(:unit) operator(=)operator(>) string<delimiter(")content(£)delimiter(")>operator(,) symbol(:separator) operator(=)operator(>) string<delimiter(")content(,)delimiter(")>operator(,) symbol(:delimiter) operator(=)operator(>) string<delimiter(")delimiter(")>operator(})operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_number_to_percentage) + ident(assert_equal)operator(()string<delimiter(")content(100.000%)delimiter(")>operator(,) ident(number_to_percentage)operator(()integer(100)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(100%)delimiter(")>operator(,) ident(number_to_percentage)operator(()integer(100)operator(,) operator({)symbol(:precision) operator(=)operator(>) integer(0)operator(})operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(302.06%)delimiter(")>operator(,) ident(number_to_percentage)operator(()float(302.0574)operator(,) operator({)symbol(:precision) operator(=)operator(>) integer(2)operator(})operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_number_with_delimiter) + ident(assert_equal)operator(()string<delimiter(")content(12,345,678)delimiter(")>operator(,) ident(number_with_delimiter)operator(()integer(12345678)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_number_to_human_size) + ident(assert_equal) string<delimiter(')content(0 Bytes)delimiter(')>operator(,) ident(human_size)operator(()integer(0)operator(\)) + ident(assert_equal) string<delimiter(')content(3 Bytes)delimiter(')>operator(,) ident(human_size)operator(()float(3.14159265)operator(\)) + ident(assert_equal) string<delimiter(')content(123 Bytes)delimiter(')>operator(,) ident(human_size)operator(()float(123.0)operator(\)) + ident(assert_equal) string<delimiter(')content(123 Bytes)delimiter(')>operator(,) ident(human_size)operator(()integer(123)operator(\)) + ident(assert_equal) string<delimiter(')content(1.2 KB)delimiter(')>operator(,) ident(human_size)operator(()integer(1234)operator(\)) + ident(assert_equal) string<delimiter(')content(12.1 KB)delimiter(')>operator(,) ident(human_size)operator(()integer(12345)operator(\)) + ident(assert_equal) string<delimiter(')content(1.2 MB)delimiter(')>operator(,) ident(human_size)operator(()integer(1234567)operator(\)) + ident(assert_equal) string<delimiter(')content(1.1 GB)delimiter(')>operator(,) ident(human_size)operator(()integer(1234567890)operator(\)) + ident(assert_equal) string<delimiter(')content(1.1 TB)delimiter(')>operator(,) ident(human_size)operator(()integer(1234567890123)operator(\)) + ident(assert_equal) string<delimiter(')content(444 KB)delimiter(')>operator(,) ident(human_size)operator(()integer(444)operator(.)ident(kilobytes)operator(\)) + ident(assert_equal) string<delimiter(')content(1023 MB)delimiter(')>operator(,) ident(human_size)operator(()integer(1023)operator(.)ident(megabytes)operator(\)) + ident(assert_equal) string<delimiter(')content(3 TB)delimiter(')>operator(,) ident(human_size)operator(()integer(3)operator(.)ident(terabytes)operator(\)) + ident(assert_nil) ident(human_size)operator(()string<delimiter(')content(x)delimiter(')>operator(\)) + ident(assert_nil) ident(human_size)operator(()pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(test_number_with_precision) + ident(assert_equal)operator(()string<delimiter(")content(111.235)delimiter(")>operator(,) ident(number_with_precision)operator(()float(111.2346)operator(\))operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(module) class(BaseTest) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(PrototypeHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(ScriptaculousHelper) + + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(CaptureHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(url) operator(=) string<delimiter(")content(http://www.example.com/)delimiter(")> + ident(url) operator(<<) ident(options)operator([)symbol(:action)operator(])operator(.)ident(to_s) reserved(if) ident(options) reserved(and) ident(options)operator([)symbol(:action)operator(]) + ident(url) operator(<<) string<delimiter(")content(?a=)inline<inline_delimiter(#{)ident(options)operator([)symbol(:a)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options) operator(&&) ident(options)operator([)symbol(:a)operator(]) + ident(url) operator(<<) string<delimiter(")content(&b=)inline<inline_delimiter(#{)ident(options)operator([)symbol(:b)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options) operator(&&) ident(options)operator([)symbol(:a)operator(]) operator(&&) ident(options)operator([)symbol(:b)operator(]) + ident(url) + reserved(end) + reserved(end)operator(.)ident(new) + reserved(end) + +ident(protected) + reserved(def) method(create_generator) + ident(block) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|*)ident(args)operator(|) reserved(yield) operator(*)ident(args) reserved(if) ident(block_given?) operator(}) + constant(JavaScriptGenerator)operator(.)ident(new) pre_constant(self)operator(,) operator(&)ident(block) + reserved(end) +reserved(end) + +reserved(class) class(PrototypeHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(BaseTest) + + reserved(def) method(test_link_to_remote) + ident(assert_dom_equal) string<delimiter(%()content(<a class=)char(\\")content(fine)char(\\")content( href=)char(\\")content(#)char(\\")content( onclick=)char(\\")content(new Ajax.Request)nesting_delimiter(()content('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true})nesting_delimiter(\))content(; return false;)char(\\")content(>Remote outpost</a>)delimiter(\))>operator(,) + ident(link_to_remote)operator(()string<delimiter(")content(Remote outpost)delimiter(")>operator(,) operator({) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(whatnot)delimiter(")> operator(})operator(})operator(,) operator({) symbol(:class) operator(=)operator(>) string<delimiter(")content(fine)delimiter(")> operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<a href=)char(\\")content(#)char(\\")content( onclick=)char(\\")content(new Ajax.Request)nesting_delimiter(()content('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({alert)nesting_delimiter(()content(request.reponseText)nesting_delimiter(\))content(}})nesting_delimiter(\))content(; return false;)char(\\")content(>Remote outpost</a>)delimiter(\))>operator(,) + ident(link_to_remote)operator(()string<delimiter(")content(Remote outpost)delimiter(")>operator(,) symbol(:complete) operator(=)operator(>) string<delimiter(")content(alert(request.reponseText\))delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(whatnot)delimiter(")> operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<a href=)char(\\")content(#)char(\\")content( onclick=)char(\\")content(new Ajax.Request)nesting_delimiter(()content('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({alert)nesting_delimiter(()content(request.reponseText)nesting_delimiter(\))content(}})nesting_delimiter(\))content(; return false;)char(\\")content(>Remote outpost</a>)delimiter(\))>operator(,) + ident(link_to_remote)operator(()string<delimiter(")content(Remote outpost)delimiter(")>operator(,) symbol(:success) operator(=)operator(>) string<delimiter(")content(alert(request.reponseText\))delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(whatnot)delimiter(")> operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<a href=)char(\\")content(#)char(\\")content( onclick=)char(\\")content(new Ajax.Request)nesting_delimiter(()content('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({alert)nesting_delimiter(()content(request.reponseText)nesting_delimiter(\))content(}})nesting_delimiter(\))content(; return false;)char(\\")content(>Remote outpost</a>)delimiter(\))>operator(,) + ident(link_to_remote)operator(()string<delimiter(")content(Remote outpost)delimiter(")>operator(,) symbol(:failure) operator(=)operator(>) string<delimiter(")content(alert(request.reponseText\))delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(whatnot)delimiter(")> operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<a href=)char(\\")content(#)char(\\")content( onclick=)char(\\")content(new Ajax.Request)nesting_delimiter(()content('http://www.example.com/whatnot?a=10&b=20', {asynchronous:true, evalScripts:true, onFailure:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({alert)nesting_delimiter(()content(request.reponseText)nesting_delimiter(\))content(}})nesting_delimiter(\))content(; return false;)char(\\")content(>Remote outpost</a>)delimiter(\))>operator(,) + ident(link_to_remote)operator(()string<delimiter(")content(Remote outpost)delimiter(")>operator(,) symbol(:failure) operator(=)operator(>) string<delimiter(")content(alert(request.reponseText\))delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(whatnot)delimiter(")>operator(,) symbol(:a) operator(=)operator(>) string<delimiter(')content(10)delimiter(')>operator(,) symbol(:b) operator(=)operator(>) string<delimiter(')content(20)delimiter(')> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_periodically_call_remote) + ident(assert_dom_equal) string<delimiter(%()content(<script type="text/javascript">)char(\\n)content(//<![CDATA[)char(\\n)content(new PeriodicalExecuter)nesting_delimiter(()content(function)nesting_delimiter(()nesting_delimiter(\))content( {new Ajax.Updater)nesting_delimiter(()content('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})nesting_delimiter(\))content(}, 10)nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(periodically_call_remote)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(schremser_bier)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(mehr_bier)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_form_remote_tag) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;)char(\\")content(>)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;)char(\\")content(>)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) operator({) symbol(:success) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")> operator(})operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content({failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;)char(\\")content(>)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) operator({) symbol(:failure) operator(=)operator(>) string<delimiter(")content(glass_of_water)delimiter(")> operator(})operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;)char(\\")content(>)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) operator({) symbol(:success) operator(=)operator(>) string<delimiter(')content(glass_of_beer)delimiter(')>operator(,) symbol(:failure) operator(=)operator(>) string<delimiter(")content(glass_of_water)delimiter(")> operator(})operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(\)) + reserved(end) + + reserved(def) method(test_on_callbacks) + ident(callbacks) operator(=) operator([)symbol(:uninitialized)operator(,) symbol(:loading)operator(,) symbol(:loaded)operator(,) symbol(:interactive)operator(,) symbol(:complete)operator(,) symbol(:success)operator(,) symbol(:failure)operator(]) + ident(callbacks)operator(.)ident(each) reserved(do) operator(|)ident(callback)operator(|) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on)inline<inline_delimiter(#{)ident(callback)operator(.)ident(to_s)operator(.)ident(capitalize)inline_delimiter(})>content(:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on)inline<inline_delimiter(#{)ident(callback)operator(.)ident(to_s)operator(.)ident(capitalize)inline_delimiter(})>content(:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) operator({) symbol(:success) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")> operator(})operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content({failure:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on)inline<inline_delimiter(#{)ident(callback)operator(.)ident(to_s)operator(.)ident(capitalize)inline_delimiter(})>content(:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) operator({) symbol(:failure) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")> operator(})operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on)inline<inline_delimiter(#{)ident(callback)operator(.)ident(to_s)operator(.)ident(capitalize)inline_delimiter(})>content(:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) operator({) symbol(:success) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:failure) operator(=)operator(>) string<delimiter(")content(glass_of_water)delimiter(")> operator(})operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + reserved(end) + + comment(#HTTP status codes 200 up to 599 have callbacks) + comment(#these should work) + integer(100)operator(.)ident(upto)operator(()integer(599)operator(\)) reserved(do) operator(|)ident(callback)operator(|) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on)inline<inline_delimiter(#{)ident(callback)operator(.)ident(to_s)operator(.)ident(capitalize)inline_delimiter(})>content(:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + reserved(end) + + comment(#test 200 and 404) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, on404:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({bananas)nesting_delimiter(()nesting_delimiter(\))content(;}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) integer(200)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(,) integer(404)operator(=)operator(>)string<delimiter(")content(bananas(\);)delimiter(")>operator(\)) + + comment(#these shouldn't) + integer(1)operator(.)ident(upto)operator(()integer(99)operator(\)) reserved(do) operator(|)ident(callback)operator(|) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + reserved(end) + integer(600)operator(.)ident(upto)operator(()integer(999)operator(\)) reserved(do) operator(|)ident(callback)operator(|) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;">)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) ident(callback)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(\)) + reserved(end) + + comment(#test ultimate combo) + ident(assert_dom_equal) string<delimiter(%()content(<form action=)char(\\")content(http://www.example.com/fast)char(\\")content( method=)char(\\")content(post)char(\\")content( onsubmit=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({monkeys)nesting_delimiter(()nesting_delimiter(\))content(;}, on404:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({bananas)nesting_delimiter(()nesting_delimiter(\))content(;}, onComplete:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({c)nesting_delimiter(()nesting_delimiter(\))content(;}, onFailure:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({f)nesting_delimiter(()nesting_delimiter(\))content(;}, onLoading:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({c1)nesting_delimiter(()nesting_delimiter(\))content(}, onSuccess:function)nesting_delimiter(()content(request)nesting_delimiter(\))content({s)nesting_delimiter(()nesting_delimiter(\))content(}, parameters:Form.serialize)nesting_delimiter(()content(this)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;)char(\\")content(>)delimiter(\))>operator(,) + ident(form_remote_tag)operator(()symbol(:update) operator(=)operator(>) string<delimiter(")content(glass_of_beer)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) symbol(:fast) operator(})operator(,) symbol(:loading) operator(=)operator(>) string<delimiter(")content(c1(\))delimiter(")>operator(,) symbol(:success) operator(=)operator(>) string<delimiter(")content(s(\))delimiter(")>operator(,) symbol(:failure) operator(=)operator(>) string<delimiter(")content(f(\);)delimiter(")>operator(,) symbol(:complete) operator(=)operator(>) string<delimiter(")content(c(\);)delimiter(")>operator(,) integer(200)operator(=)operator(>)string<delimiter(")content(monkeys(\);)delimiter(")>operator(,) integer(404)operator(=)operator(>)string<delimiter(")content(bananas(\);)delimiter(")>operator(\)) + + reserved(end) + + reserved(def) method(test_submit_to_remote) + ident(assert_dom_equal) string<delimiter(%()content(<input name=)char(\\")content(More beer!)char(\\")content( onclick=)char(\\")content(new Ajax.Updater)nesting_delimiter(()content('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize)nesting_delimiter(()content(this.form)nesting_delimiter(\))content(})nesting_delimiter(\))content(; return false;)char(\\")content( type=)char(\\")content(button)char(\\")content( value=)char(\\")content(1000000)char(\\")content( />)delimiter(\))>operator(,) + ident(submit_to_remote)operator(()string<delimiter(")content(More beer!)delimiter(")>operator(,) integer(1_000_000)operator(,) symbol(:update) operator(=)operator(>) string<delimiter(")content(empty_bottle)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_observe_field) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Form.Element.Observer)nesting_delimiter(()content('glass', 300, function)nesting_delimiter(()content(element, value)nesting_delimiter(\))content( {new Ajax.Request)nesting_delimiter(()content('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true})nesting_delimiter(\))content(})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(observe_field)operator(()string<delimiter(")content(glass)delimiter(")>operator(,) symbol(:frequency) operator(=)operator(>) integer(5)operator(.)ident(minutes)operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(reorder_if_empty)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_observe_field_using_function_for_callback) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Form.Element.Observer)nesting_delimiter(()content('glass', 300, function)nesting_delimiter(()content(element, value)nesting_delimiter(\))content( {alert)nesting_delimiter(()content('Element changed')nesting_delimiter(\))content(})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(observe_field)operator(()string<delimiter(")content(glass)delimiter(")>operator(,) symbol(:frequency) operator(=)operator(>) integer(5)operator(.)ident(minutes)operator(,) symbol(:function) operator(=)operator(>) string<delimiter(")content(alert('Element changed'\))delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_observe_form) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Form.Observer)nesting_delimiter(()content('cart', 2, function)nesting_delimiter(()content(element, value)nesting_delimiter(\))content( {new Ajax.Request)nesting_delimiter(()content('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true})nesting_delimiter(\))content(})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(observe_form)operator(()string<delimiter(")content(cart)delimiter(")>operator(,) symbol(:frequency) operator(=)operator(>) integer(2)operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(cart_changed)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_observe_form_using_function_for_callback) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Form.Observer)nesting_delimiter(()content('cart', 2, function)nesting_delimiter(()content(element, value)nesting_delimiter(\))content( {alert)nesting_delimiter(()content('Form changed')nesting_delimiter(\))content(})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(observe_form)operator(()string<delimiter(")content(cart)delimiter(")>operator(,) symbol(:frequency) operator(=)operator(>) integer(2)operator(,) symbol(:function) operator(=)operator(>) string<delimiter(")content(alert('Form changed'\))delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_update_element_function) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content('myelement')nesting_delimiter(\))content(.innerHTML = 'blub';)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:content) operator(=)operator(>) string<delimiter(')content(blub)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content('myelement')nesting_delimiter(\))content(.innerHTML = 'blub';)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) symbol(:update)operator(,) symbol(:content) operator(=)operator(>) string<delimiter(')content(blub)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content('myelement')nesting_delimiter(\))content(.innerHTML = '';)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) symbol(:empty)operator(\)) + ident(assert_equal) string<delimiter(%()content(Element.remove)nesting_delimiter(()content('myelement')nesting_delimiter(\))content(;)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) symbol(:remove)operator(\)) + + ident(assert_equal) string<delimiter(%()content(new Insertion.Bottom)nesting_delimiter(()content('myelement','blub')nesting_delimiter(\))content(;)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:position) operator(=)operator(>) string<delimiter(')content(bottom)delimiter(')>operator(,) symbol(:content) operator(=)operator(>) string<delimiter(')content(blub)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%()content(new Insertion.Bottom)nesting_delimiter(()content('myelement','blub')nesting_delimiter(\))content(;)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:action) operator(=)operator(>) symbol(:update)operator(,) symbol(:position) operator(=)operator(>) symbol(:bottom)operator(,) symbol(:content) operator(=)operator(>) string<delimiter(')content(blub)delimiter(')>operator(\)) + + ident(_erbout) operator(=) string<delimiter(")delimiter(")> + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content('myelement')nesting_delimiter(\))content(.innerHTML = 'test';)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(\)) operator({) ident(_erbout) operator(<<) string<delimiter(")content(test)delimiter(")> operator(}) + + ident(_erbout) operator(=) string<delimiter(")delimiter(")> + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content('myelement')nesting_delimiter(\))content(.innerHTML = 'blockstuff';)char(\\n)delimiter(\))>operator(,) + ident(update_element_function)operator(()string<delimiter(')content(myelement)delimiter(')>operator(,) symbol(:content) operator(=)operator(>) string<delimiter(')content(paramstuff)delimiter(')>operator(\)) operator({) ident(_erbout) operator(<<) string<delimiter(")content(blockstuff)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_update_page) + ident(block) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(page)operator(|) ident(page)operator(.)ident(replace_html)operator(()string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(\)) operator(}) + ident(assert_equal) ident(create_generator)operator(()operator(&)ident(block)operator(\))operator(.)ident(to_s)operator(,) ident(update_page)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(test_update_page_tag) + ident(block) operator(=) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(page)operator(|) ident(page)operator(.)ident(replace_html)operator(()string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(\)) operator(}) + ident(assert_equal) ident(javascript_tag)operator(()ident(create_generator)operator(()operator(&)ident(block)operator(\))operator(.)ident(to_s)operator(\))operator(,) ident(update_page_tag)operator(()operator(&)ident(block)operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(JavaScriptGeneratorTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(BaseTest) + + reserved(def) method(setup) + reserved(super) + instance_variable(@generator) operator(=) ident(create_generator) + reserved(end) + + reserved(def) method(test_insert_html_with_string) + ident(assert_equal) string<delimiter(')content(new Insertion.Top("element", "<p>This is a test</p>"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(insert_html)operator(()symbol(:top)operator(,) string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(new Insertion.Bottom("element", "<p>This is a test</p>"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(insert_html)operator(()symbol(:bottom)operator(,) string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(new Insertion.Before("element", "<p>This is a test</p>"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(insert_html)operator(()symbol(:before)operator(,) string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(new Insertion.After("element", "<p>This is a test</p>"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(insert_html)operator(()symbol(:after)operator(,) string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_replace_html_with_string) + ident(assert_equal) string<delimiter(')content(Element.update("element", "<p>This is a test</p>"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(replace_html)operator(()string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_replace_element_with_string) + ident(assert_equal) string<delimiter(')content(Element.replace("element", "<div id=)content(\\")content(element)content(\\")content(><p>This is a test</p></div>"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(replace)operator(()string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<div id="element"><p>This is a test</p></div>)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_remove) + ident(assert_equal) string<delimiter(')content(["foo"].each(Element.remove\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(remove)operator(()string<delimiter(')content(foo)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(["foo", "bar", "baz"].each(Element.remove\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(remove)operator(()string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(,) string<delimiter(')content(baz)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_show) + ident(assert_equal) string<delimiter(')content(Element.show("foo"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(show)operator(()string<delimiter(')content(foo)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(Element.show("foo", "bar", "baz"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(show)operator(()string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(,) string<delimiter(')content(baz)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_hide) + ident(assert_equal) string<delimiter(')content(Element.hide("foo"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(hide)operator(()string<delimiter(')content(foo)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(Element.hide("foo", "bar", "baz"\);)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(hide)operator(()string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(,) string<delimiter(')content(baz)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_alert) + ident(assert_equal) string<delimiter(')content(alert("hello"\);)delimiter(')>operator(,) instance_variable(@generator)operator(.)ident(alert)operator(()string<delimiter(')content(hello)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_redirect_to) + ident(assert_equal) string<delimiter(')content(window.location.href = "http://www.example.com/welcome";)delimiter(')>operator(,) + instance_variable(@generator)operator(.)ident(redirect_to)operator(()symbol(:action) operator(=)operator(>) string<delimiter(')content(welcome)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_delay) + instance_variable(@generator)operator(.)ident(delay)operator(()integer(20)operator(\)) reserved(do) + instance_variable(@generator)operator(.)ident(hide)operator(()string<delimiter(')content(foo)delimiter(')>operator(\)) + reserved(end) + + ident(assert_equal) string<delimiter(")content(setTimeout(function(\) {)char(\\n)content(;)char(\\n)content(Element.hide()char(\\")content(foo)char(\\")content(\);)char(\\n)content(}, 20000\);)delimiter(")>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_to_s) + instance_variable(@generator)operator(.)ident(insert_html)operator(()symbol(:top)operator(,) string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + instance_variable(@generator)operator(.)ident(insert_html)operator(()symbol(:bottom)operator(,) string<delimiter(')content(element)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + instance_variable(@generator)operator(.)ident(remove)operator(()string<delimiter(')content(foo)delimiter(')>operator(,) string<delimiter(')content(bar)delimiter(')>operator(\)) + instance_variable(@generator)operator(.)ident(replace_html)operator(()string<delimiter(')content(baz)delimiter(')>operator(,) string<delimiter(')content(<p>This is a test</p>)delimiter(')>operator(\)) + + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(chomp)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +new Insertion.Top("element", "<p>This is a test</p>"\); +new Insertion.Bottom("element", "<p>This is a test</p>"\); +["foo", "bar"].each(Element.remove\); +Element.update("baz", "<p>This is a test</p>"\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_element_access) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content("hello")nesting_delimiter(\))content(;)delimiter(\))>operator(,) instance_variable(@generator)operator([)string<delimiter(')content(hello)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_element_proxy_one_deep) + instance_variable(@generator)operator([)string<delimiter(')content(hello)delimiter(')>operator(])operator(.)ident(hide) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content("hello")nesting_delimiter(\))content(.hide)nesting_delimiter(()nesting_delimiter(\))content(;)delimiter(\))>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_element_proxy_assignment) + instance_variable(@generator)operator([)string<delimiter(')content(hello)delimiter(')>operator(])operator(.)ident(width) operator(=) integer(400) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content("hello")nesting_delimiter(\))content(.width = 400;)delimiter(\))>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_element_proxy_two_deep) + instance_variable(@generator)operator([)string<delimiter(')content(hello)delimiter(')>operator(])operator(.)ident(hide)operator(()string<delimiter(")content(first)delimiter(")>operator(\))operator(.)ident(clean_whitespace) + ident(assert_equal) string<delimiter(%()content($)nesting_delimiter(()content("hello")nesting_delimiter(\))content(.hide)nesting_delimiter(()content("first")nesting_delimiter(\))content(.cleanWhitespace)nesting_delimiter(()nesting_delimiter(\))content(;)delimiter(\))>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_select_access) + ident(assert_equal) string<delimiter(%()content($$)nesting_delimiter(()content("div.hello")nesting_delimiter(\))content(;)delimiter(\))>operator(,) instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(div.hello)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_select_proxy_one_deep) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p.welcome b)delimiter(')>operator(\))operator(.)ident(first)operator(.)ident(hide) + ident(assert_equal) string<delimiter(%()content($$)nesting_delimiter(()content("p.welcome b")nesting_delimiter(\))content(.first)nesting_delimiter(()nesting_delimiter(\))content(.hide)nesting_delimiter(()nesting_delimiter(\))content(;)delimiter(\))>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_visual_effect) + ident(assert_equal) string<delimiter(%()content(new Effect.Puff)nesting_delimiter(()content("blah",{})nesting_delimiter(\))content(;)delimiter(\))>operator(,) + instance_variable(@generator)operator(.)ident(visual_effect)operator(()symbol(:puff)operator(,)string<delimiter(')content(blah)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_visual_effect_toggle) + ident(assert_equal) string<delimiter(%()content(Effect.toggle)nesting_delimiter(()content("blah",'appear',{})nesting_delimiter(\))content(;)delimiter(\))>operator(,) + instance_variable(@generator)operator(.)ident(visual_effect)operator(()symbol(:toggle_appear)operator(,)string<delimiter(')content(blah)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_sortable) + ident(assert_equal) string<delimiter(%()content(Sortable.create)nesting_delimiter(()content("blah", {onUpdate:function)nesting_delimiter(()nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize)nesting_delimiter(()content("blah")nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))content(;)delimiter(\))>operator(,) + instance_variable(@generator)operator(.)ident(sortable)operator(()string<delimiter(')content(blah)delimiter(')>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_draggable) + ident(assert_equal) string<delimiter(%()content(new Draggable)nesting_delimiter(()content("blah", {})nesting_delimiter(\))content(;)delimiter(\))>operator(,) + instance_variable(@generator)operator(.)ident(draggable)operator(()string<delimiter(')content(blah)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_drop_receiving) + ident(assert_equal) string<delimiter(%()content(Droppables.add)nesting_delimiter(()content("blah", {onDrop:function)nesting_delimiter(()content(element)nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent)nesting_delimiter(()content(element.id)nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))content(;)delimiter(\))>operator(,) + instance_variable(@generator)operator(.)ident(drop_receiving)operator(()string<delimiter(')content(blah)delimiter(')>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_collection_first_and_last) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p.welcome b)delimiter(')>operator(\))operator(.)ident(first)operator(.)ident(hide)operator(()operator(\)) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p.welcome b)delimiter(')>operator(\))operator(.)ident(last)operator(.)ident(show)operator(()operator(\)) + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +$$("p.welcome b"\).first(\).hide(\); +$$("p.welcome b"\).last(\).show(\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_collection_proxy_with_each) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p.welcome b)delimiter(')>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(value)operator(|) + ident(value)operator(.)ident(remove_class_name) string<delimiter(')content(selected)delimiter(')> + reserved(end) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p.welcome b)delimiter(')>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(value)operator(,) ident(index)operator(|) + instance_variable(@generator)operator(.)ident(visual_effect) symbol(:highlight)operator(,) ident(value) + reserved(end) + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +$$("p.welcome b"\).each(function(value, index\) { +value.removeClassName("selected"\); +}\); +$$("p.welcome b"\).each(function(value, index\) { +new Effect.Highlight(value,{}\); +}\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_collection_proxy_on_collect) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(collect)operator(()string<delimiter(')content(a)delimiter(')>operator(\)) operator({) operator(|)ident(para)operator(|) ident(para)operator(.)ident(show) operator(}) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(collect) operator({) operator(|)ident(para)operator(|) ident(para)operator(.)ident(hide) operator(}) + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +var a = $$("p"\).collect(function(value, index\) { +return value.show(\); +}\); +$$("p"\).collect(function(value, index\) { +return value.hide(\); +}\);)delimiter( + EOS)> + instance_variable(@generator) operator(=) ident(create_generator) + reserved(end) + + reserved(def) method(test_collection_proxy_with_grep) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(grep) string<delimiter(')content(a)delimiter(')>operator(,) regexp<delimiter(/)content(^a)delimiter(/)> reserved(do) operator(|)ident(value)operator(|) + instance_variable(@generator) operator(<<) string<delimiter(')content((value.className == "welcome"\))delimiter(')> + reserved(end) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(grep) string<delimiter(')content(b)delimiter(')>operator(,) regexp<delimiter(/)content(b$)delimiter(/)> reserved(do) operator(|)ident(value)operator(,) ident(index)operator(|) + instance_variable(@generator)operator(.)ident(call) string<delimiter(')content(alert)delimiter(')>operator(,) ident(value) + instance_variable(@generator) operator(<<) string<delimiter(')content((value.className == "welcome"\))delimiter(')> + reserved(end) + + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +var a = $$("p"\).grep(/^a/, function(value, index\) { +return (value.className == "welcome"\); +}\); +var b = $$("p"\).grep(/b$/, function(value, index\) { +alert(value\); +return (value.className == "welcome"\); +}\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_collection_proxy_with_inject) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(inject) string<delimiter(')content(a)delimiter(')>operator(,) operator([)operator(]) reserved(do) operator(|)ident(memo)operator(,) ident(value)operator(|) + instance_variable(@generator) operator(<<) string<delimiter(')content((value.className == "welcome"\))delimiter(')> + reserved(end) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(inject) string<delimiter(')content(b)delimiter(')>operator(,) pre_constant(nil) reserved(do) operator(|)ident(memo)operator(,) ident(value)operator(,) ident(index)operator(|) + instance_variable(@generator)operator(.)ident(call) string<delimiter(')content(alert)delimiter(')>operator(,) ident(memo) + instance_variable(@generator) operator(<<) string<delimiter(')content((value.className == "welcome"\))delimiter(')> + reserved(end) + + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +var a = $$("p"\).inject([], function(memo, value, index\) { +return (value.className == "welcome"\); +}\); +var b = $$("p"\).inject(null, function(memo, value, index\) { +alert(memo\); +return (value.className == "welcome"\); +}\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_collection_proxy_with_pluck) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(pluck)operator(()string<delimiter(')content(a)delimiter(')>operator(,) string<delimiter(')content(className)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(%()content(var a = $$)nesting_delimiter(()content("p")nesting_delimiter(\))content(.pluck)nesting_delimiter(()content("className")nesting_delimiter(\))content(;)delimiter(\))>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_collection_proxy_with_zip) + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptCollectionProxy)operator(.)ident(new)operator(()instance_variable(@generator)operator(,) string<delimiter(')content([1, 2, 3])delimiter(')>operator(\))operator(.)ident(zip)operator(()string<delimiter(')content(a)delimiter(')>operator(,) operator([)integer(4)operator(,) integer(5)operator(,) integer(6)operator(])operator(,) operator([)integer(7)operator(,) integer(8)operator(,) integer(9)operator(])operator(\)) + constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptCollectionProxy)operator(.)ident(new)operator(()instance_variable(@generator)operator(,) string<delimiter(')content([1, 2, 3])delimiter(')>operator(\))operator(.)ident(zip)operator(()string<delimiter(')content(b)delimiter(')>operator(,) operator([)integer(4)operator(,) integer(5)operator(,) integer(6)operator(])operator(,) operator([)integer(7)operator(,) integer(8)operator(,) integer(9)operator(])operator(\)) reserved(do) operator(|)ident(array)operator(|) + instance_variable(@generator)operator(.)ident(call) string<delimiter(')content(array.reverse)delimiter(')> + reserved(end) + + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +var a = [1, 2, 3].zip([4, 5, 6], [7, 8, 9]\); +var b = [1, 2, 3].zip([4, 5, 6], [7, 8, 9], function(array\) { +return array.reverse(\); +}\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_collection_proxy_with_find_all) + instance_variable(@generator)operator(.)ident(select)operator(()string<delimiter(')content(p)delimiter(')>operator(\))operator(.)ident(find_all) string<delimiter(')content(a)delimiter(')> reserved(do) operator(|)ident(value)operator(,) ident(index)operator(|) + instance_variable(@generator) operator(<<) string<delimiter(')content((value.className == "welcome"\))delimiter(')> + reserved(end) + + ident(assert_equal) string<delimiter(<<-EOS)>operator(.)ident(strip)operator(,) instance_variable(@generator)operator(.)ident(to_s)string<content( +var a = $$("p"\).findAll(function(value, index\) { +return (value.className == "welcome"\); +}\);)delimiter( + EOS)> + reserved(end) + + reserved(def) method(test_debug_rjs) + constant(ActionView)operator(::)constant(Base)operator(.)ident(debug_rjs) operator(=) pre_constant(true) + instance_variable(@generator)operator([)string<delimiter(')content(welcome)delimiter(')>operator(])operator(.)ident(replace_html) string<delimiter(')content(Welcome)delimiter(')> + ident(assert_equal) string<delimiter(")content(try {)char(\\n)content($()char(\\")content(welcome)char(\\")content(\).update()char(\\")content(Welcome)char(\\")content(\);)char(\\n)content(} catch (e\) { alert('RJS error:)char(\\\\)content(n)char(\\\\)content(n' + e.toString(\)\); alert('$()char(\\\\)char(\\")content(welcome)char(\\\\)char(\\")content(\).update()char(\\\\)char(\\")content(Welcome)char(\\\\)char(\\")content(\);'\); throw e })delimiter(")>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(ensure) + constant(ActionView)operator(::)constant(Base)operator(.)ident(debug_rjs) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(test_class_proxy) + instance_variable(@generator)operator(.)ident(form)operator(.)ident(focus)operator(()string<delimiter(')content(my_field)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content(Form.focus()char(\\")content(my_field)char(\\")content(\);)delimiter(")>operator(,) instance_variable(@generator)operator(.)ident(to_s) + reserved(end) +reserved(end) + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +reserved(class) class(ScriptaculousHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(JavaScriptHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(PrototypeHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(ScriptaculousHelper) + + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(FormHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(CaptureHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(url) operator(=) string<delimiter(")content(http://www.example.com/)delimiter(")> + ident(url) operator(<<) ident(options)operator([)symbol(:action)operator(])operator(.)ident(to_s) reserved(if) ident(options) reserved(and) ident(options)operator([)symbol(:action)operator(]) + ident(url) + reserved(end) + reserved(end)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_effect) + ident(assert_equal) string<delimiter(")content(new Effect.Highlight()char(\\")content(posts)char(\\")content(,{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:highlight)operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(new Effect.Highlight()char(\\")content(posts)char(\\")content(,{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()string<delimiter(")content(highlight)delimiter(")>operator(,) symbol(:posts)operator(\)) + ident(assert_equal) string<delimiter(")content(new Effect.Highlight()char(\\")content(posts)char(\\")content(,{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:highlight)operator(,) symbol(:posts)operator(\)) + ident(assert_equal) string<delimiter(")content(new Effect.Fade()char(\\")content(fademe)char(\\")content(,{duration:4.0}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:fade)operator(,) string<delimiter(")content(fademe)delimiter(")>operator(,) symbol(:duration) operator(=)operator(>) float(4.0)operator(\)) + ident(assert_equal) string<delimiter(")content(new Effect.Shake(element,{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:shake)operator(\)) + ident(assert_equal) string<delimiter(")content(new Effect.DropOut()char(\\")content(dropme)char(\\")content(,{queue:'end'}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:drop_out)operator(,) string<delimiter(')content(dropme)delimiter(')>operator(,) symbol(:queue) operator(=)operator(>) symbol(:end)operator(\)) + + comment(# chop the queue params into a comma separated list) + ident(beginning)operator(,) ident(ending) operator(=) string<delimiter(')content(new Effect.DropOut("dropme",{queue:{)delimiter(')>operator(,) string<delimiter(')content(}}\);)delimiter(')> + ident(ve) operator(=) operator([) + ident(visual_effect)operator(()symbol(:drop_out)operator(,) string<delimiter(')content(dropme)delimiter(')>operator(,) symbol(:queue) operator(=)operator(>) operator({)symbol(:position) operator(=)operator(>) string<delimiter(")content(end)delimiter(")>operator(,) symbol(:scope) operator(=)operator(>) string<delimiter(")content(test)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(})operator(\))operator(,) + ident(visual_effect)operator(()symbol(:drop_out)operator(,) string<delimiter(')content(dropme)delimiter(')>operator(,) symbol(:queue) operator(=)operator(>) operator({)symbol(:scope) operator(=)operator(>) symbol(:list)operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(})operator(\))operator(,) + ident(visual_effect)operator(()symbol(:drop_out)operator(,) string<delimiter(')content(dropme)delimiter(')>operator(,) symbol(:queue) operator(=)operator(>) operator({)symbol(:position) operator(=)operator(>) symbol(:end)operator(,) symbol(:scope) operator(=)operator(>) symbol(:test)operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(})operator(\)) + operator(])operator(.)ident(collect) operator({) operator(|)ident(v)operator(|) ident(v)operator([)ident(beginning)operator(.)ident(length)operator(..)operator(-)ident(ending)operator(.)ident(length)operator(-)integer(1)operator(])operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) operator(}) + + ident(assert) ident(ve)operator([)integer(0)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(limit:2)delimiter(")>operator(\)) + ident(assert) ident(ve)operator([)integer(0)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(scope:'test')delimiter(")>operator(\)) + ident(assert) ident(ve)operator([)integer(0)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(position:'end')delimiter(")>operator(\)) + + ident(assert) ident(ve)operator([)integer(1)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(limit:2)delimiter(")>operator(\)) + ident(assert) ident(ve)operator([)integer(1)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(scope:'list')delimiter(")>operator(\)) + + ident(assert) ident(ve)operator([)integer(2)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(limit:2)delimiter(")>operator(\)) + ident(assert) ident(ve)operator([)integer(2)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(scope:'test')delimiter(")>operator(\)) + ident(assert) ident(ve)operator([)integer(2)operator(])operator(.)ident(include?)operator(()string<delimiter(")content(position:'end')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_toggle_effects) + ident(assert_equal) string<delimiter(")content(Effect.toggle()char(\\")content(posts)char(\\")content(,'appear',{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:toggle_appear)operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Effect.toggle()char(\\")content(posts)char(\\")content(,'slide',{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:toggle_slide)operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Effect.toggle()char(\\")content(posts)char(\\")content(,'blind',{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()symbol(:toggle_blind)operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Effect.toggle()char(\\")content(posts)char(\\")content(,'appear',{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()string<delimiter(")content(toggle_appear)delimiter(")>operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Effect.toggle()char(\\")content(posts)char(\\")content(,'slide',{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()string<delimiter(")content(toggle_slide)delimiter(")>operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Effect.toggle()char(\\")content(posts)char(\\")content(,'blind',{}\);)delimiter(")>operator(,) ident(visual_effect)operator(()string<delimiter(")content(toggle_blind)delimiter(")>operator(,) string<delimiter(")content(posts)delimiter(")>operator(\)) + reserved(end) + + + reserved(def) method(test_sortable_element) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Sortable.create)nesting_delimiter(()char(\\")content(mylist)char(\\")content(, {onUpdate:function)nesting_delimiter(()nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize)nesting_delimiter(()char(\\")content(mylist)char(\\")nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(sortable_element)operator(()string<delimiter(")content(mylist)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + ident(assert_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Sortable.create)nesting_delimiter(()char(\\")content(mylist)char(\\")content(, {constraint:'horizontal', onUpdate:function)nesting_delimiter(()nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize)nesting_delimiter(()char(\\")content(mylist)char(\\")nesting_delimiter(\))content(})nesting_delimiter(\))content(}, tag:'div'})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(sortable_element)operator(()string<delimiter(")content(mylist)delimiter(")>operator(,) symbol(:tag) operator(=)operator(>) string<delimiter(")content(div)delimiter(")>operator(,) symbol(:constraint) operator(=)operator(>) string<delimiter(")content(horizontal)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%|)content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Sortable.create()char(\\")content(mylist)char(\\")content(, {constraint:'horizontal', containment:['list1','list2'], onUpdate:function(\){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize()char(\\")content(mylist)char(\\")content(\)}\)}}\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(|)>operator(,) + ident(sortable_element)operator(()string<delimiter(")content(mylist)delimiter(")>operator(,) symbol(:containment) operator(=)operator(>) operator([)string<delimiter(')content(list1)delimiter(')>operator(,)string<delimiter(')content(list2)delimiter(')>operator(])operator(,) symbol(:constraint) operator(=)operator(>) string<delimiter(")content(horizontal)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Sortable.create)nesting_delimiter(()char(\\")content(mylist)char(\\")content(, {constraint:'horizontal', containment:'list1', onUpdate:function)nesting_delimiter(()nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize)nesting_delimiter(()char(\\")content(mylist)char(\\")nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(sortable_element)operator(()string<delimiter(")content(mylist)delimiter(")>operator(,) symbol(:containment) operator(=)operator(>) string<delimiter(')content(list1)delimiter(')>operator(,) symbol(:constraint) operator(=)operator(>) string<delimiter(")content(horizontal)delimiter(")>operator(,) symbol(:url) operator(=)operator(>) operator({) symbol(:action) operator(=)operator(>) string<delimiter(")content(order)delimiter(")> operator(})operator(\)) + reserved(end) + + reserved(def) method(test_draggable_element) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Draggable)nesting_delimiter(()char(\\")content(product_13)char(\\")content(, {})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(draggable_element)operator(()string<delimiter(")content(product_13)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(new Draggable)nesting_delimiter(()char(\\")content(product_13)char(\\")content(, {revert:true})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(draggable_element)operator(()string<delimiter(")content(product_13)delimiter(")>operator(,) symbol(:revert) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_drop_receiving_element) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Droppables.add)nesting_delimiter(()char(\\")content(droptarget1)char(\\")content(, {onDrop:function)nesting_delimiter(()content(element)nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent)nesting_delimiter(()content(element.id)nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(drop_receiving_element)operator(()string<delimiter(")content(droptarget1)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Droppables.add)nesting_delimiter(()char(\\")content(droptarget1)char(\\")content(, {accept:'products', onDrop:function)nesting_delimiter(()content(element)nesting_delimiter(\))content({new Ajax.Request)nesting_delimiter(()content('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent)nesting_delimiter(()content(element.id)nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(drop_receiving_element)operator(()string<delimiter(")content(droptarget1)delimiter(")>operator(,) symbol(:accept) operator(=)operator(>) string<delimiter(')content(products)delimiter(')>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Droppables.add)nesting_delimiter(()char(\\")content(droptarget1)char(\\")content(, {accept:'products', onDrop:function)nesting_delimiter(()content(element)nesting_delimiter(\))content({new Ajax.Updater)nesting_delimiter(()content('infobox', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent)nesting_delimiter(()content(element.id)nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(drop_receiving_element)operator(()string<delimiter(")content(droptarget1)delimiter(")>operator(,) symbol(:accept) operator(=)operator(>) string<delimiter(')content(products)delimiter(')>operator(,) symbol(:update) operator(=)operator(>) string<delimiter(')content(infobox)delimiter(')>operator(\)) + ident(assert_dom_equal) string<delimiter(%()content(<script type=)char(\\")content(text/javascript)char(\\")content(>)char(\\n)content(//<![CDATA[)char(\\n)content(Droppables.add)nesting_delimiter(()char(\\")content(droptarget1)char(\\")content(, {accept:['tshirts','mugs'], onDrop:function)nesting_delimiter(()content(element)nesting_delimiter(\))content({new Ajax.Updater)nesting_delimiter(()content('infobox', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent)nesting_delimiter(()content(element.id)nesting_delimiter(\))content(})nesting_delimiter(\))content(}})nesting_delimiter(\))char(\\n)content(//]]>)char(\\n)content(</script>)delimiter(\))>operator(,) + ident(drop_receiving_element)operator(()string<delimiter(")content(droptarget1)delimiter(")>operator(,) symbol(:accept) operator(=)operator(>) operator([)string<delimiter(')content(tshirts)delimiter(')>operator(,)string<delimiter(')content(mugs)delimiter(')>operator(])operator(,) symbol(:update) operator(=)operator(>) string<delimiter(')content(infobox)delimiter(')>operator(\)) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/tag_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/url_helper)delimiter(')> + +reserved(class) class(TagHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + + reserved(def) method(test_tag) + ident(assert_equal) string<delimiter(")content(<p class=)char(\\")content(show)char(\\")content( />)delimiter(")>operator(,) ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(\)) + ident(assert_equal) ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(\))operator(,) ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_tag_options) + ident(assert_equal) string<delimiter(")content(<p class=)char(\\")content(elsewhere)char(\\")content( />)delimiter(")>operator(,) ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(")content(elsewhere)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_tag_options_rejects_nil_option) + ident(assert_equal) string<delimiter(")content(<p />)delimiter(")>operator(,) ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) symbol(:ignored) operator(=)operator(>) pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(test_tag_options_accepts_blank_option) + ident(assert_equal) string<delimiter(")content(<p included=)char(\\")char(\\")content( />)delimiter(")>operator(,) ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) symbol(:included) operator(=)operator(>) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_tag_options_converts_boolean_option) + ident(assert_equal) string<delimiter(')content(<p disabled="disabled" multiple="multiple" readonly="readonly" />)delimiter(')>operator(,) + ident(tag)operator(()string<delimiter(")content(p)delimiter(")>operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(,) symbol(:multiple) operator(=)operator(>) pre_constant(true)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_content_tag) + ident(assert_equal) string<delimiter(")content(<a href=)char(\\")content(create)char(\\")content(>Create</a>)delimiter(")>operator(,) ident(content_tag)operator(()string<delimiter(")content(a)delimiter(")>operator(,) string<delimiter(")content(Create)delimiter(")>operator(,) string<delimiter(")content(href)delimiter(")> operator(=)operator(>) string<delimiter(")content(create)delimiter(")>operator(\)) + ident(assert_equal) ident(content_tag)operator(()string<delimiter(")content(a)delimiter(")>operator(,) string<delimiter(")content(Create)delimiter(")>operator(,) string<delimiter(")content(href)delimiter(")> operator(=)operator(>) string<delimiter(")content(create)delimiter(")>operator(\))operator(,) + ident(content_tag)operator(()string<delimiter(")content(a)delimiter(")>operator(,) string<delimiter(")content(Create)delimiter(")>operator(,) symbol(:href) operator(=)operator(>) string<delimiter(")content(create)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_cdata_section) + ident(assert_equal) string<delimiter(")content(<![CDATA[<hello world>]]>)delimiter(")>operator(,) ident(cdata_section)operator(()string<delimiter(")content(<hello world>)delimiter(")>operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> +ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../testing_sandbox)delimiter(")> + +reserved(class) class(TextHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TextHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + ident(include) constant(TestingSandbox) + + reserved(def) method(setup) + comment(# This simulates the fact that instance variables are reset every time) + comment(# a view is rendered. The cycle helper depends on this behavior.) + instance_variable(@_cycles) operator(=) pre_constant(nil) reserved(if) operator(()reserved(defined?) instance_variable(@_cycles)operator(\)) + reserved(end) + + reserved(def) method(test_simple_format) + ident(assert_equal) string<delimiter(")content(<p>crazy)char(\\n)content(<br /> cross)char(\\n)content(<br /> platform linebreaks</p>)delimiter(")>operator(,) ident(simple_format)operator(()string<delimiter(")content(crazy)char(\\r)char(\\n)content( cross)char(\\r)content( platform linebreaks)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(<p>A paragraph</p>)char(\\n)char(\\n)content(<p>and another one!</p>)delimiter(")>operator(,) ident(simple_format)operator(()string<delimiter(")content(A paragraph)char(\\n)char(\\n)content(and another one!)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(<p>A paragraph)char(\\n)content(<br /> With a newline</p>)delimiter(")>operator(,) ident(simple_format)operator(()string<delimiter(")content(A paragraph)char(\\n)content( With a newline)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_truncate) + ident(assert_equal) string<delimiter(")content(Hello World!)delimiter(")>operator(,) ident(truncate)operator(()string<delimiter(")content(Hello World!)delimiter(")>operator(,) integer(12)operator(\)) + ident(assert_equal) string<delimiter(")content(Hello Wor...)delimiter(")>operator(,) ident(truncate)operator(()string<delimiter(")content(Hello World!!)delimiter(")>operator(,) integer(12)operator(\)) + reserved(end) + + reserved(def) method(test_truncate_multibyte_without_kcode) + ident(result) operator(=) ident(execute_in_sandbox)operator(()string<delimiter(<<-'CODE')>operator(\))string<content( + require File.dirname(__FILE__\) + '/../../activesupport/lib/active_support/core_ext/kernel' + require "#{File.dirname(__FILE__\)}/../lib/action_view/helpers/text_helper" + include ActionView::Helpers::TextHelper + truncate(")content(\\3)content(54)content(\\2)content(25)content(\\2)content(10)content(\\3)content(53)content(\\2)content(05)content(\\2)content(25)content(\\3)content(55)content(\\2)content(25)content(\\2)content(30)content(\\3)content(54)content(\\2)content(04)content(\\2)content(70)content(\\3)content(54)content(\\2)content(32)content(\\2)content(24", 10\))delimiter( + CODE)> + + ident(assert_equal) string<delimiter(")char(\\354)char(\\225)char(\\210)char(\\353)char(\\205)char(\\225)char(\\355)content(...)delimiter(")>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_truncate_multibyte_with_kcode) + ident(result) operator(=) ident(execute_in_sandbox)operator(()string<delimiter(<<-'CODE')>operator(\))string<content( + $KCODE = "u" + require 'jcode' + + require File.dirname(__FILE__\) + '/../../activesupport/lib/active_support/core_ext/kernel' + require "#{File.dirname(__FILE__\)}/../lib/action_view/helpers/text_helper" + include ActionView::Helpers::TextHelper + truncate(")content(\\3)content(54)content(\\2)content(25)content(\\2)content(04)content(\\3)content(53)content(\\2)content(46)content(\\2)content(54)content(\\3)content(53)content(\\2)content(36)content(\\2)content(21 )content(\\3)content(54)content(\\2)content(25)content(\\2)content(04)content(\\3)content(53)content(\\2)content(46)content(\\2)content(54)content(\\3)content(53)content(\\2)content(36 )content(\\3)content(54)content(\\2)content(25)content(\\2)content(04)content(\\3)content(53)content(\\2)content(35)content(\\2)content(74)content(\\3)content(53)content(\\2)content(46)content(\\2)content(54)content(\\3)content(54)content(\\2)content(30)content(\\2)content(44", 10\))delimiter( + CODE)> + + ident(assert_equal) string<delimiter(")char(\\354)char(\\225)char(\\204)char(\\353)char(\\246)char(\\254)char(\\353)char(\\236)char(\\221)content( )char(\\354)char(\\225)char(\\204)char(\\353)char(\\246)char(\\254)char(\\353)char(\\236)content( ...)delimiter(")>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_strip_links) + ident(assert_equal) string<delimiter(")content(on my mind)delimiter(")>operator(,) ident(strip_links)operator(()string<delimiter(")content(<a href='almost'>on my mind</a>)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_highlighter) + ident(assert_equal)operator(() + string<delimiter(")content(This is a <strong class=)char(\\")content(highlight)char(\\")content(>beautiful</strong> morning)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This is a beautiful morning)delimiter(")>operator(,) string<delimiter(")content(beautiful)delimiter(")>operator(\)) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(")content(This is a <strong class=)char(\\")content(highlight)char(\\")content(>beautiful</strong> morning, but also a <strong class=)char(\\")content(highlight)char(\\")content(>beautiful</strong> day)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This is a beautiful morning, but also a beautiful day)delimiter(")>operator(,) string<delimiter(")content(beautiful)delimiter(")>operator(\)) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(")content(This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This is a beautiful morning, but also a beautiful day)delimiter(")>operator(,) string<delimiter(")content(beautiful)delimiter(")>operator(,) string<delimiter(')content(<b>)content(\\1)content(</b>)delimiter(')>operator(\)) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(")content(This text is not changed because we supplied an empty phrase)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This text is not changed because we supplied an empty phrase)delimiter(")>operator(,) pre_constant(nil)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_highlighter_with_regexp) + ident(assert_equal)operator(() + string<delimiter(")content(This is a <strong class=)char(\\")content(highlight)char(\\")content(>beautiful!</strong> morning)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This is a beautiful! morning)delimiter(")>operator(,) string<delimiter(")content(beautiful!)delimiter(")>operator(\)) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(")content(This is a <strong class=)char(\\")content(highlight)char(\\")content(>beautiful! morning</strong>)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This is a beautiful! morning)delimiter(")>operator(,) string<delimiter(")content(beautiful! morning)delimiter(")>operator(\)) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(")content(This is a <strong class=)char(\\")content(highlight)char(\\")content(>beautiful? morning</strong>)delimiter(")>operator(,) + ident(highlight)operator(()string<delimiter(")content(This is a beautiful? morning)delimiter(")>operator(,) string<delimiter(")content(beautiful? morning)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_excerpt) + ident(assert_equal)operator(()string<delimiter(")content(...is a beautiful morni...)delimiter(")>operator(,) ident(excerpt)operator(()string<delimiter(")content(This is a beautiful morning)delimiter(")>operator(,) string<delimiter(")content(beautiful)delimiter(")>operator(,) integer(5)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(This is a...)delimiter(")>operator(,) ident(excerpt)operator(()string<delimiter(")content(This is a beautiful morning)delimiter(")>operator(,) string<delimiter(")content(this)delimiter(")>operator(,) integer(5)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(...iful morning)delimiter(")>operator(,) ident(excerpt)operator(()string<delimiter(")content(This is a beautiful morning)delimiter(")>operator(,) string<delimiter(")content(morning)delimiter(")>operator(,) integer(5)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(...iful morning)delimiter(")>operator(,) ident(excerpt)operator(()string<delimiter(")content(This is a beautiful morning)delimiter(")>operator(,) string<delimiter(")content(morning)delimiter(")>operator(,) integer(5)operator(\))operator(\)) + ident(assert_nil) ident(excerpt)operator(()string<delimiter(")content(This is a beautiful morning)delimiter(")>operator(,) string<delimiter(")content(day)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_excerpt_with_regex) + ident(assert_equal)operator(()string<delimiter(')content(...is a beautiful! morn...)delimiter(')>operator(,) ident(excerpt)operator(()string<delimiter(')content(This is a beautiful! morning)delimiter(')>operator(,) string<delimiter(')content(beautiful)delimiter(')>operator(,) integer(5)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(...is a beautiful? morn...)delimiter(')>operator(,) ident(excerpt)operator(()string<delimiter(')content(This is a beautiful? morning)delimiter(')>operator(,) string<delimiter(')content(beautiful)delimiter(')>operator(,) integer(5)operator(\))operator(\)) + reserved(end) + + + reserved(def) method(test_word_wrap) + ident(assert_equal)operator(()string<delimiter(")content(my very very)char(\\n)content(very long)char(\\n)content(string)delimiter(")>operator(,) ident(word_wrap)operator(()string<delimiter(")content(my very very very long string)delimiter(")>operator(,) integer(15)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_pluralization) + ident(assert_equal)operator(()string<delimiter(")content(1 count)delimiter(")>operator(,) ident(pluralize)operator(()integer(1)operator(,) string<delimiter(")content(count)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2 counts)delimiter(")>operator(,) ident(pluralize)operator(()integer(2)operator(,) string<delimiter(")content(count)delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_auto_linking) + ident(email_raw) operator(=) string<delimiter(')content(david@loudthinking.com)delimiter(')> + ident(email_result) operator(=) string<delimiter(%{)content(<a href="mailto:)inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>content(</a>)delimiter(})> + ident(link_raw) operator(=) string<delimiter(')content(http://www.rubyonrails.com)delimiter(')> + ident(link_result) operator(=) string<delimiter(%{)content(<a href=")inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(</a>)delimiter(})> + ident(link_result_with_options) operator(=) string<delimiter(%{)content(<a href=")inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(" target="_blank">)inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(</a>)delimiter(})> + ident(link2_raw) operator(=) string<delimiter(')content(www.rubyonrails.com)delimiter(')> + ident(link2_result) operator(=) string<delimiter(%{)content(<a href="http://)inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>content(</a>)delimiter(})> + ident(link3_raw) operator(=) string<delimiter(')content(http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281)delimiter(')> + ident(link3_result) operator(=) string<delimiter(%{)content(<a href=")inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content(</a>)delimiter(})> + ident(link4_raw) operator(=) string<delimiter(')content(http://foo.example.com/controller/action?parm=value&p2=v2#anchor123)delimiter(')> + ident(link4_result) operator(=) string<delimiter(%{)content(<a href=")inline<inline_delimiter(#{)ident(link4_raw)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(link4_raw)inline_delimiter(})>content(</a>)delimiter(})> + ident(link5_raw) operator(=) string<delimiter(')content(http://foo.example.com:3000/controller/action)delimiter(')> + ident(link5_result) operator(=) string<delimiter(%{)content(<a href=")inline<inline_delimiter(#{)ident(link5_raw)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(link5_raw)inline_delimiter(})>content(</a>)delimiter(})> + + ident(assert_equal) string<delimiter(%()content(hello )inline<inline_delimiter(#{)ident(email_result)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(hello )inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:email_addresses)operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link_result)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:urls)operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:email_addresses)operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link_result)inline_delimiter(})>content( and say hello to )inline<inline_delimiter(#{)ident(email_result)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content( and say hello to )inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Link )inline<inline_delimiter(#{)ident(link_result)inline_delimiter(})>content(</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>Link )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>)inline<inline_delimiter(#{)ident(link_result)inline_delimiter(})>content( Link</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content( Link</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Link )inline<inline_delimiter(#{)ident(link_result_with_options)inline_delimiter(})>content(</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>Link )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(</p>)delimiter(")>operator(,) symbol(:all)operator(,) operator({)symbol(:target) operator(=)operator(>) string<delimiter(")content(_blank)delimiter(")>operator(})operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link_result)inline_delimiter(})>content(.)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(.)delimiter(\))>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Go to )inline<inline_delimiter(#{)ident(link_result)inline_delimiter(})>content(, then say hello to )inline<inline_delimiter(#{)ident(email_result)inline_delimiter(})>content(.</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(%()content(<p>Go to )inline<inline_delimiter(#{)ident(link_raw)inline_delimiter(})>content(, then say hello to )inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>content(.</p>)delimiter(\))>operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link2_result)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:urls)operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:email_addresses)operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Link )inline<inline_delimiter(#{)ident(link2_result)inline_delimiter(})>content(</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>Link )inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>content(</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>)inline<inline_delimiter(#{)ident(link2_result)inline_delimiter(})>content( Link</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>content( Link</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link2_result)inline_delimiter(})>content(.)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>content(.)delimiter(\))>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Say hello to )inline<inline_delimiter(#{)ident(email_result)inline_delimiter(})>content(, then go to )inline<inline_delimiter(#{)ident(link2_result)inline_delimiter(})>content(.</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(%()content(<p>Say hello to )inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>content(, then go to )inline<inline_delimiter(#{)ident(link2_raw)inline_delimiter(})>content(.</p>)delimiter(\))>operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link3_result)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:urls)operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(Go to )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>delimiter(")>operator(,) symbol(:email_addresses)operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Link )inline<inline_delimiter(#{)ident(link3_result)inline_delimiter(})>content(</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>Link )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content(</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>)inline<inline_delimiter(#{)ident(link3_result)inline_delimiter(})>content( Link</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content( Link</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link3_result)inline_delimiter(})>content(.)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(%()content(Go to )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content(.)delimiter(\))>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Go to )inline<inline_delimiter(#{)ident(link3_result)inline_delimiter(})>content(. seriously, )inline<inline_delimiter(#{)ident(link3_result)inline_delimiter(})>content(? i think I'll say hello to )inline<inline_delimiter(#{)ident(email_result)inline_delimiter(})>content(. instead.</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(%()content(<p>Go to )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content(. seriously, )inline<inline_delimiter(#{)ident(link3_raw)inline_delimiter(})>content(? i think I'll say hello to )inline<inline_delimiter(#{)ident(email_raw)inline_delimiter(})>content(. instead.</p>)delimiter(\))>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>Link )inline<inline_delimiter(#{)ident(link4_result)inline_delimiter(})>content(</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>Link )inline<inline_delimiter(#{)ident(link4_raw)inline_delimiter(})>content(</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>)inline<inline_delimiter(#{)ident(link4_result)inline_delimiter(})>content( Link</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(link4_raw)inline_delimiter(})>content( Link</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(%()content(<p>)inline<inline_delimiter(#{)ident(link5_result)inline_delimiter(})>content( Link</p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(link5_raw)inline_delimiter(})>content( Link</p>)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(')delimiter(')>operator(,) ident(auto_link)operator(()pre_constant(nil)operator(\)) + ident(assert_equal) string<delimiter(')delimiter(')>operator(,) ident(auto_link)operator(()string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_auto_link_at_eol) + ident(url1) operator(=) string<delimiter(")content(http://api.rubyonrails.com/Foo.html)delimiter(")> + ident(url2) operator(=) string<delimiter(")content(http://www.ruby-doc.org/core/Bar.html)delimiter(")> + + ident(assert_equal) string<delimiter(%()content(<p><a href=")inline<inline_delimiter(#{)ident(url1)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(url1)inline_delimiter(})>content(</a><br /><a href=")inline<inline_delimiter(#{)ident(url2)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(url2)inline_delimiter(})>content(</a><br /></p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(url1)inline_delimiter(})>content(<br />)inline<inline_delimiter(#{)ident(url2)inline_delimiter(})>content(<br /></p>)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_auto_link_with_block) + ident(url) operator(=) string<delimiter(")content(http://api.rubyonrails.com/Foo.html)delimiter(")> + ident(email) operator(=) string<delimiter(")content(fantabulous@shiznadel.ic)delimiter(")> + + ident(assert_equal) string<delimiter(%()content(<p><a href=")inline<inline_delimiter(#{)ident(url)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(url)operator([)integer(0)operator(...)integer(7)operator(])inline_delimiter(})>content(...</a><br /><a href="mailto:)inline<inline_delimiter(#{)ident(email)inline_delimiter(})>content(">)inline<inline_delimiter(#{)ident(email)operator([)integer(0)operator(...)integer(7)operator(])inline_delimiter(})>content(...</a><br /></p>)delimiter(\))>operator(,) ident(auto_link)operator(()string<delimiter(")content(<p>)inline<inline_delimiter(#{)ident(url)inline_delimiter(})>content(<br />)inline<inline_delimiter(#{)ident(email)inline_delimiter(})>content(<br /></p>)delimiter(")>operator(\)) operator({) operator(|)ident(url)operator(|) ident(truncate)operator(()ident(url)operator(,) integer(10)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_sanitize_form) + ident(raw) operator(=) string<delimiter(")content(<form action=)char(\\")content(/foo/bar)char(\\")content( method=)char(\\")content(post)char(\\")content(><input></form>)delimiter(")> + ident(result) operator(=) ident(sanitize)operator(()ident(raw)operator(\)) + ident(assert_equal) string<delimiter(")content(<form action='/foo/bar' method='post'><input></form>)delimiter(")>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_sanitize_script) + ident(raw) operator(=) string<delimiter(")content(<script language=)char(\\")content(Javascript)char(\\")content(>blah blah blah</script>)delimiter(")> + ident(result) operator(=) ident(sanitize)operator(()ident(raw)operator(\)) + ident(assert_equal) string<delimiter(")content(<script language='Javascript'>blah blah blah</script>)delimiter(")>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_sanitize_js_handlers) + ident(raw) operator(=) string<delimiter(%{)content(onthis="do that" <a href="#" onclick="hello" name="foo" onbogus="remove me">hello</a>)delimiter(})> + ident(result) operator(=) ident(sanitize)operator(()ident(raw)operator(\)) + ident(assert_equal) string<delimiter(%{)content(onthis="do that" <a name='foo' href='#'>hello</a>)delimiter(})>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_sanitize_javascript_href) + ident(raw) operator(=) string<delimiter(%{)content(href="javascript:bang" <a href="javascript:bang" name="hello">foo</a>, <span href="javascript:bang">bar</span>)delimiter(})> + ident(result) operator(=) ident(sanitize)operator(()ident(raw)operator(\)) + ident(assert_equal) string<delimiter(%{)content(href="javascript:bang" <a name='hello'>foo</a>, <span>bar</span>)delimiter(})>operator(,) ident(result) + reserved(end) + + reserved(def) method(test_cycle_class) + ident(value) operator(=) constant(Cycle)operator(.)ident(new)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(one)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(one)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + ident(value)operator(.)ident(reset) + ident(assert_equal)operator(()string<delimiter(")content(one)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(value)operator(.)ident(to_s)operator(\)) + reserved(end) + + reserved(def) method(test_cycle_class_with_no_arguments) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) ident(value) operator(=) constant(Cycle)operator(.)ident(new)operator(()operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_cycle) + ident(assert_equal)operator(()string<delimiter(")content(one)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(one)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(one)delimiter(")>operator(,) integer(2)operator(,) string<delimiter(")content(3)delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_cycle_with_no_arguments) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) ident(value) operator(=) ident(cycle)operator(()operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_cycle_resets_with_new_values) + ident(assert_equal)operator(()string<delimiter(")content(even)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(even)delimiter(")>operator(,) string<delimiter(")content(odd)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(odd)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(even)delimiter(")>operator(,) string<delimiter(")content(odd)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(even)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(even)delimiter(")>operator(,) string<delimiter(")content(odd)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_named_cycles) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(numbers)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(red)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(colors)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(numbers)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(blue)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(colors)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(numbers)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(red)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(colors)delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_default_named_cycle) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(default)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(3)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_reset_cycle) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + ident(reset_cycle) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_reset_unknown_cycle) + ident(reset_cycle)operator(()string<delimiter(")content(colors)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_recet_named_cycle) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(numbers)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(red)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(colors)delimiter(")>operator(\))operator(\)) + ident(reset_cycle)operator(()string<delimiter(")content(numbers)delimiter(")>operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(1)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(numbers)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(blue)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(colors)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(2)delimiter(")>operator(,) ident(cycle)operator(()integer(1)operator(,) integer(2)operator(,) integer(3)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(numbers)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(red)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(colors)delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_cycle_no_instance_variable_clashes) + instance_variable(@cycles) operator(=) string<delimiter(%w{)content(Specialized Fuji Giant)delimiter(})> + ident(assert_equal)operator(()string<delimiter(")content(red)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(blue)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(red)delimiter(")>operator(,) ident(cycle)operator(()string<delimiter(")content(red)delimiter(")>operator(,) string<delimiter(")content(blue)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(%w{)content(Specialized Fuji Giant)delimiter(})>operator(,) instance_variable(@cycles)operator(\)) + reserved(end) + + reserved(def) method(test_strip_tags) + ident(assert_equal)operator(()string<delimiter(")content(This is a test.)delimiter(")>operator(,) ident(strip_tags)operator(()string<delimiter(")content(<p>This <u>is<u> a <a href='test.html'><strong>test</strong></a>.</p>)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(This is a test.)delimiter(")>operator(,) ident(strip_tags)operator(()string<delimiter(")content(This is a test.)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(() + string<delimiter(%{)content(This is a test.)char(\\n)char(\\n)char(\\n)content(It no longer contains any HTML.)char(\\n)delimiter(})>operator(,) ident(strip_tags)operator(() + string<delimiter(%{)content(<title>This is <b>a <a href="" target="_blank">test</a></b>.</title>)char(\\n)char(\\n)content(<!-- it has a comment -->)char(\\n)char(\\n)content(<p>It no <b>longer <strong>contains <em>any <strike>HTML</strike></em>.</strong></b></p>)char(\\n)delimiter(})>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(This has a here.)delimiter(")>operator(,) ident(strip_tags)operator(()string<delimiter(")content(This has a <!-- comment --> here.)delimiter(")>operator(\))operator(\)) + reserved(end) + +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../abstract_unit)delimiter(')> + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/url_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/asset_tag_helper)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../lib/action_view/helpers/tag_helper)delimiter(')> + +constant(RequestMock) operator(=) constant(Struct)operator(.)ident(new)operator(()string<delimiter(")content(Request)delimiter(")>operator(,) symbol(:request_uri)operator(\)) + +reserved(class) class(UrlHelperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(AssetTagHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(UrlHelper) + ident(include) constant(ActionView)operator(::)constant(Helpers)operator(::)constant(TagHelper) + + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(Class)operator(.)ident(new) reserved(do) + ident(attr_accessor) symbol(:url) + reserved(def) method(url_for)operator(()ident(options)operator(,) operator(*)ident(parameters_for_method_reference)operator(\)) + ident(url) + reserved(end) + reserved(end) + instance_variable(@controller) operator(=) instance_variable(@controller)operator(.)ident(new) + instance_variable(@controller)operator(.)ident(url) operator(=) string<delimiter(")content(http://www.example.com)delimiter(")> + reserved(end) + + reserved(def) method(test_url_for_escapes_urls) + instance_variable(@controller)operator(.)ident(url) operator(=) string<delimiter(")content(http://www.example.com?a=b&c=d)delimiter(")> + ident(assert_equal) string<delimiter(")content(http://www.example.com?a=b&c=d)delimiter(")>operator(,) ident(url_for)operator(()symbol(:a) operator(=)operator(>) string<delimiter(')content(b)delimiter(')>operator(,) symbol(:c) operator(=)operator(>) string<delimiter(')content(d)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content(http://www.example.com?a=b&c=d)delimiter(")>operator(,) ident(url_for)operator(()symbol(:a) operator(=)operator(>) string<delimiter(')content(b)delimiter(')>operator(,) symbol(:c) operator(=)operator(>) string<delimiter(')content(d)delimiter(')>operator(,) symbol(:escape) operator(=)operator(>) pre_constant(true)operator(\)) + ident(assert_equal) string<delimiter(")content(http://www.example.com?a=b&c=d)delimiter(")>operator(,) ident(url_for)operator(()symbol(:a) operator(=)operator(>) string<delimiter(')content(b)delimiter(')>operator(,) symbol(:c) operator(=)operator(>) string<delimiter(')content(d)delimiter(')>operator(,) symbol(:escape) operator(=)operator(>) pre_constant(false)operator(\)) + reserved(end) + + comment(# todo: missing test cases) + reserved(def) method(test_button_to_with_straight_url) + ident(assert_dom_equal) string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")content(http://www.example.com)char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div><input type=)char(\\")content(submit)char(\\")content( value=)char(\\")content(Hello)char(\\")content( /></div></form>)delimiter(")>operator(,) ident(button_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_button_to_with_query) + ident(assert_dom_equal) string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")content(http://www.example.com/q1=v1&q2=v2)char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div><input type=)char(\\")content(submit)char(\\")content( value=)char(\\")content(Hello)char(\\")content( /></div></form>)delimiter(")>operator(,) ident(button_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com/q1=v1&q2=v2)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_button_to_with_query_and_no_name) + ident(assert_dom_equal) string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")content(http://www.example.com?q1=v1&q2=v2)char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div><input type=)char(\\")content(submit)char(\\")content( value=)char(\\")content(http://www.example.com?q1=v1&q2=v2)char(\\")content( /></div></form>)delimiter(")>operator(,) ident(button_to)operator(()pre_constant(nil)operator(,) string<delimiter(")content(http://www.example.com?q1=v1&q2=v2)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_button_to_with_javascript_confirm) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")content(http://www.example.com)char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div><input onclick=)char(\\")content(return confirm('Are you sure?'\);)char(\\")content( type=)char(\\")content(submit)char(\\")content( value=)char(\\")content(Hello)char(\\")content( /></div></form>)delimiter(")>operator(,) + ident(button_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(Are you sure?)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_button_to_enabled_disabled) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")content(http://www.example.com)char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div><input type=)char(\\")content(submit)char(\\")content( value=)char(\\")content(Hello)char(\\")content( /></div></form>)delimiter(")>operator(,) + ident(button_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(false)operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<form method=)char(\\")content(post)char(\\")content( action=)char(\\")content(http://www.example.com)char(\\")content( class=)char(\\")content(button-to)char(\\")content(><div><input disabled=)char(\\")content(disabled)char(\\")content( type=)char(\\")content(submit)char(\\")content( value=)char(\\")content(Hello)char(\\")content( /></div></form>)delimiter(")>operator(,) + ident(button_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:disabled) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_straight_url) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content(>Hello</a>)delimiter(")>operator(,) ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_query) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com?q1=v1&q2=v2)char(\\")content(>Hello</a>)delimiter(")>operator(,) ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com?q1=v1&q2=v2)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_query_and_no_name) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com?q1=v1&q2=v2)char(\\")content(>http://www.example.com?q1=v1&q2=v2</a>)delimiter(")>operator(,) ident(link_to)operator(()pre_constant(nil)operator(,) string<delimiter(")content(http://www.example.com?q1=v1&q2=v2)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_img) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content(><img src='/favicon.jpg' /></a>)delimiter(")>operator(,) ident(link_to)operator(()string<delimiter(")content(<img src='/favicon.jpg' />)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_link_with_nil_html_options) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content(>Hello</a>)delimiter(")>operator(,) ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) operator({)symbol(:action) operator(=)operator(>) string<delimiter(')content(myaction)delimiter(')>operator(})operator(,) pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_custom_onclick) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(alert('yay!'\))char(\\")content(>Hello</a>)delimiter(")>operator(,) ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:onclick) operator(=)operator(>) string<delimiter(")content(alert('yay!'\))delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_javascript_confirm) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(return confirm('Are you sure?'\);)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(Are you sure?)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(return confirm('You can)char(\\\\)content('t possibly be sure, can you?'\);)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(You can't possibly be sure, can you?)delimiter(")>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(return confirm('You can)char(\\\\)content('t possibly be sure,)char(\\\\)content(n can you?'\);)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(You can't possibly be sure,)char(\\n)content( can you?)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_popup) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(window.open(this.href\);return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:popup) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(window.open(this.href\);return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:popup) operator(=)operator(>) string<delimiter(')content(true)delimiter(')>operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(window.open(this.href,'window_name','width=300,height=300'\);return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:popup) operator(=)operator(>) operator([)string<delimiter(')content(window_name)delimiter(')>operator(,) string<delimiter(')content(width=300,height=300)delimiter(')>operator(])operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_with_popup_and_javascript_confirm) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(if (confirm('Fo)char(\\\\)content(' sho)char(\\\\)content('?'\)\) { window.open(this.href\); };return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) operator({) symbol(:popup) operator(=)operator(>) pre_constant(true)operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(Fo' sho'?)delimiter(")> operator(})operator(\)) + operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(if (confirm('Are you serious?'\)\) { window.open(this.href,'window_name','width=300,height=300'\); };return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) operator({) symbol(:popup) operator(=)operator(>) operator([)string<delimiter(')content(window_name)delimiter(')>operator(,) string<delimiter(')content(width=300,height=300)delimiter(')>operator(])operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(Are you serious?)delimiter(")> operator(})operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_using_post_javascript) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(var f = document.createElement('form'\); this.parentNode.appendChild(f\); f.method = 'POST'; f.action = this.href; f.submit(\);return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:post) operator(=)operator(>) pre_constant(true)operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_using_post_javascript_and_confirm) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content( onclick=)char(\\")content(if (confirm('Are you serious?'\)\) { var f = document.createElement('form'\); this.parentNode.appendChild(f\); f.method = 'POST'; f.action = this.href; f.submit(\); };return false;)char(\\")content(>Hello</a>)delimiter(")>operator(,) + ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:post) operator(=)operator(>) pre_constant(true)operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(Are you serious?)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_link_tag_using_post_javascript_and_popup) + ident(assert_raises)operator(()constant(ActionView)operator(::)constant(ActionViewError)operator(\)) operator({) ident(link_to)operator(()string<delimiter(")content(Hello)delimiter(")>operator(,) string<delimiter(")content(http://www.example.com)delimiter(")>operator(,) symbol(:popup) operator(=)operator(>) pre_constant(true)operator(,) symbol(:post) operator(=)operator(>) pre_constant(true)operator(,) symbol(:confirm) operator(=)operator(>) string<delimiter(")content(Are you serious?)delimiter(")>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_link_to_unless) + ident(assert_equal) string<delimiter(")content(Showing)delimiter(")>operator(,) ident(link_to_unless)operator(()pre_constant(true)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content(>Listing</a>)delimiter(")>operator(,) ident(link_to_unless)operator(()pre_constant(false)operator(,) string<delimiter(")content(Listing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(list)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Showing)delimiter(")>operator(,) ident(link_to_unless)operator(()pre_constant(true)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) + ident(assert_equal) string<delimiter(")content(<strong>Showing</strong>)delimiter(")>operator(,) ident(link_to_unless)operator(()pre_constant(true)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) operator({) operator(|)ident(name)operator(,) ident(options)operator(,) ident(html_options)operator(,) operator(*)ident(parameters_for_method_reference)operator(|) + string<delimiter(")content(<strong>)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(</strong>)delimiter(")> + operator(}) + ident(assert_equal) string<delimiter(")content(<strong>Showing</strong>)delimiter(")>operator(,) ident(link_to_unless)operator(()pre_constant(true)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) operator({) operator(|)ident(name)operator(|) + string<delimiter(")content(<strong>)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(</strong>)delimiter(")> + operator(}) + ident(assert_equal) string<delimiter(")content(test)delimiter(")>operator(,) ident(link_to_unless)operator(()pre_constant(true)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) operator({) + string<delimiter(")content(test)delimiter(")> + operator(}) + reserved(end) + + reserved(def) method(test_link_to_if) + ident(assert_equal) string<delimiter(")content(Showing)delimiter(")>operator(,) ident(link_to_if)operator(()pre_constant(false)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content(>Listing</a>)delimiter(")>operator(,) ident(link_to_if)operator(()pre_constant(true)operator(,) string<delimiter(")content(Listing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(list)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Showing)delimiter(")>operator(,) ident(link_to_if)operator(()pre_constant(false)operator(,) string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) + reserved(end) + + reserved(def) method(xtest_link_unless_current) + instance_variable(@request) operator(=) constant(RequestMock)operator(.)ident(new)operator(()string<delimiter(")content(http://www.example.com)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Showing)delimiter(")>operator(,) ident(link_to_unless_current)operator(()string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(\)) + instance_variable(@request) operator(=) constant(RequestMock)operator(.)ident(new)operator(()string<delimiter(")content(http://www.example.org)delimiter(")>operator(\)) + ident(assert) string<delimiter(")content(<a href=)char(\\")content(http://www.example.com)char(\\")content(>Listing</a>)delimiter(")>operator(,) ident(link_to_unless_current)operator(()string<delimiter(")content(Listing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(list)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(\)) + + instance_variable(@request) operator(=) constant(RequestMock)operator(.)ident(new)operator(()string<delimiter(")content(http://www.example.com)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Showing)delimiter(")>operator(,) ident(link_to_unless_current)operator(()string<delimiter(")content(Showing)delimiter(")>operator(,) symbol(:action) operator(=)operator(>) string<delimiter(")content(show)delimiter(")>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(")content(weblog)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) integer(1)operator(\)) + reserved(end) + + reserved(def) method(test_mail_to) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:david@loudthinking.com)char(\\")content(>david@loudthinking.com</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(david@loudthinking.com)delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:david@loudthinking.com)char(\\")content(>David Heinemeier Hansson</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(david@loudthinking.com)delimiter(")>operator(,) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(\)) + ident(assert_dom_equal)operator(() + string<delimiter(")content(<a class=)char(\\")content(admin)char(\\")content( href=)char(\\")content(mailto:david@loudthinking.com)char(\\")content(>David Heinemeier Hansson</a>)delimiter(")>operator(,) + ident(mail_to)operator(()string<delimiter(")content(david@loudthinking.com)delimiter(")>operator(,) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) string<delimiter(")content(admin)delimiter(")>operator(\)) + operator(\)) + ident(assert_equal) ident(mail_to)operator(()string<delimiter(")content(david@loudthinking.com)delimiter(")>operator(,) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(,) string<delimiter(")content(class)delimiter(")> operator(=)operator(>) string<delimiter(")content(admin)delimiter(")>operator(\))operator(,) + ident(mail_to)operator(()string<delimiter(")content(david@loudthinking.com)delimiter(")>operator(,) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(,) symbol(:class) operator(=)operator(>) string<delimiter(")content(admin)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_mail_to_with_javascript) + ident(assert_dom_equal) string<delimiter(")content(<script type=)char(\\")content(text/javascript)char(\\")content(>eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'\)\)</script>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(me@domain.com)delimiter(")>operator(,) string<delimiter(")content(My email)delimiter(")>operator(,) symbol(:encode) operator(=)operator(>) string<delimiter(")content(javascript)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_mail_with_options) + ident(assert_dom_equal)operator(() + string<delimiter(%()content(<a href="mailto:me@example.com?cc=ccaddress%40example.com&bcc=bccaddress%40example.com&body=This%20is%20the%20body%20of%20the%20message.&subject=This%20is%20an%20example%20email">My email</a>)delimiter(\))>operator(,) + ident(mail_to)operator(()string<delimiter(")content(me@example.com)delimiter(")>operator(,) string<delimiter(")content(My email)delimiter(")>operator(,) symbol(:cc) operator(=)operator(>) string<delimiter(")content(ccaddress@example.com)delimiter(")>operator(,) symbol(:bcc) operator(=)operator(>) string<delimiter(")content(bccaddress@example.com)delimiter(")>operator(,) symbol(:subject) operator(=)operator(>) string<delimiter(")content(This is an example email)delimiter(")>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(")content(This is the body of the message.)delimiter(")>operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_mail_to_with_img) + ident(assert_dom_equal) string<delimiter(%()content(<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>)delimiter(\))>operator(,) ident(mail_to)operator(()string<delimiter(')content(feedback@example.com)delimiter(')>operator(,) string<delimiter(')content(<img src="/feedback.png" />)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_mail_to_with_hex) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d)char(\\")content(>My email</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(me@domain.com)delimiter(")>operator(,) string<delimiter(")content(My email)delimiter(")>operator(,) symbol(:encode) operator(=)operator(>) string<delimiter(")content(hex)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_mail_to_with_replace_options) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:wolfgang@stufenlos.net)char(\\")content(>wolfgang(at\)stufenlos(dot\)net</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(wolfgang@stufenlos.net)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:replace_at) operator(=)operator(>) string<delimiter(")content((at\))delimiter(")>operator(,) symbol(:replace_dot) operator(=)operator(>) string<delimiter(")content((dot\))delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d)char(\\")content(>me(at\)domain.com</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(me@domain.com)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:encode) operator(=)operator(>) string<delimiter(")content(hex)delimiter(")>operator(,) symbol(:replace_at) operator(=)operator(>) string<delimiter(")content((at\))delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d)char(\\")content(>My email</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(me@domain.com)delimiter(")>operator(,) string<delimiter(")content(My email)delimiter(")>operator(,) symbol(:encode) operator(=)operator(>) string<delimiter(")content(hex)delimiter(")>operator(,) symbol(:replace_at) operator(=)operator(>) string<delimiter(")content((at\))delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<a href=)char(\\")content(mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d)char(\\")content(>me(at\)domain(dot\)com</a>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(me@domain.com)delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:encode) operator(=)operator(>) string<delimiter(")content(hex)delimiter(")>operator(,) symbol(:replace_at) operator(=)operator(>) string<delimiter(")content((at\))delimiter(")>operator(,) symbol(:replace_dot) operator(=)operator(>) string<delimiter(")content((dot\))delimiter(")>operator(\)) + ident(assert_dom_equal) string<delimiter(")content(<script type=)char(\\")content(text/javascript)char(\\")content(>eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'\)\)</script>)delimiter(")>operator(,) ident(mail_to)operator(()string<delimiter(")content(me@domain.com)delimiter(")>operator(,) string<delimiter(")content(My email)delimiter(")>operator(,) symbol(:encode) operator(=)operator(>) string<delimiter(")content(javascript)delimiter(")>operator(,) symbol(:replace_at) operator(=)operator(>) string<delimiter(")content((at\))delimiter(")>operator(,) symbol(:replace_dot) operator(=)operator(>) string<delimiter(")content((dot\))delimiter(")>operator(\)) + reserved(end) +reserved(end) +reserved(module) class(TestingSandbox) + + comment(# This whole thing *could* be much simpler, but I don't think Tempfile,) + comment(# popen and others exist on all platforms (like Windows\).) + reserved(def) method(execute_in_sandbox)operator(()ident(code)operator(\)) + ident(test_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/test.)inline<inline_delimiter(#{)global_variable($$)inline_delimiter(})>content(.rb)delimiter(")> + ident(res_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/test.)inline<inline_delimiter(#{)global_variable($$)inline_delimiter(})>content(.out)delimiter(")> + + constant(File)operator(.)ident(open)operator(()ident(test_name)operator(,) string<delimiter(")content(w+)delimiter(")>operator(\)) reserved(do) operator(|)ident(file)operator(|) + ident(file)operator(.)ident(write)operator(()string<delimiter(<<-CODE)>operator(\))string<content( + $:.unshift "../lib" + block = Proc.new do + )inline<inline_delimiter(#{)ident(code)inline_delimiter(})>content( + end + print block.call)delimiter( + CODE)> + reserved(end) + + ident(system)operator(()string<delimiter(")content(ruby )inline<inline_delimiter(#{)ident(test_name)inline_delimiter(})>content( > )inline<inline_delimiter(#{)ident(res_name)inline_delimiter(})>delimiter(")>operator(\)) reserved(or) ident(raise) string<delimiter(")content(could not run test in sandbox)delimiter(")> + constant(File)operator(.)ident(read)operator(()ident(res_name)operator(\)) + reserved(ensure) + constant(File)operator(.)ident(delete)operator(()ident(test_name)operator(\)) reserved(rescue) pre_constant(nil) + constant(File)operator(.)ident(delete)operator(()ident(res_name)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + +reserved(end) +reserved(class) class(DirectoryCategory) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:fullViewableName)operator(,) symbol(:string) + ident(member) symbol(:specialEncoding)operator(,) symbol(:string) +reserved(end) + +reserved(class) class(ResultElement) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:summary)operator(,) symbol(:string) + ident(member) symbol(:URL)operator(,) symbol(:string) + ident(member) symbol(:snippet)operator(,) symbol(:string) + ident(member) symbol(:title)operator(,) symbol(:string) + ident(member) symbol(:cachedSize)operator(,) symbol(:string) + ident(member) symbol(:relatedInformationPresent)operator(,) symbol(:bool) + ident(member) symbol(:hostName)operator(,) symbol(:string) + ident(member) symbol(:directoryCategory)operator(,) constant(DirectoryCategory) + ident(member) symbol(:directoryTitle)operator(,) symbol(:string) +reserved(end) + +reserved(class) class(GoogleSearchResult) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:documentFiltering)operator(,) symbol(:bool) + ident(member) symbol(:searchComments)operator(,) symbol(:string) + ident(member) symbol(:estimatedTotalResultsCount)operator(,) symbol(:int) + ident(member) symbol(:estimateIsExact)operator(,) symbol(:bool) + ident(member) symbol(:resultElements)operator(,) operator([)constant(ResultElement)operator(]) + ident(member) symbol(:searchQuery)operator(,) symbol(:string) + ident(member) symbol(:startIndex)operator(,) symbol(:int) + ident(member) symbol(:endIndex)operator(,) symbol(:int) + ident(member) symbol(:searchTips)operator(,) symbol(:string) + ident(member) symbol(:directoryCategories)operator(,) operator([)constant(DirectoryCategory)operator(]) + ident(member) symbol(:searchTime)operator(,) symbol(:float) +reserved(end) + +reserved(class) class(GoogleSearchAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + + ident(api_method) symbol(:doGetCachedPage)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:url)operator(=)operator(>)symbol(:string)operator(})operator(]) + ident(api_method) symbol(:doGetSpellingSuggestion)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:phrase)operator(=)operator(>)symbol(:string)operator(})operator(]) + + ident(api_method) symbol(:doGoogleSearch)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(GoogleSearchResult)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:q)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:start)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator({)symbol(:maxResults)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator({)symbol(:filter)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator({)symbol(:restrict)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:safeSearch)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator({)symbol(:lr)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:ie)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:oe)operator(=)operator(>)symbol(:string)operator(}) + operator(]) +reserved(end) +reserved(class) class(GoogleSearchController) operator(<) constant(ApplicationController) + ident(wsdl_service_name) string<delimiter(')content(GoogleSearch)delimiter(')> + + reserved(def) method(doGetCachedPage) + string<delimiter(")content(<html><body>i am a cached page. my key was %s, url was %s</body></html>)delimiter(")> operator(%) operator([)instance_variable(@params)operator([)string<delimiter(')content(key)delimiter(')>operator(])operator(,) instance_variable(@params)operator([)string<delimiter(')content(url)delimiter(')>operator(])operator(]) + reserved(end) + + reserved(def) method(doSpellingSuggestion) + string<delimiter(")content(%s: Did you mean '%s'?)delimiter(")> operator(%) operator([)instance_variable(@params)operator([)string<delimiter(')content(key)delimiter(')>operator(])operator(,) instance_variable(@params)operator([)string<delimiter(')content(phrase)delimiter(')>operator(])operator(]) + reserved(end) + + reserved(def) method(doGoogleSearch) + ident(resultElement) operator(=) constant(ResultElement)operator(.)ident(new) + ident(resultElement)operator(.)ident(summary) operator(=) string<delimiter(")content(ONlamp.com: Rolling with Ruby on Rails)delimiter(")> + ident(resultElement)operator(.)constant(URL) operator(=) string<delimiter(")content(http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html)delimiter(")> + ident(resultElement)operator(.)ident(snippet) operator(=) string<delimiter(")content(Curt Hibbs shows off Ruby on Rails by building a simple application that requires )delimiter(")> operator(+) + string<delimiter(")content(almost no Ruby experience. ... Rolling with Ruby on Rails. ...)delimiter(")> + ident(resultElement)operator(.)ident(title) operator(=) string<delimiter(")content(Teh Railz0r)delimiter(")> + ident(resultElement)operator(.)ident(cachedSize) operator(=) string<delimiter(")content(Almost no lines of code!)delimiter(")> + ident(resultElement)operator(.)ident(relatedInformationPresent) operator(=) pre_constant(true) + ident(resultElement)operator(.)ident(hostName) operator(=) string<delimiter(")content(rubyonrails.com)delimiter(")> + ident(resultElement)operator(.)ident(directoryCategory) operator(=) ident(category)operator(()string<delimiter(")content(Web Development)delimiter(")>operator(,) string<delimiter(")content(UTF-8)delimiter(")>operator(\)) + + ident(result) operator(=) constant(GoogleSearchResult)operator(.)ident(new) + ident(result)operator(.)ident(documentFiltering) operator(=) instance_variable(@params)operator([)string<delimiter(')content(filter)delimiter(')>operator(]) + ident(result)operator(.)ident(searchComments) operator(=) string<delimiter(")delimiter(")> + ident(result)operator(.)ident(estimatedTotalResultsCount) operator(=) integer(322000) + ident(result)operator(.)ident(estimateIsExact) operator(=) pre_constant(false) + ident(result)operator(.)ident(resultElements) operator(=) operator([)ident(resultElement)operator(]) + ident(result)operator(.)ident(searchQuery) operator(=) string<delimiter(")content(http://www.google.com/search?q=ruby+on+rails)delimiter(")> + ident(result)operator(.)ident(startIndex) operator(=) instance_variable(@params)operator([)string<delimiter(')content(start)delimiter(')>operator(]) + ident(result)operator(.)ident(endIndex) operator(=) instance_variable(@params)operator([)string<delimiter(')content(start)delimiter(')>operator(]) operator(+) instance_variable(@params)operator([)string<delimiter(')content(maxResults)delimiter(')>operator(]) + ident(result)operator(.)ident(searchTips) operator(=) string<delimiter(")char(\\")content(on)char(\\")content( is a very common word and was not included in your search [details])delimiter(")> + ident(result)operator(.)ident(searchTime) operator(=) float(0.000001) + + comment(# For Mono, we have to clone objects if they're referenced by more than one place, otherwise) + comment(# the Ruby SOAP collapses them into one instance and uses references all over the) + comment(# place, confusing Mono. ) + comment(#) + comment(# This has recently been fixed:) + comment(# http://bugzilla.ximian.com/show_bug.cgi?id=72265) + ident(result)operator(.)ident(directoryCategories) operator(=) operator([) + ident(category)operator(()string<delimiter(")content(Web Development)delimiter(")>operator(,) string<delimiter(")content(UTF-8)delimiter(")>operator(\))operator(,) + ident(category)operator(()string<delimiter(")content(Programming)delimiter(")>operator(,) string<delimiter(")content(US-ASCII)delimiter(")>operator(\))operator(,) + operator(]) + + ident(result) + reserved(end) + + ident(private) + reserved(def) method(category)operator(()ident(name)operator(,) ident(encoding)operator(\)) + ident(cat) operator(=) constant(DirectoryCategory)operator(.)ident(new) + ident(cat)operator(.)ident(fullViewableName) operator(=) ident(name)operator(.)ident(dup) + ident(cat)operator(.)ident(specialEncoding) operator(=) ident(encoding)operator(.)ident(dup) + ident(cat) + reserved(end) +reserved(end) +reserved(class) class(DirectoryCategory) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:fullViewableName)operator(,) symbol(:string) + ident(member) symbol(:specialEncoding)operator(,) symbol(:string) +reserved(end) + +reserved(class) class(ResultElement) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:summary)operator(,) symbol(:string) + ident(member) symbol(:URL)operator(,) symbol(:string) + ident(member) symbol(:snippet)operator(,) symbol(:string) + ident(member) symbol(:title)operator(,) symbol(:string) + ident(member) symbol(:cachedSize)operator(,) symbol(:string) + ident(member) symbol(:relatedInformationPresent)operator(,) symbol(:bool) + ident(member) symbol(:hostName)operator(,) symbol(:string) + ident(member) symbol(:directoryCategory)operator(,) constant(DirectoryCategory) + ident(member) symbol(:directoryTitle)operator(,) symbol(:string) +reserved(end) + +reserved(class) class(GoogleSearchResult) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:documentFiltering)operator(,) symbol(:bool) + ident(member) symbol(:searchComments)operator(,) symbol(:string) + ident(member) symbol(:estimatedTotalResultsCount)operator(,) symbol(:int) + ident(member) symbol(:estimateIsExact)operator(,) symbol(:bool) + ident(member) symbol(:resultElements)operator(,) operator([)constant(ResultElement)operator(]) + ident(member) symbol(:searchQuery)operator(,) symbol(:string) + ident(member) symbol(:startIndex)operator(,) symbol(:int) + ident(member) symbol(:endIndex)operator(,) symbol(:int) + ident(member) symbol(:searchTips)operator(,) symbol(:string) + ident(member) symbol(:directoryCategories)operator(,) operator([)constant(DirectoryCategory)operator(]) + ident(member) symbol(:searchTime)operator(,) symbol(:float) +reserved(end) + +reserved(class) class(GoogleSearchAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + + ident(api_method) symbol(:doGetCachedPage)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:url)operator(=)operator(>)symbol(:string)operator(})operator(]) + ident(api_method) symbol(:doGetSpellingSuggestion)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:phrase)operator(=)operator(>)symbol(:string)operator(})operator(]) + + ident(api_method) symbol(:doGoogleSearch)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(GoogleSearchResult)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:q)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:start)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator({)symbol(:maxResults)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator({)symbol(:filter)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator({)symbol(:restrict)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:safeSearch)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator({)symbol(:lr)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:ie)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:oe)operator(=)operator(>)symbol(:string)operator(}) + operator(]) +reserved(end) + +reserved(class) class(GoogleSearchService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(GoogleSearchAPI) + + reserved(def) method(doGetCachedPage)operator(()ident(key)operator(,) ident(url)operator(\)) + string<delimiter(")content(<html><body>i am a cached page</body></html>)delimiter(")> + reserved(end) + + reserved(def) method(doSpellingSuggestion)operator(()ident(key)operator(,) ident(phrase)operator(\)) + string<delimiter(")content(Did you mean 'teh'?)delimiter(")> + reserved(end) + + reserved(def) method(doGoogleSearch)operator(()ident(key)operator(,) ident(q)operator(,) ident(start)operator(,) ident(maxResults)operator(,) ident(filter)operator(,) ident(restrict)operator(,) ident(safeSearch)operator(,) ident(lr)operator(,) ident(ie)operator(,) ident(oe)operator(\)) + ident(resultElement) operator(=) constant(ResultElement)operator(.)ident(new) + ident(resultElement)operator(.)ident(summary) operator(=) string<delimiter(")content(ONlamp.com: Rolling with Ruby on Rails)delimiter(")> + ident(resultElement)operator(.)constant(URL) operator(=) string<delimiter(")content(http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html)delimiter(")> + ident(resultElement)operator(.)ident(snippet) operator(=) string<delimiter(")content(Curt Hibbs shows off Ruby on Rails by building a simple application that requires )delimiter(")> operator(+) + string<delimiter(")content(almost no Ruby experience. ... Rolling with Ruby on Rails. ...)delimiter(")> + ident(resultElement)operator(.)ident(title) operator(=) string<delimiter(")content(Teh Railz0r)delimiter(")> + ident(resultElement)operator(.)ident(cachedSize) operator(=) string<delimiter(")content(Almost no lines of code!)delimiter(")> + ident(resultElement)operator(.)ident(relatedInformationPresent) operator(=) pre_constant(true) + ident(resultElement)operator(.)ident(hostName) operator(=) string<delimiter(")content(rubyonrails.com)delimiter(")> + ident(resultElement)operator(.)ident(directoryCategory) operator(=) ident(category)operator(()string<delimiter(")content(Web Development)delimiter(")>operator(,) string<delimiter(")content(UTF-8)delimiter(")>operator(\)) + + ident(result) operator(=) constant(GoogleSearchResult)operator(.)ident(new) + ident(result)operator(.)ident(documentFiltering) operator(=) ident(filter) + ident(result)operator(.)ident(searchComments) operator(=) string<delimiter(")delimiter(")> + ident(result)operator(.)ident(estimatedTotalResultsCount) operator(=) integer(322000) + ident(result)operator(.)ident(estimateIsExact) operator(=) pre_constant(false) + ident(result)operator(.)ident(resultElements) operator(=) operator([)ident(resultElement)operator(]) + ident(result)operator(.)ident(searchQuery) operator(=) string<delimiter(")content(http://www.google.com/search?q=ruby+on+rails)delimiter(")> + ident(result)operator(.)ident(startIndex) operator(=) ident(start) + ident(result)operator(.)ident(endIndex) operator(=) ident(start) operator(+) ident(maxResults) + ident(result)operator(.)ident(searchTips) operator(=) string<delimiter(")char(\\")content(on)char(\\")content( is a very common word and was not included in your search [details])delimiter(")> + ident(result)operator(.)ident(searchTime) operator(=) float(0.000001) + + comment(# For Mono, we have to clone objects if they're referenced by more than one place, otherwise) + comment(# the Ruby SOAP collapses them into one instance and uses references all over the) + comment(# place, confusing Mono. ) + comment(#) + comment(# This has recently been fixed:) + comment(# http://bugzilla.ximian.com/show_bug.cgi?id=72265) + ident(result)operator(.)ident(directoryCategories) operator(=) operator([) + ident(category)operator(()string<delimiter(")content(Web Development)delimiter(")>operator(,) string<delimiter(")content(UTF-8)delimiter(")>operator(\))operator(,) + ident(category)operator(()string<delimiter(")content(Programming)delimiter(")>operator(,) string<delimiter(")content(US-ASCII)delimiter(")>operator(\))operator(,) + operator(]) + + ident(result) + reserved(end) + + ident(private) + reserved(def) method(category)operator(()ident(name)operator(,) ident(encoding)operator(\)) + ident(cat) operator(=) constant(DirectoryCategory)operator(.)ident(new) + ident(cat)operator(.)ident(fullViewableName) operator(=) ident(name)operator(.)ident(dup) + ident(cat)operator(.)ident(specialEncoding) operator(=) ident(encoding)operator(.)ident(dup) + ident(cat) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(google_search_service)delimiter(')> + +reserved(class) class(SearchController) operator(<) constant(ApplicationController) + ident(wsdl_service_name) string<delimiter(')content(GoogleSearch)delimiter(')> + ident(web_service_dispatching_mode) symbol(:delegated) + ident(web_service) symbol(:beta3)operator(,) constant(GoogleSearchService)operator(.)ident(new) +reserved(end) +reserved(class) class(DirectoryCategory) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:fullViewableName)operator(,) symbol(:string) + ident(member) symbol(:specialEncoding)operator(,) symbol(:string) +reserved(end) + +reserved(class) class(ResultElement) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:summary)operator(,) symbol(:string) + ident(member) symbol(:URL)operator(,) symbol(:string) + ident(member) symbol(:snippet)operator(,) symbol(:string) + ident(member) symbol(:title)operator(,) symbol(:string) + ident(member) symbol(:cachedSize)operator(,) symbol(:string) + ident(member) symbol(:relatedInformationPresent)operator(,) symbol(:bool) + ident(member) symbol(:hostName)operator(,) symbol(:string) + ident(member) symbol(:directoryCategory)operator(,) constant(DirectoryCategory) + ident(member) symbol(:directoryTitle)operator(,) symbol(:string) +reserved(end) + +reserved(class) class(GoogleSearchResult) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:documentFiltering)operator(,) symbol(:bool) + ident(member) symbol(:searchComments)operator(,) symbol(:string) + ident(member) symbol(:estimatedTotalResultsCount)operator(,) symbol(:int) + ident(member) symbol(:estimateIsExact)operator(,) symbol(:bool) + ident(member) symbol(:resultElements)operator(,) operator([)constant(ResultElement)operator(]) + ident(member) symbol(:searchQuery)operator(,) symbol(:string) + ident(member) symbol(:startIndex)operator(,) symbol(:int) + ident(member) symbol(:endIndex)operator(,) symbol(:int) + ident(member) symbol(:searchTips)operator(,) symbol(:string) + ident(member) symbol(:directoryCategories)operator(,) operator([)constant(DirectoryCategory)operator(]) + ident(member) symbol(:searchTime)operator(,) symbol(:float) +reserved(end) + +reserved(class) class(GoogleSearchAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + + ident(api_method) symbol(:doGetCachedPage)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:url)operator(=)operator(>)symbol(:string)operator(})operator(]) + ident(api_method) symbol(:doGetSpellingSuggestion)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:phrase)operator(=)operator(>)symbol(:string)operator(})operator(]) + + ident(api_method) symbol(:doGoogleSearch)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(GoogleSearchResult)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:q)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:start)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator({)symbol(:maxResults)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator({)symbol(:filter)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator({)symbol(:restrict)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:safeSearch)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator({)symbol(:lr)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:ie)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:oe)operator(=)operator(>)symbol(:string)operator(}) + operator(]) +reserved(end) +reserved(class) class(SearchController) operator(<) constant(ApplicationController) + ident(web_service_api) symbol(:google_search) + ident(wsdl_service_name) string<delimiter(')content(GoogleSearch)delimiter(')> + + reserved(def) method(doGetCachedPage) + string<delimiter(")content(<html><body>i am a cached page. my key was %s, url was %s</body></html>)delimiter(")> operator(%) operator([)instance_variable(@params)operator([)string<delimiter(')content(key)delimiter(')>operator(])operator(,) instance_variable(@params)operator([)string<delimiter(')content(url)delimiter(')>operator(])operator(]) + reserved(end) + + reserved(def) method(doSpellingSuggestion) + string<delimiter(")content(%s: Did you mean '%s'?)delimiter(")> operator(%) operator([)instance_variable(@params)operator([)string<delimiter(')content(key)delimiter(')>operator(])operator(,) instance_variable(@params)operator([)string<delimiter(')content(phrase)delimiter(')>operator(])operator(]) + reserved(end) + + reserved(def) method(doGoogleSearch) + ident(resultElement) operator(=) constant(ResultElement)operator(.)ident(new) + ident(resultElement)operator(.)ident(summary) operator(=) string<delimiter(")content(ONlamp.com: Rolling with Ruby on Rails)delimiter(")> + ident(resultElement)operator(.)constant(URL) operator(=) string<delimiter(")content(http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html)delimiter(")> + ident(resultElement)operator(.)ident(snippet) operator(=) string<delimiter(")content(Curt Hibbs shows off Ruby on Rails by building a simple application that requires )delimiter(")> operator(+) + string<delimiter(")content(almost no Ruby experience. ... Rolling with Ruby on Rails. ...)delimiter(")> + ident(resultElement)operator(.)ident(title) operator(=) string<delimiter(")content(Teh Railz0r)delimiter(")> + ident(resultElement)operator(.)ident(cachedSize) operator(=) string<delimiter(")content(Almost no lines of code!)delimiter(")> + ident(resultElement)operator(.)ident(relatedInformationPresent) operator(=) pre_constant(true) + ident(resultElement)operator(.)ident(hostName) operator(=) string<delimiter(")content(rubyonrails.com)delimiter(")> + ident(resultElement)operator(.)ident(directoryCategory) operator(=) ident(category)operator(()string<delimiter(")content(Web Development)delimiter(")>operator(,) string<delimiter(")content(UTF-8)delimiter(")>operator(\)) + + ident(result) operator(=) constant(GoogleSearchResult)operator(.)ident(new) + ident(result)operator(.)ident(documentFiltering) operator(=) instance_variable(@params)operator([)string<delimiter(')content(filter)delimiter(')>operator(]) + ident(result)operator(.)ident(searchComments) operator(=) string<delimiter(")delimiter(")> + ident(result)operator(.)ident(estimatedTotalResultsCount) operator(=) integer(322000) + ident(result)operator(.)ident(estimateIsExact) operator(=) pre_constant(false) + ident(result)operator(.)ident(resultElements) operator(=) operator([)ident(resultElement)operator(]) + ident(result)operator(.)ident(searchQuery) operator(=) string<delimiter(")content(http://www.google.com/search?q=ruby+on+rails)delimiter(")> + ident(result)operator(.)ident(startIndex) operator(=) instance_variable(@params)operator([)string<delimiter(')content(start)delimiter(')>operator(]) + ident(result)operator(.)ident(endIndex) operator(=) instance_variable(@params)operator([)string<delimiter(')content(start)delimiter(')>operator(]) operator(+) instance_variable(@params)operator([)string<delimiter(')content(maxResults)delimiter(')>operator(]) + ident(result)operator(.)ident(searchTips) operator(=) string<delimiter(")char(\\")content(on)char(\\")content( is a very common word and was not included in your search [details])delimiter(")> + ident(result)operator(.)ident(searchTime) operator(=) float(0.000001) + + comment(# For Mono, we have to clone objects if they're referenced by more than one place, otherwise) + comment(# the Ruby SOAP collapses them into one instance and uses references all over the) + comment(# place, confusing Mono. ) + comment(#) + comment(# This has recently been fixed:) + comment(# http://bugzilla.ximian.com/show_bug.cgi?id=72265) + ident(result)operator(.)ident(directoryCategories) operator(=) operator([) + ident(category)operator(()string<delimiter(")content(Web Development)delimiter(")>operator(,) string<delimiter(")content(UTF-8)delimiter(")>operator(\))operator(,) + ident(category)operator(()string<delimiter(")content(Programming)delimiter(")>operator(,) string<delimiter(")content(US-ASCII)delimiter(")>operator(\))operator(,) + operator(]) + + ident(result) + reserved(end) + + ident(private) + reserved(def) method(category)operator(()ident(name)operator(,) ident(encoding)operator(\)) + ident(cat) operator(=) constant(DirectoryCategory)operator(.)ident(new) + ident(cat)operator(.)ident(fullViewableName) operator(=) ident(name)operator(.)ident(dup) + ident(cat)operator(.)ident(specialEncoding) operator(=) ident(encoding)operator(.)ident(dup) + ident(cat) + reserved(end) +reserved(end) +comment(#) +comment(# see the blogger API spec at http://www.blogger.com/developers/api/1_docs/) +comment(# note that the method signatures are subtly different to metaWeblog, they) +comment(# are not identical. take care to ensure you handle the different semantics) +comment(# properly if you want to support blogger API too, to get maximum compatibility.) +comment(#) + +reserved(module) class(Blog) + reserved(class) class(Blog) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:url)operator(,) symbol(:string) + ident(member) symbol(:blogid)operator(,) symbol(:string) + ident(member) symbol(:blogName)operator(,) symbol(:string) + reserved(end) + + reserved(class) class(User) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:nickname)operator(,) symbol(:string) + ident(member) symbol(:userid)operator(,) symbol(:string) + ident(member) symbol(:url)operator(,) symbol(:string) + ident(member) symbol(:email)operator(,) symbol(:string) + ident(member) symbol(:lastname)operator(,) symbol(:string) + ident(member) symbol(:firstname)operator(,) symbol(:string) + reserved(end) +reserved(end) + +comment(#) +comment(# blogger) +comment(#) +reserved(class) class(BloggerAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + + ident(api_method) symbol(:newPost)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:appkey)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:blogid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:content)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:publish)operator(=)operator(>)symbol(:bool)operator(}) + operator(]) + + ident(api_method) symbol(:editPost)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:bool)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:appkey)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:postid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:content)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:publish)operator(=)operator(>)symbol(:bool)operator(}) + operator(]) + + ident(api_method) symbol(:getUsersBlogs)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Blog)operator(::)constant(Blog)operator(])operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:appkey)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(}) + operator(]) + + ident(api_method) symbol(:getUserInfo)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(Blog)operator(::)constant(User)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:appkey)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(}) + operator(]) +reserved(end) +ident(require) string<delimiter(')content(blogger_api)delimiter(')> + +reserved(class) class(BloggerService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(BloggerAPI) + + reserved(def) method(initialize) + instance_variable(@postid) operator(=) integer(0) + reserved(end) + + reserved(def) method(newPost)operator(()ident(key)operator(,) ident(id)operator(,) ident(user)operator(,) ident(pw)operator(,) ident(content)operator(,) ident(publish)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(id=)inline<inline_delimiter(#{)ident(id)inline_delimiter(})>content( user=)inline<inline_delimiter(#{)ident(user)inline_delimiter(})>content( pw=)inline<inline_delimiter(#{)ident(pw)inline_delimiter(})>content(, content=)inline<inline_delimiter(#{)ident(content)operator(.)ident(inspect)inline_delimiter(})>content( [)inline<inline_delimiter(#{)ident(publish)inline_delimiter(})>content(])delimiter(")> + operator(()instance_variable(@postid) operator(+=) integer(1)operator(\))operator(.)ident(to_s) + reserved(end) + + reserved(def) method(editPost)operator(()ident(key)operator(,) ident(post_id)operator(,) ident(user)operator(,) ident(pw)operator(,) ident(content)operator(,) ident(publish)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(id=)inline<inline_delimiter(#{)ident(post_id)inline_delimiter(})>content( user=)inline<inline_delimiter(#{)ident(user)inline_delimiter(})>content( pw=)inline<inline_delimiter(#{)ident(pw)inline_delimiter(})>content( content=)inline<inline_delimiter(#{)ident(content)operator(.)ident(inspect)inline_delimiter(})>content( [)inline<inline_delimiter(#{)ident(publish)inline_delimiter(})>content(])delimiter(")> + pre_constant(true) + reserved(end) + + reserved(def) method(getUsersBlogs)operator(()ident(key)operator(,) ident(user)operator(,) ident(pw)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(getting blogs for )inline<inline_delimiter(#{)ident(user)inline_delimiter(})>delimiter(")> + ident(blog) operator(=) constant(Blog)operator(::)constant(Blog)operator(.)ident(new)operator(() + symbol(:url) operator(=)operator(>)string<delimiter(')content(http://blog)delimiter(')>operator(,) + symbol(:blogid) operator(=)operator(>) string<delimiter(')content(myblog)delimiter(')>operator(,) + symbol(:blogName) operator(=)operator(>) string<delimiter(')content(My Blog)delimiter(')> + operator(\)) + operator([)ident(blog)operator(]) + reserved(end) + + reserved(def) method(getUserInfo)operator(()ident(key)operator(,) ident(user)operator(,) ident(pw)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(getting user info for )inline<inline_delimiter(#{)ident(user)inline_delimiter(})>delimiter(")> + constant(Blog)operator(::)constant(User)operator(.)ident(new)operator(()symbol(:nickname) operator(=)operator(>) string<delimiter(')content(user)delimiter(')>operator(,) symbol(:email) operator(=)operator(>) string<delimiter(')content(user@test.com)delimiter(')>operator(\)) + reserved(end) +reserved(end) +comment(# ) +comment(# here lie structures, cousins of those on http://www.xmlrpc.com/metaWeblog) +comment(# but they don't necessarily the real world reflect) +comment(# so if you do, find that your client complains:) +comment(# please tell, of problems you suffered through) +comment(#) + +reserved(module) class(Blog) + reserved(class) class(Post) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:title)operator(,) symbol(:string) + ident(member) symbol(:link)operator(,) symbol(:string) + ident(member) symbol(:description)operator(,) symbol(:string) + ident(member) symbol(:author)operator(,) symbol(:string) + ident(member) symbol(:category)operator(,) symbol(:string) + ident(member) symbol(:comments)operator(,) symbol(:string) + ident(member) symbol(:guid)operator(,) symbol(:string) + ident(member) symbol(:pubDate)operator(,) symbol(:string) + reserved(end) + + reserved(class) class(Category) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:description)operator(,) symbol(:string) + ident(member) symbol(:htmlUrl)operator(,) symbol(:string) + ident(member) symbol(:rssUrl)operator(,) symbol(:string) + reserved(end) +reserved(end) + +comment(#) +comment(# metaWeblog) +comment(#) +reserved(class) class(MetaWeblogAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + + ident(api_method) symbol(:newPost)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:blogid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:struct)operator(=)operator(>)constant(Blog)operator(::)constant(Post)operator(})operator(,) + operator({)symbol(:publish)operator(=)operator(>)symbol(:bool)operator(}) + operator(]) + + ident(api_method) symbol(:editPost)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:bool)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:postid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:struct)operator(=)operator(>)constant(Blog)operator(::)constant(Post)operator(})operator(,) + operator({)symbol(:publish)operator(=)operator(>)symbol(:bool)operator(})operator(,) + operator(]) + + ident(api_method) symbol(:getPost)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(Blog)operator(::)constant(Post)operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:postid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator(]) + + ident(api_method) symbol(:getCategories)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Blog)operator(::)constant(Category)operator(])operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:blogid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator(]) + + ident(api_method) symbol(:getRecentPosts)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Blog)operator(::)constant(Post)operator(])operator(])operator(,) symbol(:expects) operator(=)operator(>) operator([) + operator({)symbol(:blogid)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:username)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:password)operator(=)operator(>)symbol(:string)operator(})operator(,) + operator({)symbol(:numberOfPosts)operator(=)operator(>)symbol(:int)operator(})operator(,) + operator(]) +reserved(end) +ident(require) string<delimiter(')content(meta_weblog_api)delimiter(')> + +reserved(class) class(MetaWeblogService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(MetaWeblogAPI) + + reserved(def) method(initialize) + instance_variable(@postid) operator(=) integer(0) + reserved(end) + + reserved(def) method(newPost)operator(()ident(id)operator(,) ident(user)operator(,) ident(pw)operator(,) ident(struct)operator(,) ident(publish)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(id=)inline<inline_delimiter(#{)ident(id)inline_delimiter(})>content( user=)inline<inline_delimiter(#{)ident(user)inline_delimiter(})>content( pw=)inline<inline_delimiter(#{)ident(pw)inline_delimiter(})>content(, struct=)inline<inline_delimiter(#{)ident(struct)operator(.)ident(inspect)inline_delimiter(})>content( [)inline<inline_delimiter(#{)ident(publish)inline_delimiter(})>content(])delimiter(")> + operator(()instance_variable(@postid) operator(+=) integer(1)operator(\))operator(.)ident(to_s) + reserved(end) + + reserved(def) method(editPost)operator(()ident(post_id)operator(,) ident(user)operator(,) ident(pw)operator(,) ident(struct)operator(,) ident(publish)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(id=)inline<inline_delimiter(#{)ident(post_id)inline_delimiter(})>content( user=)inline<inline_delimiter(#{)ident(user)inline_delimiter(})>content( pw=)inline<inline_delimiter(#{)ident(pw)inline_delimiter(})>content( struct=)inline<inline_delimiter(#{)ident(struct)operator(.)ident(inspect)inline_delimiter(})>content( [)inline<inline_delimiter(#{)ident(publish)inline_delimiter(})>content(])delimiter(")> + pre_constant(true) + reserved(end) + + reserved(def) method(getPost)operator(()ident(post_id)operator(,) ident(user)operator(,) ident(pw)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(get post )inline<inline_delimiter(#{)ident(post_id)inline_delimiter(})>delimiter(")> + constant(Blog)operator(::)constant(Post)operator(.)ident(new)operator(()symbol(:title) operator(=)operator(>) string<delimiter(')content(hello world)delimiter(')>operator(,) symbol(:description) operator(=)operator(>) string<delimiter(')content(first post!)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(getCategories)operator(()ident(id)operator(,) ident(user)operator(,) ident(pw)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(categories for )inline<inline_delimiter(#{)ident(user)inline_delimiter(})>delimiter(")> + ident(cat) operator(=) constant(Blog)operator(::)constant(Category)operator(.)ident(new)operator(() + symbol(:description) operator(=)operator(>) string<delimiter(')content(Tech)delimiter(')>operator(,) + symbol(:htmlUrl) operator(=)operator(>) string<delimiter(')content(http://blog/tech)delimiter(')>operator(,) + symbol(:rssUrl) operator(=)operator(>) string<delimiter(')content(http://blog/tech.rss)delimiter(')>operator(\)) + operator([)ident(cat)operator(]) + reserved(end) + + reserved(def) method(getRecentPosts)operator(()ident(id)operator(,) ident(user)operator(,) ident(pw)operator(,) ident(num)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(recent )inline<inline_delimiter(#{)ident(num)inline_delimiter(})>content( posts for )inline<inline_delimiter(#{)ident(user)inline_delimiter(})>content( on blog )inline<inline_delimiter(#{)ident(id)inline_delimiter(})>delimiter(")> + ident(post1) operator(=) constant(Blog)operator(::)constant(Post)operator(.)ident(new)operator(() + symbol(:title) operator(=)operator(>) string<delimiter(')content(first post!)delimiter(')>operator(,) + symbol(:link) operator(=)operator(>) string<delimiter(')content(http://blog.xeraph.org/testOne.html)delimiter(')>operator(,) + symbol(:description) operator(=)operator(>) string<delimiter(')content(this is the first post)delimiter(')> + operator(\)) + ident(post2) operator(=) constant(Blog)operator(::)constant(Post)operator(.)ident(new)operator(() + symbol(:title) operator(=)operator(>) string<delimiter(')content(second post!)delimiter(')>operator(,) + symbol(:link) operator(=)operator(>) string<delimiter(')content(http://blog.xeraph.org/testTwo.html)delimiter(')>operator(,) + symbol(:description) operator(=)operator(>) string<delimiter(')content(this is the second post)delimiter(')> + operator(\)) + operator([)ident(post1)operator(,) ident(post2)operator(]) + reserved(end) +reserved(end) +comment(#) +comment(# example controller implementing both blogger and metaWeblog APIs) +comment(# in a way that should be compatible with clients supporting both/either.) +comment(#) +comment(# test by pointing your client at http://URL/xmlrpc/api) +comment(# ) + +ident(require) string<delimiter(')content(meta_weblog_service)delimiter(')> +ident(require) string<delimiter(')content(blogger_service)delimiter(')> + +reserved(class) class(XmlrpcController) operator(<) constant(ApplicationController) + ident(web_service_dispatching_mode) symbol(:layered) + + ident(web_service) symbol(:metaWeblog)operator(,) constant(MetaWeblogService)operator(.)ident(new) + ident(web_service) symbol(:blogger)operator(,) constant(BloggerService)operator(.)ident(new) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(API) comment(# :nodoc:) + comment(# A web service API class specifies the methods that will be available for) + comment(# invocation for an API. It also contains metadata such as the method type) + comment(# signature hints.) + comment(#) + comment(# It is not intended to be instantiated.) + comment(#) + comment(# It is attached to web service implementation classes like) + comment(# ActionWebService::Base and ActionController::Base derivatives by using) + comment(# <tt>container.web_service_api</tt>, where <tt>container</tt> is an) + comment(# ActionController::Base or a ActionWebService::Base.) + comment(#) + comment(# See ActionWebService::Container::Direct::ClassMethods for an example) + comment(# of use.) + reserved(class) class(Base) + comment(# Action WebService API subclasses should be reloaded by the dispatcher in Rails) + comment(# when Dependencies.mechanism = :load.) + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + comment(# Whether to transform the public API method names into camel-cased names ) + ident(class_inheritable_option) symbol(:inflect_names)operator(,) pre_constant(true) + + comment(# Whether to allow ActiveRecord::Base models in <tt>:expects</tt>.) + comment(# The default is +false+; you should be aware of the security implications) + comment(# of allowing this, and ensure that you don't allow remote callers to) + comment(# easily overwrite data they should not have access to.) + ident(class_inheritable_option) symbol(:allow_active_record_expects)operator(,) pre_constant(false) + + comment(# If present, the name of a method to call when the remote caller) + comment(# tried to call a nonexistent method. Semantically equivalent to) + comment(# +method_missing+.) + ident(class_inheritable_option) symbol(:default_api_method) + + comment(# Disallow instantiation) + ident(private_class_method) symbol(:new)operator(,) symbol(:allocate) + + reserved(class) operator(<<) class(self) + ident(include) constant(ActionWebService)operator(::)constant(SignatureTypes) + + comment(# API methods have a +name+, which must be the Ruby method name to use when) + comment(# performing the invocation on the web service object.) + comment(#) + comment(# The signatures for the method input parameters and return value can) + comment(# by specified in +options+.) + comment(#) + comment(# A signature is an array of one or more parameter specifiers. ) + comment(# A parameter specifier can be one of the following:) + comment(#) + comment(# * A symbol or string representing one of the Action Web Service base types.) + comment(# See ActionWebService::SignatureTypes for a canonical list of the base types.) + comment(# * The Class object of the parameter type) + comment(# * A single-element Array containing one of the two preceding items. This) + comment(# will cause Action Web Service to treat the parameter at that position) + comment(# as an array containing only values of the given type.) + comment(# * A Hash containing as key the name of the parameter, and as value) + comment(# one of the three preceding items) + comment(# ) + comment(# If no method input parameter or method return value signatures are given,) + comment(# the method is assumed to take no parameters and/or return no values of) + comment(# interest, and any values that are received by the server will be) + comment(# discarded and ignored.) + comment(#) + comment(# Valid options:) + comment(# [<tt>:expects</tt>] Signature for the method input parameters) + comment(# [<tt>:returns</tt>] Signature for the method return value) + comment(# [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value) + reserved(def) method(api_method)operator(()ident(name)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + reserved(unless) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(raise)operator(()constant(ActionWebServiceError)operator(,) string<delimiter(")content(Expected a Hash for options)delimiter(")>operator(\)) + reserved(end) + ident(validate_options)operator(()operator([)symbol(:expects)operator(,) symbol(:returns)operator(,) symbol(:expects_and_returns)operator(])operator(,) ident(options)operator(.)ident(keys)operator(\)) + reserved(if) ident(options)operator([)symbol(:expects_and_returns)operator(]) + ident(expects) operator(=) ident(options)operator([)symbol(:expects_and_returns)operator(]) + ident(returns) operator(=) ident(options)operator([)symbol(:expects_and_returns)operator(]) + reserved(else) + ident(expects) operator(=) ident(options)operator([)symbol(:expects)operator(]) + ident(returns) operator(=) ident(options)operator([)symbol(:returns)operator(]) + reserved(end) + ident(expects) operator(=) ident(canonical_signature)operator(()ident(expects)operator(\)) + ident(returns) operator(=) ident(canonical_signature)operator(()ident(returns)operator(\)) + reserved(if) ident(expects) + ident(expects)operator(.)ident(each) reserved(do) operator(|)ident(type)operator(|) + ident(type) operator(=) ident(type)operator(.)ident(element_type) reserved(if) ident(type)operator(.)ident(is_a?)operator(()constant(ArrayType)operator(\)) + reserved(if) ident(type)operator(.)ident(type_class)operator(.)ident(ancestors)operator(.)ident(include?)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(\)) operator(&&) operator(!)ident(allow_active_record_expects) + ident(raise)operator(()constant(ActionWebServiceError)operator(,) string<delimiter(")content(ActiveRecord model classes not allowed in :expects)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + ident(name) operator(=) ident(name)operator(.)ident(to_sym) + ident(public_name) operator(=) ident(public_api_method_name)operator(()ident(name)operator(\)) + ident(method) operator(=) constant(Method)operator(.)ident(new)operator(()ident(name)operator(,) ident(public_name)operator(,) ident(expects)operator(,) ident(returns)operator(\)) + ident(write_inheritable_hash)operator(()string<delimiter(")content(api_methods)delimiter(")>operator(,) ident(name) operator(=)operator(>) ident(method)operator(\)) + ident(write_inheritable_hash)operator(()string<delimiter(")content(api_public_method_names)delimiter(")>operator(,) ident(public_name) operator(=)operator(>) ident(name)operator(\)) + reserved(end) + + comment(# Whether the given method name is a service method on this API) + reserved(def) method(has_api_method?)operator(()ident(name)operator(\)) + ident(api_methods)operator(.)ident(has_key?)operator(()ident(name)operator(\)) + reserved(end) + + comment(# Whether the given public method name has a corresponding service method) + comment(# on this API) + reserved(def) method(has_public_api_method?)operator(()ident(public_name)operator(\)) + ident(api_public_method_names)operator(.)ident(has_key?)operator(()ident(public_name)operator(\)) + reserved(end) + + comment(# The corresponding public method name for the given service method name) + reserved(def) method(public_api_method_name)operator(()ident(name)operator(\)) + reserved(if) ident(inflect_names) + ident(name)operator(.)ident(to_s)operator(.)ident(camelize) + reserved(else) + ident(name)operator(.)ident(to_s) + reserved(end) + reserved(end) + + comment(# The corresponding service method name for the given public method name) + reserved(def) method(api_method_name)operator(()ident(public_name)operator(\)) + ident(api_public_method_names)operator([)ident(public_name)operator(]) + reserved(end) + + comment(# A Hash containing all service methods on this API, and their) + comment(# associated metadata.) + reserved(def) method(api_methods) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(api_methods)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + comment(# The Method instance for the given public API method name, if any) + reserved(def) method(public_api_method_instance)operator(()ident(public_method_name)operator(\)) + ident(api_method_instance)operator(()ident(api_method_name)operator(()ident(public_method_name)operator(\))operator(\)) + reserved(end) + + comment(# The Method instance for the given API method name, if any) + reserved(def) method(api_method_instance)operator(()ident(method_name)operator(\)) + ident(api_methods)operator([)ident(method_name)operator(]) + reserved(end) + + comment(# The Method instance for the default API method, if any) + reserved(def) method(default_api_method_instance) + reserved(return) pre_constant(nil) reserved(unless) ident(name) operator(=) ident(default_api_method) + ident(instance) operator(=) ident(read_inheritable_attribute)operator(()string<delimiter(")content(default_api_method_instance)delimiter(")>operator(\)) + reserved(if) ident(instance) operator(&&) ident(instance)operator(.)ident(name) operator(==) ident(name) + reserved(return) ident(instance) + reserved(end) + ident(instance) operator(=) constant(Method)operator(.)ident(new)operator(()ident(name)operator(,) ident(public_api_method_name)operator(()ident(name)operator(\))operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(\)) + ident(write_inheritable_attribute)operator(()string<delimiter(")content(default_api_method_instance)delimiter(")>operator(,) ident(instance)operator(\)) + ident(instance) + reserved(end) + + ident(private) + reserved(def) method(api_public_method_names) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(api_public_method_names)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + reserved(def) method(validate_options)operator(()ident(valid_option_keys)operator(,) ident(supplied_option_keys)operator(\)) + ident(unknown_option_keys) operator(=) ident(supplied_option_keys) operator(-) ident(valid_option_keys) + reserved(unless) ident(unknown_option_keys)operator(.)ident(empty?) + ident(raise)operator(()constant(ActionWebServiceError)operator(,) string<delimiter(")content(Unknown options: )inline<inline_delimiter(#{)ident(unknown_option_keys)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Represents an API method and its associated metadata, and provides functionality) + comment(# to assist in commonly performed API method tasks.) + reserved(class) class(Method) + ident(attr) symbol(:name) + ident(attr) symbol(:public_name) + ident(attr) symbol(:expects) + ident(attr) symbol(:returns) + + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(public_name)operator(,) ident(expects)operator(,) ident(returns)operator(\)) + instance_variable(@name) operator(=) ident(name) + instance_variable(@public_name) operator(=) ident(public_name) + instance_variable(@expects) operator(=) ident(expects) + instance_variable(@returns) operator(=) ident(returns) + instance_variable(@caster) operator(=) constant(ActionWebService)operator(::)constant(Casting)operator(::)constant(BaseCaster)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# The list of parameter names for this method) + reserved(def) method(param_names) + reserved(return) operator([)operator(]) reserved(unless) instance_variable(@expects) + instance_variable(@expects)operator(.)ident(map)operator({) operator(|)ident(type)operator(|) ident(type)operator(.)ident(name) operator(}) + reserved(end) + + comment(# Casts a set of Ruby values into the expected Ruby values) + reserved(def) method(cast_expects)operator(()ident(params)operator(\)) + instance_variable(@caster)operator(.)ident(cast_expects)operator(()ident(params)operator(\)) + reserved(end) + + comment(# Cast a Ruby return value into the expected Ruby value) + reserved(def) method(cast_returns)operator(()ident(return_value)operator(\)) + instance_variable(@caster)operator(.)ident(cast_returns)operator(()ident(return_value)operator(\)) + reserved(end) + + comment(# Returns the index of the first expected parameter) + comment(# with the given name) + reserved(def) method(expects_index_of)operator(()ident(param_name)operator(\)) + reserved(return) integer(-1) reserved(if) instance_variable(@expects)operator(.)ident(nil?) + operator(()integer(0)operator(..)operator(()instance_variable(@expects)operator(.)ident(length)operator(-)integer(1)operator(\))operator(\))operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + reserved(return) ident(i) reserved(if) instance_variable(@expects)operator([)ident(i)operator(])operator(.)ident(name)operator(.)ident(to_s) operator(==) ident(param_name)operator(.)ident(to_s) + reserved(end) + integer(-1) + reserved(end) + + comment(# Returns a hash keyed by parameter name for the given) + comment(# parameter list) + reserved(def) method(expects_to_hash)operator(()ident(params)operator(\)) + reserved(return) operator({)operator(}) reserved(if) instance_variable(@expects)operator(.)ident(nil?) + ident(h) operator(=) operator({)operator(}) + instance_variable(@expects)operator(.)ident(zip)operator(()ident(params)operator(\))operator({) operator(|)ident(type)operator(,) ident(param)operator(|) ident(h)operator([)ident(type)operator(.)ident(name)operator(]) operator(=) ident(param) operator(}) + ident(h) + reserved(end) + + comment(# Backwards compatibility with previous API) + reserved(def) method([])operator(()ident(sig_type)operator(\)) + reserved(case) ident(sig_type) + reserved(when) symbol(:expects) + instance_variable(@expects)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(compat_signature_entry)operator(()ident(x)operator(\))operator(}) + reserved(when) symbol(:returns) + instance_variable(@returns)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(compat_signature_entry)operator(()ident(x)operator(\))operator(}) + reserved(end) + reserved(end) + + comment(# String representation of this method) + reserved(def) method(to_s) + ident(fqn) operator(=) string<delimiter(")delimiter(")> + ident(fqn) operator(<<) operator(()instance_variable(@returns) operator(?) operator(()instance_variable(@returns)operator([)integer(0)operator(])operator(.)ident(human_name)operator(()pre_constant(false)operator(\)) operator(+) string<delimiter(")content( )delimiter(")>operator(\)) operator(:) string<delimiter(")content(void )delimiter(")>operator(\)) + ident(fqn) operator(<<) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@public_name)inline_delimiter(})>content(()delimiter(")> + ident(fqn) operator(<<) instance_variable(@expects)operator(.)ident(map)operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(human_name) operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) reserved(if) instance_variable(@expects) + ident(fqn) operator(<<) string<delimiter(")content(\))delimiter(")> + ident(fqn) + reserved(end) + + ident(private) + reserved(def) method(compat_signature_entry)operator(()ident(entry)operator(\)) + reserved(if) ident(entry)operator(.)ident(array?) + operator([)ident(compat_signature_entry)operator(()ident(entry)operator(.)ident(element_type)operator(\))operator(]) + reserved(else) + reserved(if) ident(entry)operator(.)ident(spec)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + operator({)ident(entry)operator(.)ident(spec)operator(.)ident(keys)operator(.)ident(first) operator(=)operator(>) ident(entry)operator(.)ident(type_class)operator(}) + reserved(else) + ident(entry)operator(.)ident(type_class) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(class) class(ActionWebServiceError) operator(<) constant(StandardError) comment(# :nodoc:) + reserved(end) + + comment(# An Action Web Service object implements a specified API.) + comment(#) + comment(# Used by controllers operating in _Delegated_ dispatching mode.) + comment(#) + comment(# ==== Example) + comment(# ) + comment(# class PersonService < ActionWebService::Base) + comment(# web_service_api PersonAPI) + comment(#) + comment(# def find_person(criteria\)) + comment(# Person.find_all [...]) + comment(# end) + comment(#) + comment(# def delete_person(id\)) + comment(# Person.find_by_id(id\).destroy) + comment(# end) + comment(# end) + comment(#) + comment(# class PersonAPI < ActionWebService::API::Base) + comment(# api_method :find_person, :expects => [SearchCriteria], :returns => [[Person]]) + comment(# api_method :delete_person, :expects => [:int]) + comment(# end) + comment(#) + comment(# class SearchCriteria < ActionWebService::Struct) + comment(# member :firstname, :string) + comment(# member :lastname, :string) + comment(# member :email, :string) + comment(# end) + reserved(class) class(Base) + comment(# Action WebService subclasses should be reloaded by the dispatcher in Rails) + comment(# when Dependencies.mechanism = :load.) + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + comment(# Whether to report exceptions back to the caller in the protocol's exception) + comment(# format) + ident(class_inheritable_option) symbol(:web_service_exception_reporting)operator(,) pre_constant(true) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(time)delimiter(')> +ident(require) string<delimiter(')content(date)delimiter(')> +ident(require) string<delimiter(')content(xmlrpc/datetime)delimiter(')> + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Casting) comment(# :nodoc:) + reserved(class) class(CastingError) operator(<) constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + comment(# Performs casting of arbitrary values into the correct types for the signature) + reserved(class) class(BaseCaster) comment(# :nodoc:) + reserved(def) method(initialize)operator(()ident(api_method)operator(\)) + instance_variable(@api_method) operator(=) ident(api_method) + reserved(end) + + comment(# Coerces the parameters in +params+ (an Enumerable\) into the types) + comment(# this method expects) + reserved(def) method(cast_expects)operator(()ident(params)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(cast_expects)operator(()instance_variable(@api_method)operator(,) ident(params)operator(\)) + reserved(end) + + comment(# Coerces the given +return_value+ into the type returned by this) + comment(# method) + reserved(def) method(cast_returns)operator(()ident(return_value)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(cast_returns)operator(()instance_variable(@api_method)operator(,) ident(return_value)operator(\)) + reserved(end) + + reserved(class) operator(<<) class(self) + ident(include) constant(ActionWebService)operator(::)constant(SignatureTypes) + + reserved(def) method(cast_expects)operator(()ident(api_method)operator(,) ident(params)operator(\)) comment(# :nodoc:) + reserved(return) operator([)operator(]) reserved(if) ident(api_method)operator(.)ident(expects)operator(.)ident(nil?) + ident(api_method)operator(.)ident(expects)operator(.)ident(zip)operator(()ident(params)operator(\))operator(.)ident(map)operator({) operator(|)ident(type)operator(,) ident(param)operator(|) ident(cast)operator(()ident(param)operator(,) ident(type)operator(\)) operator(}) + reserved(end) + + reserved(def) method(cast_returns)operator(()ident(api_method)operator(,) ident(return_value)operator(\)) comment(# :nodoc:) + reserved(return) pre_constant(nil) reserved(if) ident(api_method)operator(.)ident(returns)operator(.)ident(nil?) + ident(cast)operator(()ident(return_value)operator(,) ident(api_method)operator(.)ident(returns)operator([)integer(0)operator(])operator(\)) + reserved(end) + + reserved(def) method(cast)operator(()ident(value)operator(,) ident(signature_type)operator(\)) comment(# :nodoc:) + reserved(return) ident(value) reserved(if) ident(signature_type)operator(.)ident(nil?) comment(# signature.length != params.length) + reserved(return) pre_constant(nil) reserved(if) ident(value)operator(.)ident(nil?) + comment(# XMLRPC protocol doesn't support nil values. It uses false instead.) + comment(# It should never happen for SOAP.) + reserved(if) ident(signature_type)operator(.)ident(structured?) operator(&&) ident(value)operator(.)ident(equal?)operator(()pre_constant(false)operator(\)) + reserved(return) pre_constant(nil) + reserved(end) + reserved(unless) ident(signature_type)operator(.)ident(array?) operator(||) ident(signature_type)operator(.)ident(structured?) + reserved(return) ident(value) reserved(if) ident(canonical_type)operator(()ident(value)operator(.)ident(class)operator(\)) operator(==) ident(signature_type)operator(.)ident(type) + reserved(end) + reserved(if) ident(signature_type)operator(.)ident(array?) + reserved(unless) ident(value)operator(.)ident(respond_to?)operator(()symbol(:entries)operator(\)) operator(&&) operator(!)ident(value)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(raise) constant(CastingError)operator(,) string<delimiter(")content(Don't know how to cast )inline<inline_delimiter(#{)ident(value)operator(.)ident(class)inline_delimiter(})>content( into )inline<inline_delimiter(#{)ident(signature_type)operator(.)ident(type)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + ident(value)operator(.)ident(entries)operator(.)ident(map) reserved(do) operator(|)ident(entry)operator(|) + ident(cast)operator(()ident(entry)operator(,) ident(signature_type)operator(.)ident(element_type)operator(\)) + reserved(end) + reserved(elsif) ident(signature_type)operator(.)ident(structured?) + ident(cast_to_structured_type)operator(()ident(value)operator(,) ident(signature_type)operator(\)) + reserved(elsif) operator(!)ident(signature_type)operator(.)ident(custom?) + ident(cast_base_type)operator(()ident(value)operator(,) ident(signature_type)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(cast_base_type)operator(()ident(value)operator(,) ident(signature_type)operator(\)) comment(# :nodoc:) + comment(# This is a work-around for the fact that XML-RPC special-cases DateTime values into its own DateTime type) + comment(# in order to support iso8601 dates. This doesn't work too well for us, so we'll convert it into a Time,) + comment(# with the caveat that we won't be able to handle pre-1970 dates that are sent to us.) + comment(# ) + comment(# See http://dev.rubyonrails.com/ticket/2516) + ident(value) operator(=) ident(value)operator(.)ident(to_time) reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(XMLRPC)operator(::)constant(DateTime)operator(\)) + + reserved(case) ident(signature_type)operator(.)ident(type) + reserved(when) symbol(:int) + ident(Integer)operator(()ident(value)operator(\)) + reserved(when) symbol(:string) + ident(value)operator(.)ident(to_s) + reserved(when) symbol(:base64) + reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(ActionWebService)operator(::)constant(Base64)operator(\)) + ident(value) + reserved(else) + constant(ActionWebService)operator(::)constant(Base64)operator(.)ident(new)operator(()ident(value)operator(.)ident(to_s)operator(\)) + reserved(end) + reserved(when) symbol(:bool) + reserved(return) pre_constant(false) reserved(if) ident(value)operator(.)ident(nil?) + reserved(return) ident(value) reserved(if) ident(value) operator(==) pre_constant(true) operator(||) ident(value) operator(==) pre_constant(false) + reserved(case) ident(value)operator(.)ident(to_s)operator(.)ident(downcase) + reserved(when) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(true)delimiter(')>operator(,) string<delimiter(')content(y)delimiter(')>operator(,) string<delimiter(')content(yes)delimiter(')> + pre_constant(true) + reserved(when) string<delimiter(')content(0)delimiter(')>operator(,) string<delimiter(')content(false)delimiter(')>operator(,) string<delimiter(')content(n)delimiter(')>operator(,) string<delimiter(')content(no)delimiter(')> + pre_constant(false) + reserved(else) + ident(raise) constant(CastingError)operator(,) string<delimiter(")content(Don't know how to cast )inline<inline_delimiter(#{)ident(value)operator(.)ident(class)inline_delimiter(})>content( into Boolean)delimiter(")> + reserved(end) + reserved(when) symbol(:float) + ident(Float)operator(()ident(value)operator(\)) + reserved(when) symbol(:time) + ident(value) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(2)delimiter(')>operator(])inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(3)delimiter(')>operator(])inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(1)delimiter(')>operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(4)delimiter(')>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(5)delimiter(')>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(6)delimiter(')>operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(Hash)operator(\)) + constant(Time)operator(.)ident(parse)operator(()ident(value)operator(.)ident(to_s)operator(\)) + reserved(when) symbol(:date) + ident(value) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(2)delimiter(')>operator(])inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(3)delimiter(')>operator(])inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(1)delimiter(')>operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(Hash)operator(\)) + constant(Date)operator(.)ident(parse)operator(()ident(value)operator(.)ident(to_s)operator(\)) + reserved(when) symbol(:datetime) + ident(value) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(2)delimiter(')>operator(])inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(3)delimiter(')>operator(])inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(1)delimiter(')>operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(4)delimiter(')>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(5)delimiter(')>operator(])inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(value)operator([)string<delimiter(')content(6)delimiter(')>operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(Hash)operator(\)) + constant(DateTime)operator(.)ident(parse)operator(()ident(value)operator(.)ident(to_s)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(cast_to_structured_type)operator(()ident(value)operator(,) ident(signature_type)operator(\)) comment(# :nodoc:) + ident(obj) operator(=) pre_constant(nil) + ident(obj) operator(=) ident(value) reserved(if) ident(canonical_type)operator(()ident(value)operator(.)ident(class)operator(\)) operator(==) ident(canonical_type)operator(()ident(signature_type)operator(.)ident(type)operator(\)) + ident(obj) operator(||=) ident(signature_type)operator(.)ident(type_class)operator(.)ident(new) + reserved(if) ident(value)operator(.)ident(respond_to?)operator(()symbol(:each_pair)operator(\)) + ident(klass) operator(=) ident(signature_type)operator(.)ident(type_class) + ident(value)operator(.)ident(each_pair) reserved(do) operator(|)ident(name)operator(,) ident(val)operator(|) + ident(type) operator(=) ident(klass)operator(.)ident(respond_to?)operator(()symbol(:member_type)operator(\)) operator(?) ident(klass)operator(.)ident(member_type)operator(()ident(name)operator(\)) operator(:) pre_constant(nil) + ident(val) operator(=) ident(cast)operator(()ident(val)operator(,) ident(type)operator(\)) reserved(if) ident(type) + comment(# See http://dev.rubyonrails.com/ticket/3567) + ident(val) operator(=) ident(val)operator(.)ident(to_time) reserved(if) ident(val)operator(.)ident(is_a?)operator(()constant(XMLRPC)operator(::)constant(DateTime)operator(\)) + ident(obj)operator(.)ident(__send__)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(=)delimiter(")>operator(,) ident(val)operator(\)) reserved(if) ident(obj)operator(.)ident(respond_to?)operator(()ident(name)operator(\)) + reserved(end) + reserved(elsif) ident(value)operator(.)ident(respond_to?)operator(()symbol(:attributes)operator(\)) + ident(signature_type)operator(.)ident(each_member) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(|) + ident(val) operator(=) ident(value)operator(.)ident(__send__)operator(()ident(name)operator(\)) + ident(obj)operator(.)ident(__send__)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(=)delimiter(")>operator(,) ident(cast)operator(()ident(val)operator(,) ident(type)operator(\))operator(\)) reserved(if) ident(obj)operator(.)ident(respond_to?)operator(()ident(name)operator(\)) + reserved(end) + reserved(else) + ident(raise) constant(CastingError)operator(,) string<delimiter(")content(Don't know how to cast )inline<inline_delimiter(#{)ident(value)operator(.)ident(class)inline_delimiter(})>content( to )inline<inline_delimiter(#{)ident(signature_type)operator(.)ident(type_class)inline_delimiter(})>delimiter(")> + reserved(end) + ident(obj) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Client) comment(# :nodoc:) + reserved(class) class(ClientError) operator(<) constant(StandardError) comment(# :nodoc:) + reserved(end) + + reserved(class) class(Base) comment(# :nodoc:) + reserved(def) method(initialize)operator(()ident(api)operator(,) ident(endpoint_uri)operator(\)) + instance_variable(@api) operator(=) ident(api) + instance_variable(@endpoint_uri) operator(=) ident(endpoint_uri) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) comment(# :nodoc:) + ident(call_name) operator(=) ident(method_name)operator(()ident(name)operator(\)) + reserved(return) reserved(super)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) reserved(if) ident(call_name)operator(.)ident(nil?) + pre_constant(self)operator(.)ident(perform_invocation)operator(()ident(call_name)operator(,) ident(args)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(method_name)operator(()ident(name)operator(\)) + reserved(if) instance_variable(@api)operator(.)ident(has_api_method?)operator(()ident(name)operator(.)ident(to_sym)operator(\)) + ident(name)operator(.)ident(to_s) + reserved(elsif) instance_variable(@api)operator(.)ident(has_public_api_method?)operator(()ident(name)operator(.)ident(to_s)operator(\)) + instance_variable(@api)operator(.)ident(api_method_name)operator(()ident(name)operator(.)ident(to_s)operator(\))operator(.)ident(to_s) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(soap/rpc/driver)delimiter(')> +ident(require) string<delimiter(')content(uri)delimiter(')> + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Client) comment(# :nodoc:) + + comment(# Implements SOAP client support (using RPC encoding for the messages\).) + comment(#) + comment(# ==== Example Usage) + comment(#) + comment(# class PersonAPI < ActionWebService::API::Base) + comment(# api_method :find_all, :returns => [[Person]]) + comment(# end) + comment(#) + comment(# soap_client = ActionWebService::Client::Soap.new(PersonAPI, "http://..."\)) + comment(# persons = soap_client.find_all) + comment(#) + reserved(class) class(Soap) operator(<) constant(Base) + + comment(# Creates a new web service client using the SOAP RPC protocol.) + comment(#) + comment(# +api+ must be an ActionWebService::API::Base derivative, and) + comment(# +endpoint_uri+ must point at the relevant URL to which protocol requests) + comment(# will be sent with HTTP POST.) + comment(#) + comment(# Valid options:) + comment(# [<tt>:namespace</tt>] If the remote server has used a custom namespace to) + comment(# declare its custom types, you can specify it here. This would) + comment(# be the namespace declared with a [WebService(Namespace = "http://namespace"\)] attribute) + comment(# in .NET, for example.) + comment(# [<tt>:driver_options</tt>] If you want to supply any custom SOAP RPC driver) + comment(# options, you can provide them as a Hash here) + comment(#) + comment(# The <tt>:driver_options</tt> option can be used to configure the backend SOAP) + comment(# RPC driver. An example of configuring the SOAP backend to do) + comment(# client-certificate authenticated SSL connections to the server:) + comment(#) + comment(# opts = {}) + comment(# opts['protocol.http.ssl_config.verify_mode'] = 'OpenSSL::SSL::VERIFY_PEER') + comment(# opts['protocol.http.ssl_config.client_cert'] = client_cert_file_path) + comment(# opts['protocol.http.ssl_config.client_key'] = client_key_file_path) + comment(# opts['protocol.http.ssl_config.ca_file'] = ca_cert_file_path) + comment(# client = ActionWebService::Client::Soap.new(api, 'https://some/service', :driver_options => opts\)) + reserved(def) method(initialize)operator(()ident(api)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + reserved(super)operator(()ident(api)operator(,) ident(endpoint_uri)operator(\)) + instance_variable(@namespace) operator(=) ident(options)operator([)symbol(:namespace)operator(]) operator(||) string<delimiter(')content(urn:ActionWebService)delimiter(')> + instance_variable(@driver_options) operator(=) ident(options)operator([)symbol(:driver_options)operator(]) operator(||) operator({)operator(}) + instance_variable(@protocol) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol)operator(.)ident(new) instance_variable(@namespace) + instance_variable(@soap_action_base) operator(=) ident(options)operator([)symbol(:soap_action_base)operator(]) + instance_variable(@soap_action_base) operator(||=) constant(URI)operator(.)ident(parse)operator(()ident(endpoint_uri)operator(\))operator(.)ident(path) + instance_variable(@driver) operator(=) ident(create_soap_rpc_driver)operator(()ident(api)operator(,) ident(endpoint_uri)operator(\)) + instance_variable(@driver_options)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(value)operator(|) + instance_variable(@driver)operator(.)ident(options)operator([)ident(name)operator(.)ident(to_s)operator(]) operator(=) ident(value) + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(perform_invocation)operator(()ident(method_name)operator(,) ident(args)operator(\)) + ident(method) operator(=) instance_variable(@api)operator(.)ident(api_methods)operator([)ident(method_name)operator(.)ident(to_sym)operator(]) + ident(args) operator(=) ident(method)operator(.)ident(cast_expects)operator(()ident(args)operator(.)ident(dup)operator(\)) reserved(rescue) ident(args) + ident(return_value) operator(=) instance_variable(@driver)operator(.)ident(send)operator(()ident(method_name)operator(,) operator(*)ident(args)operator(\)) + ident(method)operator(.)ident(cast_returns)operator(()ident(return_value)operator(.)ident(dup)operator(\)) reserved(rescue) ident(return_value) + reserved(end) + + reserved(def) method(soap_action)operator(()ident(method_name)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@soap_action_base)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(method_name)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(private) + reserved(def) method(create_soap_rpc_driver)operator(()ident(api)operator(,) ident(endpoint_uri)operator(\)) + instance_variable(@protocol)operator(.)ident(register_api)operator(()ident(api)operator(\)) + ident(driver) operator(=) constant(SoapDriver)operator(.)ident(new)operator(()ident(endpoint_uri)operator(,) pre_constant(nil)operator(\)) + ident(driver)operator(.)ident(mapping_registry) operator(=) instance_variable(@protocol)operator(.)ident(marshaler)operator(.)ident(registry) + ident(api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + ident(qname) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new)operator(()instance_variable(@namespace)operator(,) ident(method)operator(.)ident(public_name)operator(\)) + ident(action) operator(=) ident(soap_action)operator(()ident(method)operator(.)ident(public_name)operator(\)) + ident(expects) operator(=) ident(method)operator(.)ident(expects) + ident(returns) operator(=) ident(method)operator(.)ident(returns) + ident(param_def) operator(=) operator([)operator(]) + reserved(if) ident(expects) + ident(expects)operator(.)ident(each) reserved(do) operator(|)ident(type)operator(|) + ident(type_binding) operator(=) instance_variable(@protocol)operator(.)ident(marshaler)operator(.)ident(lookup_type)operator(()ident(type)operator(\)) + reserved(if) constant(SOAP)operator(::)constant(Version) operator(>)operator(=) string<delimiter(")content(1.5.5)delimiter(")> + ident(param_def) operator(<<) operator([)string<delimiter(')content(in)delimiter(')>operator(,) ident(type)operator(.)ident(name)operator(.)ident(to_s)operator(,) operator([)ident(type_binding)operator(.)ident(type)operator(.)ident(type_class)operator(.)ident(to_s)operator(])operator(]) + reserved(else) + ident(param_def) operator(<<) operator([)string<delimiter(')content(in)delimiter(')>operator(,) ident(type)operator(.)ident(name)operator(,) ident(type_binding)operator(.)ident(mapping)operator(]) + reserved(end) + reserved(end) + reserved(end) + reserved(if) ident(returns) + ident(type_binding) operator(=) instance_variable(@protocol)operator(.)ident(marshaler)operator(.)ident(lookup_type)operator(()ident(returns)operator([)integer(0)operator(])operator(\)) + reserved(if) constant(SOAP)operator(::)constant(Version) operator(>)operator(=) string<delimiter(")content(1.5.5)delimiter(")> + ident(param_def) operator(<<) operator([)string<delimiter(')content(retval)delimiter(')>operator(,) string<delimiter(')content(return)delimiter(')>operator(,) operator([)ident(type_binding)operator(.)ident(type)operator(.)ident(type_class)operator(.)ident(to_s)operator(])operator(]) + reserved(else) + ident(param_def) operator(<<) operator([)string<delimiter(')content(retval)delimiter(')>operator(,) string<delimiter(')content(return)delimiter(')>operator(,) ident(type_binding)operator(.)ident(mapping)operator(]) + reserved(end) + reserved(end) + ident(driver)operator(.)ident(add_method)operator(()ident(qname)operator(,) ident(action)operator(,) ident(method)operator(.)ident(name)operator(.)ident(to_s)operator(,) ident(param_def)operator(\)) + reserved(end) + ident(driver) + reserved(end) + + reserved(class) class(SoapDriver) operator(<) constant(SOAP)operator(::)constant(RPC)operator(::)constant(Driver) comment(# :nodoc:) + reserved(def) method(add_method)operator(()ident(qname)operator(,) ident(soapaction)operator(,) ident(name)operator(,) ident(param_def)operator(\)) + instance_variable(@proxy)operator(.)ident(add_rpc_method)operator(()ident(qname)operator(,) ident(soapaction)operator(,) ident(name)operator(,) ident(param_def)operator(\)) + ident(add_rpc_method_interface)operator(()ident(name)operator(,) ident(param_def)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(uri)delimiter(')> +ident(require) string<delimiter(')content(xmlrpc/client)delimiter(')> + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Client) comment(# :nodoc:) + + comment(# Implements XML-RPC client support) + comment(#) + comment(# ==== Example Usage) + comment(#) + comment(# class BloggerAPI < ActionWebService::API::Base) + comment(# inflect_names false) + comment(# api_method :getRecentPosts, :returns => [[Blog::Post]]) + comment(# end) + comment(#) + comment(# blog = ActionWebService::Client::XmlRpc.new(BloggerAPI, "http://.../RPC", :handler_name => "blogger"\)) + comment(# posts = blog.getRecentPosts) + reserved(class) class(XmlRpc) operator(<) constant(Base) + + comment(# Creates a new web service client using the XML-RPC protocol.) + comment(#) + comment(# +api+ must be an ActionWebService::API::Base derivative, and) + comment(# +endpoint_uri+ must point at the relevant URL to which protocol requests) + comment(# will be sent with HTTP POST.) + comment(#) + comment(# Valid options:) + comment(# [<tt>:handler_name</tt>] If the remote server defines its services inside special) + comment(# handler (the Blogger API uses a <tt>"blogger"</tt> handler name for example\),) + comment(# provide it here, or your method calls will fail) + reserved(def) method(initialize)operator(()ident(api)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + instance_variable(@api) operator(=) ident(api) + instance_variable(@handler_name) operator(=) ident(options)operator([)symbol(:handler_name)operator(]) + instance_variable(@protocol) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol)operator(.)ident(new) + instance_variable(@client) operator(=) constant(XMLRPC)operator(::)constant(Client)operator(.)ident(new2)operator(()ident(endpoint_uri)operator(,) ident(options)operator([)symbol(:proxy)operator(])operator(,) ident(options)operator([)symbol(:timeout)operator(])operator(\)) + reserved(end) + + ident(protected) + reserved(def) method(perform_invocation)operator(()ident(method_name)operator(,) ident(args)operator(\)) + ident(method) operator(=) instance_variable(@api)operator(.)ident(api_methods)operator([)ident(method_name)operator(.)ident(to_sym)operator(]) + reserved(if) ident(method)operator(.)ident(expects) operator(&&) ident(method)operator(.)ident(expects)operator(.)ident(length) operator(!=) ident(args)operator(.)ident(length) + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(method)operator(.)ident(public_name)inline_delimiter(})>content(: wrong number of arguments ()inline<inline_delimiter(#{)ident(args)operator(.)ident(length)inline_delimiter(})>content( for )inline<inline_delimiter(#{)ident(method)operator(.)ident(expects)operator(.)ident(length)inline_delimiter(})>content(\))delimiter(")>operator(\)) + reserved(end) + ident(args) operator(=) ident(method)operator(.)ident(cast_expects)operator(()ident(args)operator(.)ident(dup)operator(\)) reserved(rescue) ident(args) + reserved(if) ident(method)operator(.)ident(expects) + ident(method)operator(.)ident(expects)operator(.)ident(each_with_index)operator({) operator(|)ident(type)operator(,) ident(i)operator(|) ident(args)operator([)ident(i)operator(]) operator(=) instance_variable(@protocol)operator(.)ident(value_to_xmlrpc_wire_format)operator(()ident(args)operator([)ident(i)operator(])operator(,) ident(type)operator(\)) operator(}) + reserved(end) + ident(ok)operator(,) ident(return_value) operator(=) instance_variable(@client)operator(.)ident(call2)operator(()ident(public_name)operator(()ident(method_name)operator(\))operator(,) operator(*)ident(args)operator(\)) + reserved(return) operator(()ident(method)operator(.)ident(cast_returns)operator(()ident(return_value)operator(.)ident(dup)operator(\)) reserved(rescue) ident(return_value)operator(\)) reserved(if) ident(ok) + ident(raise)operator(()constant(ClientError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(return_value)operator(.)ident(faultCode)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(return_value)operator(.)ident(faultString)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(public_name)operator(()ident(method_name)operator(\)) + ident(public_name) operator(=) instance_variable(@api)operator(.)ident(public_api_method_name)operator(()ident(method_name)operator(\)) + instance_variable(@handler_name) operator(?) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@handler_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(public_name)inline_delimiter(})>delimiter(")> operator(:) ident(public_name) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_web_service/client/base)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/client/soap_client)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/client/xmlrpc_client)delimiter(')> +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Container) comment(# :nodoc:) + reserved(module) class(ActionController) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(class) operator(<<) class(base) + ident(include) constant(ClassMethods) + ident(alias_method) symbol(:inherited_without_api)operator(,) symbol(:inherited) + ident(alias_method) symbol(:inherited)operator(,) symbol(:inherited_with_api) + ident(alias_method) symbol(:web_service_api_without_require)operator(,) symbol(:web_service_api) + ident(alias_method) symbol(:web_service_api)operator(,) symbol(:web_service_api_with_require) + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Creates a client for accessing remote web services, using the) + comment(# given +protocol+ to communicate with the +endpoint_uri+.) + comment(#) + comment(# ==== Example) + comment(#) + comment(# class MyController < ActionController::Base) + comment(# web_client_api :blogger, :xmlrpc, "http://blogger.com/myblog/api/RPC2", :handler_name => 'blogger') + comment(# end) + comment(#) + comment(# In this example, a protected method named <tt>blogger</tt> will) + comment(# now exist on the controller, and calling it will return the) + comment(# XML-RPC client object for working with that remote service.) + comment(#) + comment(# +options+ is the set of protocol client specific options (see) + comment(# a protocol client class for details\).) + comment(#) + comment(# If your API definition does not exist on the load path with the) + comment(# correct rules for it to be found using +name+, you can pass in) + comment(# the API definition class via +options+, using a key of <tt>:api</tt>) + reserved(def) method(web_client_api)operator(()ident(name)operator(,) ident(protocol)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + reserved(unless) ident(method_defined?)operator(()ident(name)operator(\)) + ident(api_klass) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:api)operator(\)) operator(||) ident(require_web_service_api)operator(()ident(name)operator(\)) + ident(class_eval) reserved(do) + ident(define_method)operator(()ident(name)operator(\)) reserved(do) + ident(create_web_service_client)operator(()ident(api_klass)operator(,) ident(protocol)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(\)) + reserved(end) + ident(protected) ident(name) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(web_service_api_with_require)operator(()ident(definition)operator(=)pre_constant(nil)operator(\)) comment(# :nodoc:) + reserved(return) ident(web_service_api_without_require) reserved(if) ident(definition)operator(.)ident(nil?) + reserved(case) ident(definition) + reserved(when) constant(String)operator(,) constant(Symbol) + ident(klass) operator(=) ident(require_web_service_api)operator(()ident(definition)operator(\)) + reserved(else) + ident(klass) operator(=) ident(definition) + reserved(end) + ident(web_service_api_without_require)operator(()ident(klass)operator(\)) + reserved(end) + + reserved(def) method(require_web_service_api)operator(()ident(name)operator(\)) comment(# :nodoc:) + reserved(case) ident(name) + reserved(when) constant(String)operator(,) constant(Symbol) + ident(file_name) operator(=) ident(name)operator(.)ident(to_s)operator(.)ident(underscore) operator(+) string<delimiter(")content(_api)delimiter(")> + ident(class_name) operator(=) ident(file_name)operator(.)ident(camelize) + ident(class_names) operator(=) operator([)ident(class_name)operator(,) ident(class_name)operator(.)ident(sub)operator(()regexp<delimiter(/)content(Api$)delimiter(/)>operator(,) string<delimiter(')content(API)delimiter(')>operator(\))operator(]) + reserved(begin) + ident(require_dependency)operator(()ident(file_name)operator(\)) + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(load_error) + ident(requiree) operator(=) regexp<delimiter(/)content( -- (.*?\)()char(\\.)content(rb\)?$)delimiter(/)>operator(.)ident(match)operator(()ident(load_error)operator(\))operator(.)ident(to_a)operator([)integer(1)operator(]) + ident(msg) operator(=) ident(requiree) operator(==) ident(file_name) operator(?) string<delimiter(")content(Missing API definition file in apis/)inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>content(.rb)delimiter(")> operator(:) string<delimiter(")content(Can't load file: )inline<inline_delimiter(#{)ident(requiree)inline_delimiter(})>delimiter(")> + ident(raise) constant(LoadError)operator(.)ident(new)operator(()ident(msg)operator(\))operator(.)ident(copy_blame!)operator(()ident(load_error)operator(\)) + reserved(end) + ident(klass) operator(=) pre_constant(nil) + ident(class_names)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(klass) operator(=) ident(name)operator(.)ident(constantize) reserved(rescue) pre_constant(nil) + reserved(break) reserved(unless) ident(klass)operator(.)ident(nil?) + reserved(end) + reserved(unless) ident(klass) + ident(raise)operator(()constant(NameError)operator(,) string<delimiter(")content(neither )inline<inline_delimiter(#{)ident(class_names)operator([)integer(0)operator(])inline_delimiter(})>content( or )inline<inline_delimiter(#{)ident(class_names)operator([)integer(1)operator(])inline_delimiter(})>content( found)delimiter(")>operator(\)) + reserved(end) + ident(klass) + reserved(else) + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")content(expected String or Symbol argument)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(inherited_with_api)operator(()ident(child)operator(\)) + ident(inherited_without_api)operator(()ident(child)operator(\)) + reserved(begin) ident(child)operator(.)ident(web_service_api)operator(()ident(child)operator(.)ident(controller_path)operator(\)) + reserved(rescue) constant(MissingSourceFile) operator(=)operator(>) ident(e) + ident(raise) reserved(unless) ident(e)operator(.)ident(is_missing?)operator(()string<delimiter(")content(apis/)inline<inline_delimiter(#{)ident(child)operator(.)ident(controller_path)inline_delimiter(})>content(_api)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Container) comment(# :nodoc:) + reserved(module) class(Delegated) comment(# :nodoc:) + reserved(class) class(ContainerError) operator(<) constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Delegated)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Declares a web service that will provide access to the API of the given) + comment(# +object+. +object+ must be an ActionWebService::Base derivative.) + comment(#) + comment(# Web service object creation can either be _immediate_, where the object) + comment(# instance is given at class definition time, or _deferred_, where) + comment(# object instantiation is delayed until request time.) + comment(#) + comment(# ==== Immediate web service object example) + comment(#) + comment(# class ApiController < ApplicationController) + comment(# web_service_dispatching_mode :delegated) + comment(#) + comment(# web_service :person, PersonService.new) + comment(# end) + comment(#) + comment(# For deferred instantiation, a block should be given instead of an) + comment(# object instance. This block will be executed in controller instance) + comment(# context, so it can rely on controller instance variables being present.) + comment(#) + comment(# ==== Deferred web service object example) + comment(#) + comment(# class ApiController < ApplicationController) + comment(# web_service_dispatching_mode :delegated) + comment(#) + comment(# web_service(:person\) { PersonService.new(request.env\) }) + comment(# end) + reserved(def) method(web_service)operator(()ident(name)operator(,) ident(object)operator(=)pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + reserved(if) operator(()ident(object) operator(&&) ident(block_given?)operator(\)) operator(||) operator(()ident(object)operator(.)ident(nil?) operator(&&) ident(block)operator(.)ident(nil?)operator(\)) + ident(raise)operator(()constant(ContainerError)operator(,) string<delimiter(")content(either service, or a block must be given)delimiter(")>operator(\)) + reserved(end) + ident(name) operator(=) ident(name)operator(.)ident(to_sym) + reserved(if) ident(block_given?) + ident(info) operator(=) operator({) ident(name) operator(=)operator(>) operator({) symbol(:block) operator(=)operator(>) ident(block) operator(}) operator(}) + reserved(else) + ident(info) operator(=) operator({) ident(name) operator(=)operator(>) operator({) symbol(:object) operator(=)operator(>) ident(object) operator(}) operator(}) + reserved(end) + ident(write_inheritable_hash)operator(()string<delimiter(")content(web_services)delimiter(")>operator(,) ident(info)operator(\)) + ident(call_web_service_definition_callbacks)operator(()pre_constant(self)operator(,) ident(name)operator(,) ident(info)operator(\)) + reserved(end) + + comment(# Whether this service contains a service with the given +name+) + reserved(def) method(has_web_service?)operator(()ident(name)operator(\)) + ident(web_services)operator(.)ident(has_key?)operator(()ident(name)operator(.)ident(to_sym)operator(\)) + reserved(end) + + reserved(def) method(web_services) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(web_services)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + reserved(def) method(add_web_service_definition_callback)operator(()operator(&)ident(block)operator(\)) comment(# :nodoc:) + ident(write_inheritable_array)operator(()string<delimiter(")content(web_service_definition_callbacks)delimiter(")>operator(,) operator([)ident(block)operator(])operator(\)) + reserved(end) + + ident(private) + reserved(def) method(call_web_service_definition_callbacks)operator(()ident(container_class)operator(,) ident(web_service_name)operator(,) ident(service_info)operator(\)) + operator(()ident(read_inheritable_attribute)operator(()string<delimiter(")content(web_service_definition_callbacks)delimiter(")>operator(\)) operator(||) operator([)operator(])operator(\))operator(.)ident(each) reserved(do) operator(|)ident(block)operator(|) + ident(block)operator(.)ident(call)operator(()ident(container_class)operator(,) ident(web_service_name)operator(,) ident(service_info)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) comment(# :nodoc:) + reserved(def) method(web_service_object)operator(()ident(web_service_name)operator(\)) + ident(info) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(web_services)operator([)ident(web_service_name)operator(.)ident(to_sym)operator(]) + reserved(unless) ident(info) + ident(raise)operator(()constant(ContainerError)operator(,) string<delimiter(")content(no such web service ')inline<inline_delimiter(#{)ident(web_service_name)inline_delimiter(})>content(')delimiter(")>operator(\)) + reserved(end) + ident(service) operator(=) ident(info)operator([)symbol(:block)operator(]) + ident(service) operator(?) pre_constant(self)operator(.)ident(instance_eval)operator(()operator(&)ident(service)operator(\)) operator(:) ident(info)operator([)symbol(:object)operator(]) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Container) comment(# :nodoc:) + reserved(module) class(Direct) comment(# :nodoc:) + reserved(class) class(ContainerError) operator(<) constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Attaches ActionWebService API +definition+ to the calling class.) + comment(#) + comment(# Action Controllers can have a default associated API, removing the need) + comment(# to call this method if you follow the Action Web Service naming conventions.) + comment(#) + comment(# A controller with a class name of GoogleSearchController will) + comment(# implicitly load <tt>app/apis/google_search_api.rb</tt>, and expect the) + comment(# API definition class to be named <tt>GoogleSearchAPI</tt> or) + comment(# <tt>GoogleSearchApi</tt>.) + comment(#) + comment(# ==== Service class example) + comment(#) + comment(# class MyService < ActionWebService::Base) + comment(# web_service_api MyAPI) + comment(# end) + comment(#) + comment(# class MyAPI < ActionWebService::API::Base) + comment(# ...) + comment(# end) + comment(#) + comment(# ==== Controller class example) + comment(#) + comment(# class MyController < ActionController::Base) + comment(# web_service_api MyAPI) + comment(# end) + comment(#) + comment(# class MyAPI < ActionWebService::API::Base) + comment(# ...) + comment(# end) + reserved(def) method(web_service_api)operator(()ident(definition)operator(=)pre_constant(nil)operator(\)) + reserved(if) ident(definition)operator(.)ident(nil?) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(web_service_api)delimiter(")>operator(\)) + reserved(else) + reserved(if) ident(definition)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + ident(raise)operator(()constant(ContainerError)operator(,) string<delimiter(")content(symbols can only be used for #web_service_api inside of a controller)delimiter(")>operator(\)) + reserved(end) + reserved(unless) ident(definition)operator(.)ident(respond_to?)operator(()symbol(:ancestors)operator(\)) operator(&&) ident(definition)operator(.)ident(ancestors)operator(.)ident(include?)operator(()constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base)operator(\)) + ident(raise)operator(()constant(ContainerError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(definition)operator(.)ident(to_s)inline_delimiter(})>content( is not a valid API definition)delimiter(")>operator(\)) + reserved(end) + ident(write_inheritable_attribute)operator(()string<delimiter(")content(web_service_api)delimiter(")>operator(,) ident(definition)operator(\)) + ident(call_web_service_api_callbacks)operator(()pre_constant(self)operator(,) ident(definition)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(add_web_service_api_callback)operator(()operator(&)ident(block)operator(\)) comment(# :nodoc:) + ident(write_inheritable_array)operator(()string<delimiter(")content(web_service_api_callbacks)delimiter(")>operator(,) operator([)ident(block)operator(])operator(\)) + reserved(end) + + ident(private) + reserved(def) method(call_web_service_api_callbacks)operator(()ident(container_class)operator(,) ident(definition)operator(\)) + operator(()ident(read_inheritable_attribute)operator(()string<delimiter(")content(web_service_api_callbacks)delimiter(")>operator(\)) operator(||) operator([)operator(])operator(\))operator(.)ident(each) reserved(do) operator(|)ident(block)operator(|) + ident(block)operator(.)ident(call)operator(()ident(container_class)operator(,) ident(definition)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_web_service/container/direct_container)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/container/delegated_container)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/container/action_controller_container)delimiter(')> +ident(require) string<delimiter(')content(benchmark)delimiter(')> + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Dispatcher) comment(# :nodoc:) + reserved(class) class(DispatcherError) operator(<) constant(ActionWebService)operator(::)constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + ident(base)operator(.)ident(class_inheritable_option)operator(()symbol(:web_service_dispatching_mode)operator(,) symbol(:direct)operator(\)) + ident(base)operator(.)ident(class_inheritable_option)operator(()symbol(:web_service_exception_reporting)operator(,) pre_constant(true)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionWebService)operator(::)constant(Dispatcher)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + reserved(module) class(InstanceMethods) comment(# :nodoc:) + ident(private) + reserved(def) method(invoke_web_service_request)operator(()ident(protocol_request)operator(\)) + ident(invocation) operator(=) ident(web_service_invocation)operator(()ident(protocol_request)operator(\)) + reserved(if) ident(invocation)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(&&) ident(protocol_request)operator(.)ident(protocol)operator(.)ident(is_a?)operator(()constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol)operator(\)) + ident(xmlrpc_multicall_invoke)operator(()ident(invocation)operator(\)) + reserved(else) + ident(web_service_invoke)operator(()ident(invocation)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(web_service_direct_invoke)operator(()ident(invocation)operator(\)) + instance_variable(@method_params) operator(=) ident(invocation)operator(.)ident(method_ordered_params) + ident(arity) operator(=) ident(method)operator(()ident(invocation)operator(.)ident(api_method)operator(.)ident(name)operator(\))operator(.)ident(arity) reserved(rescue) integer(0) + reserved(if) ident(arity) operator(<) integer(0) operator(||) ident(arity) operator(>) integer(0) + ident(params) operator(=) instance_variable(@method_params) + reserved(else) + ident(params) operator(=) operator([)operator(]) + reserved(end) + ident(web_service_filtered_invoke)operator(()ident(invocation)operator(,) ident(params)operator(\)) + reserved(end) + + reserved(def) method(web_service_delegated_invoke)operator(()ident(invocation)operator(\)) + ident(web_service_filtered_invoke)operator(()ident(invocation)operator(,) ident(invocation)operator(.)ident(method_ordered_params)operator(\)) + reserved(end) + + reserved(def) method(web_service_filtered_invoke)operator(()ident(invocation)operator(,) ident(params)operator(\)) + ident(cancellation_reason) operator(=) pre_constant(nil) + ident(return_value) operator(=) ident(invocation)operator(.)ident(service)operator(.)ident(perform_invocation)operator(()ident(invocation)operator(.)ident(api_method)operator(.)ident(name)operator(,) ident(params)operator(\)) reserved(do) operator(|)ident(x)operator(|) + ident(cancellation_reason) operator(=) ident(x) + reserved(end) + reserved(if) ident(cancellation_reason) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(request canceled: )inline<inline_delimiter(#{)ident(cancellation_reason)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + ident(return_value) + reserved(end) + + reserved(def) method(web_service_invoke)operator(()ident(invocation)operator(\)) + reserved(case) ident(web_service_dispatching_mode) + reserved(when) symbol(:direct) + ident(return_value) operator(=) ident(web_service_direct_invoke)operator(()ident(invocation)operator(\)) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + ident(return_value) operator(=) ident(web_service_delegated_invoke)operator(()ident(invocation)operator(\)) + reserved(end) + ident(web_service_create_response)operator(()ident(invocation)operator(.)ident(protocol)operator(,) ident(invocation)operator(.)ident(protocol_options)operator(,) ident(invocation)operator(.)ident(api)operator(,) ident(invocation)operator(.)ident(api_method)operator(,) ident(return_value)operator(\)) + reserved(end) + + reserved(def) method(xmlrpc_multicall_invoke)operator(()ident(invocations)operator(\)) + ident(responses) operator(=) operator([)operator(]) + ident(invocations)operator(.)ident(each) reserved(do) operator(|)ident(invocation)operator(|) + reserved(if) ident(invocation)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(responses) operator(<<) ident(invocation) + reserved(next) + reserved(end) + reserved(begin) + reserved(case) ident(web_service_dispatching_mode) + reserved(when) symbol(:direct) + ident(return_value) operator(=) ident(web_service_direct_invoke)operator(()ident(invocation)operator(\)) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + ident(return_value) operator(=) ident(web_service_delegated_invoke)operator(()ident(invocation)operator(\)) + reserved(end) + ident(api_method) operator(=) ident(invocation)operator(.)ident(api_method) + reserved(if) ident(invocation)operator(.)ident(api)operator(.)ident(has_api_method?)operator(()ident(api_method)operator(.)ident(name)operator(\)) + ident(return_value) operator(=) ident(api_method)operator(.)ident(cast_returns)operator(()ident(return_value)operator(\)) + reserved(end) + ident(responses) operator(<<) operator([)ident(return_value)operator(]) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(responses) operator(<<) operator({) string<delimiter(')content(faultCode)delimiter(')> operator(=)operator(>) integer(3)operator(,) string<delimiter(')content(faultString)delimiter(')> operator(=)operator(>) ident(e)operator(.)ident(message) operator(}) + reserved(end) + reserved(end) + ident(invocation) operator(=) ident(invocations)operator([)integer(0)operator(]) + ident(invocation)operator(.)ident(protocol)operator(.)ident(encode_response)operator(()string<delimiter(')content(system.multicall)delimiter(')>operator(,) ident(responses)operator(,) pre_constant(nil)operator(,) ident(invocation)operator(.)ident(protocol_options)operator(\)) + reserved(end) + + reserved(def) method(web_service_invocation)operator(()ident(request)operator(,) ident(level) operator(=) integer(0)operator(\)) + ident(public_method_name) operator(=) ident(request)operator(.)ident(method_name) + ident(invocation) operator(=) constant(Invocation)operator(.)ident(new) + ident(invocation)operator(.)ident(protocol) operator(=) ident(request)operator(.)ident(protocol) + ident(invocation)operator(.)ident(protocol_options) operator(=) ident(request)operator(.)ident(protocol_options) + ident(invocation)operator(.)ident(service_name) operator(=) ident(request)operator(.)ident(service_name) + reserved(if) ident(web_service_dispatching_mode) operator(==) symbol(:layered) + reserved(case) ident(invocation)operator(.)ident(protocol) + reserved(when) constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol) + ident(soap_action) operator(=) ident(request)operator(.)ident(protocol_options)operator([)symbol(:soap_action)operator(]) + reserved(if) ident(soap_action) operator(&&) ident(soap_action) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\/)char(\\w)content(+)char(\\/)content(()char(\\w)content(+\))char(\\/)delimiter(/)> + ident(invocation)operator(.)ident(service_name) operator(=) global_variable($1) + reserved(end) + reserved(when) constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol) + reserved(if) ident(request)operator(.)ident(method_name) operator(=)operator(~) regexp<delimiter(/)content(^([^)char(\\.)content(]+\))char(\\.)content((.*\)$)delimiter(/)> + ident(public_method_name) operator(=) global_variable($2) + ident(invocation)operator(.)ident(service_name) operator(=) global_variable($1) + reserved(end) + reserved(end) + reserved(end) + reserved(if) ident(invocation)operator(.)ident(protocol)operator(.)ident(is_a?) constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol) + reserved(if) ident(public_method_name) operator(==) string<delimiter(')content(multicall)delimiter(')> operator(&&) ident(invocation)operator(.)ident(service_name) operator(==) string<delimiter(')content(system)delimiter(')> + reserved(if) ident(level) operator(>) integer(0) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(Recursive system.multicall invocations not allowed)delimiter(")>operator(\)) + reserved(end) + ident(multicall) operator(=) ident(request)operator(.)ident(method_params)operator(.)ident(dup) + reserved(unless) ident(multicall)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(&&) ident(multicall)operator([)integer(0)operator(])operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(Malformed multicall (expected array of Hash elements\))delimiter(")>operator(\)) + reserved(end) + ident(multicall) operator(=) ident(multicall)operator([)integer(0)operator(]) + reserved(return) ident(multicall)operator(.)ident(map) reserved(do) operator(|)ident(item)operator(|) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(Multicall elements must be Hash)delimiter(")>operator(\)) reserved(unless) ident(item)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(Multicall elements must contain a 'methodName' key)delimiter(")>operator(\)) reserved(unless) ident(item)operator(.)ident(has_key?)operator(()string<delimiter(')content(methodName)delimiter(')>operator(\)) + ident(method_name) operator(=) ident(item)operator([)string<delimiter(')content(methodName)delimiter(')>operator(]) + ident(params) operator(=) ident(item)operator(.)ident(has_key?)operator(()string<delimiter(')content(params)delimiter(')>operator(\)) operator(?) ident(item)operator([)string<delimiter(')content(params)delimiter(')>operator(]) operator(:) operator([)operator(]) + ident(multicall_request) operator(=) ident(request)operator(.)ident(dup) + ident(multicall_request)operator(.)ident(method_name) operator(=) ident(method_name) + ident(multicall_request)operator(.)ident(method_params) operator(=) ident(params) + reserved(begin) + ident(web_service_invocation)operator(()ident(multicall_request)operator(,) ident(level) operator(+) integer(1)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + operator({)string<delimiter(')content(faultCode)delimiter(')> operator(=)operator(>) integer(4)operator(,) string<delimiter(')content(faultMessage)delimiter(')> operator(=)operator(>) ident(e)operator(.)ident(message)operator(}) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(case) ident(web_service_dispatching_mode) + reserved(when) symbol(:direct) + ident(invocation)operator(.)ident(api) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(web_service_api) + ident(invocation)operator(.)ident(service) operator(=) pre_constant(self) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + ident(invocation)operator(.)ident(service) operator(=) ident(web_service_object)operator(()ident(invocation)operator(.)ident(service_name)operator(\)) + ident(invocation)operator(.)ident(api) operator(=) ident(invocation)operator(.)ident(service)operator(.)ident(class)operator(.)ident(web_service_api) + reserved(end) + reserved(if) ident(invocation)operator(.)ident(api)operator(.)ident(nil?) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(no API attached to )inline<inline_delimiter(#{)ident(invocation)operator(.)ident(service)operator(.)ident(class)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + ident(invocation)operator(.)ident(protocol)operator(.)ident(register_api)operator(()ident(invocation)operator(.)ident(api)operator(\)) + ident(request)operator(.)ident(api) operator(=) ident(invocation)operator(.)ident(api) + reserved(if) ident(invocation)operator(.)ident(api)operator(.)ident(has_public_api_method?)operator(()ident(public_method_name)operator(\)) + ident(invocation)operator(.)ident(api_method) operator(=) ident(invocation)operator(.)ident(api)operator(.)ident(public_api_method_instance)operator(()ident(public_method_name)operator(\)) + reserved(else) + reserved(if) ident(invocation)operator(.)ident(api)operator(.)ident(default_api_method)operator(.)ident(nil?) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(no such method ')inline<inline_delimiter(#{)ident(public_method_name)inline_delimiter(})>content(' on API )inline<inline_delimiter(#{)ident(invocation)operator(.)ident(api)inline_delimiter(})>delimiter(")>operator(\)) + reserved(else) + ident(invocation)operator(.)ident(api_method) operator(=) ident(invocation)operator(.)ident(api)operator(.)ident(default_api_method_instance) + reserved(end) + reserved(end) + reserved(if) ident(invocation)operator(.)ident(service)operator(.)ident(nil?) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(no service available for service name )inline<inline_delimiter(#{)ident(invocation)operator(.)ident(service_name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(unless) ident(invocation)operator(.)ident(service)operator(.)ident(respond_to?)operator(()ident(invocation)operator(.)ident(api_method)operator(.)ident(name)operator(\)) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(no such method ')inline<inline_delimiter(#{)ident(public_method_name)inline_delimiter(})>content(' on API )inline<inline_delimiter(#{)ident(invocation)operator(.)ident(api)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(invocation)operator(.)ident(api_method)operator(.)ident(name)inline_delimiter(})>content(\))delimiter(")>operator(\)) + reserved(end) + ident(request)operator(.)ident(api_method) operator(=) ident(invocation)operator(.)ident(api_method) + reserved(begin) + ident(invocation)operator(.)ident(method_ordered_params) operator(=) ident(invocation)operator(.)ident(api_method)operator(.)ident(cast_expects)operator(()ident(request)operator(.)ident(method_params)operator(.)ident(dup)operator(\)) + reserved(rescue) + ident(logger)operator(.)ident(warn) string<delimiter(")content(Casting of method parameters failed)delimiter(")> reserved(unless) ident(logger)operator(.)ident(nil?) + ident(invocation)operator(.)ident(method_ordered_params) operator(=) ident(request)operator(.)ident(method_params) + reserved(end) + ident(request)operator(.)ident(method_params) operator(=) ident(invocation)operator(.)ident(method_ordered_params) + ident(invocation)operator(.)ident(method_named_params) operator(=) operator({)operator(}) + ident(invocation)operator(.)ident(api_method)operator(.)ident(param_names)operator(.)ident(inject)operator(()integer(0)operator(\)) reserved(do) operator(|)ident(m)operator(,) ident(n)operator(|) + ident(invocation)operator(.)ident(method_named_params)operator([)ident(n)operator(]) operator(=) ident(invocation)operator(.)ident(method_ordered_params)operator([)ident(m)operator(]) + ident(m) operator(+) integer(1) + reserved(end) + ident(invocation) + reserved(end) + + reserved(def) method(web_service_create_response)operator(()ident(protocol)operator(,) ident(protocol_options)operator(,) ident(api)operator(,) ident(api_method)operator(,) ident(return_value)operator(\)) + reserved(if) ident(api)operator(.)ident(has_api_method?)operator(()ident(api_method)operator(.)ident(name)operator(\)) + ident(return_type) operator(=) ident(api_method)operator(.)ident(returns) operator(?) ident(api_method)operator(.)ident(returns)operator([)integer(0)operator(]) operator(:) pre_constant(nil) + ident(return_value) operator(=) ident(api_method)operator(.)ident(cast_returns)operator(()ident(return_value)operator(\)) + reserved(else) + ident(return_type) operator(=) constant(ActionWebService)operator(::)constant(SignatureTypes)operator(.)ident(canonical_signature_entry)operator(()ident(return_value)operator(.)ident(class)operator(,) integer(0)operator(\)) + reserved(end) + ident(protocol)operator(.)ident(encode_response)operator(()ident(api_method)operator(.)ident(public_name) operator(+) string<delimiter(')content(Response)delimiter(')>operator(,) ident(return_value)operator(,) ident(return_type)operator(,) ident(protocol_options)operator(\)) + reserved(end) + + reserved(class) class(Invocation) comment(# :nodoc:) + ident(attr_accessor) symbol(:protocol) + ident(attr_accessor) symbol(:protocol_options) + ident(attr_accessor) symbol(:service_name) + ident(attr_accessor) symbol(:api) + ident(attr_accessor) symbol(:api_method) + ident(attr_accessor) symbol(:method_ordered_params) + ident(attr_accessor) symbol(:method_named_params) + ident(attr_accessor) symbol(:service) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(benchmark)delimiter(')> +ident(require) string<delimiter(')content(builder/xmlmarkup)delimiter(')> + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Dispatcher) comment(# :nodoc:) + reserved(module) class(ActionController) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + reserved(class) operator(<<) class(base) + ident(include) constant(ClassMethods) + ident(alias_method) symbol(:inherited_without_action_controller)operator(,) symbol(:inherited) + ident(alias_method) symbol(:inherited)operator(,) symbol(:inherited_with_action_controller) + reserved(end) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:web_service_direct_invoke_without_controller)operator(,) symbol(:web_service_direct_invoke) + reserved(end) + ident(base)operator(.)ident(add_web_service_api_callback) reserved(do) operator(|)ident(klass)operator(,) ident(api)operator(|) + reserved(if) ident(klass)operator(.)ident(web_service_dispatching_mode) operator(==) symbol(:direct) + ident(klass)operator(.)ident(class_eval) string<delimiter(')content(def api; dispatch_web_service_request; end)delimiter(')> + reserved(end) + reserved(end) + ident(base)operator(.)ident(add_web_service_definition_callback) reserved(do) operator(|)ident(klass)operator(,) ident(name)operator(,) ident(info)operator(|) + reserved(if) ident(klass)operator(.)ident(web_service_dispatching_mode) operator(==) symbol(:delegated) + ident(klass)operator(.)ident(class_eval) string<delimiter(")content(def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(; dispatch_web_service_request; end)delimiter(")> + reserved(elsif) ident(klass)operator(.)ident(web_service_dispatching_mode) operator(==) symbol(:layered) + ident(klass)operator(.)ident(class_eval) string<delimiter(')content(def api; dispatch_web_service_request; end)delimiter(')> + reserved(end) + reserved(end) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionWebService)operator(::)constant(Dispatcher)operator(::)constant(ActionController)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) comment(# :nodoc:) + reserved(def) method(inherited_with_action_controller)operator(()ident(child)operator(\)) + ident(inherited_without_action_controller)operator(()ident(child)operator(\)) + ident(child)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionWebService)operator(::)constant(Dispatcher)operator(::)constant(ActionController)operator(::)constant(WsdlAction)operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) comment(# :nodoc:) + ident(private) + reserved(def) method(dispatch_web_service_request) + ident(exception) operator(=) pre_constant(nil) + reserved(begin) + ident(ws_request) operator(=) ident(discover_web_service_request)operator(()ident(request)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(exception) operator(=) ident(e) + reserved(end) + reserved(if) ident(ws_request) + ident(ws_response) operator(=) pre_constant(nil) + ident(exception) operator(=) pre_constant(nil) + ident(bm) operator(=) constant(Benchmark)operator(.)ident(measure) reserved(do) + reserved(begin) + ident(ws_response) operator(=) ident(invoke_web_service_request)operator(()ident(ws_request)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(exception) operator(=) ident(e) + reserved(end) + reserved(end) + ident(log_request)operator(()ident(ws_request)operator(,) ident(request)operator(.)ident(raw_post)operator(\)) + reserved(if) ident(exception) + ident(log_error)operator(()ident(exception)operator(\)) reserved(unless) ident(logger)operator(.)ident(nil?) + ident(send_web_service_error_response)operator(()ident(ws_request)operator(,) ident(exception)operator(\)) + reserved(else) + ident(send_web_service_response)operator(()ident(ws_response)operator(,) ident(bm)operator(.)ident(real)operator(\)) + reserved(end) + reserved(else) + ident(exception) operator(||=) constant(DispatcherError)operator(.)ident(new)operator(()string<delimiter(")content(Malformed SOAP or XML-RPC protocol message)delimiter(")>operator(\)) + ident(log_error)operator(()ident(exception)operator(\)) reserved(unless) ident(logger)operator(.)ident(nil?) + ident(send_web_service_error_response)operator(()ident(ws_request)operator(,) ident(exception)operator(\)) + reserved(end) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(log_error)operator(()ident(e)operator(\)) reserved(unless) ident(logger)operator(.)ident(nil?) + ident(send_web_service_error_response)operator(()ident(ws_request)operator(,) ident(e)operator(\)) + reserved(end) + + reserved(def) method(send_web_service_response)operator(()ident(ws_response)operator(,) ident(elapsed)operator(=)pre_constant(nil)operator(\)) + ident(log_response)operator(()ident(ws_response)operator(,) ident(elapsed)operator(\)) + ident(options) operator(=) operator({) symbol(:type) operator(=)operator(>) ident(ws_response)operator(.)ident(content_type)operator(,) symbol(:disposition) operator(=)operator(>) string<delimiter(')content(inline)delimiter(')> operator(}) + ident(send_data)operator(()ident(ws_response)operator(.)ident(body)operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(send_web_service_error_response)operator(()ident(ws_request)operator(,) ident(exception)operator(\)) + reserved(if) ident(ws_request) + reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(web_service_exception_reporting) + ident(exception) operator(=) constant(DispatcherError)operator(.)ident(new)operator(()string<delimiter(")content(Internal server error (exception raised\))delimiter(")>operator(\)) + reserved(end) + ident(api_method) operator(=) ident(ws_request)operator(.)ident(api_method) + ident(public_method_name) operator(=) ident(api_method) operator(?) ident(api_method)operator(.)ident(public_name) operator(:) ident(ws_request)operator(.)ident(method_name) + ident(return_type) operator(=) constant(ActionWebService)operator(::)constant(SignatureTypes)operator(.)ident(canonical_signature_entry)operator(()constant(Exception)operator(,) integer(0)operator(\)) + ident(ws_response) operator(=) ident(ws_request)operator(.)ident(protocol)operator(.)ident(encode_response)operator(()ident(public_method_name) operator(+) string<delimiter(')content(Response)delimiter(')>operator(,) ident(exception)operator(,) ident(return_type)operator(,) ident(ws_request)operator(.)ident(protocol_options)operator(\)) + ident(send_web_service_response)operator(()ident(ws_response)operator(\)) + reserved(else) + reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(web_service_exception_reporting) + ident(message) operator(=) ident(exception)operator(.)ident(message) + ident(backtrace) operator(=) string<delimiter(")char(\\n)content(Backtrace:)char(\\n)inline<inline_delimiter(#{)ident(exception)operator(.)ident(backtrace)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))inline_delimiter(})>delimiter(")> + reserved(else) + ident(message) operator(=) string<delimiter(")content(Exception raised)delimiter(")> + ident(backtrace) operator(=) string<delimiter(")delimiter(")> + reserved(end) + ident(render_text)operator(()string<delimiter(")content(Internal protocol error: )inline<inline_delimiter(#{)ident(message)inline_delimiter(})>inline<inline_delimiter(#{)ident(backtrace)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(500 Internal Protocol Error)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(web_service_direct_invoke)operator(()ident(invocation)operator(\)) + ident(invocation)operator(.)ident(method_named_params)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(value)operator(|) + ident(params)operator([)ident(name)operator(]) operator(=) ident(value) + reserved(end) + ident(params)operator([)string<delimiter(')content(action)delimiter(')>operator(]) operator(=) ident(invocation)operator(.)ident(api_method)operator(.)ident(name)operator(.)ident(to_s) + reserved(if) ident(before_action) operator(==) pre_constant(false) + ident(raise)operator(()constant(DispatcherError)operator(,) string<delimiter(")content(Method filtered)delimiter(")>operator(\)) + reserved(end) + ident(return_value) operator(=) ident(web_service_direct_invoke_without_controller)operator(()ident(invocation)operator(\)) + ident(after_action) + ident(return_value) + reserved(end) + + reserved(def) method(log_request)operator(()ident(ws_request)operator(,) ident(body)operator(\)) + reserved(unless) ident(logger)operator(.)ident(nil?) + ident(name) operator(=) ident(ws_request)operator(.)ident(method_name) + ident(api_method) operator(=) ident(ws_request)operator(.)ident(api_method) + ident(params) operator(=) ident(ws_request)operator(.)ident(method_params) + reserved(if) ident(api_method) operator(&&) ident(api_method)operator(.)ident(expects) + ident(params) operator(=) ident(api_method)operator(.)ident(expects)operator(.)ident(zip)operator(()ident(params)operator(\))operator(.)ident(map)operator({) operator(|)ident(type)operator(,) ident(param)operator(|) string<delimiter(")inline<inline_delimiter(#{)ident(type)operator(.)ident(name)inline_delimiter(})>content(=>)inline<inline_delimiter(#{)ident(param)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> operator(}) + reserved(else) + ident(params) operator(=) ident(params)operator(.)ident(map)operator({) operator(|)ident(param)operator(|) ident(param)operator(.)ident(inspect) operator(}) + reserved(end) + ident(service) operator(=) ident(ws_request)operator(.)ident(service_name) + ident(logger)operator(.)ident(debug)operator(()string<delimiter(")char(\\n)content(Web Service Request: )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(params)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))inline_delimiter(})>content(\) Entrypoint: )inline<inline_delimiter(#{)ident(service)inline_delimiter(})>delimiter(")>operator(\)) + ident(logger)operator(.)ident(debug)operator(()ident(indent)operator(()ident(body)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(log_response)operator(()ident(ws_response)operator(,) ident(elapsed)operator(=)pre_constant(nil)operator(\)) + reserved(unless) ident(logger)operator(.)ident(nil?) + ident(elapsed) operator(=) operator(()ident(elapsed) operator(?) string<delimiter(")content( (%f\):)delimiter(")> operator(%) ident(elapsed) operator(:) string<delimiter(")content(:)delimiter(")>operator(\)) + ident(logger)operator(.)ident(debug)operator(()string<delimiter(")char(\\n)content(Web Service Response)delimiter(")> operator(+) ident(elapsed) operator(+) string<delimiter(")content( => )inline<inline_delimiter(#{)ident(ws_response)operator(.)ident(return_value)operator(.)ident(inspect)inline_delimiter(})>delimiter(")>operator(\)) + ident(logger)operator(.)ident(debug)operator(()ident(indent)operator(()ident(ws_response)operator(.)ident(body)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(indent)operator(()ident(body)operator(\)) + ident(body)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\n)delimiter(/)>operator(\))operator(.)ident(map)operator({)operator(|)ident(x)operator(|) string<delimiter(")content( )inline<inline_delimiter(#{)ident(x)inline_delimiter(})>delimiter(")>operator(})operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(WsdlAction) comment(# :nodoc:) + constant(XsdNs) operator(=) string<delimiter(')content(http://www.w3.org/2001/XMLSchema)delimiter(')> + constant(WsdlNs) operator(=) string<delimiter(')content(http://schemas.xmlsoap.org/wsdl/)delimiter(')> + constant(SoapNs) operator(=) string<delimiter(')content(http://schemas.xmlsoap.org/wsdl/soap/)delimiter(')> + constant(SoapEncodingNs) operator(=) string<delimiter(')content(http://schemas.xmlsoap.org/soap/encoding/)delimiter(')> + constant(SoapHttpTransport) operator(=) string<delimiter(')content(http://schemas.xmlsoap.org/soap/http)delimiter(')> + + reserved(def) method(wsdl) + reserved(case) ident(request)operator(.)ident(method) + reserved(when) symbol(:get) + reserved(begin) + ident(options) operator(=) operator({) symbol(:type) operator(=)operator(>) string<delimiter(')content(text/xml)delimiter(')>operator(,) symbol(:disposition) operator(=)operator(>) string<delimiter(')content(inline)delimiter(')> operator(}) + ident(send_data)operator(()ident(to_wsdl)operator(,) ident(options)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(log_error)operator(()ident(e)operator(\)) reserved(unless) ident(logger)operator(.)ident(nil?) + reserved(end) + reserved(when) symbol(:post) + ident(render_text)operator(()string<delimiter(')content(POST not supported)delimiter(')>operator(,) string<delimiter(')content(500 POST not supported)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(base_uri) + ident(host) operator(=) ident(request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_HOST)delimiter(')>operator(]) operator(||) ident(request)operator(.)ident(env)operator([)string<delimiter(')content(SERVER_NAME)delimiter(')>operator(]) operator(||) string<delimiter(')content(localhost)delimiter(')> + ident(relative_url_root) operator(=) ident(request)operator(.)ident(relative_url_root) + ident(scheme) operator(=) ident(request)operator(.)ident(ssl?) operator(?) string<delimiter(')content(https)delimiter(')> operator(:) string<delimiter(')content(http)delimiter(')> + string<delimiter(')content(%s://%s%s/%s/)delimiter(')> operator(%) operator([)ident(scheme)operator(,) ident(host)operator(,) ident(relative_url_root)operator(,) pre_constant(self)operator(.)ident(class)operator(.)ident(controller_path)operator(]) + reserved(end) + + reserved(def) method(to_wsdl) + ident(xml) operator(=) string<delimiter(')delimiter(')> + ident(dispatching_mode) operator(=) ident(web_service_dispatching_mode) + ident(global_service_name) operator(=) ident(wsdl_service_name) + ident(namespace) operator(=) ident(wsdl_namespace) operator(||) string<delimiter(')content(urn:ActionWebService)delimiter(')> + ident(soap_action_base) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(controller_name)inline_delimiter(})>delimiter(")> + + ident(marshaler) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapMarshaler)operator(.)ident(new)operator(()ident(namespace)operator(\)) + ident(apis) operator(=) operator({)operator(}) + reserved(case) ident(dispatching_mode) + reserved(when) symbol(:direct) + ident(api) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(web_service_api) + ident(web_service_name) operator(=) ident(controller_class_name)operator(.)ident(sub)operator(()regexp<delimiter(/)content(Controller$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(underscore) + ident(apis)operator([)ident(web_service_name)operator(]) operator(=) operator([)ident(api)operator(,) ident(register_api)operator(()ident(api)operator(,) ident(marshaler)operator(\))operator(]) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + pre_constant(self)operator(.)ident(class)operator(.)ident(web_services)operator(.)ident(each) reserved(do) operator(|)ident(web_service_name)operator(,) ident(info)operator(|) + ident(service) operator(=) ident(web_service_object)operator(()ident(web_service_name)operator(\)) + ident(api) operator(=) ident(service)operator(.)ident(class)operator(.)ident(web_service_api) + ident(apis)operator([)ident(web_service_name)operator(]) operator(=) operator([)ident(api)operator(,) ident(register_api)operator(()ident(api)operator(,) ident(marshaler)operator(\))operator(]) + reserved(end) + reserved(end) + ident(custom_types) operator(=) operator([)operator(]) + ident(apis)operator(.)ident(values)operator(.)ident(each) reserved(do) operator(|)ident(api)operator(,) ident(bindings)operator(|) + ident(bindings)operator(.)ident(each) reserved(do) operator(|)ident(b)operator(|) + ident(custom_types) operator(<<) ident(b) reserved(unless) ident(custom_types)operator(.)ident(include?)operator(()ident(b)operator(\)) + reserved(end) + reserved(end) + + ident(xm) operator(=) constant(Builder)operator(::)constant(XmlMarkup)operator(.)ident(new)operator(()symbol(:target) operator(=)operator(>) ident(xml)operator(,) symbol(:indent) operator(=)operator(>) integer(2)operator(\)) + ident(xm)operator(.)ident(instruct!) + ident(xm)operator(.)ident(definitions)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(wsdl_service_name)operator(,) + string<delimiter(')content(targetNamespace)delimiter(')> operator(=)operator(>) ident(namespace)operator(,) + string<delimiter(')content(xmlns:typens)delimiter(')> operator(=)operator(>) ident(namespace)operator(,) + string<delimiter(')content(xmlns:xsd)delimiter(')> operator(=)operator(>) constant(XsdNs)operator(,) + string<delimiter(')content(xmlns:soap)delimiter(')> operator(=)operator(>) constant(SoapNs)operator(,) + string<delimiter(')content(xmlns:soapenc)delimiter(')> operator(=)operator(>) constant(SoapEncodingNs)operator(,) + string<delimiter(')content(xmlns:wsdl)delimiter(')> operator(=)operator(>) constant(WsdlNs)operator(,) + string<delimiter(')content(xmlns)delimiter(')> operator(=)operator(>) constant(WsdlNs)operator(\)) reserved(do) + comment(# Generate XSD) + reserved(if) ident(custom_types)operator(.)ident(size) operator(>) integer(0) + ident(xm)operator(.)ident(types) reserved(do) + ident(xm)operator(.)ident(xsd)operator(()symbol(:schema)operator(,) string<delimiter(')content(xmlns)delimiter(')> operator(=)operator(>) constant(XsdNs)operator(,) string<delimiter(')content(targetNamespace)delimiter(')> operator(=)operator(>) ident(namespace)operator(\)) reserved(do) + ident(custom_types)operator(.)ident(each) reserved(do) operator(|)ident(binding)operator(|) + reserved(case) + reserved(when) ident(binding)operator(.)ident(type)operator(.)ident(array?) + ident(xm)operator(.)ident(xsd)operator(()symbol(:complexType)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(binding)operator(.)ident(type_name)operator(\)) reserved(do) + ident(xm)operator(.)ident(xsd)operator(()symbol(:complexContent)operator(\)) reserved(do) + ident(xm)operator(.)ident(xsd)operator(()symbol(:restriction)operator(,) string<delimiter(')content(base)delimiter(')> operator(=)operator(>) string<delimiter(')content(soapenc:Array)delimiter(')>operator(\)) reserved(do) + ident(xm)operator(.)ident(xsd)operator(()symbol(:attribute)operator(,) string<delimiter(')content(ref)delimiter(')> operator(=)operator(>) string<delimiter(')content(soapenc:arrayType)delimiter(')>operator(,) + string<delimiter(')content(wsdl:arrayType)delimiter(')> operator(=)operator(>) ident(binding)operator(.)ident(element_binding)operator(.)ident(qualified_type_name)operator(()string<delimiter(')content(typens)delimiter(')>operator(\)) operator(+) string<delimiter(')content([])delimiter(')>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(when) ident(binding)operator(.)ident(type)operator(.)ident(structured?) + ident(xm)operator(.)ident(xsd)operator(()symbol(:complexType)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(binding)operator(.)ident(type_name)operator(\)) reserved(do) + ident(xm)operator(.)ident(xsd)operator(()symbol(:all)operator(\)) reserved(do) + ident(binding)operator(.)ident(type)operator(.)ident(each_member) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(|) + ident(b) operator(=) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(\)) + ident(xm)operator(.)ident(xsd)operator(()symbol(:element)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(name)operator(,) string<delimiter(')content(type)delimiter(')> operator(=)operator(>) ident(b)operator(.)ident(qualified_type_name)operator(()string<delimiter(')content(typens)delimiter(')>operator(\))operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# APIs) + ident(apis)operator(.)ident(each) reserved(do) operator(|)ident(api_name)operator(,) ident(values)operator(|) + ident(api) operator(=) ident(values)operator([)integer(0)operator(]) + ident(api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + ident(gen) operator(=) ident(lambda) reserved(do) operator(|)ident(msg_name)operator(,) ident(direction)operator(|) + ident(xm)operator(.)ident(message)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(message_name_for)operator(()ident(api_name)operator(,) ident(msg_name)operator(\))operator(\)) reserved(do) + ident(sym) operator(=) pre_constant(nil) + reserved(if) ident(direction) operator(==) symbol(:out) + ident(returns) operator(=) ident(method)operator(.)ident(returns) + reserved(if) ident(returns) + ident(binding) operator(=) ident(marshaler)operator(.)ident(register_type)operator(()ident(returns)operator([)integer(0)operator(])operator(\)) + ident(xm)operator(.)ident(part)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(return)delimiter(')>operator(,) string<delimiter(')content(type)delimiter(')> operator(=)operator(>) ident(binding)operator(.)ident(qualified_type_name)operator(()string<delimiter(')content(typens)delimiter(')>operator(\))operator(\)) + reserved(end) + reserved(else) + ident(expects) operator(=) ident(method)operator(.)ident(expects) + ident(expects)operator(.)ident(each) reserved(do) operator(|)ident(type)operator(|) + ident(binding) operator(=) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(\)) + ident(xm)operator(.)ident(part)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(type)operator(.)ident(name)operator(,) string<delimiter(')content(type)delimiter(')> operator(=)operator(>) ident(binding)operator(.)ident(qualified_type_name)operator(()string<delimiter(')content(typens)delimiter(')>operator(\))operator(\)) + reserved(end) reserved(if) ident(expects) + reserved(end) + reserved(end) + reserved(end) + ident(public_name) operator(=) ident(method)operator(.)ident(public_name) + ident(gen)operator(.)ident(call)operator(()ident(public_name)operator(,) symbol(:in)operator(\)) + ident(gen)operator(.)ident(call)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(public_name)inline_delimiter(})>content(Response)delimiter(")>operator(,) symbol(:out)operator(\)) + reserved(end) + + comment(# Port) + ident(port_name) operator(=) ident(port_name_for)operator(()ident(global_service_name)operator(,) ident(api_name)operator(\)) + ident(xm)operator(.)ident(portType)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(port_name)operator(\)) reserved(do) + ident(api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + ident(xm)operator(.)ident(operation)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(method)operator(.)ident(public_name)operator(\)) reserved(do) + ident(xm)operator(.)ident(input)operator(()string<delimiter(')content(message)delimiter(')> operator(=)operator(>) string<delimiter(")content(typens:)delimiter(")> operator(+) ident(message_name_for)operator(()ident(api_name)operator(,) ident(method)operator(.)ident(public_name)operator(\))operator(\)) + ident(xm)operator(.)ident(output)operator(()string<delimiter(')content(message)delimiter(')> operator(=)operator(>) string<delimiter(")content(typens:)delimiter(")> operator(+) ident(message_name_for)operator(()ident(api_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(method)operator(.)ident(public_name)inline_delimiter(})>content(Response)delimiter(")>operator(\))operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Bind it) + ident(binding_name) operator(=) ident(binding_name_for)operator(()ident(global_service_name)operator(,) ident(api_name)operator(\)) + ident(xm)operator(.)ident(binding)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(binding_name)operator(,) string<delimiter(')content(type)delimiter(')> operator(=)operator(>) string<delimiter(")content(typens:)inline<inline_delimiter(#{)ident(port_name)inline_delimiter(})>delimiter(")>operator(\)) reserved(do) + ident(xm)operator(.)ident(soap)operator(()symbol(:binding)operator(,) string<delimiter(')content(style)delimiter(')> operator(=)operator(>) string<delimiter(')content(rpc)delimiter(')>operator(,) string<delimiter(')content(transport)delimiter(')> operator(=)operator(>) constant(SoapHttpTransport)operator(\)) + ident(api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + ident(xm)operator(.)ident(operation)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(method)operator(.)ident(public_name)operator(\)) reserved(do) + reserved(case) ident(web_service_dispatching_mode) + reserved(when) symbol(:direct) + ident(soap_action) operator(=) ident(soap_action_base) operator(+) string<delimiter(")content(/api/)delimiter(")> operator(+) ident(method)operator(.)ident(public_name) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + ident(soap_action) operator(=) ident(soap_action_base) \ + operator(+) string<delimiter(")content(/)delimiter(")> operator(+) ident(api_name)operator(.)ident(to_s) \ + operator(+) string<delimiter(")content(/)delimiter(")> operator(+) ident(method)operator(.)ident(public_name) + reserved(end) + ident(xm)operator(.)ident(soap)operator(()symbol(:operation)operator(,) string<delimiter(')content(soapAction)delimiter(')> operator(=)operator(>) ident(soap_action)operator(\)) + ident(xm)operator(.)ident(input) reserved(do) + ident(xm)operator(.)ident(soap)operator(()symbol(:body)operator(,) + string<delimiter(')content(use)delimiter(')> operator(=)operator(>) string<delimiter(')content(encoded)delimiter(')>operator(,) + string<delimiter(')content(namespace)delimiter(')> operator(=)operator(>) ident(namespace)operator(,) + string<delimiter(')content(encodingStyle)delimiter(')> operator(=)operator(>) constant(SoapEncodingNs)operator(\)) + reserved(end) + ident(xm)operator(.)ident(output) reserved(do) + ident(xm)operator(.)ident(soap)operator(()symbol(:body)operator(,) + string<delimiter(')content(use)delimiter(')> operator(=)operator(>) string<delimiter(')content(encoded)delimiter(')>operator(,) + string<delimiter(')content(namespace)delimiter(')> operator(=)operator(>) ident(namespace)operator(,) + string<delimiter(')content(encodingStyle)delimiter(')> operator(=)operator(>) constant(SoapEncodingNs)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Define it) + ident(xm)operator(.)ident(service)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(global_service_name)inline_delimiter(})>content(Service)delimiter(")>operator(\)) reserved(do) + ident(apis)operator(.)ident(each) reserved(do) operator(|)ident(api_name)operator(,) ident(values)operator(|) + ident(port_name) operator(=) ident(port_name_for)operator(()ident(global_service_name)operator(,) ident(api_name)operator(\)) + ident(binding_name) operator(=) ident(binding_name_for)operator(()ident(global_service_name)operator(,) ident(api_name)operator(\)) + reserved(case) ident(web_service_dispatching_mode) + reserved(when) symbol(:direct)operator(,) symbol(:layered) + ident(binding_target) operator(=) string<delimiter(')content(api)delimiter(')> + reserved(when) symbol(:delegated) + ident(binding_target) operator(=) ident(api_name)operator(.)ident(to_s) + reserved(end) + ident(xm)operator(.)ident(port)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) ident(port_name)operator(,) string<delimiter(')content(binding)delimiter(')> operator(=)operator(>) string<delimiter(")content(typens:)inline<inline_delimiter(#{)ident(binding_name)inline_delimiter(})>delimiter(")>operator(\)) reserved(do) + ident(xm)operator(.)ident(soap)operator(()symbol(:address)operator(,) string<delimiter(')content(location)delimiter(')> operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(base_uri)inline_delimiter(})>inline<inline_delimiter(#{)ident(binding_target)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(port_name_for)operator(()ident(global_service)operator(,) ident(service)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(global_service)inline_delimiter(})>inline<inline_delimiter(#{)ident(service)operator(.)ident(to_s)operator(.)ident(camelize)inline_delimiter(})>content(Port)delimiter(")> + reserved(end) + + reserved(def) method(binding_name_for)operator(()ident(global_service)operator(,) ident(service)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(global_service)inline_delimiter(})>inline<inline_delimiter(#{)ident(service)operator(.)ident(to_s)operator(.)ident(camelize)inline_delimiter(})>content(Binding)delimiter(")> + reserved(end) + + reserved(def) method(message_name_for)operator(()ident(api_name)operator(,) ident(message_name)operator(\)) + ident(mode) operator(=) ident(web_service_dispatching_mode) + reserved(if) ident(mode) operator(==) symbol(:layered) operator(||) ident(mode) operator(==) symbol(:delegated) + ident(api_name)operator(.)ident(to_s) operator(+) string<delimiter(')content(-)delimiter(')> operator(+) ident(message_name) + reserved(else) + ident(message_name) + reserved(end) + reserved(end) + + reserved(def) method(register_api)operator(()ident(api)operator(,) ident(marshaler)operator(\)) + ident(bindings) operator(=) operator({)operator(}) + ident(traverse_custom_types)operator(()ident(api)operator(,) ident(marshaler)operator(,) ident(bindings)operator(\)) reserved(do) operator(|)ident(binding)operator(|) + ident(bindings)operator([)ident(binding)operator(]) operator(=) pre_constant(nil) reserved(unless) ident(bindings)operator(.)ident(has_key?)operator(()ident(binding)operator(\)) + ident(element_binding) operator(=) ident(binding)operator(.)ident(element_binding) + ident(bindings)operator([)ident(element_binding)operator(]) operator(=) pre_constant(nil) reserved(if) ident(element_binding) operator(&&) operator(!)ident(bindings)operator(.)ident(has_key?)operator(()ident(element_binding)operator(\)) + reserved(end) + ident(bindings)operator(.)ident(keys) + reserved(end) + + reserved(def) method(traverse_custom_types)operator(()ident(api)operator(,) ident(marshaler)operator(,) ident(bindings)operator(,) operator(&)ident(block)operator(\)) + ident(api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + ident(expects)operator(,) ident(returns) operator(=) ident(method)operator(.)ident(expects)operator(,) ident(method)operator(.)ident(returns) + ident(expects)operator(.)ident(each)operator({) operator(|)ident(type)operator(|) ident(traverse_type)operator(()ident(marshaler)operator(,) ident(type)operator(,) ident(bindings)operator(,) operator(&)ident(block)operator(\)) reserved(if) ident(type)operator(.)ident(custom?) operator(}) reserved(if) ident(expects) + ident(returns)operator(.)ident(each)operator({) operator(|)ident(type)operator(|) ident(traverse_type)operator(()ident(marshaler)operator(,) ident(type)operator(,) ident(bindings)operator(,) operator(&)ident(block)operator(\)) reserved(if) ident(type)operator(.)ident(custom?) operator(}) reserved(if) ident(returns) + reserved(end) + reserved(end) + + reserved(def) method(traverse_type)operator(()ident(marshaler)operator(,) ident(type)operator(,) ident(bindings)operator(,) operator(&)ident(block)operator(\)) + ident(binding) operator(=) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(\)) + reserved(return) reserved(if) ident(bindings)operator(.)ident(has_key?)operator(()ident(binding)operator(\)) + ident(bindings)operator([)ident(binding)operator(]) operator(=) pre_constant(nil) + reserved(yield) ident(binding) + reserved(if) ident(type)operator(.)ident(array?) + reserved(yield) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(.)ident(element_type)operator(\)) + ident(type) operator(=) ident(type)operator(.)ident(element_type) + reserved(end) + ident(type)operator(.)ident(each_member)operator({) operator(|)ident(name)operator(,) ident(type)operator(|) ident(traverse_type)operator(()ident(marshaler)operator(,) ident(type)operator(,) ident(bindings)operator(,) operator(&)ident(block)operator(\)) operator(}) reserved(if) ident(type)operator(.)ident(structured?) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_web_service/dispatcher/abstract)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/dispatcher/action_controller_dispatcher)delimiter(')> +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Invocation) comment(# :nodoc:) + reserved(class) class(InvocationError) operator(<) constant(ActionWebService)operator(::)constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionWebService)operator(::)constant(Invocation)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + comment(# Invocation interceptors provide a means to execute custom code before) + comment(# and after method invocations on ActionWebService::Base objects.) + comment(#) + comment(# When running in _Direct_ dispatching mode, ActionController filters) + comment(# should be used for this functionality instead.) + comment(#) + comment(# The semantics of invocation interceptors are the same as ActionController) + comment(# filters, and accept the same parameters and options.) + comment(#) + comment(# A _before_ interceptor can also cancel execution by returning +false+,) + comment(# or returning a <tt>[false, "cancel reason"]</tt> array if it wishes to supply) + comment(# a reason for canceling the request.) + comment(#) + comment(# === Example) + comment(#) + comment(# class CustomService < ActionWebService::Base) + comment(# before_invocation :intercept_add, :only => [:add]) + comment(#) + comment(# def add(a, b\)) + comment(# a + b) + comment(# end) + comment(#) + comment(# private) + comment(# def intercept_add) + comment(# return [false, "permission denied"] # cancel it) + comment(# end) + comment(# end) + comment(#) + comment(# Options:) + comment(# [<tt>:except</tt>] A list of methods for which the interceptor will NOT be called) + comment(# [<tt>:only</tt>] A list of methods for which the interceptor WILL be called) + reserved(module) class(ClassMethods) + comment(# Appends the given +interceptors+ to be called) + comment(# _before_ method invocation.) + reserved(def) method(append_before_invocation)operator(()operator(*)ident(interceptors)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(interceptors)operator(\)) + ident(interceptors) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_interception_conditions)operator(()ident(interceptors)operator(,) ident(conditions)operator(\)) + ident(append_interceptors_to_chain)operator(()string<delimiter(")content(before)delimiter(")>operator(,) ident(interceptors)operator(\)) + reserved(end) + + comment(# Prepends the given +interceptors+ to be called) + comment(# _before_ method invocation.) + reserved(def) method(prepend_before_invocation)operator(()operator(*)ident(interceptors)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(interceptors)operator(\)) + ident(interceptors) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_interception_conditions)operator(()ident(interceptors)operator(,) ident(conditions)operator(\)) + ident(prepend_interceptors_to_chain)operator(()string<delimiter(")content(before)delimiter(")>operator(,) ident(interceptors)operator(\)) + reserved(end) + + reserved(alias) symbol(:before_invocation) symbol(:append_before_invocation) + + comment(# Appends the given +interceptors+ to be called) + comment(# _after_ method invocation.) + reserved(def) method(append_after_invocation)operator(()operator(*)ident(interceptors)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(interceptors)operator(\)) + ident(interceptors) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_interception_conditions)operator(()ident(interceptors)operator(,) ident(conditions)operator(\)) + ident(append_interceptors_to_chain)operator(()string<delimiter(")content(after)delimiter(")>operator(,) ident(interceptors)operator(\)) + reserved(end) + + comment(# Prepends the given +interceptors+ to be called) + comment(# _after_ method invocation.) + reserved(def) method(prepend_after_invocation)operator(()operator(*)ident(interceptors)operator(,) operator(&)ident(block)operator(\)) + ident(conditions) operator(=) ident(extract_conditions!)operator(()ident(interceptors)operator(\)) + ident(interceptors) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(add_interception_conditions)operator(()ident(interceptors)operator(,) ident(conditions)operator(\)) + ident(prepend_interceptors_to_chain)operator(()string<delimiter(")content(after)delimiter(")>operator(,) ident(interceptors)operator(\)) + reserved(end) + + reserved(alias) symbol(:after_invocation) symbol(:append_after_invocation) + + reserved(def) method(before_invocation_interceptors) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(before_invocation_interceptors)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(after_invocation_interceptors) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(after_invocation_interceptors)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(included_intercepted_methods) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(included_intercepted_methods)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + reserved(def) method(excluded_intercepted_methods) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(excluded_intercepted_methods)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + ident(private) + reserved(def) method(append_interceptors_to_chain)operator(()ident(condition)operator(,) ident(interceptors)operator(\)) + ident(write_inheritable_array)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(_invocation_interceptors)delimiter(")>operator(,) ident(interceptors)operator(\)) + reserved(end) + + reserved(def) method(prepend_interceptors_to_chain)operator(()ident(condition)operator(,) ident(interceptors)operator(\)) + ident(interceptors) operator(=) ident(interceptors) operator(+) ident(read_inheritable_attribute)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(_invocation_interceptors)delimiter(")>operator(\)) + ident(write_inheritable_attribute)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(_invocation_interceptors)delimiter(")>operator(,) ident(interceptors)operator(\)) + reserved(end) + + reserved(def) method(extract_conditions!)operator(()ident(interceptors)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(interceptors)operator(.)ident(last)operator(.)ident(is_a?) constant(Hash) + ident(interceptors)operator(.)ident(pop) + reserved(end) + + reserved(def) method(add_interception_conditions)operator(()ident(interceptors)operator(,) ident(conditions)operator(\)) + reserved(return) reserved(unless) ident(conditions) + ident(included)operator(,) ident(excluded) operator(=) ident(conditions)operator([)symbol(:only)operator(])operator(,) ident(conditions)operator([)symbol(:except)operator(]) + ident(write_inheritable_hash)operator(()string<delimiter(")content(included_intercepted_methods)delimiter(")>operator(,) ident(condition_hash)operator(()ident(interceptors)operator(,) ident(included)operator(\))operator(\)) operator(&&) reserved(return) reserved(if) ident(included) + ident(write_inheritable_hash)operator(()string<delimiter(")content(excluded_intercepted_methods)delimiter(")>operator(,) ident(condition_hash)operator(()ident(interceptors)operator(,) ident(excluded)operator(\))operator(\)) reserved(if) ident(excluded) + reserved(end) + + reserved(def) method(condition_hash)operator(()ident(interceptors)operator(,) operator(*)ident(methods)operator(\)) + ident(interceptors)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({)operator(|)ident(hash)operator(,) ident(interceptor)operator(|) ident(hash)operator(.)ident(merge)operator(()ident(interceptor) operator(=)operator(>) ident(methods)operator(.)ident(flatten)operator(.)ident(map) operator({)operator(|)ident(method)operator(|) ident(method)operator(.)ident(to_s)operator(})operator(\))operator(}) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:perform_invocation_without_interception)operator(,) symbol(:perform_invocation) + ident(alias_method) symbol(:perform_invocation)operator(,) symbol(:perform_invocation_with_interception) + reserved(end) + reserved(end) + + reserved(def) method(perform_invocation_with_interception)operator(()ident(method_name)operator(,) ident(params)operator(,) operator(&)ident(block)operator(\)) + reserved(return) reserved(if) ident(before_invocation)operator(()ident(method_name)operator(,) ident(params)operator(,) operator(&)ident(block)operator(\)) operator(==) pre_constant(false) + ident(return_value) operator(=) ident(perform_invocation_without_interception)operator(()ident(method_name)operator(,) ident(params)operator(\)) + ident(after_invocation)operator(()ident(method_name)operator(,) ident(params)operator(,) ident(return_value)operator(\)) + ident(return_value) + reserved(end) + + reserved(def) method(perform_invocation)operator(()ident(method_name)operator(,) ident(params)operator(\)) + ident(send)operator(()ident(method_name)operator(,) operator(*)ident(params)operator(\)) + reserved(end) + + reserved(def) method(before_invocation)operator(()ident(name)operator(,) ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(call_interceptors)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(before_invocation_interceptors)operator(,) operator([)ident(name)operator(,) ident(args)operator(])operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(after_invocation)operator(()ident(name)operator(,) ident(args)operator(,) ident(result)operator(\)) + ident(call_interceptors)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(after_invocation_interceptors)operator(,) operator([)ident(name)operator(,) ident(args)operator(,) ident(result)operator(])operator(\)) + reserved(end) + + ident(private) + + reserved(def) method(call_interceptors)operator(()ident(interceptors)operator(,) ident(interceptor_args)operator(,) operator(&)ident(block)operator(\)) + reserved(if) ident(interceptors) reserved(and) reserved(not) ident(interceptors)operator(.)ident(empty?) + ident(interceptors)operator(.)ident(each) reserved(do) operator(|)ident(interceptor)operator(|) + reserved(next) reserved(if) ident(method_exempted?)operator(()ident(interceptor)operator(,) ident(interceptor_args)operator([)integer(0)operator(])operator(.)ident(to_s)operator(\)) + ident(result) operator(=) reserved(case) + reserved(when) ident(interceptor)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + pre_constant(self)operator(.)ident(send)operator(()ident(interceptor)operator(,) operator(*)ident(interceptor_args)operator(\)) + reserved(when) ident(interceptor_block?)operator(()ident(interceptor)operator(\)) + ident(interceptor)operator(.)ident(call)operator(()pre_constant(self)operator(,) operator(*)ident(interceptor_args)operator(\)) + reserved(when) ident(interceptor_class?)operator(()ident(interceptor)operator(\)) + ident(interceptor)operator(.)ident(intercept)operator(()pre_constant(self)operator(,) operator(*)ident(interceptor_args)operator(\)) + reserved(else) + ident(raise)operator(() + constant(InvocationError)operator(,) + string<delimiter(")content(Interceptors need to be either a symbol, proc/method, or a class implementing a static intercept method)delimiter(")> + operator(\)) + reserved(end) + ident(reason) operator(=) pre_constant(nil) + reserved(if) ident(result)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(reason) operator(=) ident(result)operator([)integer(1)operator(]) reserved(if) ident(result)operator([)integer(1)operator(]) + ident(result) operator(=) ident(result)operator([)integer(0)operator(]) + reserved(end) + reserved(if) ident(result) operator(==) pre_constant(false) + ident(block)operator(.)ident(call)operator(()ident(reason)operator(\)) reserved(if) ident(block) operator(&&) ident(reason) + reserved(return) pre_constant(false) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(interceptor_block?)operator(()ident(interceptor)operator(\)) + ident(interceptor)operator(.)ident(respond_to?)operator(()string<delimiter(")content(call)delimiter(")>operator(\)) operator(&&) operator(()ident(interceptor)operator(.)ident(arity) operator(==) integer(3) operator(||) ident(interceptor)operator(.)ident(arity) operator(==) integer(-1)operator(\)) + reserved(end) + + reserved(def) method(interceptor_class?)operator(()ident(interceptor)operator(\)) + ident(interceptor)operator(.)ident(respond_to?)operator(()string<delimiter(")content(intercept)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(method_exempted?)operator(()ident(interceptor)operator(,) ident(method_name)operator(\)) + reserved(case) + reserved(when) pre_constant(self)operator(.)ident(class)operator(.)ident(included_intercepted_methods)operator([)ident(interceptor)operator(]) + operator(!)pre_constant(self)operator(.)ident(class)operator(.)ident(included_intercepted_methods)operator([)ident(interceptor)operator(])operator(.)ident(include?)operator(()ident(method_name)operator(\)) + reserved(when) pre_constant(self)operator(.)ident(class)operator(.)ident(excluded_intercepted_methods)operator([)ident(interceptor)operator(]) + pre_constant(self)operator(.)ident(class)operator(.)ident(excluded_intercepted_methods)operator([)ident(interceptor)operator(])operator(.)ident(include?)operator(()ident(method_name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Protocol) comment(# :nodoc:) + reserved(class) class(ProtocolError) operator(<) constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + reserved(class) class(AbstractProtocol) comment(# :nodoc:) + reserved(def) method(setup)operator(()ident(controller)operator(\)) + reserved(end) + + reserved(def) method(decode_action_pack_request)operator(()ident(action_pack_request)operator(\)) + reserved(end) + + reserved(def) method(encode_action_pack_request)operator(()ident(service_name)operator(,) ident(public_method_name)operator(,) ident(raw_body)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + ident(klass) operator(=) ident(options)operator([)symbol(:request_class)operator(]) operator(||) constant(SimpleActionPackRequest) + ident(request) operator(=) ident(klass)operator(.)ident(new) + ident(request)operator(.)ident(request_parameters)operator([)string<delimiter(')content(action)delimiter(')>operator(]) operator(=) ident(service_name)operator(.)ident(to_s) + ident(request)operator(.)ident(env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) operator(=) ident(raw_body) + ident(request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(POST)delimiter(')> + ident(request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_CONTENT_TYPE)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/xml)delimiter(')> + ident(request) + reserved(end) + + reserved(def) method(decode_request)operator(()ident(raw_request)operator(,) ident(service_name)operator(,) ident(protocol_options)operator(=)operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(encode_request)operator(()ident(method_name)operator(,) ident(params)operator(,) ident(param_types)operator(\)) + reserved(end) + + reserved(def) method(decode_response)operator(()ident(raw_response)operator(\)) + reserved(end) + + reserved(def) method(encode_response)operator(()ident(method_name)operator(,) ident(return_value)operator(,) ident(return_type)operator(,) ident(protocol_options)operator(=)operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(protocol_client)operator(()ident(api)operator(,) ident(protocol_name)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(register_api)operator(()ident(api)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(Request) comment(# :nodoc:) + ident(attr) symbol(:protocol) + ident(attr_accessor) symbol(:method_name) + ident(attr_accessor) symbol(:method_params) + ident(attr) symbol(:service_name) + ident(attr_accessor) symbol(:api) + ident(attr_accessor) symbol(:api_method) + ident(attr) symbol(:protocol_options) + + reserved(def) method(initialize)operator(()ident(protocol)operator(,) ident(method_name)operator(,) ident(method_params)operator(,) ident(service_name)operator(,) ident(api)operator(=)pre_constant(nil)operator(,) ident(api_method)operator(=)pre_constant(nil)operator(,) ident(protocol_options)operator(=)pre_constant(nil)operator(\)) + instance_variable(@protocol) operator(=) ident(protocol) + instance_variable(@method_name) operator(=) ident(method_name) + instance_variable(@method_params) operator(=) ident(method_params) + instance_variable(@service_name) operator(=) ident(service_name) + instance_variable(@api) operator(=) ident(api) + instance_variable(@api_method) operator(=) ident(api_method) + instance_variable(@protocol_options) operator(=) ident(protocol_options) operator(||) operator({)operator(}) + reserved(end) + reserved(end) + + reserved(class) class(Response) comment(# :nodoc:) + ident(attr) symbol(:body) + ident(attr) symbol(:content_type) + ident(attr) symbol(:return_value) + + reserved(def) method(initialize)operator(()ident(body)operator(,) ident(content_type)operator(,) ident(return_value)operator(\)) + instance_variable(@body) operator(=) ident(body) + instance_variable(@content_type) operator(=) ident(content_type) + instance_variable(@return_value) operator(=) ident(return_value) + reserved(end) + reserved(end) + + reserved(class) class(SimpleActionPackRequest) operator(<) constant(ActionController)operator(::)constant(AbstractRequest) comment(# :nodoc:) + reserved(def) method(initialize) + instance_variable(@env) operator(=) operator({)operator(}) + instance_variable(@qparams) operator(=) operator({)operator(}) + instance_variable(@rparams) operator(=) operator({)operator(}) + instance_variable(@cookies) operator(=) operator({)operator(}) + ident(reset_session) + reserved(end) + + reserved(def) method(query_parameters) + instance_variable(@qparams) + reserved(end) + + reserved(def) method(request_parameters) + instance_variable(@rparams) + reserved(end) + + reserved(def) method(env) + instance_variable(@env) + reserved(end) + + reserved(def) method(host) + string<delimiter(')delimiter(')> + reserved(end) + + reserved(def) method(cookies) + instance_variable(@cookies) + reserved(end) + + reserved(def) method(session) + instance_variable(@session) + reserved(end) + + reserved(def) method(reset_session) + instance_variable(@session) operator(=) operator({)operator(}) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(Protocol) comment(# :nodoc:) + reserved(module) class(Discovery) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(send)operator(()symbol(:include)operator(,) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Discovery)operator(::)constant(InstanceMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) comment(# :nodoc:) + reserved(def) method(register_protocol)operator(()ident(klass)operator(\)) + ident(write_inheritable_array)operator(()string<delimiter(")content(web_service_protocols)delimiter(")>operator(,) operator([)ident(klass)operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) comment(# :nodoc:) + ident(private) + reserved(def) method(discover_web_service_request)operator(()ident(action_pack_request)operator(\)) + operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(web_service_protocols)delimiter(")>operator(\)) operator(||) operator([)operator(])operator(\))operator(.)ident(each) reserved(do) operator(|)ident(protocol)operator(|) + ident(protocol) operator(=) ident(protocol)operator(.)ident(create)operator(()pre_constant(self)operator(\)) + ident(request) operator(=) ident(protocol)operator(.)ident(decode_action_pack_request)operator(()ident(action_pack_request)operator(\)) + reserved(return) ident(request) reserved(unless) ident(request)operator(.)ident(nil?) + reserved(end) + pre_constant(nil) + reserved(end) + + reserved(def) method(create_web_service_client)operator(()ident(api)operator(,) ident(protocol_name)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(\)) + operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(web_service_protocols)delimiter(")>operator(\)) operator(||) operator([)operator(])operator(\))operator(.)ident(each) reserved(do) operator(|)ident(protocol)operator(|) + ident(protocol) operator(=) ident(protocol)operator(.)ident(create)operator(()pre_constant(self)operator(\)) + ident(client) operator(=) ident(protocol)operator(.)ident(protocol_client)operator(()ident(api)operator(,) ident(protocol_name)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(\)) + reserved(return) ident(client) reserved(unless) ident(client)operator(.)ident(nil?) + reserved(end) + pre_constant(nil) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(soap/mapping)delimiter(')> + +reserved(module) class(ActionWebService) + reserved(module) class(Protocol) + reserved(module) class(Soap) + comment(# Workaround for SOAP4R return values changing) + reserved(class) class(Registry) operator(<) constant(SOAP)operator(::)constant(Mapping)operator(::)constant(Registry) + reserved(if) constant(SOAP)operator(::)constant(Version) operator(>)operator(=) string<delimiter(")content(1.5.4)delimiter(")> + reserved(def) method(find_mapped_soap_class)operator(()ident(obj_class)operator(\)) + reserved(return) instance_variable(@map)operator(.)ident(instance_eval) operator({) instance_variable(@obj2soap)operator([)ident(obj_class)operator(])operator([)integer(0)operator(]) operator(}) + reserved(end) + + reserved(def) method(find_mapped_obj_class)operator(()ident(soap_class)operator(\)) + reserved(return) instance_variable(@map)operator(.)ident(instance_eval) operator({) instance_variable(@soap2obj)operator([)ident(soap_class)operator(])operator([)integer(0)operator(]) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(SoapMarshaler) + ident(attr) symbol(:namespace) + ident(attr) symbol(:registry) + + reserved(def) method(initialize)operator(()ident(namespace)operator(=)pre_constant(nil)operator(\)) + instance_variable(@namespace) operator(=) ident(namespace) operator(||) string<delimiter(')content(urn:ActionWebService)delimiter(')> + instance_variable(@registry) operator(=) constant(Registry)operator(.)ident(new) + instance_variable(@type2binding) operator(=) operator({)operator(}) + ident(register_static_factories) + reserved(end) + + reserved(def) method(soap_to_ruby)operator(()ident(obj)operator(\)) + constant(SOAP)operator(::)constant(Mapping)operator(.)ident(soap2obj)operator(()ident(obj)operator(,) instance_variable(@registry)operator(\)) + reserved(end) + + reserved(def) method(ruby_to_soap)operator(()ident(obj)operator(\)) + ident(soap) operator(=) constant(SOAP)operator(::)constant(Mapping)operator(.)ident(obj2soap)operator(()ident(obj)operator(,) instance_variable(@registry)operator(\)) + ident(soap)operator(.)ident(elename) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new) reserved(if) constant(SOAP)operator(::)constant(Version) operator(>)operator(=) string<delimiter(")content(1.5.5)delimiter(")> operator(&&) ident(soap)operator(.)ident(elename) operator(==) constant(XSD)operator(::)constant(QName)operator(::)constant(EMPTY) + ident(soap) + reserved(end) + + reserved(def) method(register_type)operator(()ident(type)operator(\)) + reserved(return) instance_variable(@type2binding)operator([)ident(type)operator(]) reserved(if) instance_variable(@type2binding)operator(.)ident(has_key?)operator(()ident(type)operator(\)) + + reserved(if) ident(type)operator(.)ident(array?) + ident(array_mapping) operator(=) instance_variable(@registry)operator(.)ident(find_mapped_soap_class)operator(()constant(Array)operator(\)) + ident(qname) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new)operator(()instance_variable(@namespace)operator(,) ident(soap_type_name)operator(()ident(type)operator(.)ident(element_type)operator(.)ident(type_class)operator(.)ident(name)operator(\)) operator(+) string<delimiter(')content(Array)delimiter(')>operator(\)) + ident(element_type_binding) operator(=) ident(register_type)operator(()ident(type)operator(.)ident(element_type)operator(\)) + instance_variable(@type2binding)operator([)ident(type)operator(]) operator(=) constant(SoapBinding)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(qname)operator(,) ident(type)operator(,) ident(array_mapping)operator(,) ident(element_type_binding)operator(\)) + reserved(elsif) operator(()ident(mapping) operator(=) instance_variable(@registry)operator(.)ident(find_mapped_soap_class)operator(()ident(type)operator(.)ident(type_class)operator(\)) reserved(rescue) pre_constant(nil)operator(\)) + ident(qname) operator(=) ident(mapping)operator([)integer(2)operator(]) operator(?) ident(mapping)operator([)integer(2)operator(])operator([)symbol(:type)operator(]) operator(:) pre_constant(nil) + ident(qname) operator(||=) ident(soap_base_type_name)operator(()ident(mapping)operator([)integer(0)operator(])operator(\)) + instance_variable(@type2binding)operator([)ident(type)operator(]) operator(=) constant(SoapBinding)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(qname)operator(,) ident(type)operator(,) ident(mapping)operator(\)) + reserved(else) + ident(qname) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new)operator(()instance_variable(@namespace)operator(,) ident(soap_type_name)operator(()ident(type)operator(.)ident(type_class)operator(.)ident(name)operator(\))operator(\)) + instance_variable(@registry)operator(.)ident(add)operator(()ident(type)operator(.)ident(type_class)operator(,) + constant(SOAP)operator(::)constant(SOAPStruct)operator(,) + ident(typed_struct_factory)operator(()ident(type)operator(.)ident(type_class)operator(\))operator(,) + operator({) symbol(:type) operator(=)operator(>) ident(qname) operator(})operator(\)) + ident(mapping) operator(=) instance_variable(@registry)operator(.)ident(find_mapped_soap_class)operator(()ident(type)operator(.)ident(type_class)operator(\)) + instance_variable(@type2binding)operator([)ident(type)operator(]) operator(=) constant(SoapBinding)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(qname)operator(,) ident(type)operator(,) ident(mapping)operator(\)) + reserved(end) + + reserved(if) ident(type)operator(.)ident(structured?) + ident(type)operator(.)ident(each_member) reserved(do) operator(|)ident(m_name)operator(,) ident(m_type)operator(|) + ident(register_type)operator(()ident(m_type)operator(\)) + reserved(end) + reserved(end) + + instance_variable(@type2binding)operator([)ident(type)operator(]) + reserved(end) + reserved(alias) symbol(:lookup_type) symbol(:register_type) + + reserved(def) method(annotate_arrays)operator(()ident(binding)operator(,) ident(value)operator(\)) + reserved(if) ident(value)operator(.)ident(nil?) + reserved(return) + reserved(elsif) ident(binding)operator(.)ident(type)operator(.)ident(array?) + ident(mark_typed_array)operator(()ident(value)operator(,) ident(binding)operator(.)ident(element_binding)operator(.)ident(qname)operator(\)) + reserved(if) ident(binding)operator(.)ident(element_binding)operator(.)ident(type)operator(.)ident(custom?) + ident(value)operator(.)ident(each) reserved(do) operator(|)ident(element)operator(|) + ident(annotate_arrays)operator(()ident(binding)operator(.)ident(element_binding)operator(,) ident(element)operator(\)) + reserved(end) + reserved(end) + reserved(elsif) ident(binding)operator(.)ident(type)operator(.)ident(structured?) + ident(binding)operator(.)ident(type)operator(.)ident(each_member) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(|) + ident(member_binding) operator(=) ident(register_type)operator(()ident(type)operator(\)) + ident(member_value) operator(=) ident(value)operator(.)ident(respond_to?)operator(()string<delimiter(')content([])delimiter(')>operator(\)) operator(?) ident(value)operator([)ident(name)operator(]) operator(:) ident(value)operator(.)ident(send)operator(()ident(name)operator(\)) + ident(annotate_arrays)operator(()ident(member_binding)operator(,) ident(member_value)operator(\)) reserved(if) ident(type)operator(.)ident(custom?) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(typed_struct_factory)operator(()ident(type_class)operator(\)) + reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()string<delimiter(')content(ActiveRecord)delimiter(')>operator(\)) + reserved(if) ident(type_class)operator(.)ident(ancestors)operator(.)ident(include?)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(\)) + ident(qname) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new)operator(()instance_variable(@namespace)operator(,) ident(soap_type_name)operator(()ident(type_class)operator(.)ident(name)operator(\))operator(\)) + ident(type_class)operator(.)ident(instance_variable_set)operator(()string<delimiter(')content(@qname)delimiter(')>operator(,) ident(qname)operator(\)) + reserved(return) constant(SoapActiveRecordStructFactory)operator(.)ident(new) + reserved(end) + reserved(end) + constant(SOAP)operator(::)constant(Mapping)operator(::)constant(Registry)operator(::)constant(TypedStructFactory) + reserved(end) + + reserved(def) method(mark_typed_array)operator(()ident(array)operator(,) ident(qname)operator(\)) + operator(()reserved(class) operator(<<) class(array)operator(;) pre_constant(self)operator(;) reserved(end)operator(\))operator(.)ident(class_eval) reserved(do) + ident(define_method)operator(()symbol(:arytype)operator(\)) reserved(do) + ident(qname) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(soap_base_type_name)operator(()ident(type)operator(\)) + ident(xsd_type) operator(=) ident(type)operator(.)ident(ancestors)operator(.)ident(find)operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(const_defined?) string<delimiter(')content(Type)delimiter(')> operator(}) + ident(xsd_type) operator(?) ident(xsd_type)operator(.)ident(const_get)operator(()string<delimiter(')content(Type)delimiter(')>operator(\)) operator(:) constant(XSD)operator(::)constant(XSDAnySimpleType)operator(::)constant(Type) + reserved(end) + + reserved(def) method(soap_type_name)operator(()ident(type_name)operator(\)) + ident(type_name)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(::)delimiter(/)>operator(,) string<delimiter(')content(..)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(register_static_factories) + instance_variable(@registry)operator(.)ident(add)operator(()constant(ActionWebService)operator(::)constant(Base64)operator(,) + constant(SOAP)operator(::)constant(SOAPBase64)operator(,) + constant(SoapBase64Factory)operator(.)ident(new)operator(,) + pre_constant(nil)operator(\)) + ident(mapping) operator(=) instance_variable(@registry)operator(.)ident(find_mapped_soap_class)operator(()constant(ActionWebService)operator(::)constant(Base64)operator(\)) + instance_variable(@type2binding)operator([)constant(ActionWebService)operator(::)constant(Base64)operator(]) operator(=) + constant(SoapBinding)operator(.)ident(new)operator(()pre_constant(self)operator(,) constant(SOAP)operator(::)constant(SOAPBase64)operator(::)constant(Type)operator(,) + constant(ActionWebService)operator(::)constant(Base64)operator(,) ident(mapping)operator(\)) + instance_variable(@registry)operator(.)ident(add)operator(()constant(Array)operator(,) + constant(SOAP)operator(::)constant(SOAPArray)operator(,) + constant(SoapTypedArrayFactory)operator(.)ident(new)operator(,) + pre_constant(nil)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(SoapBinding) + ident(attr) symbol(:qname) + ident(attr) symbol(:type) + ident(attr) symbol(:mapping) + ident(attr) symbol(:element_binding) + + reserved(def) method(initialize)operator(()ident(marshaler)operator(,) ident(qname)operator(,) ident(type)operator(,) ident(mapping)operator(,) ident(element_binding)operator(=)pre_constant(nil)operator(\)) + instance_variable(@marshaler) operator(=) ident(marshaler) + instance_variable(@qname) operator(=) ident(qname) + instance_variable(@type) operator(=) ident(type) + instance_variable(@mapping) operator(=) ident(mapping) + instance_variable(@element_binding) operator(=) ident(element_binding) + reserved(end) + + reserved(def) method(type_name) + instance_variable(@type)operator(.)ident(custom?) operator(?) instance_variable(@qname)operator(.)ident(name) operator(:) pre_constant(nil) + reserved(end) + + reserved(def) method(qualified_type_name)operator(()ident(ns)operator(=)pre_constant(nil)operator(\)) + reserved(if) instance_variable(@type)operator(.)ident(custom?) + string<delimiter(")inline<inline_delimiter(#{)ident(ns) operator(?) ident(ns) operator(:) instance_variable(@qname)operator(.)ident(namespace)inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@qname)operator(.)ident(name)inline_delimiter(})>delimiter(")> + reserved(else) + ident(ns) operator(=) constant(XSD)operator(::)constant(NS)operator(.)ident(new) + ident(ns)operator(.)ident(assign)operator(()constant(XSD)operator(::)constant(Namespace)operator(,) constant(SOAP)operator(::)constant(XSDNamespaceTag)operator(\)) + ident(ns)operator(.)ident(assign)operator(()constant(SOAP)operator(::)constant(EncodingNamespace)operator(,) string<delimiter(")content(soapenc)delimiter(")>operator(\)) + ident(xsd_klass) operator(=) ident(mapping)operator([)integer(0)operator(])operator(.)ident(ancestors)operator(.)ident(find)operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(const_defined?)operator(()string<delimiter(')content(Type)delimiter(')>operator(\))operator(}) + reserved(return) ident(ns)operator(.)ident(name)operator(()constant(XSD)operator(::)constant(AnyTypeName)operator(\)) reserved(unless) ident(xsd_klass) + ident(ns)operator(.)ident(name)operator(()ident(xsd_klass)operator(.)ident(const_get)operator(()string<delimiter(')content(Type)delimiter(')>operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(eql?)operator(()ident(other)operator(\)) + instance_variable(@qname) operator(==) ident(other)operator(.)ident(qname) + reserved(end) + reserved(alias) symbol(:==) symbol(:eql?) + + reserved(def) method(hash) + instance_variable(@qname)operator(.)ident(hash) + reserved(end) + reserved(end) + + reserved(class) class(SoapActiveRecordStructFactory) operator(<) constant(SOAP)operator(::)constant(Mapping)operator(::)constant(Factory) + reserved(def) method(obj2soap)operator(()ident(soap_class)operator(,) ident(obj)operator(,) ident(info)operator(,) ident(map)operator(\)) + reserved(unless) ident(obj)operator(.)ident(is_a?)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(\)) + reserved(return) pre_constant(nil) + reserved(end) + ident(soap_obj) operator(=) ident(soap_class)operator(.)ident(new)operator(()ident(obj)operator(.)ident(class)operator(.)ident(instance_variable_get)operator(()string<delimiter(')content(@qname)delimiter(')>operator(\))operator(\)) + ident(obj)operator(.)ident(class)operator(.)ident(columns)operator(.)ident(each) reserved(do) operator(|)ident(column)operator(|) + ident(key) operator(=) ident(column)operator(.)ident(name)operator(.)ident(to_s) + ident(value) operator(=) ident(obj)operator(.)ident(send)operator(()ident(key)operator(\)) + ident(soap_obj)operator([)ident(key)operator(]) operator(=) constant(SOAP)operator(::)constant(Mapping)operator(.)ident(_obj2soap)operator(()ident(value)operator(,) ident(map)operator(\)) + reserved(end) + ident(soap_obj) + reserved(end) + + reserved(def) method(soap2obj)operator(()ident(obj_class)operator(,) ident(node)operator(,) ident(info)operator(,) ident(map)operator(\)) + reserved(unless) ident(node)operator(.)ident(type) operator(==) ident(obj_class)operator(.)ident(instance_variable_get)operator(()string<delimiter(')content(@qname)delimiter(')>operator(\)) + reserved(return) pre_constant(false) + reserved(end) + ident(obj) operator(=) ident(obj_class)operator(.)ident(new) + ident(node)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + ident(obj)operator([)ident(key)operator(]) operator(=) ident(value)operator(.)ident(data) + reserved(end) + ident(obj)operator(.)ident(instance_variable_set)operator(()string<delimiter(')content(@new_record)delimiter(')>operator(,) pre_constant(false)operator(\)) + reserved(return) pre_constant(true)operator(,) ident(obj) + reserved(end) + reserved(end) + + reserved(class) class(SoapTypedArrayFactory) operator(<) constant(SOAP)operator(::)constant(Mapping)operator(::)constant(Factory) + reserved(def) method(obj2soap)operator(()ident(soap_class)operator(,) ident(obj)operator(,) ident(info)operator(,) ident(map)operator(\)) + reserved(unless) ident(obj)operator(.)ident(respond_to?)operator(()symbol(:arytype)operator(\)) + reserved(return) pre_constant(nil) + reserved(end) + ident(soap_obj) operator(=) ident(soap_class)operator(.)ident(new)operator(()constant(SOAP)operator(::)constant(ValueArrayName)operator(,) integer(1)operator(,) ident(obj)operator(.)ident(arytype)operator(\)) + ident(mark_marshalled_obj)operator(()ident(obj)operator(,) ident(soap_obj)operator(\)) + ident(obj)operator(.)ident(each) reserved(do) operator(|)ident(item)operator(|) + ident(child) operator(=) constant(SOAP)operator(::)constant(Mapping)operator(.)ident(_obj2soap)operator(()ident(item)operator(,) ident(map)operator(\)) + ident(soap_obj)operator(.)ident(add)operator(()ident(child)operator(\)) + reserved(end) + ident(soap_obj) + reserved(end) + + reserved(def) method(soap2obj)operator(()ident(obj_class)operator(,) ident(node)operator(,) ident(info)operator(,) ident(map)operator(\)) + reserved(return) pre_constant(false) + reserved(end) + reserved(end) + + reserved(class) class(SoapBase64Factory) operator(<) constant(SOAP)operator(::)constant(Mapping)operator(::)constant(Factory) + reserved(def) method(obj2soap)operator(()ident(soap_class)operator(,) ident(obj)operator(,) ident(info)operator(,) ident(map)operator(\)) + reserved(unless) ident(obj)operator(.)ident(is_a?)operator(()constant(ActionWebService)operator(::)constant(Base64)operator(\)) + reserved(return) pre_constant(nil) + reserved(end) + reserved(return) ident(soap_class)operator(.)ident(new)operator(()ident(obj)operator(\)) + reserved(end) + + reserved(def) method(soap2obj)operator(()ident(obj_class)operator(,) ident(node)operator(,) ident(info)operator(,) ident(map)operator(\)) + reserved(unless) ident(node)operator(.)ident(type) operator(==) constant(SOAP)operator(::)constant(SOAPBase64)operator(::)constant(Type) + reserved(return) pre_constant(false) + reserved(end) + reserved(return) pre_constant(true)operator(,) ident(obj_class)operator(.)ident(new)operator(()ident(node)operator(.)ident(string)operator(\)) + reserved(end) + reserved(end) + + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_web_service/protocol/soap_protocol/marshaler)delimiter(')> +ident(require) string<delimiter(')content(soap/streamHandler)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/client/soap_client)delimiter(')> + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(API) comment(# :nodoc:) + reserved(class) class(Base) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(soap_client)operator(()ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + constant(ActionWebService)operator(::)constant(Client)operator(::)constant(Soap)operator(.)ident(new) pre_constant(self)operator(,) ident(endpoint_uri)operator(,) ident(options) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(Protocol) comment(# :nodoc:) + reserved(module) class(Soap) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(register_protocol)operator(()constant(SoapProtocol)operator(\)) + ident(base)operator(.)ident(class_inheritable_option)operator(()symbol(:wsdl_service_name)operator(\)) + ident(base)operator(.)ident(class_inheritable_option)operator(()symbol(:wsdl_namespace)operator(\)) + reserved(end) + + reserved(class) class(SoapProtocol) operator(<) constant(AbstractProtocol) comment(# :nodoc:) + constant(AWSEncoding) operator(=) string<delimiter(')content(UTF-8)delimiter(')> + constant(XSDEncoding) operator(=) string<delimiter(')content(UTF8)delimiter(')> + + ident(attr) symbol(:marshaler) + + reserved(def) method(initialize)operator(()ident(namespace)operator(=)pre_constant(nil)operator(\)) + ident(namespace) operator(||=) string<delimiter(')content(urn:ActionWebService)delimiter(')> + instance_variable(@marshaler) operator(=) constant(SoapMarshaler)operator(.)ident(new) ident(namespace) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(create)operator(()ident(controller)operator(\)) + constant(SoapProtocol)operator(.)ident(new)operator(()ident(controller)operator(.)ident(wsdl_namespace)operator(\)) + reserved(end) + + reserved(def) method(decode_action_pack_request)operator(()ident(action_pack_request)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(soap_action) operator(=) ident(has_valid_soap_action?)operator(()ident(action_pack_request)operator(\)) + ident(service_name) operator(=) ident(action_pack_request)operator(.)ident(parameters)operator([)string<delimiter(')content(action)delimiter(')>operator(]) + ident(input_encoding) operator(=) ident(parse_charset)operator(()ident(action_pack_request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_CONTENT_TYPE)delimiter(')>operator(])operator(\)) + ident(protocol_options) operator(=) operator({) + symbol(:soap_action) operator(=)operator(>) ident(soap_action)operator(,) + symbol(:charset) operator(=)operator(>) ident(input_encoding) + operator(}) + ident(decode_request)operator(()ident(action_pack_request)operator(.)ident(raw_post)operator(,) ident(service_name)operator(,) ident(protocol_options)operator(\)) + reserved(end) + + reserved(def) method(encode_action_pack_request)operator(()ident(service_name)operator(,) ident(public_method_name)operator(,) ident(raw_body)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + ident(request) operator(=) reserved(super) + ident(request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_SOAPACTION)delimiter(')>operator(]) operator(=) string<delimiter(')content(/soap/%s/%s)delimiter(')> operator(%) operator([)ident(service_name)operator(,) ident(public_method_name)operator(]) + ident(request) + reserved(end) + + reserved(def) method(decode_request)operator(()ident(raw_request)operator(,) ident(service_name)operator(,) ident(protocol_options)operator(=)operator({)operator(})operator(\)) + ident(envelope) operator(=) constant(SOAP)operator(::)constant(Processor)operator(.)ident(unmarshal)operator(()ident(raw_request)operator(,) symbol(:charset) operator(=)operator(>) ident(protocol_options)operator([)symbol(:charset)operator(])operator(\)) + reserved(unless) ident(envelope) + ident(raise) constant(ProtocolError)operator(,) string<delimiter(")content(Failed to parse SOAP request message)delimiter(")> + reserved(end) + ident(request) operator(=) ident(envelope)operator(.)ident(body)operator(.)ident(request) + ident(method_name) operator(=) ident(request)operator(.)ident(elename)operator(.)ident(name) + ident(params) operator(=) ident(request)operator(.)ident(collect)operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(marshaler)operator(.)ident(soap_to_ruby)operator(()ident(request)operator([)ident(k)operator(])operator(\)) operator(}) + constant(Request)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(method_name)operator(,) ident(params)operator(,) ident(service_name)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(,) ident(protocol_options)operator(\)) + reserved(end) + + reserved(def) method(encode_request)operator(()ident(method_name)operator(,) ident(params)operator(,) ident(param_types)operator(\)) + ident(param_types)operator(.)ident(each)operator({) operator(|)ident(type)operator(|) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(\)) operator(}) reserved(if) ident(param_types) + ident(qname) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new)operator(()ident(marshaler)operator(.)ident(namespace)operator(,) ident(method_name)operator(\)) + ident(param_def) operator(=) operator([)operator(]) + reserved(if) ident(param_types) + ident(params) operator(=) ident(param_types)operator(.)ident(zip)operator(()ident(params)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(type)operator(,) ident(param)operator(|) + ident(param_def) operator(<<) operator([)string<delimiter(')content(in)delimiter(')>operator(,) ident(type)operator(.)ident(name)operator(,) ident(marshaler)operator(.)ident(lookup_type)operator(()ident(type)operator(\))operator(.)ident(mapping)operator(]) + operator([)ident(type)operator(.)ident(name)operator(,) ident(marshaler)operator(.)ident(ruby_to_soap)operator(()ident(param)operator(\))operator(]) + reserved(end) + reserved(else) + ident(params) operator(=) operator([)operator(]) + reserved(end) + ident(request) operator(=) constant(SOAP)operator(::)constant(RPC)operator(::)constant(SOAPMethodRequest)operator(.)ident(new)operator(()ident(qname)operator(,) ident(param_def)operator(\)) + ident(request)operator(.)ident(set_param)operator(()ident(params)operator(\)) + ident(envelope) operator(=) ident(create_soap_envelope)operator(()ident(request)operator(\)) + constant(SOAP)operator(::)constant(Processor)operator(.)ident(marshal)operator(()ident(envelope)operator(\)) + reserved(end) + + reserved(def) method(decode_response)operator(()ident(raw_response)operator(\)) + ident(envelope) operator(=) constant(SOAP)operator(::)constant(Processor)operator(.)ident(unmarshal)operator(()ident(raw_response)operator(\)) + reserved(unless) ident(envelope) + ident(raise) constant(ProtocolError)operator(,) string<delimiter(")content(Failed to parse SOAP request message)delimiter(")> + reserved(end) + ident(method_name) operator(=) ident(envelope)operator(.)ident(body)operator(.)ident(request)operator(.)ident(elename)operator(.)ident(name) + ident(return_value) operator(=) ident(envelope)operator(.)ident(body)operator(.)ident(response) + ident(return_value) operator(=) ident(marshaler)operator(.)ident(soap_to_ruby)operator(()ident(return_value)operator(\)) reserved(unless) ident(return_value)operator(.)ident(nil?) + operator([)ident(method_name)operator(,) ident(return_value)operator(]) + reserved(end) + + reserved(def) method(encode_response)operator(()ident(method_name)operator(,) ident(return_value)operator(,) ident(return_type)operator(,) ident(protocol_options)operator(=)operator({)operator(})operator(\)) + reserved(if) ident(return_type) + ident(return_binding) operator(=) ident(marshaler)operator(.)ident(register_type)operator(()ident(return_type)operator(\)) + ident(marshaler)operator(.)ident(annotate_arrays)operator(()ident(return_binding)operator(,) ident(return_value)operator(\)) + reserved(end) + ident(qname) operator(=) constant(XSD)operator(::)constant(QName)operator(.)ident(new)operator(()ident(marshaler)operator(.)ident(namespace)operator(,) ident(method_name)operator(\)) + reserved(if) ident(return_value)operator(.)ident(nil?) + ident(response) operator(=) constant(SOAP)operator(::)constant(RPC)operator(::)constant(SOAPMethodResponse)operator(.)ident(new)operator(()ident(qname)operator(,) pre_constant(nil)operator(\)) + reserved(else) + reserved(if) ident(return_value)operator(.)ident(is_a?)operator(()constant(Exception)operator(\)) + ident(detail) operator(=) constant(SOAP)operator(::)constant(Mapping)operator(::)constant(SOAPException)operator(.)ident(new)operator(()ident(return_value)operator(\)) + ident(response) operator(=) constant(SOAP)operator(::)constant(SOAPFault)operator(.)ident(new)operator(() + constant(SOAP)operator(::)constant(SOAPQName)operator(.)ident(new)operator(()string<delimiter(')content(%s:%s)delimiter(')> operator(%) operator([)constant(SOAP)operator(::)constant(SOAPNamespaceTag)operator(,) string<delimiter(')content(Server)delimiter(')>operator(])operator(\))operator(,) + constant(SOAP)operator(::)constant(SOAPString)operator(.)ident(new)operator(()ident(return_value)operator(.)ident(to_s)operator(\))operator(,) + constant(SOAP)operator(::)constant(SOAPString)operator(.)ident(new)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(name)operator(\))operator(,) + ident(marshaler)operator(.)ident(ruby_to_soap)operator(()ident(detail)operator(\))operator(\)) + reserved(else) + reserved(if) ident(return_type) + ident(param_def) operator(=) operator([)operator([)string<delimiter(')content(retval)delimiter(')>operator(,) string<delimiter(')content(return)delimiter(')>operator(,) ident(marshaler)operator(.)ident(lookup_type)operator(()ident(return_type)operator(\))operator(.)ident(mapping)operator(])operator(]) + ident(response) operator(=) constant(SOAP)operator(::)constant(RPC)operator(::)constant(SOAPMethodResponse)operator(.)ident(new)operator(()ident(qname)operator(,) ident(param_def)operator(\)) + ident(response)operator(.)ident(retval) operator(=) ident(marshaler)operator(.)ident(ruby_to_soap)operator(()ident(return_value)operator(\)) + reserved(else) + ident(response) operator(=) constant(SOAP)operator(::)constant(RPC)operator(::)constant(SOAPMethodResponse)operator(.)ident(new)operator(()ident(qname)operator(,) pre_constant(nil)operator(\)) + reserved(end) + reserved(end) + reserved(end) + ident(envelope) operator(=) ident(create_soap_envelope)operator(()ident(response)operator(\)) + + comment(# FIXME: This is not thread-safe, but StringFactory_ in SOAP4R only) + comment(# reads target encoding from the XSD::Charset.encoding variable.) + comment(# This is required to ensure $KCODE strings are converted) + comment(# correctly to UTF-8 for any values of $KCODE.) + ident(previous_encoding) operator(=) constant(XSD)operator(::)constant(Charset)operator(.)ident(encoding) + constant(XSD)operator(::)constant(Charset)operator(.)ident(encoding) operator(=) constant(XSDEncoding) + ident(response_body) operator(=) constant(SOAP)operator(::)constant(Processor)operator(.)ident(marshal)operator(()ident(envelope)operator(,) symbol(:charset) operator(=)operator(>) constant(AWSEncoding)operator(\)) + constant(XSD)operator(::)constant(Charset)operator(.)ident(encoding) operator(=) ident(previous_encoding) + + constant(Response)operator(.)ident(new)operator(()ident(response_body)operator(,) string<delimiter(")content(text/xml; charset=)inline<inline_delimiter(#{)constant(AWSEncoding)inline_delimiter(})>delimiter(")>operator(,) ident(return_value)operator(\)) + reserved(end) + + reserved(def) method(protocol_client)operator(()ident(api)operator(,) ident(protocol_name)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(protocol_name) operator(==) symbol(:soap) + constant(ActionWebService)operator(::)constant(Client)operator(::)constant(Soap)operator(.)ident(new)operator(()ident(api)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(register_api)operator(()ident(api)operator(\)) + ident(api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + ident(method)operator(.)ident(expects)operator(.)ident(each)operator({) operator(|)ident(type)operator(|) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(\)) operator(}) reserved(if) ident(method)operator(.)ident(expects) + ident(method)operator(.)ident(returns)operator(.)ident(each)operator({) operator(|)ident(type)operator(|) ident(marshaler)operator(.)ident(register_type)operator(()ident(type)operator(\)) operator(}) reserved(if) ident(method)operator(.)ident(returns) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(has_valid_soap_action?)operator(()ident(request)operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(request)operator(.)ident(method) operator(==) symbol(:post) + ident(soap_action) operator(=) ident(request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_SOAPACTION)delimiter(')>operator(]) + reserved(return) pre_constant(nil) reserved(unless) ident(soap_action) + ident(soap_action) operator(=) ident(soap_action)operator(.)ident(dup) + ident(soap_action)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(^")delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(soap_action)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content("$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(soap_action)operator(.)ident(strip!) + reserved(return) pre_constant(nil) reserved(if) ident(soap_action)operator(.)ident(empty?) + ident(soap_action) + reserved(end) + + reserved(def) method(create_soap_envelope)operator(()ident(body)operator(\)) + ident(header) operator(=) constant(SOAP)operator(::)constant(SOAPHeader)operator(.)ident(new) + ident(body) operator(=) constant(SOAP)operator(::)constant(SOAPBody)operator(.)ident(new)operator(()ident(body)operator(\)) + constant(SOAP)operator(::)constant(SOAPEnvelope)operator(.)ident(new)operator(()ident(header)operator(,) ident(body)operator(\)) + reserved(end) + + reserved(def) method(parse_charset)operator(()ident(content_type)operator(\)) + reserved(return) constant(AWSEncoding) reserved(if) ident(content_type)operator(.)ident(nil?) + reserved(if) regexp<delimiter(/)content(^text)char(\\/)content(xml(?:)char(\\s)content(*;)char(\\s)content(*charset=([^"]+|"[^"]+"\)\)$)delimiter(/)modifier(i)> operator(=)operator(~) ident(content_type) + global_variable($1) + reserved(else) + constant(AWSEncoding) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(xmlrpc/marshal)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/client/xmlrpc_client)delimiter(')> + +reserved(module) class(XMLRPC) comment(# :nodoc:) + reserved(class) class(FaultException) comment(# :nodoc:) + reserved(alias) symbol(:message) symbol(:faultString) + reserved(end) +reserved(end) + +reserved(module) class(ActionWebService) comment(# :nodoc:) + reserved(module) class(API) comment(# :nodoc: ) + reserved(class) class(Base) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(xmlrpc_client)operator(()ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + constant(ActionWebService)operator(::)constant(Client)operator(::)constant(XmlRpc)operator(.)ident(new) pre_constant(self)operator(,) ident(endpoint_uri)operator(,) ident(options) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(Protocol) comment(# :nodoc:) + reserved(module) class(XmlRpc) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(register_protocol)operator(()constant(XmlRpcProtocol)operator(\)) + reserved(end) + + reserved(class) class(XmlRpcProtocol) operator(<) constant(AbstractProtocol) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(create)operator(()ident(controller)operator(\)) + constant(XmlRpcProtocol)operator(.)ident(new) + reserved(end) + + reserved(def) method(decode_action_pack_request)operator(()ident(action_pack_request)operator(\)) + ident(service_name) operator(=) ident(action_pack_request)operator(.)ident(parameters)operator([)string<delimiter(')content(action)delimiter(')>operator(]) + ident(decode_request)operator(()ident(action_pack_request)operator(.)ident(raw_post)operator(,) ident(service_name)operator(\)) + reserved(end) + + reserved(def) method(decode_request)operator(()ident(raw_request)operator(,) ident(service_name)operator(\)) + ident(method_name)operator(,) ident(params) operator(=) constant(XMLRPC)operator(::)constant(Marshal)operator(.)ident(load_call)operator(()ident(raw_request)operator(\)) + constant(Request)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(method_name)operator(,) ident(params)operator(,) ident(service_name)operator(\)) + reserved(end) + + reserved(def) method(encode_request)operator(()ident(method_name)operator(,) ident(params)operator(,) ident(param_types)operator(\)) + reserved(if) ident(param_types) + ident(params) operator(=) ident(params)operator(.)ident(dup) + ident(param_types)operator(.)ident(each_with_index)operator({) operator(|)ident(type)operator(,) ident(i)operator(|) ident(params)operator([)ident(i)operator(]) operator(=) ident(value_to_xmlrpc_wire_format)operator(()ident(params)operator([)ident(i)operator(])operator(,) ident(type)operator(\)) operator(}) + reserved(end) + constant(XMLRPC)operator(::)constant(Marshal)operator(.)ident(dump_call)operator(()ident(method_name)operator(,) operator(*)ident(params)operator(\)) + reserved(end) + + reserved(def) method(decode_response)operator(()ident(raw_response)operator(\)) + operator([)pre_constant(nil)operator(,) constant(XMLRPC)operator(::)constant(Marshal)operator(.)ident(load_response)operator(()ident(raw_response)operator(\))operator(]) + reserved(end) + + reserved(def) method(encode_response)operator(()ident(method_name)operator(,) ident(return_value)operator(,) ident(return_type)operator(,) ident(protocol_options)operator(=)operator({)operator(})operator(\)) + reserved(if) ident(return_value) operator(&&) ident(return_type) + ident(return_value) operator(=) ident(value_to_xmlrpc_wire_format)operator(()ident(return_value)operator(,) ident(return_type)operator(\)) + reserved(end) + ident(return_value) operator(=) pre_constant(false) reserved(if) ident(return_value)operator(.)ident(nil?) + ident(raw_response) operator(=) constant(XMLRPC)operator(::)constant(Marshal)operator(.)ident(dump_response)operator(()ident(return_value)operator(\)) + constant(Response)operator(.)ident(new)operator(()ident(raw_response)operator(,) string<delimiter(')content(text/xml)delimiter(')>operator(,) ident(return_value)operator(\)) + reserved(end) + + reserved(def) method(protocol_client)operator(()ident(api)operator(,) ident(protocol_name)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) + reserved(return) pre_constant(nil) reserved(unless) ident(protocol_name) operator(==) symbol(:xmlrpc) + constant(ActionWebService)operator(::)constant(Client)operator(::)constant(XmlRpc)operator(.)ident(new)operator(()ident(api)operator(,) ident(endpoint_uri)operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(value_to_xmlrpc_wire_format)operator(()ident(value)operator(,) ident(value_type)operator(\)) + reserved(if) ident(value_type)operator(.)ident(array?) + ident(value)operator(.)ident(map)operator({) operator(|)ident(val)operator(|) ident(value_to_xmlrpc_wire_format)operator(()ident(val)operator(,) ident(value_type)operator(.)ident(element_type)operator(\)) operator(}) + reserved(else) + reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(ActionWebService)operator(::)constant(Struct)operator(\)) + ident(struct) operator(=) operator({)operator(}) + ident(value)operator(.)ident(class)operator(.)ident(members)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(|) + ident(member_value) operator(=) ident(value)operator([)ident(name)operator(]) + reserved(next) reserved(if) ident(member_value)operator(.)ident(nil?) + ident(struct)operator([)ident(name)operator(.)ident(to_s)operator(]) operator(=) ident(value_to_xmlrpc_wire_format)operator(()ident(member_value)operator(,) ident(type)operator(\)) + reserved(end) + ident(struct) + reserved(elsif) ident(value)operator(.)ident(is_a?)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(\)) + ident(struct) operator(=) operator({)operator(}) + ident(value)operator(.)ident(attributes)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(,) ident(member_value)operator(|) + reserved(next) reserved(if) ident(member_value)operator(.)ident(nil?) + ident(struct)operator([)ident(key)operator(.)ident(to_s)operator(]) operator(=) ident(member_value) + reserved(end) + ident(struct) + reserved(elsif) ident(value)operator(.)ident(is_a?)operator(()constant(ActionWebService)operator(::)constant(Base64)operator(\)) + constant(XMLRPC)operator(::)constant(Base64)operator(.)ident(new)operator(()ident(value)operator(\)) + reserved(elsif) ident(value)operator(.)ident(is_a?)operator(()constant(Exception)operator(\)) operator(&&) operator(!)ident(value)operator(.)ident(is_a?)operator(()constant(XMLRPC)operator(::)constant(FaultException)operator(\)) + constant(XMLRPC)operator(::)constant(FaultException)operator(.)ident(new)operator(()integer(2)operator(,) ident(value)operator(.)ident(message)operator(\)) + reserved(else) + ident(value) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(action_web_service/protocol/abstract)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/protocol/discovery)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/protocol/soap_protocol)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/protocol/xmlrpc_protocol)delimiter(')> +ident(require) string<delimiter(')content(benchmark)delimiter(')> +ident(require) string<delimiter(')content(pathname)delimiter(')> + +reserved(module) class(ActionWebService) + reserved(module) class(Scaffolding) comment(# :nodoc:) + reserved(class) class(ScaffoldingError) operator(<) constant(ActionWebServiceError) comment(# :nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Web service invocation scaffolding provides a way to quickly invoke web service methods in a controller. The) + comment(# generated scaffold actions have default views to let you enter the method parameters and view the) + comment(# results.) + comment(#) + comment(# Example:) + comment(#) + comment(# class ApiController < ActionController) + comment(# web_service_scaffold :invoke) + comment(# end) + comment(#) + comment(# This example generates an +invoke+ action in the +ApiController+ that you can navigate to from) + comment(# your browser, select the API method, enter its parameters, and perform the invocation.) + comment(#) + comment(# If you want to customize the default views, create the following views in "app/views":) + comment(#) + comment(# * <tt>action_name/methods.rhtml</tt>) + comment(# * <tt>action_name/parameters.rhtml</tt>) + comment(# * <tt>action_name/result.rhtml</tt>) + comment(# * <tt>action_name/layout.rhtml</tt>) + comment(#) + comment(# Where <tt>action_name</tt> is the name of the action you gave to ClassMethods#web_service_scaffold.) + comment(#) + comment(# You can use the default views in <tt>RAILS_DIR/lib/action_web_service/templates/scaffolds</tt> as) + comment(# a guide.) + reserved(module) class(ClassMethods) + comment(# Generates web service invocation scaffolding for the current controller. The given action name) + comment(# can then be used as the entry point for invoking API methods from a web browser.) + reserved(def) method(web_service_scaffold)operator(()ident(action_name)operator(\)) + ident(add_template_helper)operator(()constant(Helpers)operator(\)) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def )inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>content( + if request.method == :get + setup_invocation_assigns + render_invocation_scaffold 'methods' + end + end + + def )inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>content(_method_params + if request.method == :get + setup_invocation_assigns + render_invocation_scaffold 'parameters' + end + end + + def )inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>content(_submit + if request.method == :post + setup_invocation_assigns + protocol_name = params['protocol'] ? params['protocol'].to_sym : :soap + case protocol_name + when :soap + @protocol = Protocol::Soap::SoapProtocol.create(self\) + when :xmlrpc + @protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self\) + end + bm = Benchmark.measure do + @protocol.register_api(@scaffold_service.api\) + post_params = params['method_params'] ? params['method_params'].dup : nil + params = [] + @scaffold_method.expects.each_with_index do |spec, i| + params << post_params[i.to_s] + end if @scaffold_method.expects + params = @scaffold_method.cast_expects(params\) + method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name\) + @method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects\) + new_request = @protocol.encode_action_pack_request(@scaffold_service.name, @scaffold_method.public_name, @method_request_xml\) + prepare_request(new_request, @scaffold_service.name, @scaffold_method.public_name\) + @request = new_request + if @scaffold_container.dispatching_mode != :direct + request.parameters['action'] = @scaffold_service.name + end + dispatch_web_service_request + @method_response_xml = @response.body + method_name, obj = @protocol.decode_response(@method_response_xml\) + return if handle_invocation_exception(obj\) + @method_return_value = @scaffold_method.cast_returns(obj\) + end + @method_elapsed = bm.real + add_instance_variables_to_assigns + reset_invocation_response + render_invocation_scaffold 'result' + end + end + + private + def setup_invocation_assigns + @scaffold_class = self.class + @scaffold_action_name = ")inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>content(" + @scaffold_container = WebServiceModel::Container.new(self\) + if params['service'] && params['method'] + @scaffold_service = @scaffold_container.services.find{ |x| x.name == params['service'] } + @scaffold_method = @scaffold_service.api_methods[params['method']] + end + add_instance_variables_to_assigns + end + + def render_invocation_scaffold(action\) + customized_template = ")char(\\#)content({self.class.controller_path}/)inline<inline_delimiter(#{)ident(action_name)inline_delimiter(})>content(/)char(\\#)content({action}" + default_template = scaffold_path(action\) + if template_exists?(customized_template\) + content = @template.render_file(customized_template\) + else + content = @template.render_file(default_template, false\) + end + @template.instance_variable_set("@content_for_layout", content\) + if self.active_layout.nil? + render_file(scaffold_path("layout"\)\) + else + render_file(self.active_layout, "200 OK", true\) + end + end + + def scaffold_path(template_name\) + File.dirname(__FILE__\) + "/templates/scaffolds/" + template_name + ".rhtml" + end + + def reset_invocation_response + erase_render_results + @response.headers = ::ActionController::AbstractResponse::DEFAULT_HEADERS.merge("cookie" => []\) + end + + def public_method_name(service_name, method_name\) + if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::XmlRpc::XmlRpcProtocol\) + service_name + '.' + method_name + else + method_name + end + end + + def prepare_request(new_request, service_name, method_name\) + new_request.parameters.update(request.parameters\) + request.env.each{ |k, v| new_request.env[k] = v unless new_request.env.has_key?(k\) } + if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol\) + new_request.env['HTTP_SOAPACTION'] = "/)char(\\#)content({controller_name(\)}/)char(\\#)content({service_name}/)char(\\#)content({method_name}" + end + end + + def handle_invocation_exception(obj\) + exception = nil + if obj.respond_to?(:detail\) && obj.detail.respond_to?(:cause\) && obj.detail.cause.is_a?(Exception\) + exception = obj.detail.cause + elsif obj.is_a?(XMLRPC::FaultException\) + exception = obj + end + return unless exception + reset_invocation_response + rescue_action(exception\) + true + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + + reserved(module) class(Helpers) comment(# :nodoc:) + reserved(def) method(method_parameter_input_fields)operator(()ident(method)operator(,) ident(type)operator(,) ident(field_name_base)operator(,) ident(idx)operator(,) ident(was_structured)operator(=)pre_constant(false)operator(\)) + reserved(if) ident(type)operator(.)ident(array?) + reserved(return) ident(content_tag)operator(()string<delimiter(')content(em)delimiter(')>operator(,) string<delimiter(")content(Typed array input fields not supported yet ()inline<inline_delimiter(#{)ident(type)operator(.)ident(name)inline_delimiter(})>content(\))delimiter(")>operator(\)) + reserved(end) + reserved(if) ident(type)operator(.)ident(structured?) + reserved(return) ident(content_tag)operator(()string<delimiter(')content(em)delimiter(')>operator(,) string<delimiter(")content(Nested structural types not supported yet ()inline<inline_delimiter(#{)ident(type)operator(.)ident(name)inline_delimiter(})>content(\))delimiter(")>operator(\)) reserved(if) ident(was_structured) + ident(parameters) operator(=) string<delimiter(")delimiter(")> + ident(type)operator(.)ident(each_member) reserved(do) operator(|)ident(member_name)operator(,) ident(member_type)operator(|) + ident(label) operator(=) ident(method_parameter_label)operator(()ident(member_name)operator(,) ident(member_type)operator(\)) + ident(nested_content) operator(=) ident(method_parameter_input_fields)operator(() + ident(method)operator(,) + ident(member_type)operator(,) + string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(idx)inline_delimiter(})>content(][)inline<inline_delimiter(#{)ident(member_name)inline_delimiter(})>content(])delimiter(")>operator(,) + ident(idx)operator(,) + pre_constant(true)operator(\)) + reserved(if) ident(member_type)operator(.)ident(custom?) + ident(parameters) operator(<<) ident(content_tag)operator(()string<delimiter(')content(li)delimiter(')>operator(,) ident(label)operator(\)) + ident(parameters) operator(<<) ident(content_tag)operator(()string<delimiter(')content(ul)delimiter(')>operator(,) ident(nested_content)operator(\)) + reserved(else) + ident(parameters) operator(<<) ident(content_tag)operator(()string<delimiter(')content(li)delimiter(')>operator(,) ident(label) operator(+) string<delimiter(')content( )delimiter(')> operator(+) ident(nested_content)operator(\)) + reserved(end) + reserved(end) + ident(content_tag)operator(()string<delimiter(')content(ul)delimiter(')>operator(,) ident(parameters)operator(\)) + reserved(else) + comment(# If the data source was structured previously we already have the index set ) + ident(field_name_base) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(idx)inline_delimiter(})>content(])delimiter(")> reserved(unless) ident(was_structured) + + reserved(case) ident(type)operator(.)ident(type) + reserved(when) symbol(:int) + ident(text_field_tag) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>delimiter(")> + reserved(when) symbol(:string) + ident(text_field_tag) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>delimiter(")> + reserved(when) symbol(:base64) + ident(text_area_tag) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>delimiter(")>operator(,) pre_constant(nil)operator(,) symbol(:size) operator(=)operator(>) string<delimiter(")content(40x5)delimiter(")> + reserved(when) symbol(:bool) + ident(radio_button_tag)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(true)delimiter(")>operator(\)) operator(+) string<delimiter(")content( True)delimiter(")> operator(+) + ident(radio_button_tag)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(false)delimiter(")>operator(\)) operator(+) string<delimiter(")content(False)delimiter(")> + reserved(when) symbol(:float) + ident(text_field_tag) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>delimiter(")> + reserved(when) symbol(:time)operator(,) symbol(:datetime) + ident(time) operator(=) constant(Time)operator(.)ident(now) + ident(i) operator(=) integer(0) + string<delimiter(%w|)content(year month day hour minute second)delimiter(|)>operator(.)ident(map) reserved(do) operator(|)ident(name)operator(|) + ident(i) operator(+=) integer(1) + ident(send)operator(()string<delimiter(")content(select_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(time)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>content(])delimiter(")>operator(,) symbol(:discard_type) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end)operator(.)ident(join) + reserved(when) symbol(:date) + ident(date) operator(=) constant(Date)operator(.)ident(today) + ident(i) operator(=) integer(0) + string<delimiter(%w|)content(year month day)delimiter(|)>operator(.)ident(map) reserved(do) operator(|)ident(name)operator(|) + ident(i) operator(+=) integer(1) + ident(send)operator(()string<delimiter(")content(select_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(date)operator(,) symbol(:prefix) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(field_name_base)inline_delimiter(})>content([)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>content(])delimiter(")>operator(,) symbol(:discard_type) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end)operator(.)ident(join) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(method_parameter_label)operator(()ident(name)operator(,) ident(type)operator(\)) + ident(name)operator(.)ident(to_s)operator(.)ident(capitalize) operator(+) string<delimiter(')content( ()delimiter(')> operator(+) ident(type)operator(.)ident(human_name)operator(()pre_constant(false)operator(\)) operator(+) string<delimiter(')content(\))delimiter(')> + reserved(end) + + reserved(def) method(service_method_list)operator(()ident(service)operator(\)) + ident(action) operator(=) instance_variable(@scaffold_action_name) operator(+) string<delimiter(')content(_method_params)delimiter(')> + ident(methods) operator(=) ident(service)operator(.)ident(api_methods_full)operator(.)ident(map) reserved(do) operator(|)ident(desc)operator(,) ident(name)operator(|) + ident(content_tag)operator(()string<delimiter(")content(li)delimiter(")>operator(,) ident(link_to)operator(()ident(desc)operator(,) symbol(:action) operator(=)operator(>) ident(action)operator(,) symbol(:service) operator(=)operator(>) ident(service)operator(.)ident(name)operator(,) symbol(:method) operator(=)operator(>) ident(name)operator(\))operator(\)) + reserved(end) + ident(content_tag)operator(()string<delimiter(")content(ul)delimiter(")>operator(,) ident(methods)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(WebServiceModel) comment(# :nodoc:) + reserved(class) class(Container) comment(# :nodoc:) + ident(attr) symbol(:services) + ident(attr) symbol(:dispatching_mode) + + reserved(def) method(initialize)operator(()ident(real_container)operator(\)) + instance_variable(@real_container) operator(=) ident(real_container) + instance_variable(@dispatching_mode) operator(=) instance_variable(@real_container)operator(.)ident(class)operator(.)ident(web_service_dispatching_mode) + instance_variable(@services) operator(=) operator([)operator(]) + reserved(if) instance_variable(@dispatching_mode) operator(==) symbol(:direct) + instance_variable(@services) operator(<<) constant(Service)operator(.)ident(new)operator(()instance_variable(@real_container)operator(.)ident(controller_name)operator(,) instance_variable(@real_container)operator(\)) + reserved(else) + instance_variable(@real_container)operator(.)ident(class)operator(.)ident(web_services)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(obj)operator(|) + instance_variable(@services) operator(<<) constant(Service)operator(.)ident(new)operator(()ident(name)operator(,) instance_variable(@real_container)operator(.)ident(instance_eval)operator({) ident(web_service_object)operator(()ident(name)operator(\)) operator(})operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Service) comment(# :nodoc:) + ident(attr) symbol(:name) + ident(attr) symbol(:object) + ident(attr) symbol(:api) + ident(attr) symbol(:api_methods) + ident(attr) symbol(:api_methods_full) + + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(real_service)operator(\)) + instance_variable(@name) operator(=) ident(name)operator(.)ident(to_s) + instance_variable(@object) operator(=) ident(real_service) + instance_variable(@api) operator(=) instance_variable(@object)operator(.)ident(class)operator(.)ident(web_service_api) + reserved(if) instance_variable(@api)operator(.)ident(nil?) + ident(raise) constant(ScaffoldingError)operator(,) string<delimiter(")content(No web service API attached to )inline<inline_delimiter(#{)ident(object)operator(.)ident(class)inline_delimiter(})>delimiter(")> + reserved(end) + instance_variable(@api_methods) operator(=) operator({)operator(}) + instance_variable(@api_methods_full) operator(=) operator([)operator(]) + instance_variable(@api)operator(.)ident(api_methods)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(method)operator(|) + instance_variable(@api_methods)operator([)ident(method)operator(.)ident(public_name)operator(.)ident(to_s)operator(]) operator(=) ident(method) + instance_variable(@api_methods_full) operator(<<) operator([)ident(method)operator(.)ident(to_s)operator(,) ident(method)operator(.)ident(public_name)operator(.)ident(to_s)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(to_s) + pre_constant(self)operator(.)ident(name)operator(.)ident(camelize) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) + comment(# To send structured types across the wire, derive from ActionWebService::Struct,) + comment(# and use +member+ to declare structure members.) + comment(#) + comment(# ActionWebService::Struct should be used in method signatures when you want to accept or return) + comment(# structured types that have no Active Record model class representations, or you don't) + comment(# want to expose your entire Active Record model to remote callers.) + comment(#) + comment(# === Example) + comment(#) + comment(# class Person < ActionWebService::Struct) + comment(# member :id, :int) + comment(# member :firstnames, [:string]) + comment(# member :lastname, :string) + comment(# member :email, :string) + comment(# end) + comment(# person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe'\)) + comment(#) + comment(# Active Record model classes are already implicitly supported in method) + comment(# signatures.) + reserved(class) class(Struct) + comment(# Action WebService Struct subclasses should be reloaded by the dispatcher in Rails) + comment(# when Dependencies.mechanism = :load.) + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + comment(# If a Hash is given as argument to an ActionWebService::Struct constructor,) + comment(# it can contain initial values for the structure member.) + reserved(def) method(initialize)operator(()ident(values)operator(=)operator({)operator(})operator(\)) + reserved(if) ident(values)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(values)operator(.)ident(map)operator({)operator(|)ident(k)operator(,)ident(v)operator(|) ident(__send__)operator(()string<delimiter(')content(%s=)delimiter(')> operator(%) ident(k)operator(.)ident(to_s)operator(,) ident(v)operator(\))operator(}) + reserved(end) + reserved(end) + + comment(# The member with the given name) + reserved(def) method([])operator(()ident(name)operator(\)) + ident(send)operator(()ident(name)operator(.)ident(to_s)operator(\)) + reserved(end) + + comment(# Iterates through each member) + reserved(def) method(each_pair)operator(()operator(&)ident(block)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(members)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(|) + reserved(yield) ident(name)operator(,) pre_constant(self)operator(.)ident(__send__)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) + + reserved(class) operator(<<) class(self) + comment(# Creates a structure member with the specified +name+ and +type+. Generates) + comment(# accessor methods for reading and writing the member value.) + reserved(def) method(member)operator(()ident(name)operator(,) ident(type)operator(\)) + ident(name) operator(=) ident(name)operator(.)ident(to_sym) + ident(type) operator(=) constant(ActionWebService)operator(::)constant(SignatureTypes)operator(.)ident(canonical_signature_entry)operator(()operator({) ident(name) operator(=)operator(>) ident(type) operator(})operator(,) integer(0)operator(\)) + ident(write_inheritable_hash)operator(()string<delimiter(")content(struct_members)delimiter(")>operator(,) ident(name) operator(=)operator(>) ident(type)operator(\)) + ident(class_eval) string<delimiter(<<-END)>string<content( + def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(; @)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(; end + def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(=(value\); @)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( = value; end)delimiter( + END)> + reserved(end) + + reserved(def) method(members) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(struct_members)delimiter(")>operator(\)) operator(||) operator({)operator(}) + reserved(end) + + reserved(def) method(member_type)operator(()ident(name)operator(\)) comment(# :nodoc:) + ident(members)operator([)ident(name)operator(.)ident(to_sym)operator(]) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(class) class(Class) comment(# :nodoc:) + reserved(def) method(class_inheritable_option)operator(()ident(sym)operator(,) ident(default_value)operator(=)pre_constant(nil)operator(\)) + ident(write_inheritable_attribute) ident(sym)operator(,) ident(default_value) + ident(class_eval) string<delimiter(<<-EOS)>string<content( + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content((value=nil\) + if !value.nil? + write_inheritable_attribute(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(, value\) + else + read_inheritable_attribute(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(\) + end + end + + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(value\) + write_inheritable_attribute(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(, value\) + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + self.class.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(value\) + self.class.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = value + end)delimiter( + EOS)> + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) comment(# :nodoc:) + comment(# Action Web Service supports the following base types in a signature:) + comment(#) + comment(# [<tt>:int</tt>] Represents an integer value, will be cast to an integer using <tt>Integer(value\)</tt>) + comment(# [<tt>:string</tt>] Represents a string value, will be cast to an string using the <tt>to_s</tt> method on an object) + comment(# [<tt>:base64</tt>] Represents a Base 64 value, will contain the binary bytes of a Base 64 value sent by the caller) + comment(# [<tt>:bool</tt>] Represents a boolean value, whatever is passed will be cast to boolean (<tt>true</tt>, '1', 'true', 'y', 'yes' are taken to represent true; <tt>false</tt>, '0', 'false', 'n', 'no' and <tt>nil</tt> represent false\)) + comment(# [<tt>:float</tt>] Represents a floating point value, will be cast to a float using <tt>Float(value\)</tt>) + comment(# [<tt>:time</tt>] Represents a timestamp, will be cast to a <tt>Time</tt> object) + comment(# [<tt>:datetime</tt>] Represents a timestamp, will be cast to a <tt>DateTime</tt> object) + comment(# [<tt>:date</tt>] Represents a date, will be cast to a <tt>Date</tt> object) + comment(#) + comment(# For structured types, you'll need to pass in the Class objects of) + comment(# ActionWebService::Struct and ActiveRecord::Base derivatives.) + reserved(module) class(SignatureTypes) + reserved(def) method(canonical_signature)operator(()ident(signature)operator(\)) comment(# :nodoc:) + reserved(return) pre_constant(nil) reserved(if) ident(signature)operator(.)ident(nil?) + reserved(unless) ident(signature)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(raise)operator(()constant(ActionWebServiceError)operator(,) string<delimiter(")content(Expected signature to be an Array)delimiter(")>operator(\)) + reserved(end) + ident(i) operator(=) integer(-1) + ident(signature)operator(.)ident(map)operator({) operator(|)ident(spec)operator(|) ident(canonical_signature_entry)operator(()ident(spec)operator(,) ident(i) operator(+=) integer(1)operator(\)) operator(}) + reserved(end) + + reserved(def) method(canonical_signature_entry)operator(()ident(spec)operator(,) ident(i)operator(\)) comment(# :nodoc:) + ident(orig_spec) operator(=) ident(spec) + ident(name) operator(=) string<delimiter(")content(param)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")> + reserved(if) ident(spec)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(name)operator(,) ident(spec) operator(=) ident(spec)operator(.)ident(keys)operator(.)ident(first)operator(,) ident(spec)operator(.)ident(values)operator(.)ident(first) + reserved(end) + ident(type) operator(=) ident(spec) + reserved(if) ident(spec)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + constant(ArrayType)operator(.)ident(new)operator(()ident(orig_spec)operator(,) ident(canonical_signature_entry)operator(()ident(spec)operator([)integer(0)operator(])operator(,) integer(0)operator(\))operator(,) ident(name)operator(\)) + reserved(else) + ident(type) operator(=) ident(canonical_type)operator(()ident(type)operator(\)) + reserved(if) ident(type)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + constant(BaseType)operator(.)ident(new)operator(()ident(orig_spec)operator(,) ident(type)operator(,) ident(name)operator(\)) + reserved(else) + constant(StructuredType)operator(.)ident(new)operator(()ident(orig_spec)operator(,) ident(type)operator(,) ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(canonical_type)operator(()ident(type)operator(\)) comment(# :nodoc:) + ident(type_name) operator(=) ident(symbol_name)operator(()ident(type)operator(\)) operator(||) ident(class_to_type_name)operator(()ident(type)operator(\)) + ident(type) operator(=) ident(type_name) operator(||) ident(type) + reserved(return) ident(canonical_type_name)operator(()ident(type)operator(\)) reserved(if) ident(type)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + ident(type) + reserved(end) + + reserved(def) method(canonical_type_name)operator(()ident(name)operator(\)) comment(# :nodoc:) + ident(name) operator(=) ident(name)operator(.)ident(to_sym) + reserved(case) ident(name) + reserved(when) symbol(:int)operator(,) symbol(:integer)operator(,) symbol(:fixnum)operator(,) symbol(:bignum) + symbol(:int) + reserved(when) symbol(:string)operator(,) symbol(:text) + symbol(:string) + reserved(when) symbol(:base64)operator(,) symbol(:binary) + symbol(:base64) + reserved(when) symbol(:bool)operator(,) symbol(:boolean) + symbol(:bool) + reserved(when) symbol(:float)operator(,) symbol(:double) + symbol(:float) + reserved(when) symbol(:time)operator(,) symbol(:timestamp) + symbol(:time) + reserved(when) symbol(:datetime) + symbol(:datetime) + reserved(when) symbol(:date) + symbol(:date) + reserved(else) + ident(raise)operator(()constant(TypeError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( is not a valid base type)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(canonical_type_class)operator(()ident(type)operator(\)) comment(# :nodoc:) + ident(type) operator(=) ident(canonical_type)operator(()ident(type)operator(\)) + ident(type)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) operator(?) ident(type_name_to_class)operator(()ident(type)operator(\)) operator(:) ident(type) + reserved(end) + + reserved(def) method(symbol_name)operator(()ident(name)operator(\)) comment(# :nodoc:) + reserved(return) ident(name)operator(.)ident(to_sym) reserved(if) ident(name)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) operator(||) ident(name)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + pre_constant(nil) + reserved(end) + + reserved(def) method(class_to_type_name)operator(()ident(klass)operator(\)) comment(# :nodoc:) + ident(klass) operator(=) ident(klass)operator(.)ident(class) reserved(unless) ident(klass)operator(.)ident(is_a?)operator(()constant(Class)operator(\)) + reserved(if) ident(derived_from?)operator(()constant(Integer)operator(,) ident(klass)operator(\)) operator(||) ident(derived_from?)operator(()constant(Fixnum)operator(,) ident(klass)operator(\)) operator(||) ident(derived_from?)operator(()constant(Bignum)operator(,) ident(klass)operator(\)) + symbol(:int) + reserved(elsif) ident(klass) operator(==) constant(String) + symbol(:string) + reserved(elsif) ident(klass) operator(==) constant(Base64) + symbol(:base64) + reserved(elsif) ident(klass) operator(==) constant(TrueClass) operator(||) ident(klass) operator(==) constant(FalseClass) + symbol(:bool) + reserved(elsif) ident(derived_from?)operator(()constant(Float)operator(,) ident(klass)operator(\)) operator(||) ident(derived_from?)operator(()constant(Precision)operator(,) ident(klass)operator(\)) operator(||) ident(derived_from?)operator(()constant(Numeric)operator(,) ident(klass)operator(\)) + symbol(:float) + reserved(elsif) ident(klass) operator(==) constant(Time) + symbol(:time) + reserved(elsif) ident(klass) operator(==) constant(DateTime) + symbol(:datetime) + reserved(elsif) ident(klass) operator(==) constant(Date) + symbol(:date) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(type_name_to_class)operator(()ident(name)operator(\)) comment(# :nodoc:) + reserved(case) ident(canonical_type_name)operator(()ident(name)operator(\)) + reserved(when) symbol(:int) + constant(Integer) + reserved(when) symbol(:string) + constant(String) + reserved(when) symbol(:base64) + constant(Base64) + reserved(when) symbol(:bool) + constant(TrueClass) + reserved(when) symbol(:float) + constant(Float) + reserved(when) symbol(:time) + constant(Time) + reserved(when) symbol(:date) + constant(Date) + reserved(when) symbol(:datetime) + constant(DateTime) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(derived_from?)operator(()ident(ancestor)operator(,) ident(child)operator(\)) comment(# :nodoc:) + ident(child)operator(.)ident(ancestors)operator(.)ident(include?)operator(()ident(ancestor)operator(\)) + reserved(end) + + ident(module_function) symbol(:type_name_to_class) + ident(module_function) symbol(:class_to_type_name) + ident(module_function) symbol(:symbol_name) + ident(module_function) symbol(:canonical_type_class) + ident(module_function) symbol(:canonical_type_name) + ident(module_function) symbol(:canonical_type) + ident(module_function) symbol(:canonical_signature_entry) + ident(module_function) symbol(:canonical_signature) + ident(module_function) symbol(:derived_from?) + reserved(end) + + reserved(class) class(BaseType) comment(# :nodoc:) + ident(include) constant(SignatureTypes) + + ident(attr) symbol(:spec) + ident(attr) symbol(:type) + ident(attr) symbol(:type_class) + ident(attr) symbol(:name) + + reserved(def) method(initialize)operator(()ident(spec)operator(,) ident(type)operator(,) ident(name)operator(\)) + instance_variable(@spec) operator(=) ident(spec) + instance_variable(@type) operator(=) ident(canonical_type)operator(()ident(type)operator(\)) + instance_variable(@type_class) operator(=) ident(canonical_type_class)operator(()instance_variable(@type)operator(\)) + instance_variable(@name) operator(=) ident(name) + reserved(end) + + reserved(def) method(custom?) + pre_constant(false) + reserved(end) + + reserved(def) method(array?) + pre_constant(false) + reserved(end) + + reserved(def) method(structured?) + pre_constant(false) + reserved(end) + + reserved(def) method(human_name)operator(()ident(show_name)operator(=)pre_constant(true)operator(\)) + ident(type_type) operator(=) ident(array?) operator(?) ident(element_type)operator(.)ident(type)operator(.)ident(to_s) operator(:) pre_constant(self)operator(.)ident(type)operator(.)ident(to_s) + ident(str) operator(=) ident(array?) operator(?) operator(()ident(type_type) operator(+) string<delimiter(')content([])delimiter(')>operator(\)) operator(:) ident(type_type) + ident(show_name) operator(?) operator(()ident(str) operator(+) string<delimiter(")content( )delimiter(")> operator(+) ident(name)operator(.)ident(to_s)operator(\)) operator(:) ident(str) + reserved(end) + reserved(end) + + reserved(class) class(ArrayType) operator(<) constant(BaseType) comment(# :nodoc:) + ident(attr) symbol(:element_type) + + reserved(def) method(initialize)operator(()ident(spec)operator(,) ident(element_type)operator(,) ident(name)operator(\)) + reserved(super)operator(()ident(spec)operator(,) constant(Array)operator(,) ident(name)operator(\)) + instance_variable(@element_type) operator(=) ident(element_type) + reserved(end) + + reserved(def) method(custom?) + pre_constant(true) + reserved(end) + + reserved(def) method(array?) + pre_constant(true) + reserved(end) + reserved(end) + + reserved(class) class(StructuredType) operator(<) constant(BaseType) comment(# :nodoc:) + reserved(def) method(each_member) + reserved(if) instance_variable(@type_class)operator(.)ident(respond_to?)operator(()symbol(:members)operator(\)) + instance_variable(@type_class)operator(.)ident(members)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(|) + reserved(yield) ident(name)operator(,) ident(type) + reserved(end) + reserved(elsif) instance_variable(@type_class)operator(.)ident(respond_to?)operator(()symbol(:columns)operator(\)) + ident(i) operator(=) integer(-1) + instance_variable(@type_class)operator(.)ident(columns)operator(.)ident(each) reserved(do) operator(|)ident(column)operator(|) + reserved(yield) ident(column)operator(.)ident(name)operator(,) ident(canonical_signature_entry)operator(()ident(column)operator(.)ident(type)operator(,) ident(i) operator(+=) integer(1)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(custom?) + pre_constant(true) + reserved(end) + + reserved(def) method(structured?) + pre_constant(true) + reserved(end) + reserved(end) + + reserved(class) class(Base64) operator(<) constant(String) comment(# :nodoc:) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> + +reserved(module) class(Test) comment(# :nodoc:) + reserved(module) class(Unit) comment(# :nodoc:) + reserved(class) class(TestCase) comment(# :nodoc:) + ident(private) + comment(# invoke the specified API method) + reserved(def) method(invoke_direct)operator(()ident(method_name)operator(,) operator(*)ident(args)operator(\)) + ident(prepare_request)operator(()string<delimiter(')content(api)delimiter(')>operator(,) string<delimiter(')content(api)delimiter(')>operator(,) ident(method_name)operator(,) operator(*)ident(args)operator(\)) + instance_variable(@controller)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\)) + ident(decode_rpc_response) + reserved(end) + ident(alias_method) symbol(:invoke)operator(,) symbol(:invoke_direct) + + comment(# invoke the specified API method on the specified service) + reserved(def) method(invoke_delegated)operator(()ident(service_name)operator(,) ident(method_name)operator(,) operator(*)ident(args)operator(\)) + ident(prepare_request)operator(()ident(service_name)operator(.)ident(to_s)operator(,) ident(service_name)operator(,) ident(method_name)operator(,) operator(*)ident(args)operator(\)) + instance_variable(@controller)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\)) + ident(decode_rpc_response) + reserved(end) + + comment(# invoke the specified layered API method on the correct service) + reserved(def) method(invoke_layered)operator(()ident(service_name)operator(,) ident(method_name)operator(,) operator(*)ident(args)operator(\)) + ident(prepare_request)operator(()string<delimiter(')content(api)delimiter(')>operator(,) ident(service_name)operator(,) ident(method_name)operator(,) operator(*)ident(args)operator(\)) + instance_variable(@controller)operator(.)ident(process)operator(()instance_variable(@request)operator(,) instance_variable(@response)operator(\)) + ident(decode_rpc_response) + reserved(end) + + comment(# ---------------------- internal ---------------------------) + + reserved(def) method(prepare_request)operator(()ident(action)operator(,) ident(service_name)operator(,) ident(api_method_name)operator(,) operator(*)ident(args)operator(\)) + instance_variable(@request)operator(.)ident(recycle!) + instance_variable(@request)operator(.)ident(request_parameters)operator([)string<delimiter(')content(action)delimiter(')>operator(]) operator(=) ident(action) + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(POST)delimiter(')> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_CONTENT_TYPE)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/xml)delimiter(')> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) operator(=) ident(encode_rpc_call)operator(()ident(service_name)operator(,) ident(api_method_name)operator(,) operator(*)ident(args)operator(\)) + reserved(case) ident(protocol) + reserved(when) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol) + ident(soap_action) operator(=) string<delimiter(")content(/)inline<inline_delimiter(#{)instance_variable(@controller)operator(.)ident(controller_name)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(service_name)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(public_method_name)operator(()ident(service_name)operator(,) ident(api_method_name)operator(\))inline_delimiter(})>delimiter(")> + instance_variable(@request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_SOAPACTION)delimiter(')>operator(]) operator(=) ident(soap_action) + reserved(when) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol) + instance_variable(@request)operator(.)ident(env)operator(.)ident(delete)operator(()string<delimiter(')content(HTTP_SOAPACTION)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(encode_rpc_call)operator(()ident(service_name)operator(,) ident(api_method_name)operator(,) operator(*)ident(args)operator(\)) + reserved(case) instance_variable(@controller)operator(.)ident(web_service_dispatching_mode) + reserved(when) symbol(:direct) + ident(api) operator(=) instance_variable(@controller)operator(.)ident(class)operator(.)ident(web_service_api) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + ident(api) operator(=) instance_variable(@controller)operator(.)ident(web_service_object)operator(()ident(service_name)operator(.)ident(to_sym)operator(\))operator(.)ident(class)operator(.)ident(web_service_api) + reserved(end) + ident(protocol)operator(.)ident(register_api)operator(()ident(api)operator(\)) + ident(method) operator(=) ident(api)operator(.)ident(api_methods)operator([)ident(api_method_name)operator(.)ident(to_sym)operator(]) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(wrong number of arguments for rpc call ()inline<inline_delimiter(#{)ident(args)operator(.)ident(length)inline_delimiter(})>content( for )inline<inline_delimiter(#{)ident(method)operator(.)ident(expects)operator(.)ident(length)inline_delimiter(})>content(\))delimiter(")> reserved(unless) ident(args)operator(.)ident(length) operator(==) ident(method)operator(.)ident(expects)operator(.)ident(length) + ident(protocol)operator(.)ident(encode_request)operator(()ident(public_method_name)operator(()ident(service_name)operator(,) ident(api_method_name)operator(\))operator(,) ident(args)operator(.)ident(dup)operator(,) ident(method)operator(.)ident(expects)operator(\)) + reserved(end) + + reserved(def) method(decode_rpc_response) + ident(public_method_name)operator(,) ident(return_value) operator(=) ident(protocol)operator(.)ident(decode_response)operator(()instance_variable(@response)operator(.)ident(body)operator(\)) + ident(exception) operator(=) ident(is_exception?)operator(()ident(return_value)operator(\)) + ident(raise) ident(exception) reserved(if) ident(exception) + ident(return_value) + reserved(end) + + reserved(def) method(public_method_name)operator(()ident(service_name)operator(,) ident(api_method_name)operator(\)) + ident(public_name) operator(=) ident(service_api)operator(()ident(service_name)operator(\))operator(.)ident(public_api_method_name)operator(()ident(api_method_name)operator(\)) + reserved(if) instance_variable(@controller)operator(.)ident(web_service_dispatching_mode) operator(==) symbol(:layered) operator(&&) ident(protocol)operator(.)ident(is_a?)operator(()constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol)operator(\)) + string<delimiter(')content(%s.%s)delimiter(')> operator(%) operator([)ident(service_name)operator(.)ident(to_s)operator(,) ident(public_name)operator(]) + reserved(else) + ident(public_name) + reserved(end) + reserved(end) + + reserved(def) method(service_api)operator(()ident(service_name)operator(\)) + reserved(case) instance_variable(@controller)operator(.)ident(web_service_dispatching_mode) + reserved(when) symbol(:direct) + instance_variable(@controller)operator(.)ident(class)operator(.)ident(web_service_api) + reserved(when) symbol(:delegated)operator(,) symbol(:layered) + instance_variable(@controller)operator(.)ident(web_service_object)operator(()ident(service_name)operator(.)ident(to_sym)operator(\))operator(.)ident(class)operator(.)ident(web_service_api) + reserved(end) + reserved(end) + + reserved(def) method(protocol) + reserved(if) instance_variable(@protocol)operator(.)ident(nil?) + instance_variable(@protocol) operator(||=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol)operator(.)ident(create)operator(()instance_variable(@controller)operator(\)) + reserved(else) + reserved(case) instance_variable(@protocol) + reserved(when) symbol(:xmlrpc) + instance_variable(@protocol) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol)operator(.)ident(create)operator(()instance_variable(@controller)operator(\)) + reserved(when) symbol(:soap) + instance_variable(@protocol) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol)operator(.)ident(create)operator(()instance_variable(@controller)operator(\)) + reserved(else) + instance_variable(@protocol) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(is_exception?)operator(()ident(obj)operator(\)) + reserved(case) ident(protocol) + reserved(when) symbol(:soap)operator(,) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol) + operator(()ident(obj)operator(.)ident(respond_to?)operator(()symbol(:detail)operator(\)) operator(&&) ident(obj)operator(.)ident(detail)operator(.)ident(respond_to?)operator(()symbol(:cause)operator(\)) operator(&&) \ + ident(obj)operator(.)ident(detail)operator(.)ident(cause)operator(.)ident(is_a?)operator(()constant(Exception)operator(\))operator(\)) operator(?) ident(obj)operator(.)ident(detail)operator(.)ident(cause) operator(:) pre_constant(nil) + reserved(when) symbol(:xmlrpc)operator(,) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol) + ident(obj)operator(.)ident(is_a?)operator(()constant(XMLRPC)operator(::)constant(FaultException)operator(\)) operator(?) ident(obj) operator(:) pre_constant(nil) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActionWebService) + reserved(module) class(VERSION) comment(#:nodoc:) + constant(MAJOR) operator(=) integer(1) + constant(MINOR) operator(=) integer(1) + constant(TINY) operator(=) integer(6) + + constant(STRING) operator(=) operator([)constant(MAJOR)operator(,) constant(MINOR)operator(,) constant(TINY)operator(])operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) +reserved(end) +comment(#--) +comment(# Copyright (C\) 2005 Leon Breedt) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +reserved(begin) + ident(require) string<delimiter(')content(active_support)delimiter(')> + ident(require) string<delimiter(')content(action_controller)delimiter(')> + ident(require) string<delimiter(')content(active_record)delimiter(')> +reserved(rescue) constant(LoadError) + ident(require) string<delimiter(')content(rubygems)delimiter(')> + ident(require_gem) string<delimiter(')content(activesupport)delimiter(')>operator(,) string<delimiter(')content(>= 1.0.2)delimiter(')> + ident(require_gem) string<delimiter(')content(actionpack)delimiter(')>operator(,) string<delimiter(')content(>= 1.6.0)delimiter(')> + ident(require_gem) string<delimiter(')content(activerecord)delimiter(')>operator(,) string<delimiter(')content(>= 1.9.0)delimiter(')> +reserved(end) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/action_web_service/vendor/)delimiter(")>operator(\)) + +ident(require) string<delimiter(')content(action_web_service/support/class_inheritable_options)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/support/signature_types)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/base)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/client)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/invocation)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/api)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/casting)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/struct)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/container)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/protocol)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/dispatcher)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/scaffolding)delimiter(')> + +constant(ActionWebService)operator(::)constant(Base)operator(.)ident(class_eval) reserved(do) + ident(include) constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Direct) + ident(include) constant(ActionWebService)operator(::)constant(Invocation) +reserved(end) + +constant(ActionController)operator(::)constant(Base)operator(.)ident(class_eval) reserved(do) + ident(include) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Discovery) + ident(include) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap) + ident(include) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc) + ident(include) constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Direct) + ident(include) constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Delegated) + ident(include) constant(ActionWebService)operator(::)constant(Container)operator(::)constant(ActionController) + ident(include) constant(ActionWebService)operator(::)constant(Invocation) + ident(include) constant(ActionWebService)operator(::)constant(Dispatcher) + ident(include) constant(ActionWebService)operator(::)constant(Dispatcher)operator(::)constant(ActionController) + ident(include) constant(ActionWebService)operator(::)constant(Scaffolding) +reserved(end) +comment(#) +comment(# setup.rb) +comment(#) +comment(# Copyright (c\) 2000-2004 Minero Aoki) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#) +comment(# Note: Originally licensed under LGPL v2+. Using MIT license for Rails) +comment(# with permission of Minero Aoki.) + +comment(#) + +reserved(unless) constant(Enumerable)operator(.)ident(method_defined?)operator(()symbol(:map)operator(\)) comment(# Ruby 1.4.6) + reserved(module) class(Enumerable) + reserved(alias) method(map) method(collect) + reserved(end) +reserved(end) + +reserved(unless) constant(File)operator(.)ident(respond_to?)operator(()symbol(:read)operator(\)) comment(# Ruby 1.6) + reserved(def) constant(File)operator(.)ident(read)operator(()ident(fname)operator(\)) + ident(open)operator(()ident(fname)operator(\)) operator({)operator(|)ident(f)operator(|) + reserved(return) ident(f)operator(.)ident(read) + operator(}) + reserved(end) +reserved(end) + +reserved(def) constant(File)operator(.)ident(binread)operator(()ident(fname)operator(\)) + ident(open)operator(()ident(fname)operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) + reserved(return) ident(f)operator(.)ident(read) + operator(}) +reserved(end) + +comment(# for corrupted windows stat(2\)) +reserved(def) constant(File)operator(.)ident(dir?)operator(()ident(path)operator(\)) + constant(File)operator(.)ident(directory?)operator(()operator(()ident(path)operator([)integer(-1)operator(,)integer(1)operator(]) operator(==) string<delimiter(')content(/)delimiter(')>operator(\)) operator(?) ident(path) operator(:) ident(path) operator(+) string<delimiter(')content(/)delimiter(')>operator(\)) +reserved(end) + + +reserved(class) class(SetupError) operator(<) constant(StandardError)operator(;) reserved(end) + +reserved(def) method(setup_rb_error)operator(()ident(msg)operator(\)) + ident(raise) constant(SetupError)operator(,) ident(msg) +reserved(end) + +comment(#) +comment(# Config) +comment(#) + +reserved(if) ident(arg) operator(=) pre_constant(ARGV)operator(.)ident(detect) operator({)operator(|)ident(arg)operator(|) regexp<delimiter(/)char(\\A)content(--rbconfig=)delimiter(/)> operator(=)operator(~) ident(arg) operator(}) + pre_constant(ARGV)operator(.)ident(delete)operator(()ident(arg)operator(\)) + ident(require) ident(arg)operator(.)ident(split)operator(()regexp<delimiter(/)content(=)delimiter(/)>operator(,) integer(2)operator(\))operator([)integer(1)operator(]) + global_variable($")operator(.)ident(push) string<delimiter(')content(rbconfig.rb)delimiter(')> +reserved(else) + ident(require) string<delimiter(')content(rbconfig)delimiter(')> +reserved(end) + +reserved(def) method(multipackage_install?) + constant(FileTest)operator(.)ident(directory?)operator(()constant(File)operator(.)ident(dirname)operator(()global_variable($0)operator(\)) operator(+) string<delimiter(')content(/packages)delimiter(')>operator(\)) +reserved(end) + + +reserved(class) class(ConfigItem) + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(template)operator(,) ident(default)operator(,) ident(desc)operator(\)) + instance_variable(@name) operator(=) ident(name)operator(.)ident(freeze) + instance_variable(@template) operator(=) ident(template) + instance_variable(@value) operator(=) ident(default) + instance_variable(@default) operator(=) ident(default)operator(.)ident(dup)operator(.)ident(freeze) + instance_variable(@description) operator(=) ident(desc) + reserved(end) + + ident(attr_reader) symbol(:name) + ident(attr_reader) symbol(:description) + + ident(attr_accessor) symbol(:default) + reserved(alias) method(help_default) method(default) + + reserved(def) method(help_opt) + string<delimiter(")content(--)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content(=)inline<inline_delimiter(#{)instance_variable(@template)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(value) + instance_variable(@value) + reserved(end) + + reserved(def) method(eval)operator(()ident(table)operator(\)) + instance_variable(@value)operator(.)ident(gsub)operator(()regexp<delimiter(%r<)char(\\$)content(([^/]+\))delimiter(>)>operator(\)) operator({) ident(table)operator([)global_variable($1)operator(]) operator(}) + reserved(end) + + reserved(def) method(set)operator(()ident(val)operator(\)) + instance_variable(@value) operator(=) ident(check)operator(()ident(val)operator(\)) + reserved(end) + + ident(private) + + reserved(def) method(check)operator(()ident(val)operator(\)) + ident(setup_rb_error) string<delimiter(")content(config: --)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( requires argument)delimiter(")> reserved(unless) ident(val) + ident(val) + reserved(end) +reserved(end) + +reserved(class) class(BoolItem) operator(<) constant(ConfigItem) + reserved(def) method(config_type) + string<delimiter(')content(bool)delimiter(')> + reserved(end) + + reserved(def) method(help_opt) + string<delimiter(")content(--)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(private) + + reserved(def) method(check)operator(()ident(val)operator(\)) + reserved(return) string<delimiter(')content(yes)delimiter(')> reserved(unless) ident(val) + reserved(unless) regexp<delimiter(/)char(\\A)content((y(es\)?|n(o\)?|t(rue\)?|f(alse\)\))char(\\z)delimiter(/)modifier(i)> operator(=)operator(~) ident(val) + ident(setup_rb_error) string<delimiter(")content(config: --)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content( accepts only yes/no for argument)delimiter(")> + reserved(end) + operator(()regexp<delimiter(/)char(\\A)content(y(es\)?|)char(\\A)content(t(rue\))delimiter(/)modifier(i)> operator(=)operator(~) ident(value)operator(\)) operator(?) string<delimiter(')content(yes)delimiter(')> operator(:) string<delimiter(')content(no)delimiter(')> + reserved(end) +reserved(end) + +reserved(class) class(PathItem) operator(<) constant(ConfigItem) + reserved(def) method(config_type) + string<delimiter(')content(path)delimiter(')> + reserved(end) + + ident(private) + + reserved(def) method(check)operator(()ident(path)operator(\)) + ident(setup_rb_error) string<delimiter(")content(config: --)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content( requires argument)delimiter(")> reserved(unless) ident(path) + ident(path)operator([)integer(0)operator(,)integer(1)operator(]) operator(==) string<delimiter(')content($)delimiter(')> operator(?) ident(path) operator(:) constant(File)operator(.)ident(expand_path)operator(()ident(path)operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(ProgramItem) operator(<) constant(ConfigItem) + reserved(def) method(config_type) + string<delimiter(')content(program)delimiter(')> + reserved(end) +reserved(end) + +reserved(class) class(SelectItem) operator(<) constant(ConfigItem) + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(template)operator(,) ident(default)operator(,) ident(desc)operator(\)) + reserved(super) + instance_variable(@ok) operator(=) ident(template)operator(.)ident(split)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(config_type) + string<delimiter(')content(select)delimiter(')> + reserved(end) + + ident(private) + + reserved(def) method(check)operator(()ident(val)operator(\)) + reserved(unless) instance_variable(@ok)operator(.)ident(include?)operator(()ident(val)operator(.)ident(strip)operator(\)) + ident(setup_rb_error) string<delimiter(")content(config: use --)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content(=)inline<inline_delimiter(#{)instance_variable(@template)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(val)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + ident(val)operator(.)ident(strip) + reserved(end) +reserved(end) + +reserved(class) class(PackageSelectionItem) operator(<) constant(ConfigItem) + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(template)operator(,) ident(default)operator(,) ident(help_default)operator(,) ident(desc)operator(\)) + reserved(super) ident(name)operator(,) ident(template)operator(,) ident(default)operator(,) ident(desc) + instance_variable(@help_default) operator(=) ident(help_default) + reserved(end) + + ident(attr_reader) symbol(:help_default) + + reserved(def) method(config_type) + string<delimiter(')content(package)delimiter(')> + reserved(end) + + ident(private) + + reserved(def) method(check)operator(()ident(val)operator(\)) + reserved(unless) constant(File)operator(.)ident(dir?)operator(()string<delimiter(")content(packages/)inline<inline_delimiter(#{)ident(val)inline_delimiter(})>delimiter(")>operator(\)) + ident(setup_rb_error) string<delimiter(")content(config: no such package: )inline<inline_delimiter(#{)ident(val)inline_delimiter(})>delimiter(")> + reserved(end) + ident(val) + reserved(end) +reserved(end) + +reserved(class) class(ConfigTable_class) + + reserved(def) method(initialize)operator(()ident(items)operator(\)) + instance_variable(@items) operator(=) ident(items) + instance_variable(@table) operator(=) operator({)operator(}) + ident(items)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + instance_variable(@table)operator([)ident(i)operator(.)ident(name)operator(]) operator(=) ident(i) + reserved(end) + constant(ALIASES)operator(.)ident(each) reserved(do) operator(|)ident(ali)operator(,) ident(name)operator(|) + instance_variable(@table)operator([)ident(ali)operator(]) operator(=) instance_variable(@table)operator([)ident(name)operator(]) + reserved(end) + reserved(end) + + ident(include) constant(Enumerable) + + reserved(def) method(each)operator(()operator(&)ident(block)operator(\)) + instance_variable(@items)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(key?)operator(()ident(name)operator(\)) + instance_variable(@table)operator(.)ident(key?)operator(()ident(name)operator(\)) + reserved(end) + + reserved(def) method(lookup)operator(()ident(name)operator(\)) + instance_variable(@table)operator([)ident(name)operator(]) reserved(or) ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(no such config item: )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(add)operator(()ident(item)operator(\)) + instance_variable(@items)operator(.)ident(push) ident(item) + instance_variable(@table)operator([)ident(item)operator(.)ident(name)operator(]) operator(=) ident(item) + reserved(end) + + reserved(def) method(remove)operator(()ident(name)operator(\)) + ident(item) operator(=) ident(lookup)operator(()ident(name)operator(\)) + instance_variable(@items)operator(.)ident(delete_if) operator({)operator(|)ident(i)operator(|) ident(i)operator(.)ident(name) operator(==) ident(name) operator(}) + instance_variable(@table)operator(.)ident(delete_if) operator({)operator(|)ident(name)operator(,) ident(i)operator(|) ident(i)operator(.)ident(name) operator(==) ident(name) operator(}) + ident(item) + reserved(end) + + reserved(def) method(new) + ident(dup)operator(()operator(\)) + reserved(end) + + reserved(def) method(savefile) + string<delimiter(')content(.config)delimiter(')> + reserved(end) + + reserved(def) method(load) + reserved(begin) + ident(t) operator(=) ident(dup)operator(()operator(\)) + constant(File)operator(.)ident(foreach)operator(()ident(savefile)operator(()operator(\))operator(\)) reserved(do) operator(|)ident(line)operator(|) + ident(k)operator(,) ident(v) operator(=) operator(*)ident(line)operator(.)ident(split)operator(()regexp<delimiter(/)content(=)delimiter(/)>operator(,) integer(2)operator(\)) + ident(t)operator([)ident(k)operator(]) operator(=) ident(v)operator(.)ident(strip) + reserved(end) + ident(t) + reserved(rescue) constant(Errno)operator(::)constant(ENOENT) + ident(setup_rb_error) global_variable($!)operator(.)ident(message) operator(+) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(basename)operator(()global_variable($0)operator(\))inline_delimiter(})>content( config first)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(save) + instance_variable(@items)operator(.)ident(each) operator({)operator(|)ident(i)operator(|) ident(i)operator(.)ident(value) operator(}) + constant(File)operator(.)ident(open)operator(()ident(savefile)operator(()operator(\))operator(,) string<delimiter(')content(w)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) + instance_variable(@items)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + ident(f)operator(.)ident(printf) string<delimiter(")content(%s=%s)char(\\n)delimiter(")>operator(,) ident(i)operator(.)ident(name)operator(,) ident(i)operator(.)ident(value) reserved(if) ident(i)operator(.)ident(value) + reserved(end) + operator(}) + reserved(end) + + reserved(def) method([])operator(()ident(key)operator(\)) + ident(lookup)operator(()ident(key)operator(\))operator(.)ident(eval)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method([]=)operator(()ident(key)operator(,) ident(val)operator(\)) + ident(lookup)operator(()ident(key)operator(\))operator(.)ident(set) ident(val) + reserved(end) + +reserved(end) + +ident(c) operator(=) operator(::)constant(Config)operator(::)constant(CONFIG) + +ident(rubypath) operator(=) ident(c)operator([)string<delimiter(')content(bindir)delimiter(')>operator(]) operator(+) string<delimiter(')content(/)delimiter(')> operator(+) ident(c)operator([)string<delimiter(')content(ruby_install_name)delimiter(')>operator(]) + +ident(major) operator(=) ident(c)operator([)string<delimiter(')content(MAJOR)delimiter(')>operator(])operator(.)ident(to_i) +ident(minor) operator(=) ident(c)operator([)string<delimiter(')content(MINOR)delimiter(')>operator(])operator(.)ident(to_i) +ident(teeny) operator(=) ident(c)operator([)string<delimiter(')content(TEENY)delimiter(')>operator(])operator(.)ident(to_i) +ident(version) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(major)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(minor)inline_delimiter(})>delimiter(")> + +comment(# ruby ver. >= 1.4.4?) +ident(newpath_p) operator(=) operator(()operator(()ident(major) operator(>)operator(=) integer(2)operator(\)) reserved(or) + operator(()operator(()ident(major) operator(==) integer(1)operator(\)) reserved(and) + operator(()operator(()ident(minor) operator(>)operator(=) integer(5)operator(\)) reserved(or) + operator(()operator(()ident(minor) operator(==) integer(4)operator(\)) reserved(and) operator(()ident(teeny) operator(>)operator(=) integer(4)operator(\))operator(\))operator(\))operator(\))operator(\)) + +reserved(if) ident(c)operator([)string<delimiter(')content(rubylibdir)delimiter(')>operator(]) + comment(# V < 1.6.3) + ident(_stdruby) operator(=) ident(c)operator([)string<delimiter(')content(rubylibdir)delimiter(')>operator(]) + ident(_siteruby) operator(=) ident(c)operator([)string<delimiter(')content(sitedir)delimiter(')>operator(]) + ident(_siterubyver) operator(=) ident(c)operator([)string<delimiter(')content(sitelibdir)delimiter(')>operator(]) + ident(_siterubyverarch) operator(=) ident(c)operator([)string<delimiter(')content(sitearchdir)delimiter(')>operator(]) +reserved(elsif) ident(newpath_p) + comment(# 1.4.4 <= V <= 1.6.3) + ident(_stdruby) operator(=) string<delimiter(")content($prefix/lib/ruby/)inline<inline_delimiter(#{)ident(version)inline_delimiter(})>delimiter(")> + ident(_siteruby) operator(=) ident(c)operator([)string<delimiter(')content(sitedir)delimiter(')>operator(]) + ident(_siterubyver) operator(=) string<delimiter(")content($siteruby/)inline<inline_delimiter(#{)ident(version)inline_delimiter(})>delimiter(")> + ident(_siterubyverarch) operator(=) string<delimiter(")content($siterubyver/)inline<inline_delimiter(#{)ident(c)operator([)string<delimiter(')content(arch)delimiter(')>operator(])inline_delimiter(})>delimiter(")> +reserved(else) + comment(# V < 1.4.4) + ident(_stdruby) operator(=) string<delimiter(")content($prefix/lib/ruby/)inline<inline_delimiter(#{)ident(version)inline_delimiter(})>delimiter(")> + ident(_siteruby) operator(=) string<delimiter(")content($prefix/lib/ruby/)inline<inline_delimiter(#{)ident(version)inline_delimiter(})>content(/site_ruby)delimiter(")> + ident(_siterubyver) operator(=) ident(_siteruby) + ident(_siterubyverarch) operator(=) string<delimiter(")content($siterubyver/)inline<inline_delimiter(#{)ident(c)operator([)string<delimiter(')content(arch)delimiter(')>operator(])inline_delimiter(})>delimiter(")> +reserved(end) +ident(libdir) operator(=) string<delimiter(')content(-* dummy libdir *-)delimiter(')> +ident(stdruby) operator(=) string<delimiter(')content(-* dummy rubylibdir *-)delimiter(')> +ident(siteruby) operator(=) string<delimiter(')content(-* dummy site_ruby *-)delimiter(')> +ident(siterubyver) operator(=) string<delimiter(')content(-* dummy site_ruby version *-)delimiter(')> +ident(parameterize) operator(=) ident(lambda) operator({)operator(|)ident(path)operator(|) + ident(path)operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote)operator(()ident(c)operator([)string<delimiter(')content(prefix)delimiter(')>operator(])operator(\))inline_delimiter(})>delimiter(/)>operator(,) string<delimiter(')content($prefix)delimiter(')>operator(\))\ + operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote)operator(()ident(libdir)operator(\))inline_delimiter(})>delimiter(/)>operator(,) string<delimiter(')content($libdir)delimiter(')>operator(\))\ + operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote)operator(()ident(stdruby)operator(\))inline_delimiter(})>delimiter(/)>operator(,) string<delimiter(')content($stdruby)delimiter(')>operator(\))\ + operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote)operator(()ident(siteruby)operator(\))inline_delimiter(})>delimiter(/)>operator(,) string<delimiter(')content($siteruby)delimiter(')>operator(\))\ + operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)inline<inline_delimiter(#{)constant(Regexp)operator(.)ident(quote)operator(()ident(siterubyver)operator(\))inline_delimiter(})>delimiter(/)>operator(,) string<delimiter(')content($siterubyver)delimiter(')>operator(\)) +operator(}) +ident(libdir) operator(=) ident(parameterize)operator(.)ident(call)operator(()ident(c)operator([)string<delimiter(')content(libdir)delimiter(')>operator(])operator(\)) +ident(stdruby) operator(=) ident(parameterize)operator(.)ident(call)operator(()ident(_stdruby)operator(\)) +ident(siteruby) operator(=) ident(parameterize)operator(.)ident(call)operator(()ident(_siteruby)operator(\)) +ident(siterubyver) operator(=) ident(parameterize)operator(.)ident(call)operator(()ident(_siterubyver)operator(\)) +ident(siterubyverarch) operator(=) ident(parameterize)operator(.)ident(call)operator(()ident(_siterubyverarch)operator(\)) + +reserved(if) ident(arg) operator(=) ident(c)operator([)string<delimiter(')content(configure_args)delimiter(')>operator(])operator(.)ident(split)operator(.)ident(detect) operator({)operator(|)ident(arg)operator(|) regexp<delimiter(/)content(--with-make-prog=)delimiter(/)> operator(=)operator(~) ident(arg) operator(}) + ident(makeprog) operator(=) ident(arg)operator(.)ident(sub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(split)operator(()regexp<delimiter(/)content(=)delimiter(/)>operator(,) integer(2)operator(\))operator([)integer(1)operator(]) +reserved(else) + ident(makeprog) operator(=) string<delimiter(')content(make)delimiter(')> +reserved(end) + +ident(common_conf) operator(=) operator([) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(prefix)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(c)operator([)string<delimiter(')content(prefix)delimiter(')>operator(])operator(,) + string<delimiter(')content(path prefix of target environment)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(bindir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(parameterize)operator(.)ident(call)operator(()ident(c)operator([)string<delimiter(')content(bindir)delimiter(')>operator(])operator(\))operator(,) + string<delimiter(')content(the directory for commands)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(libdir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(libdir)operator(,) + string<delimiter(')content(the directory for libraries)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(datadir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(parameterize)operator(.)ident(call)operator(()ident(c)operator([)string<delimiter(')content(datadir)delimiter(')>operator(])operator(\))operator(,) + string<delimiter(')content(the directory for shared data)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(mandir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(parameterize)operator(.)ident(call)operator(()ident(c)operator([)string<delimiter(')content(mandir)delimiter(')>operator(])operator(\))operator(,) + string<delimiter(')content(the directory for man pages)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(sysconfdir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(parameterize)operator(.)ident(call)operator(()ident(c)operator([)string<delimiter(')content(sysconfdir)delimiter(')>operator(])operator(\))operator(,) + string<delimiter(')content(the directory for man pages)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(stdruby)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(stdruby)operator(,) + string<delimiter(')content(the directory for standard ruby libraries)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(siteruby)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(siteruby)operator(,) + string<delimiter(')content(the directory for version-independent aux ruby libraries)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(siterubyver)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(siterubyver)operator(,) + string<delimiter(')content(the directory for aux ruby libraries)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(siterubyverarch)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(siterubyverarch)operator(,) + string<delimiter(')content(the directory for aux ruby binaries)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(rbdir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) string<delimiter(')content($siterubyver)delimiter(')>operator(,) + string<delimiter(')content(the directory for ruby scripts)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(sodir)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) string<delimiter(')content($siterubyverarch)delimiter(')>operator(,) + string<delimiter(')content(the directory for ruby extentions)delimiter(')>operator(\))operator(,) + constant(PathItem)operator(.)ident(new)operator(()string<delimiter(')content(rubypath)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(rubypath)operator(,) + string<delimiter(')content(the path to set to #! line)delimiter(')>operator(\))operator(,) + constant(ProgramItem)operator(.)ident(new)operator(()string<delimiter(')content(rubyprog)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')>operator(,) ident(rubypath)operator(,) + string<delimiter(')content(the ruby program using for installation)delimiter(')>operator(\))operator(,) + constant(ProgramItem)operator(.)ident(new)operator(()string<delimiter(')content(makeprog)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')>operator(,) ident(makeprog)operator(,) + string<delimiter(')content(the make program to compile ruby extentions)delimiter(')>operator(\))operator(,) + constant(SelectItem)operator(.)ident(new)operator(()string<delimiter(')content(shebang)delimiter(')>operator(,) string<delimiter(')content(all/ruby/never)delimiter(')>operator(,) string<delimiter(')content(ruby)delimiter(')>operator(,) + string<delimiter(')content(shebang line (#!\) editing mode)delimiter(')>operator(\))operator(,) + constant(BoolItem)operator(.)ident(new)operator(()string<delimiter(')content(without-ext)delimiter(')>operator(,) string<delimiter(')content(yes/no)delimiter(')>operator(,) string<delimiter(')content(no)delimiter(')>operator(,) + string<delimiter(')content(does not compile/install ruby extentions)delimiter(')>operator(\)) +operator(]) +reserved(class) class(ConfigTable_class) comment(# open again) + constant(ALIASES) operator(=) operator({) + string<delimiter(')content(std-ruby)delimiter(')> operator(=)operator(>) string<delimiter(')content(stdruby)delimiter(')>operator(,) + string<delimiter(')content(site-ruby-common)delimiter(')> operator(=)operator(>) string<delimiter(')content(siteruby)delimiter(')>operator(,) comment(# For backward compatibility) + string<delimiter(')content(site-ruby)delimiter(')> operator(=)operator(>) string<delimiter(')content(siterubyver)delimiter(')>operator(,) comment(# For backward compatibility) + string<delimiter(')content(bin-dir)delimiter(')> operator(=)operator(>) string<delimiter(')content(bindir)delimiter(')>operator(,) + string<delimiter(')content(bin-dir)delimiter(')> operator(=)operator(>) string<delimiter(')content(bindir)delimiter(')>operator(,) + string<delimiter(')content(rb-dir)delimiter(')> operator(=)operator(>) string<delimiter(')content(rbdir)delimiter(')>operator(,) + string<delimiter(')content(so-dir)delimiter(')> operator(=)operator(>) string<delimiter(')content(sodir)delimiter(')>operator(,) + string<delimiter(')content(data-dir)delimiter(')> operator(=)operator(>) string<delimiter(')content(datadir)delimiter(')>operator(,) + string<delimiter(')content(ruby-path)delimiter(')> operator(=)operator(>) string<delimiter(')content(rubypath)delimiter(')>operator(,) + string<delimiter(')content(ruby-prog)delimiter(')> operator(=)operator(>) string<delimiter(')content(rubyprog)delimiter(')>operator(,) + string<delimiter(')content(ruby)delimiter(')> operator(=)operator(>) string<delimiter(')content(rubyprog)delimiter(')>operator(,) + string<delimiter(')content(make-prog)delimiter(')> operator(=)operator(>) string<delimiter(')content(makeprog)delimiter(')>operator(,) + string<delimiter(')content(make)delimiter(')> operator(=)operator(>) string<delimiter(')content(makeprog)delimiter(')> + operator(}) +reserved(end) +ident(multipackage_conf) operator(=) operator([) + constant(PackageSelectionItem)operator(.)ident(new)operator(()string<delimiter(')content(with)delimiter(')>operator(,) string<delimiter(')content(name,name...)delimiter(')>operator(,) string<delimiter(')delimiter(')>operator(,) string<delimiter(')content(ALL)delimiter(')>operator(,) + string<delimiter(')content(package names that you want to install)delimiter(')>operator(\))operator(,) + constant(PackageSelectionItem)operator(.)ident(new)operator(()string<delimiter(')content(without)delimiter(')>operator(,) string<delimiter(')content(name,name...)delimiter(')>operator(,) string<delimiter(')delimiter(')>operator(,) string<delimiter(')content(NONE)delimiter(')>operator(,) + string<delimiter(')content(package names that you do not want to install)delimiter(')>operator(\)) +operator(]) +reserved(if) ident(multipackage_install?) + constant(ConfigTable) operator(=) constant(ConfigTable_class)operator(.)ident(new)operator(()ident(common_conf) operator(+) ident(multipackage_conf)operator(\)) +reserved(else) + constant(ConfigTable) operator(=) constant(ConfigTable_class)operator(.)ident(new)operator(()ident(common_conf)operator(\)) +reserved(end) + + +reserved(module) class(MetaConfigAPI) + + reserved(def) method(eval_file_ifexist)operator(()ident(fname)operator(\)) + ident(instance_eval) constant(File)operator(.)ident(read)operator(()ident(fname)operator(\))operator(,) ident(fname)operator(,) integer(1) reserved(if) constant(File)operator(.)ident(file?)operator(()ident(fname)operator(\)) + reserved(end) + + reserved(def) method(config_names) + constant(ConfigTable)operator(.)ident(map) operator({)operator(|)ident(i)operator(|) ident(i)operator(.)ident(name) operator(}) + reserved(end) + + reserved(def) method(config?)operator(()ident(name)operator(\)) + constant(ConfigTable)operator(.)ident(key?)operator(()ident(name)operator(\)) + reserved(end) + + reserved(def) method(bool_config?)operator(()ident(name)operator(\)) + constant(ConfigTable)operator(.)ident(lookup)operator(()ident(name)operator(\))operator(.)ident(config_type) operator(==) string<delimiter(')content(bool)delimiter(')> + reserved(end) + + reserved(def) method(path_config?)operator(()ident(name)operator(\)) + constant(ConfigTable)operator(.)ident(lookup)operator(()ident(name)operator(\))operator(.)ident(config_type) operator(==) string<delimiter(')content(path)delimiter(')> + reserved(end) + + reserved(def) method(value_config?)operator(()ident(name)operator(\)) + reserved(case) constant(ConfigTable)operator(.)ident(lookup)operator(()ident(name)operator(\))operator(.)ident(config_type) + reserved(when) string<delimiter(')content(bool)delimiter(')>operator(,) string<delimiter(')content(path)delimiter(')> + pre_constant(true) + reserved(else) + pre_constant(false) + reserved(end) + reserved(end) + + reserved(def) method(add_config)operator(()ident(item)operator(\)) + constant(ConfigTable)operator(.)ident(add) ident(item) + reserved(end) + + reserved(def) method(add_bool_config)operator(()ident(name)operator(,) ident(default)operator(,) ident(desc)operator(\)) + constant(ConfigTable)operator(.)ident(add) constant(BoolItem)operator(.)ident(new)operator(()ident(name)operator(,) string<delimiter(')content(yes/no)delimiter(')>operator(,) ident(default) operator(?) string<delimiter(')content(yes)delimiter(')> operator(:) string<delimiter(')content(no)delimiter(')>operator(,) ident(desc)operator(\)) + reserved(end) + + reserved(def) method(add_path_config)operator(()ident(name)operator(,) ident(default)operator(,) ident(desc)operator(\)) + constant(ConfigTable)operator(.)ident(add) constant(PathItem)operator(.)ident(new)operator(()ident(name)operator(,) string<delimiter(')content(path)delimiter(')>operator(,) ident(default)operator(,) ident(desc)operator(\)) + reserved(end) + + reserved(def) method(set_config_default)operator(()ident(name)operator(,) ident(default)operator(\)) + constant(ConfigTable)operator(.)ident(lookup)operator(()ident(name)operator(\))operator(.)ident(default) operator(=) ident(default) + reserved(end) + + reserved(def) method(remove_config)operator(()ident(name)operator(\)) + constant(ConfigTable)operator(.)ident(remove)operator(()ident(name)operator(\)) + reserved(end) + +reserved(end) + + +comment(#) +comment(# File Operations) +comment(#) + +reserved(module) class(FileOperations) + + reserved(def) method(mkdir_p)operator(()ident(dirname)operator(,) ident(prefix) operator(=) pre_constant(nil)operator(\)) + ident(dirname) operator(=) ident(prefix) operator(+) constant(File)operator(.)ident(expand_path)operator(()ident(dirname)operator(\)) reserved(if) ident(prefix) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(mkdir -p )inline<inline_delimiter(#{)ident(dirname)inline_delimiter(})>delimiter(")> reserved(if) ident(verbose?) + reserved(return) reserved(if) ident(no_harm?) + + comment(# does not check '/'... it's too abnormal case) + ident(dirs) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(dirname)operator(\))operator(.)ident(split)operator(()regexp<delimiter(%r<)content((?=/\))delimiter(>)>operator(\)) + reserved(if) regexp<delimiter(/)char(\\A)content([a-z]:)char(\\z)delimiter(/)modifier(i)> operator(=)operator(~) ident(dirs)operator([)integer(0)operator(]) + ident(disk) operator(=) ident(dirs)operator(.)ident(shift) + ident(dirs)operator([)integer(0)operator(]) operator(=) ident(disk) operator(+) ident(dirs)operator([)integer(0)operator(]) + reserved(end) + ident(dirs)operator(.)ident(each_index) reserved(do) operator(|)ident(idx)operator(|) + ident(path) operator(=) ident(dirs)operator([)integer(0)operator(..)ident(idx)operator(])operator(.)ident(join)operator(()string<delimiter(')delimiter(')>operator(\)) + constant(Dir)operator(.)ident(mkdir) ident(path) reserved(unless) constant(File)operator(.)ident(dir?)operator(()ident(path)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(rm_f)operator(()ident(fname)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(rm -f )inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>delimiter(")> reserved(if) ident(verbose?) + reserved(return) reserved(if) ident(no_harm?) + + reserved(if) constant(File)operator(.)ident(exist?)operator(()ident(fname)operator(\)) reserved(or) constant(File)operator(.)ident(symlink?)operator(()ident(fname)operator(\)) + constant(File)operator(.)ident(chmod) integer(0777)operator(,) ident(fname) + constant(File)operator(.)ident(unlink) ident(fname) + reserved(end) + reserved(end) + + reserved(def) method(rm_rf)operator(()ident(dn)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(rm -rf )inline<inline_delimiter(#{)ident(dn)inline_delimiter(})>delimiter(")> reserved(if) ident(verbose?) + reserved(return) reserved(if) ident(no_harm?) + + constant(Dir)operator(.)ident(chdir) ident(dn) + constant(Dir)operator(.)ident(foreach)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) reserved(do) operator(|)ident(fn)operator(|) + reserved(next) reserved(if) ident(fn) operator(==) string<delimiter(')content(.)delimiter(')> + reserved(next) reserved(if) ident(fn) operator(==) string<delimiter(')content(..)delimiter(')> + reserved(if) constant(File)operator(.)ident(dir?)operator(()ident(fn)operator(\)) + ident(verbose_off) operator({) + ident(rm_rf) ident(fn) + operator(}) + reserved(else) + ident(verbose_off) operator({) + ident(rm_f) ident(fn) + operator(}) + reserved(end) + reserved(end) + constant(Dir)operator(.)ident(chdir) string<delimiter(')content(..)delimiter(')> + constant(Dir)operator(.)ident(rmdir) ident(dn) + reserved(end) + + reserved(def) method(move_file)operator(()ident(src)operator(,) ident(dest)operator(\)) + constant(File)operator(.)ident(unlink) ident(dest) reserved(if) constant(File)operator(.)ident(exist?)operator(()ident(dest)operator(\)) + reserved(begin) + constant(File)operator(.)ident(rename) ident(src)operator(,) ident(dest) + reserved(rescue) + constant(File)operator(.)ident(open)operator(()ident(dest)operator(,) string<delimiter(')content(wb)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) ident(f)operator(.)ident(write) constant(File)operator(.)ident(binread)operator(()ident(src)operator(\)) operator(}) + constant(File)operator(.)ident(chmod) constant(File)operator(.)ident(stat)operator(()ident(src)operator(\))operator(.)ident(mode)operator(,) ident(dest) + constant(File)operator(.)ident(unlink) ident(src) + reserved(end) + reserved(end) + + reserved(def) method(install)operator(()ident(from)operator(,) ident(dest)operator(,) ident(mode)operator(,) ident(prefix) operator(=) pre_constant(nil)operator(\)) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(install )inline<inline_delimiter(#{)ident(from)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(dest)inline_delimiter(})>delimiter(")> reserved(if) ident(verbose?) + reserved(return) reserved(if) ident(no_harm?) + + ident(realdest) operator(=) ident(prefix) operator(?) ident(prefix) operator(+) constant(File)operator(.)ident(expand_path)operator(()ident(dest)operator(\)) operator(:) ident(dest) + ident(realdest) operator(=) constant(File)operator(.)ident(join)operator(()ident(realdest)operator(,) constant(File)operator(.)ident(basename)operator(()ident(from)operator(\))operator(\)) reserved(if) constant(File)operator(.)ident(dir?)operator(()ident(realdest)operator(\)) + ident(str) operator(=) constant(File)operator(.)ident(binread)operator(()ident(from)operator(\)) + reserved(if) ident(diff?)operator(()ident(str)operator(,) ident(realdest)operator(\)) + ident(verbose_off) operator({) + ident(rm_f) ident(realdest) reserved(if) constant(File)operator(.)ident(exist?)operator(()ident(realdest)operator(\)) + operator(}) + constant(File)operator(.)ident(open)operator(()ident(realdest)operator(,) string<delimiter(')content(wb)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) + ident(f)operator(.)ident(write) ident(str) + operator(}) + constant(File)operator(.)ident(chmod) ident(mode)operator(,) ident(realdest) + + constant(File)operator(.)ident(open)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(objdir_root)operator(()operator(\))inline_delimiter(})>content(/InstalledFiles)delimiter(")>operator(,) string<delimiter(')content(a)delimiter(')>operator(\)) operator({)operator(|)ident(f)operator(|) + reserved(if) ident(prefix) + ident(f)operator(.)ident(puts) ident(realdest)operator(.)ident(sub)operator(()ident(prefix)operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(else) + ident(f)operator(.)ident(puts) ident(realdest) + reserved(end) + operator(}) + reserved(end) + reserved(end) + + reserved(def) method(diff?)operator(()ident(new_content)operator(,) ident(path)operator(\)) + reserved(return) pre_constant(true) reserved(unless) constant(File)operator(.)ident(exist?)operator(()ident(path)operator(\)) + ident(new_content) operator(!=) constant(File)operator(.)ident(binread)operator(()ident(path)operator(\)) + reserved(end) + + reserved(def) method(command)operator(()ident(str)operator(\)) + global_variable($stderr)operator(.)ident(puts) ident(str) reserved(if) ident(verbose?) + ident(system) ident(str) reserved(or) ident(raise) constant(RuntimeError)operator(,) string<delimiter(")content('system )inline<inline_delimiter(#{)ident(str)inline_delimiter(})>content(' failed)delimiter(")> + reserved(end) + + reserved(def) method(ruby)operator(()ident(str)operator(\)) + ident(command) ident(config)operator(()string<delimiter(')content(rubyprog)delimiter(')>operator(\)) operator(+) string<delimiter(')content( )delimiter(')> operator(+) ident(str) + reserved(end) + + reserved(def) method(make)operator(()ident(task) operator(=) string<delimiter(')delimiter(')>operator(\)) + ident(command) ident(config)operator(()string<delimiter(')content(makeprog)delimiter(')>operator(\)) operator(+) string<delimiter(')content( )delimiter(')> operator(+) ident(task) + reserved(end) + + reserved(def) method(extdir?)operator(()ident(dir)operator(\)) + constant(File)operator(.)ident(exist?)operator(()ident(dir) operator(+) string<delimiter(')content(/MANIFEST)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(all_files_in)operator(()ident(dirname)operator(\)) + constant(Dir)operator(.)ident(open)operator(()ident(dirname)operator(\)) operator({)operator(|)ident(d)operator(|) + reserved(return) ident(d)operator(.)ident(select) operator({)operator(|)ident(ent)operator(|) constant(File)operator(.)ident(file?)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(ent)inline_delimiter(})>delimiter(")>operator(\)) operator(}) + operator(}) + reserved(end) + + constant(REJECT_DIRS) operator(=) string<delimiter(%w()content( + CVS SCCS RCS CVS.adm .svn + )delimiter(\))> + + reserved(def) method(all_dirs_in)operator(()ident(dirname)operator(\)) + constant(Dir)operator(.)ident(open)operator(()ident(dirname)operator(\)) operator({)operator(|)ident(d)operator(|) + reserved(return) ident(d)operator(.)ident(select) operator({)operator(|)ident(n)operator(|) constant(File)operator(.)ident(dir?)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(dirname)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>delimiter(")>operator(\)) operator(}) operator(-) string<delimiter(%w()content(. ..)delimiter(\))> operator(-) constant(REJECT_DIRS) + operator(}) + reserved(end) + +reserved(end) + + +comment(#) +comment(# Main Installer) +comment(#) + +reserved(module) class(HookUtils) + + reserved(def) method(run_hook)operator(()ident(name)operator(\)) + ident(try_run_hook) string<delimiter(")inline<inline_delimiter(#{)ident(curr_srcdir)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> reserved(or) + ident(try_run_hook) string<delimiter(")inline<inline_delimiter(#{)ident(curr_srcdir)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(.rb)delimiter(")> + reserved(end) + + reserved(def) method(try_run_hook)operator(()ident(fname)operator(\)) + reserved(return) pre_constant(false) reserved(unless) constant(File)operator(.)ident(file?)operator(()ident(fname)operator(\)) + reserved(begin) + ident(instance_eval) constant(File)operator(.)ident(read)operator(()ident(fname)operator(\))operator(,) ident(fname)operator(,) integer(1) + reserved(rescue) + ident(setup_rb_error) string<delimiter(")content(hook )inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>content( failed:)char(\\n)delimiter(")> operator(+) global_variable($!)operator(.)ident(message) + reserved(end) + pre_constant(true) + reserved(end) + +reserved(end) + + +reserved(module) class(HookScriptAPI) + + reserved(def) method(get_config)operator(()ident(key)operator(\)) + instance_variable(@config)operator([)ident(key)operator(]) + reserved(end) + + reserved(alias) method(config) method(get_config) + + reserved(def) method(set_config)operator(()ident(key)operator(,) ident(val)operator(\)) + instance_variable(@config)operator([)ident(key)operator(]) operator(=) ident(val) + reserved(end) + + comment(#) + comment(# srcdir/objdir (works only in the package directory\)) + comment(#) + + comment(#abstract srcdir_root) + comment(#abstract objdir_root) + comment(#abstract relpath) + + reserved(def) method(curr_srcdir) + string<delimiter(")inline<inline_delimiter(#{)ident(srcdir_root)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(relpath)operator(()operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(curr_objdir) + string<delimiter(")inline<inline_delimiter(#{)ident(objdir_root)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(relpath)operator(()operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(srcfile)operator(()ident(path)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(curr_srcdir)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(srcexist?)operator(()ident(path)operator(\)) + constant(File)operator(.)ident(exist?)operator(()ident(srcfile)operator(()ident(path)operator(\))operator(\)) + reserved(end) + + reserved(def) method(srcdirectory?)operator(()ident(path)operator(\)) + constant(File)operator(.)ident(dir?)operator(()ident(srcfile)operator(()ident(path)operator(\))operator(\)) + reserved(end) + + reserved(def) method(srcfile?)operator(()ident(path)operator(\)) + constant(File)operator(.)ident(file?) ident(srcfile)operator(()ident(path)operator(\)) + reserved(end) + + reserved(def) method(srcentries)operator(()ident(path) operator(=) string<delimiter(')content(.)delimiter(')>operator(\)) + constant(Dir)operator(.)ident(open)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(curr_srcdir)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(path)inline_delimiter(})>delimiter(")>operator(\)) operator({)operator(|)ident(d)operator(|) + reserved(return) ident(d)operator(.)ident(to_a) operator(-) string<delimiter(%w()content(. ..)delimiter(\))> + operator(}) + reserved(end) + + reserved(def) method(srcfiles)operator(()ident(path) operator(=) string<delimiter(')content(.)delimiter(')>operator(\)) + ident(srcentries)operator(()ident(path)operator(\))operator(.)ident(select) operator({)operator(|)ident(fname)operator(|) + constant(File)operator(.)ident(file?)operator(()constant(File)operator(.)ident(join)operator(()ident(curr_srcdir)operator(()operator(\))operator(,) ident(path)operator(,) ident(fname)operator(\))operator(\)) + operator(}) + reserved(end) + + reserved(def) method(srcdirectories)operator(()ident(path) operator(=) string<delimiter(')content(.)delimiter(')>operator(\)) + ident(srcentries)operator(()ident(path)operator(\))operator(.)ident(select) operator({)operator(|)ident(fname)operator(|) + constant(File)operator(.)ident(dir?)operator(()constant(File)operator(.)ident(join)operator(()ident(curr_srcdir)operator(()operator(\))operator(,) ident(path)operator(,) ident(fname)operator(\))operator(\)) + operator(}) + reserved(end) + +reserved(end) + + +reserved(class) class(ToplevelInstaller) + + constant(Version) operator(=) string<delimiter(')content(3.3.1)delimiter(')> + constant(Copyright) operator(=) string<delimiter(')content(Copyright (c\) 2000-2004 Minero Aoki)delimiter(')> + + constant(TASKS) operator(=) operator([) + operator([) string<delimiter(')content(all)delimiter(')>operator(,) string<delimiter(')content(do config, setup, then install)delimiter(')> operator(])operator(,) + operator([) string<delimiter(')content(config)delimiter(')>operator(,) string<delimiter(')content(saves your configurations)delimiter(')> operator(])operator(,) + operator([) string<delimiter(')content(show)delimiter(')>operator(,) string<delimiter(')content(shows current configuration)delimiter(')> operator(])operator(,) + operator([) string<delimiter(')content(setup)delimiter(')>operator(,) string<delimiter(')content(compiles ruby extentions and others)delimiter(')> operator(])operator(,) + operator([) string<delimiter(')content(install)delimiter(')>operator(,) string<delimiter(')content(installs files)delimiter(')> operator(])operator(,) + operator([) string<delimiter(')content(clean)delimiter(')>operator(,) string<delimiter(")content(does `make clean' for each extention)delimiter(")> operator(])operator(,) + operator([) string<delimiter(')content(distclean)delimiter(')>operator(,)string<delimiter(")content(does `make distclean' for each extention)delimiter(")> operator(]) + operator(]) + + reserved(def) constant(ToplevelInstaller)operator(.)ident(invoke) + ident(instance)operator(()operator(\))operator(.)ident(invoke) + reserved(end) + + instance_variable(@singleton) operator(=) pre_constant(nil) + + reserved(def) constant(ToplevelInstaller)operator(.)ident(instance) + instance_variable(@singleton) operator(||=) ident(new)operator(()constant(File)operator(.)ident(dirname)operator(()global_variable($0)operator(\))operator(\)) + instance_variable(@singleton) + reserved(end) + + ident(include) constant(MetaConfigAPI) + + reserved(def) method(initialize)operator(()ident(ardir_root)operator(\)) + instance_variable(@config) operator(=) pre_constant(nil) + instance_variable(@options) operator(=) operator({) string<delimiter(')content(verbose)delimiter(')> operator(=)operator(>) pre_constant(true) operator(}) + instance_variable(@ardir) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(ardir_root)operator(\)) + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(__id__)operator(()operator(\))inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(invoke) + ident(run_metaconfigs) + reserved(case) ident(task) operator(=) ident(parsearg_global)operator(()operator(\)) + reserved(when) pre_constant(nil)operator(,) string<delimiter(')content(all)delimiter(')> + instance_variable(@config) operator(=) ident(load_config)operator(()string<delimiter(')content(config)delimiter(')>operator(\)) + ident(parsearg_config) + ident(init_installers) + ident(exec_config) + ident(exec_setup) + ident(exec_install) + reserved(else) + instance_variable(@config) operator(=) ident(load_config)operator(()ident(task)operator(\)) + ident(__send__) string<delimiter(")content(parsearg_)inline<inline_delimiter(#{)ident(task)inline_delimiter(})>delimiter(")> + ident(init_installers) + ident(__send__) string<delimiter(")content(exec_)inline<inline_delimiter(#{)ident(task)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(run_metaconfigs) + ident(eval_file_ifexist) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@ardir)inline_delimiter(})>content(/metaconfig)delimiter(")> + reserved(end) + + reserved(def) method(load_config)operator(()ident(task)operator(\)) + reserved(case) ident(task) + reserved(when) string<delimiter(')content(config)delimiter(')> + constant(ConfigTable)operator(.)ident(new) + reserved(when) string<delimiter(')content(clean)delimiter(')>operator(,) string<delimiter(')content(distclean)delimiter(')> + reserved(if) constant(File)operator(.)ident(exist?)operator(()constant(ConfigTable)operator(.)ident(savefile)operator(\)) + reserved(then) constant(ConfigTable)operator(.)ident(load) + reserved(else) constant(ConfigTable)operator(.)ident(new) + reserved(end) + reserved(else) + constant(ConfigTable)operator(.)ident(load) + reserved(end) + reserved(end) + + reserved(def) method(init_installers) + instance_variable(@installer) operator(=) constant(Installer)operator(.)ident(new)operator(()instance_variable(@config)operator(,) instance_variable(@options)operator(,) instance_variable(@ardir)operator(,) constant(File)operator(.)ident(expand_path)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(\)) + reserved(end) + + comment(#) + comment(# Hook Script API bases) + comment(#) + + reserved(def) method(srcdir_root) + instance_variable(@ardir) + reserved(end) + + reserved(def) method(objdir_root) + string<delimiter(')content(.)delimiter(')> + reserved(end) + + reserved(def) method(relpath) + string<delimiter(')content(.)delimiter(')> + reserved(end) + + comment(#) + comment(# Option Parsing) + comment(#) + + reserved(def) method(parsearg_global) + ident(valid_task) operator(=) regexp<delimiter(/)char(\\A)content((?:)inline<inline_delimiter(#{)constant(TASKS)operator(.)ident(map) operator({)operator(|)ident(task)operator(,)ident(desc)operator(|) ident(task) operator(})operator(.)ident(join) string<delimiter(')content(|)delimiter(')>inline_delimiter(})>content(\))char(\\z)delimiter(/)> + + reserved(while) ident(arg) operator(=) pre_constant(ARGV)operator(.)ident(shift) + reserved(case) ident(arg) + reserved(when) regexp<delimiter(/)char(\\A)char(\\w)content(+)char(\\z)delimiter(/)> + ident(setup_rb_error) string<delimiter(")content(invalid task: )inline<inline_delimiter(#{)ident(arg)inline_delimiter(})>delimiter(")> reserved(unless) ident(valid_task) operator(=)operator(~) ident(arg) + reserved(return) ident(arg) + + reserved(when) string<delimiter(')content(-q)delimiter(')>operator(,) string<delimiter(')content(--quiet)delimiter(')> + instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) operator(=) pre_constant(false) + + reserved(when) string<delimiter(')content(--verbose)delimiter(')> + instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) operator(=) pre_constant(true) + + reserved(when) string<delimiter(')content(-h)delimiter(')>operator(,) string<delimiter(')content(--help)delimiter(')> + ident(print_usage) global_variable($stdout) + ident(exit) integer(0) + + reserved(when) string<delimiter(')content(-v)delimiter(')>operator(,) string<delimiter(')content(--version)delimiter(')> + ident(puts) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(basename)operator(()global_variable($0)operator(\))inline_delimiter(})>content( version )inline<inline_delimiter(#{)constant(Version)inline_delimiter(})>delimiter(")> + ident(exit) integer(0) + + reserved(when) string<delimiter(')content(--copyright)delimiter(')> + ident(puts) constant(Copyright) + ident(exit) integer(0) + + reserved(else) + ident(setup_rb_error) string<delimiter(")content(unknown global option ')inline<inline_delimiter(#{)ident(arg)inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + + pre_constant(nil) + reserved(end) + + + reserved(def) method(parsearg_no_options) + reserved(unless) pre_constant(ARGV)operator(.)ident(empty?) + ident(setup_rb_error) string<delimiter(")inline<inline_delimiter(#{)ident(task)inline_delimiter(})>content(: unknown options: )inline<inline_delimiter(#{)pre_constant(ARGV)operator(.)ident(join) string<delimiter(')content( )delimiter(')>inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(alias) method(parsearg_show) method(parsearg_no_options) + reserved(alias) method(parsearg_setup) method(parsearg_no_options) + reserved(alias) method(parsearg_clean) method(parsearg_no_options) + reserved(alias) method(parsearg_distclean) method(parsearg_no_options) + + reserved(def) method(parsearg_config) + ident(re) operator(=) regexp<delimiter(/)char(\\A)content(--()inline<inline_delimiter(#{)constant(ConfigTable)operator(.)ident(map) operator({)operator(|)ident(i)operator(|) ident(i)operator(.)ident(name) operator(})operator(.)ident(join)operator(()string<delimiter(')content(|)delimiter(')>operator(\))inline_delimiter(})>content(\)(?:=(.*\)\)?)char(\\z)delimiter(/)> + instance_variable(@options)operator([)string<delimiter(')content(config-opt)delimiter(')>operator(]) operator(=) operator([)operator(]) + + reserved(while) ident(i) operator(=) pre_constant(ARGV)operator(.)ident(shift) + reserved(if) regexp<delimiter(/)char(\\A)content(--?)char(\\z)delimiter(/)> operator(=)operator(~) ident(i) + instance_variable(@options)operator([)string<delimiter(')content(config-opt)delimiter(')>operator(]) operator(=) pre_constant(ARGV)operator(.)ident(dup) + reserved(break) + reserved(end) + ident(m) operator(=) ident(re)operator(.)ident(match)operator(()ident(i)operator(\)) reserved(or) ident(setup_rb_error) string<delimiter(")content(config: unknown option )inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")> + ident(name)operator(,) ident(value) operator(=) operator(*)ident(m)operator(.)ident(to_a)operator([)integer(1)operator(,)integer(2)operator(]) + instance_variable(@config)operator([)ident(name)operator(]) operator(=) ident(value) + reserved(end) + reserved(end) + + reserved(def) method(parsearg_install) + instance_variable(@options)operator([)string<delimiter(')content(no-harm)delimiter(')>operator(]) operator(=) pre_constant(false) + instance_variable(@options)operator([)string<delimiter(')content(install-prefix)delimiter(')>operator(]) operator(=) string<delimiter(')delimiter(')> + reserved(while) ident(a) operator(=) pre_constant(ARGV)operator(.)ident(shift) + reserved(case) ident(a) + reserved(when) regexp<delimiter(/)char(\\A)content(--no-harm)char(\\z)delimiter(/)> + instance_variable(@options)operator([)string<delimiter(')content(no-harm)delimiter(')>operator(]) operator(=) pre_constant(true) + reserved(when) regexp<delimiter(/)char(\\A)content(--prefix=(.*\))char(\\z)delimiter(/)> + ident(path) operator(=) global_variable($1) + ident(path) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(path)operator(\)) reserved(unless) ident(path)operator([)integer(0)operator(,)integer(1)operator(]) operator(==) string<delimiter(')content(/)delimiter(')> + instance_variable(@options)operator([)string<delimiter(')content(install-prefix)delimiter(')>operator(]) operator(=) ident(path) + reserved(else) + ident(setup_rb_error) string<delimiter(")content(install: unknown option )inline<inline_delimiter(#{)ident(a)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(print_usage)operator(()ident(out)operator(\)) + ident(out)operator(.)ident(puts) string<delimiter(')content(Typical Installation Procedure:)delimiter(')> + ident(out)operator(.)ident(puts) string<delimiter(")content( $ ruby )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename) global_variable($0)inline_delimiter(})>content( config)delimiter(")> + ident(out)operator(.)ident(puts) string<delimiter(")content( $ ruby )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename) global_variable($0)inline_delimiter(})>content( setup)delimiter(")> + ident(out)operator(.)ident(puts) string<delimiter(")content( # ruby )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename) global_variable($0)inline_delimiter(})>content( install (may require root privilege\))delimiter(")> + ident(out)operator(.)ident(puts) + ident(out)operator(.)ident(puts) string<delimiter(')content(Detailed Usage:)delimiter(')> + ident(out)operator(.)ident(puts) string<delimiter(")content( ruby )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename) global_variable($0)inline_delimiter(})>content( <global option>)delimiter(")> + ident(out)operator(.)ident(puts) string<delimiter(")content( ruby )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename) global_variable($0)inline_delimiter(})>content( [<global options>] <task> [<task options>])delimiter(")> + + ident(fmt) operator(=) string<delimiter(")content( %-24s %s)char(\\n)delimiter(")> + ident(out)operator(.)ident(puts) + ident(out)operator(.)ident(puts) string<delimiter(')content(Global options:)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content(-q,--quiet)delimiter(')>operator(,) string<delimiter(')content(suppress message outputs)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content( --verbose)delimiter(')>operator(,) string<delimiter(')content(output messages verbosely)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content(-h,--help)delimiter(')>operator(,) string<delimiter(')content(print this message)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content(-v,--version)delimiter(')>operator(,) string<delimiter(')content(print version and quit)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content( --copyright)delimiter(')>operator(,) string<delimiter(')content(print copyright and quit)delimiter(')> + ident(out)operator(.)ident(puts) + ident(out)operator(.)ident(puts) string<delimiter(')content(Tasks:)delimiter(')> + constant(TASKS)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(desc)operator(|) + ident(out)operator(.)ident(printf) ident(fmt)operator(,) ident(name)operator(,) ident(desc) + reserved(end) + + ident(fmt) operator(=) string<delimiter(")content( %-24s %s [%s])char(\\n)delimiter(")> + ident(out)operator(.)ident(puts) + ident(out)operator(.)ident(puts) string<delimiter(')content(Options for CONFIG or ALL:)delimiter(')> + constant(ConfigTable)operator(.)ident(each) reserved(do) operator(|)ident(item)operator(|) + ident(out)operator(.)ident(printf) ident(fmt)operator(,) ident(item)operator(.)ident(help_opt)operator(,) ident(item)operator(.)ident(description)operator(,) ident(item)operator(.)ident(help_default) + reserved(end) + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content(--rbconfig=path)delimiter(')>operator(,) string<delimiter(')content(rbconfig.rb to load)delimiter(')>operator(,)string<delimiter(")content(running ruby's)delimiter(")> + ident(out)operator(.)ident(puts) + ident(out)operator(.)ident(puts) string<delimiter(')content(Options for INSTALL:)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content(--no-harm)delimiter(')>operator(,) string<delimiter(')content(only display what to do if given)delimiter(')>operator(,) string<delimiter(')content(off)delimiter(')> + ident(out)operator(.)ident(printf) ident(fmt)operator(,) string<delimiter(')content(--prefix=path)delimiter(')>operator(,) string<delimiter(')content(install path prefix)delimiter(')>operator(,) string<delimiter(')content($prefix)delimiter(')> + ident(out)operator(.)ident(puts) + reserved(end) + + comment(#) + comment(# Task Handlers) + comment(#) + + reserved(def) method(exec_config) + instance_variable(@installer)operator(.)ident(exec_config) + instance_variable(@config)operator(.)ident(save) comment(# must be final) + reserved(end) + + reserved(def) method(exec_setup) + instance_variable(@installer)operator(.)ident(exec_setup) + reserved(end) + + reserved(def) method(exec_install) + instance_variable(@installer)operator(.)ident(exec_install) + reserved(end) + + reserved(def) method(exec_show) + constant(ConfigTable)operator(.)ident(each) reserved(do) operator(|)ident(i)operator(|) + ident(printf) string<delimiter(")content(%-20s %s)char(\\n)delimiter(")>operator(,) ident(i)operator(.)ident(name)operator(,) ident(i)operator(.)ident(value) + reserved(end) + reserved(end) + + reserved(def) method(exec_clean) + instance_variable(@installer)operator(.)ident(exec_clean) + reserved(end) + + reserved(def) method(exec_distclean) + instance_variable(@installer)operator(.)ident(exec_distclean) + reserved(end) + +reserved(end) + + +reserved(class) class(ToplevelInstallerMulti) operator(<) constant(ToplevelInstaller) + + ident(include) constant(HookUtils) + ident(include) constant(HookScriptAPI) + ident(include) constant(FileOperations) + + reserved(def) method(initialize)operator(()ident(ardir)operator(\)) + reserved(super) + instance_variable(@packages) operator(=) ident(all_dirs_in)operator(()string<delimiter(")inline<inline_delimiter(#{)instance_variable(@ardir)inline_delimiter(})>content(/packages)delimiter(")>operator(\)) + ident(raise) string<delimiter(')content(no package exists)delimiter(')> reserved(if) instance_variable(@packages)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(run_metaconfigs) + ident(eval_file_ifexist) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@ardir)inline_delimiter(})>content(/metaconfig)delimiter(")> + instance_variable(@packages)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(eval_file_ifexist) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@ardir)inline_delimiter(})>content(/packages/)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(/metaconfig)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(init_installers) + instance_variable(@installers) operator(=) operator({)operator(}) + instance_variable(@packages)operator(.)ident(each) reserved(do) operator(|)ident(pack)operator(|) + instance_variable(@installers)operator([)ident(pack)operator(]) operator(=) constant(Installer)operator(.)ident(new)operator(()instance_variable(@config)operator(,) instance_variable(@options)operator(,) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@ardir)inline_delimiter(})>content(/packages/)inline<inline_delimiter(#{)ident(pack)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(packages/)inline<inline_delimiter(#{)ident(pack)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + ident(with) operator(=) ident(extract_selection)operator(()ident(config)operator(()string<delimiter(')content(with)delimiter(')>operator(\))operator(\)) + ident(without) operator(=) ident(extract_selection)operator(()ident(config)operator(()string<delimiter(')content(without)delimiter(')>operator(\))operator(\)) + instance_variable(@selected) operator(=) instance_variable(@installers)operator(.)ident(keys)operator(.)ident(select) operator({)operator(|)ident(name)operator(|) + operator(()ident(with)operator(.)ident(empty?) reserved(or) ident(with)operator(.)ident(include?)operator(()ident(name)operator(\))operator(\)) \ + reserved(and) reserved(not) ident(without)operator(.)ident(include?)operator(()ident(name)operator(\)) + operator(}) + reserved(end) + + reserved(def) method(extract_selection)operator(()ident(list)operator(\)) + ident(a) operator(=) ident(list)operator(.)ident(split)operator(()regexp<delimiter(/)content(,)delimiter(/)>operator(\)) + ident(a)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(setup_rb_error) string<delimiter(")content(no such package: )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> reserved(unless) instance_variable(@installers)operator(.)ident(key?)operator(()ident(name)operator(\)) + reserved(end) + ident(a) + reserved(end) + + reserved(def) method(print_usage)operator(()ident(f)operator(\)) + reserved(super) + ident(f)operator(.)ident(puts) string<delimiter(')content(Inluded packages:)delimiter(')> + ident(f)operator(.)ident(puts) string<delimiter(')content( )delimiter(')> operator(+) instance_variable(@packages)operator(.)ident(sort)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\)) + ident(f)operator(.)ident(puts) + reserved(end) + + comment(#) + comment(# multi-package metaconfig API) + comment(#) + + ident(attr_reader) symbol(:packages) + + reserved(def) method(declare_packages)operator(()ident(list)operator(\)) + ident(raise) string<delimiter(')content(package list is empty)delimiter(')> reserved(if) ident(list)operator(.)ident(empty?) + ident(list)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(raise) string<delimiter(")content(directory packages/)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( does not exist)delimiter(")>\ + reserved(unless) constant(File)operator(.)ident(dir?)operator(()string<delimiter(")inline<inline_delimiter(#{)instance_variable(@ardir)inline_delimiter(})>content(/packages/)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + instance_variable(@packages) operator(=) ident(list) + reserved(end) + + comment(#) + comment(# Task Handlers) + comment(#) + + reserved(def) method(exec_config) + ident(run_hook) string<delimiter(')content(pre-config)delimiter(')> + ident(each_selected_installers) operator({)operator(|)ident(inst)operator(|) ident(inst)operator(.)ident(exec_config) operator(}) + ident(run_hook) string<delimiter(')content(post-config)delimiter(')> + instance_variable(@config)operator(.)ident(save) comment(# must be final) + reserved(end) + + reserved(def) method(exec_setup) + ident(run_hook) string<delimiter(')content(pre-setup)delimiter(')> + ident(each_selected_installers) operator({)operator(|)ident(inst)operator(|) ident(inst)operator(.)ident(exec_setup) operator(}) + ident(run_hook) string<delimiter(')content(post-setup)delimiter(')> + reserved(end) + + reserved(def) method(exec_install) + ident(run_hook) string<delimiter(')content(pre-install)delimiter(')> + ident(each_selected_installers) operator({)operator(|)ident(inst)operator(|) ident(inst)operator(.)ident(exec_install) operator(}) + ident(run_hook) string<delimiter(')content(post-install)delimiter(')> + reserved(end) + + reserved(def) method(exec_clean) + ident(rm_f) constant(ConfigTable)operator(.)ident(savefile) + ident(run_hook) string<delimiter(')content(pre-clean)delimiter(')> + ident(each_selected_installers) operator({)operator(|)ident(inst)operator(|) ident(inst)operator(.)ident(exec_clean) operator(}) + ident(run_hook) string<delimiter(')content(post-clean)delimiter(')> + reserved(end) + + reserved(def) method(exec_distclean) + ident(rm_f) constant(ConfigTable)operator(.)ident(savefile) + ident(run_hook) string<delimiter(')content(pre-distclean)delimiter(')> + ident(each_selected_installers) operator({)operator(|)ident(inst)operator(|) ident(inst)operator(.)ident(exec_distclean) operator(}) + ident(run_hook) string<delimiter(')content(post-distclean)delimiter(')> + reserved(end) + + comment(#) + comment(# lib) + comment(#) + + reserved(def) method(each_selected_installers) + constant(Dir)operator(.)ident(mkdir) string<delimiter(')content(packages)delimiter(')> reserved(unless) constant(File)operator(.)ident(dir?)operator(()string<delimiter(')content(packages)delimiter(')>operator(\)) + instance_variable(@selected)operator(.)ident(each) reserved(do) operator(|)ident(pack)operator(|) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(Processing the package `)inline<inline_delimiter(#{)ident(pack)inline_delimiter(})>content(' ...)delimiter(")> reserved(if) instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) + constant(Dir)operator(.)ident(mkdir) string<delimiter(")content(packages/)inline<inline_delimiter(#{)ident(pack)inline_delimiter(})>delimiter(")> reserved(unless) constant(File)operator(.)ident(dir?)operator(()string<delimiter(")content(packages/)inline<inline_delimiter(#{)ident(pack)inline_delimiter(})>delimiter(")>operator(\)) + constant(Dir)operator(.)ident(chdir) string<delimiter(")content(packages/)inline<inline_delimiter(#{)ident(pack)inline_delimiter(})>delimiter(")> + reserved(yield) instance_variable(@installers)operator([)ident(pack)operator(]) + constant(Dir)operator(.)ident(chdir) string<delimiter(')content(../..)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(verbose?) + instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(no_harm?) + instance_variable(@options)operator([)string<delimiter(')content(no-harm)delimiter(')>operator(]) + reserved(end) + +reserved(end) + + +reserved(class) class(Installer) + + constant(FILETYPES) operator(=) string<delimiter(%w()content( bin lib ext data )delimiter(\))> + + ident(include) constant(HookScriptAPI) + ident(include) constant(HookUtils) + ident(include) constant(FileOperations) + + reserved(def) method(initialize)operator(()ident(config)operator(,) ident(opt)operator(,) ident(srcroot)operator(,) ident(objroot)operator(\)) + instance_variable(@config) operator(=) ident(config) + instance_variable(@options) operator(=) ident(opt) + instance_variable(@srcdir) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(srcroot)operator(\)) + instance_variable(@objdir) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(objroot)operator(\)) + instance_variable(@currdir) operator(=) string<delimiter(')content(.)delimiter(')> + reserved(end) + + reserved(def) method(inspect) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content( )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename)operator(()instance_variable(@srcdir)operator(\))inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + comment(#) + comment(# Hook Script API base methods) + comment(#) + + reserved(def) method(srcdir_root) + instance_variable(@srcdir) + reserved(end) + + reserved(def) method(objdir_root) + instance_variable(@objdir) + reserved(end) + + reserved(def) method(relpath) + instance_variable(@currdir) + reserved(end) + + comment(#) + comment(# configs/options) + comment(#) + + reserved(def) method(no_harm?) + instance_variable(@options)operator([)string<delimiter(')content(no-harm)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(verbose?) + instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(verbose_off) + reserved(begin) + ident(save)operator(,) instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) operator(=) instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(])operator(,) pre_constant(false) + reserved(yield) + reserved(ensure) + instance_variable(@options)operator([)string<delimiter(')content(verbose)delimiter(')>operator(]) operator(=) ident(save) + reserved(end) + reserved(end) + + comment(#) + comment(# TASK config) + comment(#) + + reserved(def) method(exec_config) + ident(exec_task_traverse) string<delimiter(')content(config)delimiter(')> + reserved(end) + + reserved(def) method(config_dir_bin)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(config_dir_lib)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(config_dir_ext)operator(()ident(rel)operator(\)) + ident(extconf) reserved(if) ident(extdir?)operator(()ident(curr_srcdir)operator(()operator(\))operator(\)) + reserved(end) + + reserved(def) method(extconf) + ident(opt) operator(=) instance_variable(@options)operator([)string<delimiter(')content(config-opt)delimiter(')>operator(])operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\)) + ident(command) string<delimiter(")inline<inline_delimiter(#{)ident(config)operator(()string<delimiter(')content(rubyprog)delimiter(')>operator(\))inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(curr_srcdir)operator(()operator(\))inline_delimiter(})>content(/extconf.rb )inline<inline_delimiter(#{)ident(opt)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(config_dir_data)operator(()ident(rel)operator(\)) + reserved(end) + + comment(#) + comment(# TASK setup) + comment(#) + + reserved(def) method(exec_setup) + ident(exec_task_traverse) string<delimiter(')content(setup)delimiter(')> + reserved(end) + + reserved(def) method(setup_dir_bin)operator(()ident(rel)operator(\)) + ident(all_files_in)operator(()ident(curr_srcdir)operator(()operator(\))operator(\))operator(.)ident(each) reserved(do) operator(|)ident(fname)operator(|) + ident(adjust_shebang) string<delimiter(")inline<inline_delimiter(#{)ident(curr_srcdir)operator(()operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(fname)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(adjust_shebang)operator(()ident(path)operator(\)) + reserved(return) reserved(if) ident(no_harm?) + ident(tmpfile) operator(=) constant(File)operator(.)ident(basename)operator(()ident(path)operator(\)) operator(+) string<delimiter(')content(.tmp)delimiter(')> + reserved(begin) + constant(File)operator(.)ident(open)operator(()ident(path)operator(,) string<delimiter(')content(rb)delimiter(')>operator(\)) operator({)operator(|)ident(r)operator(|) + ident(first) operator(=) ident(r)operator(.)ident(gets) + reserved(return) reserved(unless) constant(File)operator(.)ident(basename)operator(()ident(config)operator(()string<delimiter(')content(rubypath)delimiter(')>operator(\))operator(\)) operator(==) string<delimiter(')content(ruby)delimiter(')> + reserved(return) reserved(unless) constant(File)operator(.)ident(basename)operator(()ident(first)operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)char(\\#)content(!)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(split)operator([)integer(0)operator(])operator(\)) operator(==) string<delimiter(')content(ruby)delimiter(')> + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(adjusting shebang: )inline<inline_delimiter(#{)constant(File)operator(.)ident(basename)operator(()ident(path)operator(\))inline_delimiter(})>delimiter(")> reserved(if) ident(verbose?) + constant(File)operator(.)ident(open)operator(()ident(tmpfile)operator(,) string<delimiter(')content(wb)delimiter(')>operator(\)) operator({)operator(|)ident(w)operator(|) + ident(w)operator(.)ident(print) ident(first)operator(.)ident(sub)operator(()regexp<delimiter(/)char(\\A)char(\\#)content(!)char(\\s)content(*)char(\\S)content(+)delimiter(/)>operator(,) string<delimiter(')content(#! )delimiter(')> operator(+) ident(config)operator(()string<delimiter(')content(rubypath)delimiter(')>operator(\))operator(\)) + ident(w)operator(.)ident(write) ident(r)operator(.)ident(read) + operator(}) + ident(move_file) ident(tmpfile)operator(,) constant(File)operator(.)ident(basename)operator(()ident(path)operator(\)) + operator(}) + reserved(ensure) + constant(File)operator(.)ident(unlink) ident(tmpfile) reserved(if) constant(File)operator(.)ident(exist?)operator(()ident(tmpfile)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(setup_dir_lib)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(setup_dir_ext)operator(()ident(rel)operator(\)) + ident(make) reserved(if) ident(extdir?)operator(()ident(curr_srcdir)operator(()operator(\))operator(\)) + reserved(end) + + reserved(def) method(setup_dir_data)operator(()ident(rel)operator(\)) + reserved(end) + + comment(#) + comment(# TASK install) + comment(#) + + reserved(def) method(exec_install) + ident(rm_f) string<delimiter(')content(InstalledFiles)delimiter(')> + ident(exec_task_traverse) string<delimiter(')content(install)delimiter(')> + reserved(end) + + reserved(def) method(install_dir_bin)operator(()ident(rel)operator(\)) + ident(install_files) ident(collect_filenames_auto)operator(()operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(config)operator(()string<delimiter(')content(bindir)delimiter(')>operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(rel)inline_delimiter(})>delimiter(")>operator(,) integer(0755) + reserved(end) + + reserved(def) method(install_dir_lib)operator(()ident(rel)operator(\)) + ident(install_files) ident(ruby_scripts)operator(()operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(config)operator(()string<delimiter(')content(rbdir)delimiter(')>operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(rel)inline_delimiter(})>delimiter(")>operator(,) integer(0644) + reserved(end) + + reserved(def) method(install_dir_ext)operator(()ident(rel)operator(\)) + reserved(return) reserved(unless) ident(extdir?)operator(()ident(curr_srcdir)operator(()operator(\))operator(\)) + ident(install_files) ident(ruby_extentions)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(,) + string<delimiter(")inline<inline_delimiter(#{)ident(config)operator(()string<delimiter(')content(sodir)delimiter(')>operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()ident(rel)operator(\))inline_delimiter(})>delimiter(")>operator(,) + integer(0555) + reserved(end) + + reserved(def) method(install_dir_data)operator(()ident(rel)operator(\)) + ident(install_files) ident(collect_filenames_auto)operator(()operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(config)operator(()string<delimiter(')content(datadir)delimiter(')>operator(\))inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(rel)inline_delimiter(})>delimiter(")>operator(,) integer(0644) + reserved(end) + + reserved(def) method(install_files)operator(()ident(list)operator(,) ident(dest)operator(,) ident(mode)operator(\)) + ident(mkdir_p) ident(dest)operator(,) instance_variable(@options)operator([)string<delimiter(')content(install-prefix)delimiter(')>operator(]) + ident(list)operator(.)ident(each) reserved(do) operator(|)ident(fname)operator(|) + ident(install) ident(fname)operator(,) ident(dest)operator(,) ident(mode)operator(,) instance_variable(@options)operator([)string<delimiter(')content(install-prefix)delimiter(')>operator(]) + reserved(end) + reserved(end) + + reserved(def) method(ruby_scripts) + ident(collect_filenames_auto)operator(()operator(\))operator(.)ident(select) operator({)operator(|)ident(n)operator(|) regexp<delimiter(/)char(\\.)content(rb)char(\\z)delimiter(/)> operator(=)operator(~) ident(n) operator(}) + reserved(end) + + comment(# picked up many entries from cvs-1.11.1/src/ignore.c) + ident(reject_patterns) operator(=) string<delimiter(%w()content( + core RCSLOG tags TAGS .make.state + .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb + *~ *.old *.bak *.BAK *.orig *.rej _$* *$ + + *.org *.in .* + )delimiter(\))> + ident(mapping) operator(=) operator({) + string<delimiter(')content(.)delimiter(')> operator(=)operator(>) string<delimiter(')content(\\.)delimiter(')>operator(,) + string<delimiter(')content($)delimiter(')> operator(=)operator(>) string<delimiter(')content(\\$)delimiter(')>operator(,) + string<delimiter(')content(#)delimiter(')> operator(=)operator(>) string<delimiter(')content(\\#)delimiter(')>operator(,) + string<delimiter(')content(*)delimiter(')> operator(=)operator(>) string<delimiter(')content(.*)delimiter(')> + operator(}) + constant(REJECT_PATTERNS) operator(=) constant(Regexp)operator(.)ident(new)operator(()string<delimiter(')content(\\A)content((?:)delimiter(')> operator(+) + ident(reject_patterns)operator(.)ident(map) operator({)operator(|)ident(pat)operator(|) + ident(pat)operator(.)ident(gsub)operator(()regexp<delimiter(/)content([)char(\\.)char(\\$)char(\\#)char(\\*)content(])delimiter(/)>operator(\)) operator({)operator(|)ident(ch)operator(|) ident(mapping)operator([)ident(ch)operator(]) operator(}) + operator(})operator(.)ident(join)operator(()string<delimiter(')content(|)delimiter(')>operator(\)) operator(+) + string<delimiter(')content(\))content(\\z)delimiter(')>operator(\)) + + reserved(def) method(collect_filenames_auto) + ident(mapdir)operator(()operator(()ident(existfiles)operator(()operator(\)) operator(-) ident(hookfiles)operator(()operator(\))operator(\))operator(.)ident(reject) operator({)operator(|)ident(fname)operator(|) + constant(REJECT_PATTERNS) operator(=)operator(~) ident(fname) + operator(})operator(\)) + reserved(end) + + reserved(def) method(existfiles) + ident(all_files_in)operator(()ident(curr_srcdir)operator(()operator(\))operator(\)) operator(|) ident(all_files_in)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(hookfiles) + string<delimiter(%w()content( pre-%s post-%s pre-%s.rb post-%s.rb )delimiter(\))>operator(.)ident(map) operator({)operator(|)ident(fmt)operator(|) + string<delimiter(%w()content( config setup install clean )delimiter(\))>operator(.)ident(map) operator({)operator(|)ident(t)operator(|) ident(sprintf)operator(()ident(fmt)operator(,) ident(t)operator(\)) operator(}) + operator(})operator(.)ident(flatten) + reserved(end) + + reserved(def) method(mapdir)operator(()ident(filelist)operator(\)) + ident(filelist)operator(.)ident(map) operator({)operator(|)ident(fname)operator(|) + reserved(if) constant(File)operator(.)ident(exist?)operator(()ident(fname)operator(\)) comment(# objdir) + ident(fname) + reserved(else) comment(# srcdir) + constant(File)operator(.)ident(join)operator(()ident(curr_srcdir)operator(()operator(\))operator(,) ident(fname)operator(\)) + reserved(end) + operator(}) + reserved(end) + + reserved(def) method(ruby_extentions)operator(()ident(dir)operator(\)) + constant(Dir)operator(.)ident(open)operator(()ident(dir)operator(\)) operator({)operator(|)ident(d)operator(|) + ident(ents) operator(=) ident(d)operator(.)ident(select) operator({)operator(|)ident(fname)operator(|) regexp<delimiter(/)char(\\.)inline<inline_delimiter(#{)operator(::)constant(Config)operator(::)constant(CONFIG)operator([)string<delimiter(')content(DLEXT)delimiter(')>operator(])inline_delimiter(})>char(\\z)delimiter(/)> operator(=)operator(~) ident(fname) operator(}) + reserved(if) ident(ents)operator(.)ident(empty?) + ident(setup_rb_error) string<delimiter(")content(no ruby extention exists: 'ruby )inline<inline_delimiter(#{)global_variable($0)inline_delimiter(})>content( setup' first)delimiter(")> + reserved(end) + reserved(return) ident(ents) + operator(}) + reserved(end) + + comment(#) + comment(# TASK clean) + comment(#) + + reserved(def) method(exec_clean) + ident(exec_task_traverse) string<delimiter(')content(clean)delimiter(')> + ident(rm_f) constant(ConfigTable)operator(.)ident(savefile) + ident(rm_f) string<delimiter(')content(InstalledFiles)delimiter(')> + reserved(end) + + reserved(def) method(clean_dir_bin)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(clean_dir_lib)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(clean_dir_ext)operator(()ident(rel)operator(\)) + reserved(return) reserved(unless) ident(extdir?)operator(()ident(curr_srcdir)operator(()operator(\))operator(\)) + ident(make) string<delimiter(')content(clean)delimiter(')> reserved(if) constant(File)operator(.)ident(file?)operator(()string<delimiter(')content(Makefile)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(clean_dir_data)operator(()ident(rel)operator(\)) + reserved(end) + + comment(#) + comment(# TASK distclean) + comment(#) + + reserved(def) method(exec_distclean) + ident(exec_task_traverse) string<delimiter(')content(distclean)delimiter(')> + ident(rm_f) constant(ConfigTable)operator(.)ident(savefile) + ident(rm_f) string<delimiter(')content(InstalledFiles)delimiter(')> + reserved(end) + + reserved(def) method(distclean_dir_bin)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(distclean_dir_lib)operator(()ident(rel)operator(\)) + reserved(end) + + reserved(def) method(distclean_dir_ext)operator(()ident(rel)operator(\)) + reserved(return) reserved(unless) ident(extdir?)operator(()ident(curr_srcdir)operator(()operator(\))operator(\)) + ident(make) string<delimiter(')content(distclean)delimiter(')> reserved(if) constant(File)operator(.)ident(file?)operator(()string<delimiter(')content(Makefile)delimiter(')>operator(\)) + reserved(end) + + comment(#) + comment(# lib) + comment(#) + + reserved(def) method(exec_task_traverse)operator(()ident(task)operator(\)) + ident(run_hook) string<delimiter(")content(pre-)inline<inline_delimiter(#{)ident(task)inline_delimiter(})>delimiter(")> + constant(FILETYPES)operator(.)ident(each) reserved(do) operator(|)ident(type)operator(|) + reserved(if) ident(config)operator(()string<delimiter(')content(without-ext)delimiter(')>operator(\)) operator(==) string<delimiter(')content(yes)delimiter(')> reserved(and) ident(type) operator(==) string<delimiter(')content(ext)delimiter(')> + global_variable($stderr)operator(.)ident(puts) string<delimiter(')content(skipping ext/* by user option)delimiter(')> reserved(if) ident(verbose?) + reserved(next) + reserved(end) + ident(traverse) ident(task)operator(,) ident(type)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(task)inline_delimiter(})>content(_dir_)inline<inline_delimiter(#{)ident(type)inline_delimiter(})>delimiter(")> + reserved(end) + ident(run_hook) string<delimiter(")content(post-)inline<inline_delimiter(#{)ident(task)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(traverse)operator(()ident(task)operator(,) ident(rel)operator(,) ident(mid)operator(\)) + ident(dive_into)operator(()ident(rel)operator(\)) operator({) + ident(run_hook) string<delimiter(")content(pre-)inline<inline_delimiter(#{)ident(task)inline_delimiter(})>delimiter(")> + ident(__send__) ident(mid)operator(,) ident(rel)operator(.)ident(sub)operator(()regexp<delimiter(%r[)char(\\A)content(.*?(?:/|)char(\\z)content(\))delimiter(])>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(all_dirs_in)operator(()ident(curr_srcdir)operator(()operator(\))operator(\))operator(.)ident(each) reserved(do) operator(|)ident(d)operator(|) + ident(traverse) ident(task)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(rel)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(d)inline_delimiter(})>delimiter(")>operator(,) ident(mid) + reserved(end) + ident(run_hook) string<delimiter(")content(post-)inline<inline_delimiter(#{)ident(task)inline_delimiter(})>delimiter(")> + operator(}) + reserved(end) + + reserved(def) method(dive_into)operator(()ident(rel)operator(\)) + reserved(return) reserved(unless) constant(File)operator(.)ident(dir?)operator(()string<delimiter(")inline<inline_delimiter(#{)instance_variable(@srcdir)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(rel)inline_delimiter(})>delimiter(")>operator(\)) + + ident(dir) operator(=) constant(File)operator(.)ident(basename)operator(()ident(rel)operator(\)) + constant(Dir)operator(.)ident(mkdir) ident(dir) reserved(unless) constant(File)operator(.)ident(dir?)operator(()ident(dir)operator(\)) + ident(prevdir) operator(=) constant(Dir)operator(.)ident(pwd) + constant(Dir)operator(.)ident(chdir) ident(dir) + global_variable($stderr)operator(.)ident(puts) string<delimiter(')content(---> )delimiter(')> operator(+) ident(rel) reserved(if) ident(verbose?) + instance_variable(@currdir) operator(=) ident(rel) + reserved(yield) + constant(Dir)operator(.)ident(chdir) ident(prevdir) + global_variable($stderr)operator(.)ident(puts) string<delimiter(')content(<--- )delimiter(')> operator(+) ident(rel) reserved(if) ident(verbose?) + instance_variable(@currdir) operator(=) constant(File)operator(.)ident(dirname)operator(()ident(rel)operator(\)) + reserved(end) + +reserved(end) + + +reserved(if) global_variable($0) operator(==) pre_constant(__FILE__) + reserved(begin) + reserved(if) ident(multipackage_install?) + constant(ToplevelInstallerMulti)operator(.)ident(invoke) + reserved(else) + constant(ToplevelInstaller)operator(.)ident(invoke) + reserved(end) + reserved(rescue) constant(SetupError) + ident(raise) reserved(if) global_variable($DEBUG) + global_variable($stderr)operator(.)ident(puts) global_variable($!)operator(.)ident(message) + global_variable($stderr)operator(.)ident(puts) string<delimiter(")content(Try 'ruby )inline<inline_delimiter(#{)global_variable($0)inline_delimiter(})>content( --help' for detailed usage.)delimiter(")> + ident(exit) integer(1) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(webrick)delimiter(')> +ident(require) string<delimiter(')content(webrick/log)delimiter(')> +ident(require) string<delimiter(')content(singleton)delimiter(')> + +reserved(module) class(ClientTest) + reserved(class) class(Person) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:firstnames)operator(,) operator([)symbol(:string)operator(]) + ident(member) symbol(:lastname)operator(,) symbol(:string) + + reserved(def) method(==)operator(()ident(other)operator(\)) + ident(firstnames) operator(==) ident(other)operator(.)ident(firstnames) operator(&&) ident(lastname) operator(==) ident(other)operator(.)ident(lastname) + reserved(end) + reserved(end) + + reserved(class) class(Inner) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:name)operator(,) symbol(:string) + reserved(end) + + reserved(class) class(Outer) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:name)operator(,) symbol(:string) + ident(member) symbol(:inner)operator(,) constant(Inner) + reserved(end) + + reserved(class) class(User) operator(<) constant(ActiveRecord)operator(::)constant(Base) + reserved(end) + + reserved(module) class(Accounting) + reserved(class) class(User) operator(<) constant(ActiveRecord)operator(::)constant(Base) + reserved(end) + reserved(end) + + reserved(class) class(WithModel) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:user)operator(,) constant(User) + ident(member) symbol(:users)operator(,) operator([)constant(User)operator(]) + reserved(end) + + reserved(class) class(WithMultiDimArray) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:pref)operator(,) operator([)operator([)symbol(:string)operator(])operator(]) + reserved(end) + + reserved(class) class(API) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:void) + ident(api_method) symbol(:normal)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(,) symbol(:int)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:array_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Person)operator(])operator(]) + ident(api_method) symbol(:struct_pass)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator([)constant(Person)operator(])operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:bool)operator(]) + ident(api_method) symbol(:nil_struct_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(Person)operator(]) + ident(api_method) symbol(:inner_nil)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(Outer)operator(]) + ident(api_method) symbol(:client_container)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:named_parameters)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:key)operator(=)operator(>)symbol(:string)operator(})operator(,) operator({)symbol(:id)operator(=)operator(>)symbol(:int)operator(})operator(]) + ident(api_method) symbol(:thrower) + ident(api_method) symbol(:user_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(User)operator(]) + ident(api_method) symbol(:with_model_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(WithModel)operator(]) + ident(api_method) symbol(:scoped_model_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(Accounting)operator(::)constant(User)operator(]) + ident(api_method) symbol(:multi_dim_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)constant(WithMultiDimArray)operator(]) + reserved(end) + + reserved(class) class(NullLogOut) + reserved(def) method(<<)operator(()operator(*)ident(args)operator(\))operator(;) reserved(end) + reserved(end) + + reserved(class) class(Container) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_service_api) constant(API) + + ident(attr_accessor) symbol(:value_void) + ident(attr_accessor) symbol(:value_normal) + ident(attr_accessor) symbol(:value_array_return) + ident(attr_accessor) symbol(:value_struct_pass) + ident(attr_accessor) symbol(:value_named_parameters) + + reserved(def) method(initialize) + instance_variable(@session) operator(=) instance_variable(@assigns) operator(=) operator({)operator(}) + instance_variable(@value_void) operator(=) pre_constant(nil) + instance_variable(@value_normal) operator(=) pre_constant(nil) + instance_variable(@value_array_return) operator(=) pre_constant(nil) + instance_variable(@value_struct_pass) operator(=) pre_constant(nil) + instance_variable(@value_named_parameters) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(void) + instance_variable(@value_void) operator(=) instance_variable(@method_params) + reserved(end) + + reserved(def) method(normal) + instance_variable(@value_normal) operator(=) instance_variable(@method_params) + integer(5) + reserved(end) + + reserved(def) method(array_return) + ident(person) operator(=) constant(Person)operator(.)ident(new) + ident(person)operator(.)ident(firstnames) operator(=) operator([)string<delimiter(")content(one)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")>operator(]) + ident(person)operator(.)ident(lastname) operator(=) string<delimiter(")content(last)delimiter(")> + instance_variable(@value_array_return) operator(=) operator([)ident(person)operator(]) + reserved(end) + + reserved(def) method(struct_pass) + instance_variable(@value_struct_pass) operator(=) instance_variable(@method_params) + pre_constant(true) + reserved(end) + + reserved(def) method(nil_struct_return) + pre_constant(nil) + reserved(end) + + reserved(def) method(inner_nil) + constant(Outer)operator(.)ident(new) symbol(:name) operator(=)operator(>) string<delimiter(')content(outer)delimiter(')>operator(,) symbol(:inner) operator(=)operator(>) pre_constant(nil) + reserved(end) + + reserved(def) method(client_container) + integer(50) + reserved(end) + + reserved(def) method(named_parameters) + instance_variable(@value_named_parameters) operator(=) instance_variable(@method_params) + reserved(end) + + reserved(def) method(thrower) + ident(raise) string<delimiter(")content(Hi)delimiter(")> + reserved(end) + + reserved(def) method(user_return) + constant(User)operator(.)ident(find)operator(()integer(1)operator(\)) + reserved(end) + + reserved(def) method(with_model_return) + constant(WithModel)operator(.)ident(new) symbol(:user) operator(=)operator(>) constant(User)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) symbol(:users) operator(=)operator(>) constant(User)operator(.)ident(find)operator(()symbol(:all)operator(\)) + reserved(end) + + reserved(def) method(scoped_model_return) + constant(Accounting)operator(::)constant(User)operator(.)ident(find)operator(()integer(1)operator(\)) + reserved(end) + + reserved(def) method(multi_dim_return) + constant(WithMultiDimArray)operator(.)ident(new) symbol(:pref) operator(=)operator(>) operator([)string<delimiter(%w{)content(pref1 value1)delimiter(})>operator(,) string<delimiter(%w{)content(pref2 value2)delimiter(})>operator(]) + reserved(end) + reserved(end) + + reserved(class) class(AbstractClientLet) operator(<) constant(WEBrick)operator(::)constant(HTTPServlet)operator(::)constant(AbstractServlet) + reserved(def) method(initialize)operator(()ident(controller)operator(\)) + instance_variable(@controller) operator(=) ident(controller) + reserved(end) + + reserved(def) method(get_instance)operator(()operator(*)ident(args)operator(\)) + pre_constant(self) + reserved(end) + + reserved(def) method(require_path_info?) + pre_constant(false) + reserved(end) + + reserved(def) method(do_GET)operator(()ident(req)operator(,) ident(res)operator(\)) + ident(raise) constant(WEBrick)operator(::)constant(HTTPStatus)operator(::)constant(MethodNotAllowed)operator(,) string<delimiter(")content(GET request not allowed.)delimiter(")> + reserved(end) + + reserved(def) method(do_POST)operator(()ident(req)operator(,) ident(res)operator(\)) + ident(raise) constant(NotImplementedError) + reserved(end) + reserved(end) + + reserved(class) class(AbstractServer) + ident(include) constant(ClientTest) + ident(include) constant(Singleton) + ident(attr) symbol(:container) + reserved(def) method(initialize) + instance_variable(@container) operator(=) constant(Container)operator(.)ident(new) + instance_variable(@clientlet) operator(=) ident(create_clientlet)operator(()instance_variable(@container)operator(\)) + ident(log) operator(=) constant(WEBrick)operator(::)constant(BasicLog)operator(.)ident(new)operator(()constant(NullLogOut)operator(.)ident(new)operator(\)) + instance_variable(@server) operator(=) constant(WEBrick)operator(::)constant(HTTPServer)operator(.)ident(new)operator(()symbol(:Port) operator(=)operator(>) ident(server_port)operator(,) symbol(:Logger) operator(=)operator(>) ident(log)operator(,) symbol(:AccessLog) operator(=)operator(>) ident(log)operator(\)) + instance_variable(@server)operator(.)ident(mount)operator(()string<delimiter(')content(/)delimiter(')>operator(,) instance_variable(@clientlet)operator(\)) + instance_variable(@thr) operator(=) constant(Thread)operator(.)ident(new) operator({) instance_variable(@server)operator(.)ident(start) operator(}) + reserved(until) instance_variable(@server)operator(.)ident(status) operator(==) symbol(:Running)operator(;) reserved(end) + ident(at_exit) operator({) instance_variable(@server)operator(.)ident(stop)operator(;) instance_variable(@thr)operator(.)ident(join) operator(}) + reserved(end) + + ident(protected) + reserved(def) method(create_clientlet) + ident(raise) constant(NotImplementedError) + reserved(end) + + reserved(def) method(server_port) + ident(raise) constant(NotImplementedError) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(stringio)delimiter(')> + +reserved(class) class(ActionController::Base)operator(;) reserved(def) method(rescue_action)operator(()ident(e)operator(\)) ident(raise) ident(e) reserved(end)operator(;) reserved(end) + +reserved(module) class(DispatcherTest) + constant(Utf8String) operator(=) string<delimiter(")content(One World Caf)char(\\303)char(\\251)delimiter(")> + constant(WsdlNamespace) operator(=) string<delimiter(')content(http://rubyonrails.com/some/namespace)delimiter(')> + + reserved(class) class(Node) operator(<) constant(ActiveRecord)operator(::)constant(Base) + reserved(def) method(initialize)operator(()operator(*)ident(args)operator(\)) + reserved(super)operator(()operator(*)ident(args)operator(\)) + instance_variable(@new_record) operator(=) pre_constant(false) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(def) method(name) + string<delimiter(")content(DispatcherTest::Node)delimiter(")> + reserved(end) + + reserved(def) method(columns)operator(()operator(*)ident(args)operator(\)) + operator([) + constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(Column)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')>operator(,) integer(0)operator(,) string<delimiter(')content(int)delimiter(')>operator(\))operator(,) + constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(Column)operator(.)ident(new)operator(()string<delimiter(')content(name)delimiter(')>operator(,) pre_constant(nil)operator(,) string<delimiter(')content(string)delimiter(')>operator(\))operator(,) + constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(Column)operator(.)ident(new)operator(()string<delimiter(')content(description)delimiter(')>operator(,) pre_constant(nil)operator(,) string<delimiter(')content(string)delimiter(')>operator(\))operator(,) + operator(]) + reserved(end) + + reserved(def) method(connection) + pre_constant(self) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Person) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:id)operator(,) symbol(:int) + ident(member) symbol(:name)operator(,) symbol(:string) + + reserved(def) method(==)operator(()ident(other)operator(\)) + pre_constant(self)operator(.)ident(id) operator(==) ident(other)operator(.)ident(id) operator(&&) pre_constant(self)operator(.)ident(name) operator(==) ident(other)operator(.)ident(name) + reserved(end) + reserved(end) + + reserved(class) class(API) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:add)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(,) symbol(:int)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:interceptee) + ident(api_method) symbol(:struct_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Node)operator(])operator(]) + ident(api_method) symbol(:void) + reserved(end) + + reserved(class) class(DirectAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:add)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:a)operator(=)operator(>)symbol(:int)operator(})operator(,) operator({)symbol(:b)operator(=)operator(>)symbol(:int)operator(})operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:add2)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:a)operator(=)operator(>)symbol(:int)operator(})operator(,) operator({)symbol(:b)operator(=)operator(>)symbol(:int)operator(})operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:before_filtered) + ident(api_method) symbol(:after_filtered)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)symbol(:int)operator(])operator(]) + ident(api_method) symbol(:struct_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Node)operator(])operator(]) + ident(api_method) symbol(:struct_pass)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:person) operator(=)operator(>) constant(Person)operator(})operator(]) + ident(api_method) symbol(:base_struct_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Person)operator(])operator(]) + ident(api_method) symbol(:hash_struct_return)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(Person)operator(])operator(]) + ident(api_method) symbol(:thrower) + ident(api_method) symbol(:void) + ident(api_method) symbol(:test_utf8)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:hex)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:base64)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:unhex)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:string)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:base64)operator(]) + ident(api_method) symbol(:time)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:time)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:time)operator(]) + reserved(end) + + reserved(class) class(VirtualAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(default_api_method) symbol(:fallback) + reserved(end) + + reserved(class) class(Service) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(API) + + ident(before_invocation) symbol(:do_intercept)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:interceptee)operator(]) + + ident(attr) symbol(:added) + ident(attr) symbol(:intercepted) + ident(attr) symbol(:void_called) + + reserved(def) method(initialize) + instance_variable(@void_called) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(add)operator(()ident(a)operator(,) ident(b)operator(\)) + instance_variable(@added) operator(=) ident(a) operator(+) ident(b) + reserved(end) + + reserved(def) method(interceptee) + instance_variable(@intercepted) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(struct_return) + ident(n1) operator(=) constant(Node)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(1)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(node1)delimiter(')>operator(,) string<delimiter(')content(description)delimiter(')> operator(=)operator(>) string<delimiter(')content(Node 1)delimiter(')>operator(\)) + ident(n2) operator(=) constant(Node)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(2)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(node2)delimiter(')>operator(,) string<delimiter(')content(description)delimiter(')> operator(=)operator(>) string<delimiter(')content(Node 2)delimiter(')>operator(\)) + operator([)ident(n1)operator(,) ident(n2)operator(]) + reserved(end) + + reserved(def) method(void)operator(()operator(*)ident(args)operator(\)) + instance_variable(@void_called) operator(=) ident(args) + reserved(end) + + reserved(def) method(do_intercept)operator(()ident(name)operator(,) ident(args)operator(\)) + operator([)pre_constant(false)operator(,) string<delimiter(")content(permission denied)delimiter(")>operator(]) + reserved(end) + reserved(end) + + reserved(class) class(MTAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + ident(api_method) symbol(:getCategories)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)symbol(:string)operator(])operator(]) + ident(api_method) symbol(:bool)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:bool)operator(]) + ident(api_method) symbol(:alwaysFail) + reserved(end) + + reserved(class) class(BloggerAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + ident(api_method) symbol(:getCategories)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)symbol(:string)operator(])operator(]) + ident(api_method) symbol(:str)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:alwaysFail) + reserved(end) + + reserved(class) class(MTService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(MTAPI) + + reserved(def) method(getCategories) + operator([)string<delimiter(")content(mtCat1)delimiter(")>operator(,) string<delimiter(")content(mtCat2)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(bool) + string<delimiter(')content(y)delimiter(')> + reserved(end) + + reserved(def) method(alwaysFail) + ident(raise) string<delimiter(")content(MT AlwaysFail)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(BloggerService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(BloggerAPI) + + reserved(def) method(getCategories) + operator([)string<delimiter(")content(bloggerCat1)delimiter(")>operator(,) string<delimiter(")content(bloggerCat2)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(str)operator(()ident(int)operator(\)) + reserved(unless) ident(int)operator(.)ident(is_a?)operator(()constant(Integer)operator(\)) + ident(raise) string<delimiter(")content(Not an integer!)delimiter(")> + reserved(end) + integer(500) operator(+) ident(int) + reserved(end) + + reserved(def) method(alwaysFail) + ident(raise) string<delimiter(")content(Blogger AlwaysFail)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(AbstractController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(generate_wsdl) + instance_variable(@request) operator(||=) operator(::)constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(to_wsdl) + reserved(end) + reserved(end) + + reserved(class) class(DelegatedController) operator(<) constant(AbstractController) + ident(web_service_dispatching_mode) symbol(:delegated) + ident(wsdl_namespace) constant(WsdlNamespace) + + ident(web_service)operator(()symbol(:test_service)operator(\)) operator({) instance_variable(@service) operator(||=) constant(Service)operator(.)ident(new)operator(;) instance_variable(@service) operator(}) + reserved(end) + + reserved(class) class(LayeredController) operator(<) constant(AbstractController) + ident(web_service_dispatching_mode) symbol(:layered) + ident(wsdl_namespace) constant(WsdlNamespace) + + ident(web_service)operator(()symbol(:mt)operator(\)) operator({) instance_variable(@mt_service) operator(||=) constant(MTService)operator(.)ident(new)operator(;) instance_variable(@mt_service) operator(}) + ident(web_service)operator(()symbol(:blogger)operator(\)) operator({) instance_variable(@blogger_service) operator(||=) constant(BloggerService)operator(.)ident(new)operator(;) instance_variable(@blogger_service) operator(}) + reserved(end) + + reserved(class) class(DirectController) operator(<) constant(AbstractController) + ident(web_service_api) constant(DirectAPI) + ident(web_service_dispatching_mode) symbol(:direct) + ident(wsdl_namespace) constant(WsdlNamespace) + + ident(before_invocation) symbol(:alwaysfail)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:before_filtered)operator(]) + ident(after_invocation) symbol(:alwaysok)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:after_filtered)operator(]) + + ident(attr) symbol(:added) + ident(attr) symbol(:added2) + ident(attr) symbol(:before_filter_called) + ident(attr) symbol(:before_filter_target_called) + ident(attr) symbol(:after_filter_called) + ident(attr) symbol(:after_filter_target_called) + ident(attr) symbol(:void_called) + ident(attr) symbol(:struct_pass_value) + + reserved(def) method(initialize) + instance_variable(@before_filter_called) operator(=) pre_constant(false) + instance_variable(@before_filter_target_called) operator(=) pre_constant(false) + instance_variable(@after_filter_called) operator(=) pre_constant(false) + instance_variable(@after_filter_target_called) operator(=) pre_constant(false) + instance_variable(@void_called) operator(=) pre_constant(false) + instance_variable(@struct_pass_value) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(add) + instance_variable(@added) operator(=) instance_variable(@params)operator([)string<delimiter(')content(a)delimiter(')>operator(]) operator(+) instance_variable(@params)operator([)string<delimiter(')content(b)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(add2)operator(()ident(a)operator(,) ident(b)operator(\)) + instance_variable(@added2) operator(=) ident(a) operator(+) ident(b) + reserved(end) + + reserved(def) method(before_filtered) + instance_variable(@before_filter_target_called) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(after_filtered) + instance_variable(@after_filter_target_called) operator(=) pre_constant(true) + operator([)integer(5)operator(,) integer(6)operator(,) integer(7)operator(]) + reserved(end) + + reserved(def) method(thrower) + ident(raise) string<delimiter(")content(Hi, I'm an exception)delimiter(")> + reserved(end) + + reserved(def) method(struct_return) + ident(n1) operator(=) constant(Node)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(1)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(node1)delimiter(')>operator(,) string<delimiter(')content(description)delimiter(')> operator(=)operator(>) string<delimiter(')content(Node 1)delimiter(')>operator(\)) + ident(n2) operator(=) constant(Node)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(2)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(node2)delimiter(')>operator(,) string<delimiter(')content(description)delimiter(')> operator(=)operator(>) string<delimiter(')content(Node 2)delimiter(')>operator(\)) + operator([)ident(n1)operator(,) ident(n2)operator(]) + reserved(end) + + reserved(def) method(struct_pass)operator(()ident(person)operator(\)) + instance_variable(@struct_pass_value) operator(=) ident(person) + reserved(end) + + reserved(def) method(base_struct_return) + ident(p1) operator(=) constant(Person)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(1)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(person1)delimiter(')>operator(\)) + ident(p2) operator(=) constant(Person)operator(.)ident(new)operator(()string<delimiter(')content(id)delimiter(')> operator(=)operator(>) integer(2)operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(person2)delimiter(')>operator(\)) + operator([)ident(p1)operator(,) ident(p2)operator(]) + reserved(end) + + reserved(def) method(hash_struct_return) + ident(p1) operator(=) operator({) symbol(:id) operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(test)delimiter(')> operator(}) + ident(p2) operator(=) operator({) string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(person2)delimiter(')> operator(}) + operator([)ident(p1)operator(,) ident(p2)operator(]) + reserved(end) + + reserved(def) method(void) + instance_variable(@void_called) operator(=) instance_variable(@method_params) + reserved(end) + + reserved(def) method(test_utf8) + constant(Utf8String) + reserved(end) + + reserved(def) method(hex)operator(()ident(s)operator(\)) + reserved(return) ident(s)operator(.)ident(unpack)operator(()string<delimiter(")content(H*)delimiter(")>operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(unhex)operator(()ident(s)operator(\)) + reserved(return) operator([)ident(s)operator(])operator(.)ident(pack)operator(()string<delimiter(")content(H*)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(time)operator(()ident(t)operator(\)) + ident(t) + reserved(end) + + ident(protected) + reserved(def) method(alwaysfail)operator(()ident(method_name)operator(,) ident(params)operator(\)) + instance_variable(@before_filter_called) operator(=) pre_constant(true) + pre_constant(false) + reserved(end) + + reserved(def) method(alwaysok)operator(()ident(method_name)operator(,) ident(params)operator(,) ident(return_value)operator(\)) + instance_variable(@after_filter_called) operator(=) pre_constant(true) + reserved(end) + reserved(end) + + reserved(class) class(VirtualController) operator(<) constant(AbstractController) + ident(web_service_api) constant(VirtualAPI) + ident(wsdl_namespace) constant(WsdlNamespace) + + reserved(def) method(fallback) + string<delimiter(")content(fallback!)delimiter(")> + reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(DispatcherCommonTests) + reserved(def) method(test_direct_dispatching) + ident(assert_equal)operator(()integer(70)operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Add)delimiter(')>operator(,) integer(20)operator(,) integer(50)operator(\))operator(\)) + ident(assert_equal)operator(()integer(70)operator(,) instance_variable(@direct_controller)operator(.)ident(added)operator(\)) + ident(assert_equal)operator(()integer(50)operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Add2)delimiter(')>operator(,) integer(25)operator(,) integer(25)operator(\))operator(\)) + ident(assert_equal)operator(()integer(50)operator(,) instance_variable(@direct_controller)operator(.)ident(added2)operator(\)) + ident(assert)operator(()instance_variable(@direct_controller)operator(.)ident(void_called) operator(==) pre_constant(false)operator(\)) + ident(assert)operator(()ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Void)delimiter(')>operator(,) integer(3)operator(,) integer(4)operator(,) integer(5)operator(\))operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@direct_controller)operator(.)ident(void_called) operator(==) operator([)operator(])operator(\)) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(BaseStructReturn)delimiter(')>operator(\)) + ident(assert)operator(()ident(result)operator([)integer(0)operator(])operator(.)ident(is_a?)operator(()constant(DispatcherTest)operator(::)constant(Person)operator(\))operator(\)) + ident(assert)operator(()ident(result)operator([)integer(1)operator(])operator(.)ident(is_a?)operator(()constant(DispatcherTest)operator(::)constant(Person)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(cafe)delimiter(")>operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Hex)delimiter(')>operator(,) string<delimiter(")char(\\xca)char(\\xfe)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")char(\\xca)char(\\xfe)delimiter(")>operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Unhex)delimiter(')>operator(,) string<delimiter(")content(cafe)delimiter(")>operator(\))operator(\)) + ident(time) operator(=) constant(Time)operator(.)ident(gm)operator(()integer(1998)operator(,) string<delimiter(")content(Feb)delimiter(")>operator(,) integer(02)operator(,) integer(15)operator(,) integer(12)operator(,) integer(01)operator(\)) + ident(assert_equal)operator(()ident(time)operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Time)delimiter(')>operator(,) ident(time)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_direct_entrypoint) + ident(assert)operator(()instance_variable(@direct_controller)operator(.)ident(respond_to?)operator(()symbol(:api)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_virtual_dispatching) + ident(assert_equal)operator(()string<delimiter(")content(fallback!)delimiter(")>operator(,) ident(do_method_call)operator(()instance_variable(@virtual_controller)operator(,) string<delimiter(')content(VirtualOne)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(fallback!)delimiter(")>operator(,) ident(do_method_call)operator(()instance_variable(@virtual_controller)operator(,) string<delimiter(')content(VirtualTwo)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_direct_filtering) + ident(assert_equal)operator(()pre_constant(false)operator(,) instance_variable(@direct_controller)operator(.)ident(before_filter_called)operator(\)) + ident(assert_equal)operator(()pre_constant(false)operator(,) instance_variable(@direct_controller)operator(.)ident(before_filter_target_called)operator(\)) + ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(BeforeFiltered)delimiter(')>operator(\)) + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@direct_controller)operator(.)ident(before_filter_called)operator(\)) + ident(assert_equal)operator(()pre_constant(false)operator(,) instance_variable(@direct_controller)operator(.)ident(before_filter_target_called)operator(\)) + ident(assert_equal)operator(()pre_constant(false)operator(,) instance_variable(@direct_controller)operator(.)ident(after_filter_called)operator(\)) + ident(assert_equal)operator(()pre_constant(false)operator(,) instance_variable(@direct_controller)operator(.)ident(after_filter_target_called)operator(\)) + ident(assert_equal)operator(()operator([)integer(5)operator(,) integer(6)operator(,) integer(7)operator(])operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(AfterFiltered)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@direct_controller)operator(.)ident(after_filter_called)operator(\)) + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@direct_controller)operator(.)ident(after_filter_target_called)operator(\)) + reserved(end) + + reserved(def) method(test_delegated_dispatching) + ident(assert_equal)operator(()integer(130)operator(,) ident(do_method_call)operator(()instance_variable(@delegated_controller)operator(,) string<delimiter(')content(Add)delimiter(')>operator(,) integer(50)operator(,) integer(80)operator(\))operator(\)) + ident(service) operator(=) instance_variable(@delegated_controller)operator(.)ident(web_service_object)operator(()symbol(:test_service)operator(\)) + ident(assert_equal)operator(()integer(130)operator(,) ident(service)operator(.)ident(added)operator(\)) + instance_variable(@delegated_controller)operator(.)ident(web_service_exception_reporting) operator(=) pre_constant(true) + ident(assert)operator(()ident(service)operator(.)ident(intercepted)operator(.)ident(nil?)operator(\)) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@delegated_controller)operator(,) string<delimiter(')content(Interceptee)delimiter(')>operator(\)) + ident(assert)operator(()ident(service)operator(.)ident(intercepted)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()ident(is_exception?)operator(()ident(result)operator(\))operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(permission denied)delimiter(/)>operator(,) ident(exception_message)operator(()ident(result)operator(\))operator(\)) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@delegated_controller)operator(,) string<delimiter(')content(NonExistentMethod)delimiter(')>operator(\)) + ident(assert)operator(()ident(is_exception?)operator(()ident(result)operator(\))operator(\)) + ident(assert_match)operator(()regexp<delimiter(/)content(NonExistentMethod)delimiter(/)>operator(,) ident(exception_message)operator(()ident(result)operator(\))operator(\)) + ident(assert)operator(()ident(service)operator(.)ident(void_called) operator(==) pre_constant(false)operator(\)) + ident(assert)operator(()ident(do_method_call)operator(()instance_variable(@delegated_controller)operator(,) string<delimiter(')content(Void)delimiter(')>operator(,) integer(3)operator(,) integer(4)operator(,) integer(5)operator(\))operator(.)ident(nil?)operator(\)) + ident(assert)operator(()ident(service)operator(.)ident(void_called) operator(==) operator([)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_garbage_request) + operator([)instance_variable(@direct_controller)operator(,) instance_variable(@delegated_controller)operator(])operator(.)ident(each) reserved(do) operator(|)ident(controller)operator(|) + ident(controller)operator(.)ident(class)operator(.)ident(web_service_exception_reporting) operator(=) pre_constant(true) + ident(send_garbage_request) operator(=) ident(lambda) reserved(do) + ident(service_name) operator(=) ident(service_name)operator(()ident(controller)operator(\)) + ident(request) operator(=) ident(protocol)operator(.)ident(encode_action_pack_request)operator(()ident(service_name)operator(,) string<delimiter(')content(broken, method, name!)delimiter(')>operator(,) string<delimiter(')content(broken request body)delimiter(')>operator(,) symbol(:request_class) operator(=)operator(>) constant(ActionController)operator(::)constant(TestRequest)operator(\)) + ident(response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + ident(controller)operator(.)ident(process)operator(()ident(request)operator(,) ident(response)operator(\)) + comment(# puts response.body) + ident(assert)operator(()ident(response)operator(.)ident(headers)operator([)string<delimiter(')content(Status)delimiter(')>operator(]) operator(=)operator(~) regexp<delimiter(/)content(^500)delimiter(/)>operator(\)) + reserved(end) + ident(send_garbage_request)operator(.)ident(call) + ident(controller)operator(.)ident(class)operator(.)ident(web_service_exception_reporting) operator(=) pre_constant(false) + ident(send_garbage_request)operator(.)ident(call) + reserved(end) + reserved(end) + + reserved(def) method(test_exception_marshaling) + instance_variable(@direct_controller)operator(.)ident(web_service_exception_reporting) operator(=) pre_constant(true) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Thrower)delimiter(')>operator(\)) + ident(assert)operator(()ident(is_exception?)operator(()ident(result)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(Hi, I'm an exception)delimiter(")>operator(,) ident(exception_message)operator(()ident(result)operator(\))operator(\)) + instance_variable(@direct_controller)operator(.)ident(web_service_exception_reporting) operator(=) pre_constant(false) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Thrower)delimiter(')>operator(\)) + ident(assert)operator(()ident(exception_message)operator(()ident(result)operator(\)) operator(!=) string<delimiter(")content(Hi, I'm an exception)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_ar_struct_return) + operator([)instance_variable(@direct_controller)operator(,) instance_variable(@delegated_controller)operator(])operator(.)ident(each) reserved(do) operator(|)ident(controller)operator(|) + ident(result) operator(=) ident(do_method_call)operator(()ident(controller)operator(,) string<delimiter(')content(StructReturn)delimiter(')>operator(\)) + ident(assert)operator(()ident(result)operator([)integer(0)operator(])operator(.)ident(is_a?)operator(()constant(DispatcherTest)operator(::)constant(Node)operator(\))operator(\)) + ident(assert)operator(()ident(result)operator([)integer(1)operator(])operator(.)ident(is_a?)operator(()constant(DispatcherTest)operator(::)constant(Node)operator(\))operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(node1)delimiter(')>operator(,) ident(result)operator([)integer(0)operator(])operator(.)ident(name)operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(node2)delimiter(')>operator(,) ident(result)operator([)integer(1)operator(])operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_casting) + ident(assert_equal) integer(70)operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(Add)delimiter(')>operator(,) string<delimiter(")content(50)delimiter(")>operator(,) string<delimiter(")content(20)delimiter(")>operator(\)) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@direct_controller)operator(.)ident(struct_pass_value) + ident(person) operator(=) constant(DispatcherTest)operator(::)constant(Person)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(1)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(test)delimiter(')>operator(\)) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(StructPass)delimiter(')>operator(,) ident(person)operator(\)) + ident(assert)operator(()pre_constant(nil) operator(==) ident(result) operator(||) pre_constant(true) operator(==) ident(result)operator(\)) + ident(assert_equal) ident(person)operator(,) instance_variable(@direct_controller)operator(.)ident(struct_pass_value) + ident(assert) operator(!)ident(person)operator(.)ident(equal?)operator(()instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(StructPass)delimiter(')>operator(,) operator({)string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(test)delimiter(')>operator(})operator(\)) + reserved(case) + reserved(when) ident(soap?) + ident(assert_equal)operator(()ident(person)operator(,) instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + ident(assert) operator(!)ident(person)operator(.)ident(equal?)operator(()instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + reserved(when) ident(xmlrpc?) + ident(assert_equal)operator(()ident(person)operator(,) instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + ident(assert) operator(!)ident(person)operator(.)ident(equal?)operator(()instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + reserved(end) + ident(assert_equal) ident(person)operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(HashStructReturn)delimiter(')>operator(\))operator([)integer(0)operator(]) + ident(result) operator(=) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(StructPass)delimiter(')>operator(,) operator({)string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(test)delimiter(')>operator(,) string<delimiter(')content(nonexistent_attribute)delimiter(')> operator(=)operator(>) string<delimiter(')content(value)delimiter(')>operator(})operator(\)) + reserved(case) + reserved(when) ident(soap?) + ident(assert_equal)operator(()ident(person)operator(,) instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + ident(assert) operator(!)ident(person)operator(.)ident(equal?)operator(()instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + reserved(when) ident(xmlrpc?) + ident(assert_equal)operator(()ident(person)operator(,) instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + ident(assert) operator(!)ident(person)operator(.)ident(equal?)operator(()instance_variable(@direct_controller)operator(.)ident(struct_pass_value)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_logging) + ident(buf) operator(=) string<delimiter(")delimiter(")> + constant(ActionController)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()constant(StringIO)operator(.)ident(new)operator(()ident(buf)operator(\))operator(\)) + ident(test_casting) + ident(test_garbage_request) + ident(test_exception_marshaling) + constant(ActionController)operator(::)constant(Base)operator(.)ident(logger) operator(=) pre_constant(nil) + ident(assert_match) regexp<delimiter(/)content(Web Service Response)delimiter(/)>operator(,) ident(buf) + ident(assert_match) regexp<delimiter(/)content(Web Service Request)delimiter(/)>operator(,) ident(buf) + reserved(end) + + ident(protected) + reserved(def) method(service_name)operator(()ident(container)operator(\)) + ident(raise) constant(NotImplementedError) + reserved(end) + + reserved(def) method(exception_message)operator(()ident(obj)operator(\)) + ident(raise) constant(NotImplementedError) + reserved(end) + + reserved(def) method(is_exception?)operator(()ident(obj)operator(\)) + ident(raise) constant(NotImplementedError) + reserved(end) + + reserved(def) method(protocol) + instance_variable(@protocol) + reserved(end) + + reserved(def) method(soap?) + ident(protocol)operator(.)ident(is_a?) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol) + reserved(end) + + reserved(def) method(xmlrpc?) + ident(protocol)operator(.)ident(is_a?) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol) + reserved(end) + + reserved(def) method(do_method_call)operator(()ident(container)operator(,) ident(public_method_name)operator(,) operator(*)ident(params)operator(\)) + ident(request_env) operator(=) operator({)operator(}) + ident(mode) operator(=) ident(container)operator(.)ident(web_service_dispatching_mode) + reserved(case) ident(mode) + reserved(when) symbol(:direct) + ident(service_name) operator(=) ident(service_name)operator(()ident(container)operator(\)) + ident(api) operator(=) ident(container)operator(.)ident(class)operator(.)ident(web_service_api) + ident(method) operator(=) ident(api)operator(.)ident(public_api_method_instance)operator(()ident(public_method_name)operator(\)) + reserved(when) symbol(:delegated) + ident(service_name) operator(=) ident(service_name)operator(()ident(container)operator(\)) + ident(api) operator(=) ident(container)operator(.)ident(web_service_object)operator(()ident(service_name)operator(\))operator(.)ident(class)operator(.)ident(web_service_api) + ident(method) operator(=) ident(api)operator(.)ident(public_api_method_instance)operator(()ident(public_method_name)operator(\)) + reserved(when) symbol(:layered) + ident(service_name) operator(=) pre_constant(nil) + ident(real_method_name) operator(=) pre_constant(nil) + reserved(if) ident(public_method_name) operator(=)operator(~) regexp<delimiter(/)content(^([^)char(\\.)content(]+\))char(\\.)content((.*\)$)delimiter(/)> + ident(service_name) operator(=) global_variable($1) + ident(real_method_name) operator(=) global_variable($2) + reserved(end) + reserved(if) ident(soap?) + ident(public_method_name) operator(=) ident(real_method_name) + ident(request_env)operator([)string<delimiter(')content(HTTP_SOAPACTION)delimiter(')>operator(]) operator(=) string<delimiter(")content(/soap/)inline<inline_delimiter(#{)ident(service_name)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(real_method_name)inline_delimiter(})>delimiter(")> + reserved(end) + ident(api) operator(=) ident(container)operator(.)ident(web_service_object)operator(()ident(service_name)operator(.)ident(to_sym)operator(\))operator(.)ident(class)operator(.)ident(web_service_api) reserved(rescue) pre_constant(nil) + ident(method) operator(=) ident(api)operator(.)ident(public_api_method_instance)operator(()ident(real_method_name)operator(\)) reserved(rescue) pre_constant(nil) + ident(service_name) operator(=) pre_constant(self)operator(.)ident(service_name)operator(()ident(container)operator(\)) + reserved(end) + ident(protocol)operator(.)ident(register_api)operator(()ident(api)operator(\)) + ident(virtual) operator(=) pre_constant(false) + reserved(unless) ident(method) + ident(virtual) operator(=) pre_constant(true) + ident(method) operator(||=) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Method)operator(.)ident(new)operator(()ident(public_method_name)operator(.)ident(underscore)operator(.)ident(to_sym)operator(,) ident(public_method_name)operator(,) pre_constant(nil)operator(,) pre_constant(nil)operator(\)) + reserved(end) + ident(body) operator(=) ident(protocol)operator(.)ident(encode_request)operator(()ident(public_method_name)operator(,) ident(params)operator(.)ident(dup)operator(,) ident(method)operator(.)ident(expects)operator(\)) + comment(# puts body) + ident(ap_request) operator(=) ident(protocol)operator(.)ident(encode_action_pack_request)operator(()ident(service_name)operator(,) ident(public_method_name)operator(,) ident(body)operator(,) symbol(:request_class) operator(=)operator(>) constant(ActionController)operator(::)constant(TestRequest)operator(\)) + ident(ap_request)operator(.)ident(env)operator(.)ident(update)operator(()ident(request_env)operator(\)) + ident(ap_response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + ident(container)operator(.)ident(process)operator(()ident(ap_request)operator(,) ident(ap_response)operator(\)) + comment(# puts ap_response.body) + instance_variable(@response_body) operator(=) ident(ap_response)operator(.)ident(body) + ident(public_method_name)operator(,) ident(return_value) operator(=) ident(protocol)operator(.)ident(decode_response)operator(()ident(ap_response)operator(.)ident(body)operator(\)) + reserved(unless) ident(is_exception?)operator(()ident(return_value)operator(\)) operator(||) ident(virtual) + ident(return_value) operator(=) ident(method)operator(.)ident(cast_returns)operator(()ident(return_value)operator(\)) + reserved(end) + reserved(if) ident(soap?) + comment(# http://dev.rubyonrails.com/changeset/920) + ident(assert_match)operator(()regexp<delimiter(/)content(Response$)delimiter(/)>operator(,) ident(public_method_name)operator(\)) reserved(unless) ident(public_method_name) operator(==) string<delimiter(")content(fault)delimiter(")> + reserved(end) + ident(return_value) + reserved(end) +reserved(end) +constant(ENV)operator([)string<delimiter(")content(RAILS_ENV)delimiter(")>operator(]) operator(=) string<delimiter(")content(test)delimiter(")> +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../lib)delimiter(')>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../activesupport/lib)delimiter(')>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../actionpack/lib)delimiter(')>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../activerecord/lib)delimiter(')>operator(\)) + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(action_web_service)delimiter(')> +ident(require) string<delimiter(')content(action_controller)delimiter(')> +ident(require) string<delimiter(')content(action_controller/test_process)delimiter(')> + +constant(ActionController)operator(::)constant(Base)operator(.)ident(logger) operator(=) pre_constant(nil) +constant(ActionController)operator(::)constant(Base)operator(.)ident(ignore_missing_templates) operator(=) pre_constant(true) + +reserved(begin) + constant(PATH_TO_AR) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../activerecord)delimiter(')> + ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(PATH_TO_AR)inline_delimiter(})>content(/lib/active_record)delimiter(")> reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:ActiveRecord)operator(\)) + ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(PATH_TO_AR)inline_delimiter(})>content(/lib/active_record/fixtures)delimiter(")> reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:Fixtures)operator(\)) +reserved(rescue) constant(Object) operator(=)operator(>) ident(e) + ident(fail) string<delimiter(")char(\\n)content(Failed to load activerecord: )inline<inline_delimiter(#{)ident(e)inline_delimiter(})>delimiter(")> +reserved(end) + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(mysql)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:encoding) operator(=)operator(>) string<delimiter(")content(utf8)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) string<delimiter(")content(activewebservice_unittest)delimiter(")> +operator(\)) +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + +constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase)operator(.)ident(fixture_path) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/)delimiter(")> + +comment(# restore default raw_post functionality) +reserved(class) class(ActionController::TestRequest) + reserved(def) method(raw_post) + reserved(super) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +reserved(module) class(APITest) + reserved(class) class(API) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:void) + ident(api_method) symbol(:expects_and_returns)operator(,) symbol(:expects_and_returns) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:expects)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(,) symbol(:bool)operator(]) + ident(api_method) symbol(:returns)operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(,) operator([)symbol(:string)operator(])operator(]) + ident(api_method) symbol(:named_signature)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:appkey)operator(=)operator(>)symbol(:int)operator(})operator(,) operator({)symbol(:publish)operator(=)operator(>)symbol(:bool)operator(})operator(]) + ident(api_method) symbol(:string_types)operator(,) symbol(:expects) operator(=)operator(>) operator([)string<delimiter(')content(int)delimiter(')>operator(,) string<delimiter(')content(string)delimiter(')>operator(,) string<delimiter(')content(bool)delimiter(')>operator(,) string<delimiter(')content(base64)delimiter(')>operator(]) + ident(api_method) symbol(:class_types)operator(,) symbol(:expects) operator(=)operator(>) operator([)constant(TrueClass)operator(,) constant(Bignum)operator(,) constant(String)operator(]) + reserved(end) +reserved(end) + +reserved(class) class(TC_API) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + constant(API) operator(=) constant(APITest)operator(::)constant(API) + + reserved(def) method(test_api_method_declaration) + string<delimiter(%w()content( + void + expects_and_returns + expects + returns + named_signature + string_types + class_types + )delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(name) operator(=) ident(name)operator(.)ident(to_sym) + ident(public_name) operator(=) constant(API)operator(.)ident(public_api_method_name)operator(()ident(name)operator(\)) + ident(assert)operator(()constant(API)operator(.)ident(has_api_method?)operator(()ident(name)operator(\))operator(\)) + ident(assert)operator(()constant(API)operator(.)ident(has_public_api_method?)operator(()ident(public_name)operator(\))operator(\)) + ident(assert)operator(()constant(API)operator(.)ident(api_method_name)operator(()ident(public_name)operator(\)) operator(==) ident(name)operator(\)) + ident(assert)operator(()constant(API)operator(.)ident(api_methods)operator(.)ident(has_key?)operator(()ident(name)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_signature_canonicalization) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:void)operator(])operator(.)ident(expects)operator(\)) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:void)operator(])operator(.)ident(returns)operator(\)) + ident(assert_equal)operator(()operator([)constant(String)operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:expects_and_returns)operator(])operator(.)ident(expects)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(type_class)operator(})operator(\)) + ident(assert_equal)operator(()operator([)constant(String)operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:expects_and_returns)operator(])operator(.)ident(returns)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(type_class)operator(})operator(\)) + ident(assert_equal)operator(()operator([)constant(Integer)operator(,) constant(TrueClass)operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:expects)operator(])operator(.)ident(expects)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(type_class)operator(})operator(\)) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:expects)operator(])operator(.)ident(returns)operator(\)) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:returns)operator(])operator(.)ident(expects)operator(\)) + ident(assert_equal)operator(()operator([)constant(Integer)operator(,) operator([)constant(String)operator(])operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:returns)operator(])operator(.)ident(returns)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(array?)operator(?) operator([)ident(x)operator(.)ident(element_type)operator(.)ident(type_class)operator(]) operator(:) ident(x)operator(.)ident(type_class)operator(})operator(\)) + ident(assert_equal)operator(()operator([)operator([)symbol(:appkey)operator(,) constant(Integer)operator(])operator(,) operator([)symbol(:publish)operator(,) constant(TrueClass)operator(])operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:named_signature)operator(])operator(.)ident(expects)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) operator([)ident(x)operator(.)ident(name)operator(,) ident(x)operator(.)ident(type_class)operator(])operator(})operator(\)) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:named_signature)operator(])operator(.)ident(returns)operator(\)) + ident(assert_equal)operator(()operator([)constant(Integer)operator(,) constant(String)operator(,) constant(TrueClass)operator(,) constant(ActionWebService)operator(::)constant(Base64)operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:string_types)operator(])operator(.)ident(expects)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(type_class)operator(})operator(\)) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:string_types)operator(])operator(.)ident(returns)operator(\)) + ident(assert_equal)operator(()operator([)constant(TrueClass)operator(,) constant(Integer)operator(,) constant(String)operator(])operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:class_types)operator(])operator(.)ident(expects)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(type_class)operator(})operator(\)) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:class_types)operator(])operator(.)ident(returns)operator(\)) + reserved(end) + + reserved(def) method(test_not_instantiable) + ident(assert_raises)operator(()constant(NoMethodError)operator(\)) reserved(do) + constant(API)operator(.)ident(new) + reserved(end) + reserved(end) + + reserved(def) method(test_api_errors) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(ActionWebServiceError)operator(\)) reserved(do) + ident(klass) operator(=) constant(Class)operator(.)ident(new)operator(()constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base)operator(\)) reserved(do) + ident(api_method) symbol(:test)operator(,) symbol(:expects) operator(=)operator(>) operator([)constant(ActiveRecord)operator(::)constant(Base)operator(]) + reserved(end) + reserved(end) + ident(klass) operator(=) constant(Class)operator(.)ident(new)operator(()constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base)operator(\)) reserved(do) + ident(allow_active_record_expects) pre_constant(true) + ident(api_method) symbol(:test2)operator(,) symbol(:expects) operator(=)operator(>) operator([)constant(ActiveRecord)operator(::)constant(Base)operator(]) + reserved(end) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(ActionWebServiceError)operator(\)) reserved(do) + ident(klass) operator(=) constant(Class)operator(.)ident(new)operator(()constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base)operator(\)) reserved(do) + ident(api_method) symbol(:test)operator(,) symbol(:invalid) operator(=)operator(>) operator([)symbol(:int)operator(]) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_parameter_names) + ident(method) operator(=) constant(API)operator(.)ident(api_methods)operator([)symbol(:named_signature)operator(]) + ident(assert_equal) integer(0)operator(,) ident(method)operator(.)ident(expects_index_of)operator(()symbol(:appkey)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(method)operator(.)ident(expects_index_of)operator(()symbol(:publish)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(method)operator(.)ident(expects_index_of)operator(()string<delimiter(')content(publish)delimiter(')>operator(\)) + ident(assert_equal) integer(0)operator(,) ident(method)operator(.)ident(expects_index_of)operator(()string<delimiter(')content(appkey)delimiter(')>operator(\)) + ident(assert_equal) integer(-1)operator(,) ident(method)operator(.)ident(expects_index_of)operator(()string<delimiter(')content(blah)delimiter(')>operator(\)) + ident(assert_equal) integer(-1)operator(,) ident(method)operator(.)ident(expects_index_of)operator(()symbol(:missing)operator(\)) + ident(assert_equal) integer(-1)operator(,) constant(API)operator(.)ident(api_methods)operator([)symbol(:void)operator(])operator(.)ident(expects_index_of)operator(()string<delimiter(')content(test)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_parameter_hash) + ident(method) operator(=) constant(API)operator(.)ident(api_methods)operator([)symbol(:named_signature)operator(]) + ident(hash) operator(=) ident(method)operator(.)ident(expects_to_hash)operator(()operator([)integer(5)operator(,) pre_constant(false)operator(])operator(\)) + ident(assert_equal)operator(()operator({)symbol(:appkey) operator(=)operator(>) integer(5)operator(,) symbol(:publish) operator(=)operator(>) pre_constant(false)operator(})operator(,) ident(hash)operator(\)) + reserved(end) + + reserved(def) method(test_api_methods_compat) + ident(sig) operator(=) constant(API)operator(.)ident(api_methods)operator([)symbol(:named_signature)operator(])operator([)symbol(:expects)operator(]) + ident(assert_equal) operator([)operator({)symbol(:appkey)operator(=)operator(>)constant(Integer)operator(})operator(,) operator({)symbol(:publish)operator(=)operator(>)constant(TrueClass)operator(})operator(])operator(,) ident(sig) + reserved(end) + + reserved(def) method(test_to_s) + ident(assert_equal) string<delimiter(')content(void Expects(int param0, bool param1\))delimiter(')>operator(,) constant(APITest)operator(::)constant(API)operator(.)ident(api_methods)operator([)symbol(:expects)operator(])operator(.)ident(to_s) + reserved(end) +reserved(end) +reserved(class) class(AutoLoadAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:void) +reserved(end) + + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +reserved(module) class(BaseTest) + reserved(class) class(API) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:add)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(,) symbol(:int)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:void) + reserved(end) + + reserved(class) class(PristineAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(inflect_names) pre_constant(false) + + ident(api_method) symbol(:add) + ident(api_method) symbol(:under_score) + reserved(end) + + reserved(class) class(Service) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(API) + + reserved(def) method(add)operator(()ident(a)operator(,) ident(b)operator(\)) + reserved(end) + + reserved(def) method(void) + reserved(end) + reserved(end) + + reserved(class) class(PristineService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(PristineAPI) + + reserved(def) method(add) + reserved(end) + + reserved(def) method(under_score) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(TC_Base) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_options) + ident(assert)operator(()constant(BaseTest)operator(::)constant(PristineService)operator(.)ident(web_service_api)operator(.)ident(inflect_names) operator(==) pre_constant(false)operator(\)) + ident(assert)operator(()constant(BaseTest)operator(::)constant(Service)operator(.)ident(web_service_api)operator(.)ident(inflect_names) operator(==) pre_constant(true)operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +reserved(module) class(CastingTest) + reserved(class) class(API) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:int)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:str)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:base64)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:base64)operator(]) + ident(api_method) symbol(:bool)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:bool)operator(]) + ident(api_method) symbol(:float)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:float)operator(]) + ident(api_method) symbol(:time)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:time)operator(]) + ident(api_method) symbol(:datetime)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:datetime)operator(]) + ident(api_method) symbol(:date)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:date)operator(]) + + ident(api_method) symbol(:int_array)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator([)symbol(:int)operator(])operator(]) + ident(api_method) symbol(:str_array)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator([)symbol(:string)operator(])operator(]) + ident(api_method) symbol(:bool_array)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator([)symbol(:bool)operator(])operator(]) + reserved(end) +reserved(end) + +reserved(class) class(TC_Casting) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(CastingTest) + + reserved(def) method(test_base_type_casting_valid) + ident(assert_equal) integer(10000)operator(,) ident(cast_expects)operator(()symbol(:int)operator(,) string<delimiter(')content(10000)delimiter(')>operator(\))operator([)integer(0)operator(]) + ident(assert_equal) string<delimiter(')content(10000)delimiter(')>operator(,) ident(cast_expects)operator(()symbol(:str)operator(,) integer(10000)operator(\))operator([)integer(0)operator(]) + ident(base64) operator(=) ident(cast_expects)operator(()symbol(:base64)operator(,) integer(10000)operator(\))operator([)integer(0)operator(]) + ident(assert_equal) string<delimiter(')content(10000)delimiter(')>operator(,) ident(base64) + ident(assert_instance_of) constant(ActionWebService)operator(::)constant(Base64)operator(,) ident(base64) + operator([)integer(1)operator(,) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(true)delimiter(')>operator(,) string<delimiter(')content(y)delimiter(')>operator(,) string<delimiter(')content(yes)delimiter(')>operator(])operator(.)ident(each) reserved(do) operator(|)ident(val)operator(|) + ident(assert_equal) pre_constant(true)operator(,) ident(cast_expects)operator(()symbol(:bool)operator(,) ident(val)operator(\))operator([)integer(0)operator(]) + reserved(end) + operator([)integer(0)operator(,) string<delimiter(')content(0)delimiter(')>operator(,) string<delimiter(')content(false)delimiter(')>operator(,) string<delimiter(')content(n)delimiter(')>operator(,) string<delimiter(')content(no)delimiter(')>operator(])operator(.)ident(each) reserved(do) operator(|)ident(val)operator(|) + ident(assert_equal) pre_constant(false)operator(,) ident(cast_expects)operator(()symbol(:bool)operator(,) ident(val)operator(\))operator([)integer(0)operator(]) + reserved(end) + ident(assert_equal) float(3.14159)operator(,) ident(cast_expects)operator(()symbol(:float)operator(,) string<delimiter(')content(3.14159)delimiter(')>operator(\))operator([)integer(0)operator(]) + ident(now) operator(=) constant(Time)operator(.)ident(at)operator(()constant(Time)operator(.)ident(now)operator(.)ident(tv_sec)operator(\)) + ident(casted) operator(=) ident(cast_expects)operator(()symbol(:time)operator(,) ident(now)operator(.)ident(to_s)operator(\))operator([)integer(0)operator(]) + ident(assert_equal) ident(now)operator(,) ident(casted) + ident(now) operator(=) constant(DateTime)operator(.)ident(now) + ident(assert_equal) ident(now)operator(.)ident(to_s)operator(,) ident(cast_expects)operator(()symbol(:datetime)operator(,) ident(now)operator(.)ident(to_s)operator(\))operator([)integer(0)operator(])operator(.)ident(to_s) + ident(today) operator(=) constant(Date)operator(.)ident(today) + ident(assert_equal) ident(today)operator(,) ident(cast_expects)operator(()symbol(:date)operator(,) ident(today)operator(.)ident(to_s)operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(test_base_type_casting_invalid) + ident(assert_raises) constant(ArgumentError) reserved(do) + ident(cast_expects)operator(()symbol(:int)operator(,) string<delimiter(')content(this is not a number)delimiter(')>operator(\)) + reserved(end) + ident(assert_raises) constant(ActionWebService)operator(::)constant(Casting)operator(::)constant(CastingError) reserved(do) + comment(# neither true or false ;\)) + ident(cast_expects)operator(()symbol(:bool)operator(,) string<delimiter(')content(i always lie)delimiter(')>operator(\)) + reserved(end) + ident(assert_raises) constant(ArgumentError) reserved(do) + ident(cast_expects)operator(()symbol(:float)operator(,) string<delimiter(')content(not a float)delimiter(')>operator(\)) + reserved(end) + ident(assert_raises) constant(ArgumentError) reserved(do) + ident(cast_expects)operator(()symbol(:time)operator(,) string<delimiter(')content(111111111111111111111111111111111)delimiter(')>operator(\)) + reserved(end) + ident(assert_raises) constant(ArgumentError) reserved(do) + ident(cast_expects)operator(()symbol(:datetime)operator(,) string<delimiter(')content(-1)delimiter(')>operator(\)) + reserved(end) + ident(assert_raises) constant(ArgumentError) reserved(do) + ident(cast_expects)operator(()symbol(:date)operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_array_type_casting) + ident(assert_equal) operator([)integer(1)operator(,) integer(2)operator(,) integer(3213992)operator(,) integer(4)operator(])operator(,) ident(cast_expects)operator(()symbol(:int_array)operator(,) operator([)string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(3213992)delimiter(')>operator(,) string<delimiter(')content(4)delimiter(')>operator(])operator(\))operator([)integer(0)operator(]) + ident(assert_equal) operator([)string<delimiter(')content(one)delimiter(')>operator(,) string<delimiter(')content(two)delimiter(')>operator(,) string<delimiter(')content(5.0)delimiter(')>operator(,) string<delimiter(')content(200)delimiter(')>operator(,) pre_constant(nil)operator(,) string<delimiter(')content(true)delimiter(')>operator(])operator(,) ident(cast_expects)operator(()symbol(:str_array)operator(,) operator([)symbol(:one)operator(,) string<delimiter(')content(two)delimiter(')>operator(,) float(5.0)operator(,) integer(200)operator(,) pre_constant(nil)operator(,) pre_constant(true)operator(])operator(\))operator([)integer(0)operator(]) + ident(assert_equal) operator([)pre_constant(true)operator(,) pre_constant(nil)operator(,) pre_constant(true)operator(,) pre_constant(true)operator(,) pre_constant(false)operator(])operator(,) ident(cast_expects)operator(()symbol(:bool_array)operator(,) operator([)string<delimiter(')content(1)delimiter(')>operator(,) pre_constant(nil)operator(,) string<delimiter(')content(y)delimiter(')>operator(,) pre_constant(true)operator(,) string<delimiter(')content(false)delimiter(')>operator(])operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(test_array_type_casting_failure) + ident(assert_raises) constant(ActionWebService)operator(::)constant(Casting)operator(::)constant(CastingError) reserved(do) + ident(cast_expects)operator(()symbol(:bool_array)operator(,) operator([)string<delimiter(')content(false)delimiter(')>operator(,) string<delimiter(')content(blahblah)delimiter(')>operator(])operator(\)) + reserved(end) + ident(assert_raises) constant(ArgumentError) reserved(do) + ident(cast_expects)operator(()symbol(:int_array)operator(,) operator([)string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(2.021)delimiter(')>operator(,) string<delimiter(')content(4)delimiter(')>operator(])operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(cast_expects)operator(()ident(method_name)operator(,) operator(*)ident(args)operator(\)) + constant(API)operator(.)ident(api_method_instance)operator(()ident(method_name)operator(.)ident(to_sym)operator(\))operator(.)ident(cast_expects)operator(()operator([)operator(*)ident(args)operator(])operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_client)delimiter(')> + + +reserved(module) class(ClientSoapTest) + constant(PORT) operator(=) integer(8998) + + reserved(class) class(SoapClientLet) operator(<) constant(ClientTest)operator(::)constant(AbstractClientLet) + reserved(def) method(do_POST)operator(()ident(req)operator(,) ident(res)operator(\)) + ident(test_request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(test_request)operator(.)ident(request_parameters)operator([)string<delimiter(')content(action)delimiter(')>operator(]) operator(=) ident(req)operator(.)ident(path)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(^)char(\\/)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator([)integer(1)operator(]) + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(")content(POST)delimiter(")> + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_CONTENTTYPE)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/xml)delimiter(')> + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_SOAPACTION)delimiter(')>operator(]) operator(=) ident(req)operator(.)ident(header)operator([)string<delimiter(')content(soapaction)delimiter(')>operator(])operator([)integer(0)operator(]) + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) operator(=) ident(req)operator(.)ident(body) + ident(response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@controller)operator(.)ident(process)operator(()ident(test_request)operator(,) ident(response)operator(\)) + ident(res)operator(.)ident(header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/xml)delimiter(')> + ident(res)operator(.)ident(body) operator(=) ident(response)operator(.)ident(body) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + global_variable($stderr)operator(.)ident(puts) ident(e)operator(.)ident(message) + global_variable($stderr)operator(.)ident(puts) ident(e)operator(.)ident(backtrace)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(ClientContainer) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_client_api) symbol(:client)operator(,) symbol(:soap)operator(,) string<delimiter(")content(http://localhost:)inline<inline_delimiter(#{)constant(PORT)inline_delimiter(})>content(/client/api)delimiter(")>operator(,) symbol(:api) operator(=)operator(>) constant(ClientTest)operator(::)constant(API) + ident(web_client_api) symbol(:invalid)operator(,) symbol(:null)operator(,) string<delimiter(")delimiter(")>operator(,) symbol(:api) operator(=)operator(>) pre_constant(true) + + reserved(def) method(get_client) + ident(client) + reserved(end) + + reserved(def) method(get_invalid) + ident(invalid) + reserved(end) + reserved(end) + + reserved(class) class(SoapServer) operator(<) constant(ClientTest)operator(::)constant(AbstractServer) + reserved(def) method(create_clientlet)operator(()ident(controller)operator(\)) + constant(SoapClientLet)operator(.)ident(new)operator(()ident(controller)operator(\)) + reserved(end) + + reserved(def) method(server_port) + constant(PORT) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(TC_ClientSoap) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ClientTest) + ident(include) constant(ClientSoapTest) + + ident(fixtures) symbol(:users) + + reserved(def) method(setup) + instance_variable(@server) operator(=) constant(SoapServer)operator(.)ident(instance) + instance_variable(@container) operator(=) instance_variable(@server)operator(.)ident(container) + instance_variable(@client) operator(=) constant(ActionWebService)operator(::)constant(Client)operator(::)constant(Soap)operator(.)ident(new)operator(()constant(API)operator(,) string<delimiter(")content(http://localhost:)inline<inline_delimiter(#{)instance_variable(@server)operator(.)ident(server_port)inline_delimiter(})>content(/client/api)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_void) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_void)operator(.)ident(nil?)operator(\)) + instance_variable(@client)operator(.)ident(void) + ident(assert)operator(()operator(!)instance_variable(@container)operator(.)ident(value_void)operator(.)ident(nil?)operator(\)) + reserved(end) + + reserved(def) method(test_normal) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_normal)operator(.)ident(nil?)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(normal)operator(()integer(5)operator(,) integer(6)operator(\))operator(\)) + ident(assert_equal)operator(()operator([)integer(5)operator(,) integer(6)operator(])operator(,) instance_variable(@container)operator(.)ident(value_normal)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(normal)operator(()string<delimiter(")content(7)delimiter(")>operator(,) string<delimiter(")content(8)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()operator([)integer(7)operator(,) integer(8)operator(])operator(,) instance_variable(@container)operator(.)ident(value_normal)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(normal)operator(()pre_constant(true)operator(,) pre_constant(false)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_array_return) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_array_return)operator(.)ident(nil?)operator(\)) + ident(new_person) operator(=) constant(Person)operator(.)ident(new) + ident(new_person)operator(.)ident(firstnames) operator(=) operator([)string<delimiter(")content(one)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")>operator(]) + ident(new_person)operator(.)ident(lastname) operator(=) string<delimiter(")content(last)delimiter(")> + ident(assert_equal)operator(()operator([)ident(new_person)operator(])operator(,) instance_variable(@client)operator(.)ident(array_return)operator(\)) + ident(assert_equal)operator(()operator([)ident(new_person)operator(])operator(,) instance_variable(@container)operator(.)ident(value_array_return)operator(\)) + reserved(end) + + reserved(def) method(test_struct_pass) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_struct_pass)operator(.)ident(nil?)operator(\)) + ident(new_person) operator(=) constant(Person)operator(.)ident(new) + ident(new_person)operator(.)ident(firstnames) operator(=) operator([)string<delimiter(")content(one)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")>operator(]) + ident(new_person)operator(.)ident(lastname) operator(=) string<delimiter(")content(last)delimiter(")> + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@client)operator(.)ident(struct_pass)operator(()operator([)ident(new_person)operator(])operator(\))operator(\)) + ident(assert_equal)operator(()operator([)operator([)ident(new_person)operator(])operator(])operator(,) instance_variable(@container)operator(.)ident(value_struct_pass)operator(\)) + reserved(end) + + reserved(def) method(test_nil_struct_return) + ident(assert_nil) instance_variable(@client)operator(.)ident(nil_struct_return) + reserved(end) + + reserved(def) method(test_inner_nil) + ident(outer) operator(=) instance_variable(@client)operator(.)ident(inner_nil) + ident(assert_equal) string<delimiter(')content(outer)delimiter(')>operator(,) ident(outer)operator(.)ident(name) + ident(assert_nil) ident(outer)operator(.)ident(inner) + reserved(end) + + reserved(def) method(test_client_container) + ident(assert_equal)operator(()integer(50)operator(,) constant(ClientContainer)operator(.)ident(new)operator(.)ident(get_client)operator(.)ident(client_container)operator(\)) + ident(assert)operator(()constant(ClientContainer)operator(.)ident(new)operator(.)ident(get_invalid)operator(.)ident(nil?)operator(\)) + reserved(end) + + reserved(def) method(test_named_parameters) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_named_parameters)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@client)operator(.)ident(named_parameters)operator(()string<delimiter(")content(key)delimiter(")>operator(,) integer(5)operator(\))operator(.)ident(nil?)operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(")content(key)delimiter(")>operator(,) integer(5)operator(])operator(,) instance_variable(@container)operator(.)ident(value_named_parameters)operator(\)) + reserved(end) + + reserved(def) method(test_capitalized_method_name) + instance_variable(@container)operator(.)ident(value_normal) operator(=) pre_constant(nil) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(Normal)operator(()integer(5)operator(,) integer(6)operator(\))operator(\)) + ident(assert_equal)operator(()operator([)integer(5)operator(,) integer(6)operator(])operator(,) instance_variable(@container)operator(.)ident(value_normal)operator(\)) + instance_variable(@container)operator(.)ident(value_normal) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(test_model_return) + ident(user) operator(=) instance_variable(@client)operator(.)ident(user_return) + ident(assert_equal) integer(1)operator(,) ident(user)operator(.)ident(id) + ident(assert_equal) string<delimiter(')content(Kent)delimiter(')>operator(,) ident(user)operator(.)ident(name) + ident(assert) ident(user)operator(.)ident(active?) + ident(assert_kind_of) constant(Date)operator(,) ident(user)operator(.)ident(created_on) + ident(assert_equal) constant(Date)operator(.)ident(today)operator(,) ident(user)operator(.)ident(created_on) + reserved(end) + + reserved(def) method(test_with_model) + ident(with_model) operator(=) instance_variable(@client)operator(.)ident(with_model_return) + ident(assert_equal) string<delimiter(')content(Kent)delimiter(')>operator(,) ident(with_model)operator(.)ident(user)operator(.)ident(name) + ident(assert_equal) integer(2)operator(,) ident(with_model)operator(.)ident(users)operator(.)ident(size) + ident(with_model)operator(.)ident(users)operator(.)ident(each) reserved(do) operator(|)ident(user)operator(|) + ident(assert_kind_of) constant(User)operator(,) ident(user) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_model_return) + ident(scoped_model) operator(=) instance_variable(@client)operator(.)ident(scoped_model_return) + ident(assert_kind_of) constant(Accounting)operator(::)constant(User)operator(,) ident(scoped_model) + ident(assert_equal) string<delimiter(')content(Kent)delimiter(')>operator(,) ident(scoped_model)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_multi_dim_return) + ident(md_struct) operator(=) instance_variable(@client)operator(.)ident(multi_dim_return) + ident(assert_kind_of) constant(Array)operator(,) ident(md_struct)operator(.)ident(pref) + ident(assert_equal) integer(2)operator(,) ident(md_struct)operator(.)ident(pref)operator(.)ident(size) + ident(assert_kind_of) constant(Array)operator(,) ident(md_struct)operator(.)ident(pref)operator([)integer(0)operator(]) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_client)delimiter(')> + + +reserved(module) class(ClientXmlRpcTest) + constant(PORT) operator(=) integer(8999) + + reserved(class) class(XmlRpcClientLet) operator(<) constant(ClientTest)operator(::)constant(AbstractClientLet) + reserved(def) method(do_POST)operator(()ident(req)operator(,) ident(res)operator(\)) + ident(test_request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + ident(test_request)operator(.)ident(request_parameters)operator([)string<delimiter(')content(action)delimiter(')>operator(]) operator(=) ident(req)operator(.)ident(path)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(^)char(\\/)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator([)integer(1)operator(]) + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(")content(POST)delimiter(")> + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_CONTENT_TYPE)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/xml)delimiter(')> + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(RAW_POST_DATA)delimiter(')>operator(]) operator(=) ident(req)operator(.)ident(body) + ident(response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + instance_variable(@controller)operator(.)ident(process)operator(()ident(test_request)operator(,) ident(response)operator(\)) + ident(res)operator(.)ident(header)operator([)string<delimiter(')content(content-type)delimiter(')>operator(]) operator(=) string<delimiter(')content(text/xml)delimiter(')> + ident(res)operator(.)ident(body) operator(=) ident(response)operator(.)ident(body) + comment(# puts res.body) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + global_variable($stderr)operator(.)ident(puts) ident(e)operator(.)ident(message) + global_variable($stderr)operator(.)ident(puts) ident(e)operator(.)ident(backtrace)operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(ClientContainer) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_client_api) symbol(:client)operator(,) symbol(:xmlrpc)operator(,) string<delimiter(")content(http://localhost:)inline<inline_delimiter(#{)constant(PORT)inline_delimiter(})>content(/client/api)delimiter(")>operator(,) symbol(:api) operator(=)operator(>) constant(ClientTest)operator(::)constant(API) + + reserved(def) method(get_client) + ident(client) + reserved(end) + reserved(end) + + reserved(class) class(XmlRpcServer) operator(<) constant(ClientTest)operator(::)constant(AbstractServer) + reserved(def) method(create_clientlet)operator(()ident(controller)operator(\)) + constant(XmlRpcClientLet)operator(.)ident(new)operator(()ident(controller)operator(\)) + reserved(end) + + reserved(def) method(server_port) + constant(PORT) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(TC_ClientXmlRpc) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ClientTest) + ident(include) constant(ClientXmlRpcTest) + + ident(fixtures) symbol(:users) + + reserved(def) method(setup) + instance_variable(@server) operator(=) constant(XmlRpcServer)operator(.)ident(instance) + instance_variable(@container) operator(=) instance_variable(@server)operator(.)ident(container) + instance_variable(@client) operator(=) constant(ActionWebService)operator(::)constant(Client)operator(::)constant(XmlRpc)operator(.)ident(new)operator(()constant(API)operator(,) string<delimiter(")content(http://localhost:)inline<inline_delimiter(#{)instance_variable(@server)operator(.)ident(server_port)inline_delimiter(})>content(/client/api)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_void) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_void)operator(.)ident(nil?)operator(\)) + instance_variable(@client)operator(.)ident(void) + ident(assert)operator(()operator(!)instance_variable(@container)operator(.)ident(value_void)operator(.)ident(nil?)operator(\)) + reserved(end) + + reserved(def) method(test_normal) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_normal)operator(.)ident(nil?)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(normal)operator(()integer(5)operator(,) integer(6)operator(\))operator(\)) + ident(assert_equal)operator(()operator([)integer(5)operator(,) integer(6)operator(])operator(,) instance_variable(@container)operator(.)ident(value_normal)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(normal)operator(()string<delimiter(")content(7)delimiter(")>operator(,) string<delimiter(")content(8)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()operator([)integer(7)operator(,) integer(8)operator(])operator(,) instance_variable(@container)operator(.)ident(value_normal)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@client)operator(.)ident(normal)operator(()pre_constant(true)operator(,) pre_constant(false)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_array_return) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_array_return)operator(.)ident(nil?)operator(\)) + ident(new_person) operator(=) constant(Person)operator(.)ident(new) + ident(new_person)operator(.)ident(firstnames) operator(=) operator([)string<delimiter(")content(one)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")>operator(]) + ident(new_person)operator(.)ident(lastname) operator(=) string<delimiter(")content(last)delimiter(")> + ident(assert_equal)operator(()operator([)ident(new_person)operator(])operator(,) instance_variable(@client)operator(.)ident(array_return)operator(\)) + ident(assert_equal)operator(()operator([)ident(new_person)operator(])operator(,) instance_variable(@container)operator(.)ident(value_array_return)operator(\)) + reserved(end) + + reserved(def) method(test_struct_pass) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_struct_pass)operator(.)ident(nil?)operator(\)) + ident(new_person) operator(=) constant(Person)operator(.)ident(new) + ident(new_person)operator(.)ident(firstnames) operator(=) operator([)string<delimiter(")content(one)delimiter(")>operator(,) string<delimiter(")content(two)delimiter(")>operator(]) + ident(new_person)operator(.)ident(lastname) operator(=) string<delimiter(")content(last)delimiter(")> + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@client)operator(.)ident(struct_pass)operator(()operator([)ident(new_person)operator(])operator(\))operator(\)) + ident(assert_equal)operator(()operator([)operator([)ident(new_person)operator(])operator(])operator(,) instance_variable(@container)operator(.)ident(value_struct_pass)operator(\)) + reserved(end) + + reserved(def) method(test_nil_struct_return) + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@client)operator(.)ident(nil_struct_return) + reserved(end) + + reserved(def) method(test_inner_nil) + ident(outer) operator(=) instance_variable(@client)operator(.)ident(inner_nil) + ident(assert_equal) string<delimiter(')content(outer)delimiter(')>operator(,) ident(outer)operator(.)ident(name) + ident(assert_nil) ident(outer)operator(.)ident(inner) + reserved(end) + + reserved(def) method(test_client_container) + ident(assert_equal)operator(()integer(50)operator(,) constant(ClientContainer)operator(.)ident(new)operator(.)ident(get_client)operator(.)ident(client_container)operator(\)) + reserved(end) + + reserved(def) method(test_named_parameters) + ident(assert)operator(()instance_variable(@container)operator(.)ident(value_named_parameters)operator(.)ident(nil?)operator(\)) + ident(assert_equal)operator(()pre_constant(false)operator(,) instance_variable(@client)operator(.)ident(named_parameters)operator(()string<delimiter(")content(xxx)delimiter(")>operator(,) integer(7)operator(\))operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(")content(xxx)delimiter(")>operator(,) integer(7)operator(])operator(,) instance_variable(@container)operator(.)ident(value_named_parameters)operator(\)) + reserved(end) + + reserved(def) method(test_exception) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(Client)operator(::)constant(ClientError)operator(\)) reserved(do) + ident(assert)operator(()instance_variable(@client)operator(.)ident(thrower)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_invalid_signature) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) reserved(do) + instance_variable(@client)operator(.)ident(normal) + reserved(end) + reserved(end) + + reserved(def) method(test_model_return) + ident(user) operator(=) instance_variable(@client)operator(.)ident(user_return) + ident(assert_equal) integer(1)operator(,) ident(user)operator(.)ident(id) + ident(assert_equal) string<delimiter(')content(Kent)delimiter(')>operator(,) ident(user)operator(.)ident(name) + ident(assert) ident(user)operator(.)ident(active?) + ident(assert_kind_of) constant(Time)operator(,) ident(user)operator(.)ident(created_on) + ident(assert_equal) constant(Time)operator(.)ident(utc)operator(()constant(Time)operator(.)ident(now)operator(.)ident(year)operator(,) constant(Time)operator(.)ident(now)operator(.)ident(month)operator(,) constant(Time)operator(.)ident(now)operator(.)ident(day)operator(\))operator(,) ident(user)operator(.)ident(created_on) + reserved(end) + + reserved(def) method(test_with_model) + ident(with_model) operator(=) instance_variable(@client)operator(.)ident(with_model_return) + ident(assert_equal) string<delimiter(')content(Kent)delimiter(')>operator(,) ident(with_model)operator(.)ident(user)operator(.)ident(name) + ident(assert_equal) integer(2)operator(,) ident(with_model)operator(.)ident(users)operator(.)ident(size) + ident(with_model)operator(.)ident(users)operator(.)ident(each) reserved(do) operator(|)ident(user)operator(|) + ident(assert_kind_of) constant(User)operator(,) ident(user) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_model_return) + ident(scoped_model) operator(=) instance_variable(@client)operator(.)ident(scoped_model_return) + ident(assert_kind_of) constant(Accounting)operator(::)constant(User)operator(,) ident(scoped_model) + ident(assert_equal) string<delimiter(')content(Kent)delimiter(')>operator(,) ident(scoped_model)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_multi_dim_return) + ident(md_struct) operator(=) instance_variable(@client)operator(.)ident(multi_dim_return) + ident(assert_kind_of) constant(Array)operator(,) ident(md_struct)operator(.)ident(pref) + ident(assert_equal) integer(2)operator(,) ident(md_struct)operator(.)ident(pref)operator(.)ident(size) + ident(assert_kind_of) constant(Array)operator(,) ident(md_struct)operator(.)ident(pref)operator([)integer(0)operator(]) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +reserved(module) class(ContainerTest) + global_variable($immediate_service) operator(=) constant(Object)operator(.)ident(new) + global_variable($deferred_service) operator(=) constant(Object)operator(.)ident(new) + + reserved(class) class(DelegateContainer) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_service_dispatching_mode) symbol(:delegated) + + ident(attr) symbol(:flag) + ident(attr) symbol(:previous_flag) + + reserved(def) method(initialize) + instance_variable(@previous_flag) operator(=) pre_constant(nil) + instance_variable(@flag) operator(=) pre_constant(true) + reserved(end) + + ident(web_service) symbol(:immediate_service)operator(,) global_variable($immediate_service) + ident(web_service)operator(()symbol(:deferred_service)operator(\)) operator({) instance_variable(@previous_flag) operator(=) instance_variable(@flag)operator(;) instance_variable(@flag) operator(=) pre_constant(false)operator(;) global_variable($deferred_service) operator(}) + reserved(end) + + reserved(class) class(DirectContainer) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_service_dispatching_mode) symbol(:direct) + reserved(end) + + reserved(class) class(InvalidContainer) + ident(include) constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Direct) + reserved(end) +reserved(end) + +reserved(class) class(TC_Container) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ContainerTest) + + reserved(def) method(setup) + instance_variable(@delegate_container) operator(=) constant(DelegateContainer)operator(.)ident(new) + instance_variable(@direct_container) operator(=) constant(DirectContainer)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_registration) + ident(assert)operator(()constant(DelegateContainer)operator(.)ident(has_web_service?)operator(()symbol(:immediate_service)operator(\))operator(\)) + ident(assert)operator(()constant(DelegateContainer)operator(.)ident(has_web_service?)operator(()symbol(:deferred_service)operator(\))operator(\)) + ident(assert)operator(()operator(!)constant(DelegateContainer)operator(.)ident(has_web_service?)operator(()symbol(:fake_service)operator(\))operator(\)) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Delegated)operator(::)constant(ContainerError)operator(\)) reserved(do) + constant(DelegateContainer)operator(.)ident(web_service)operator(()string<delimiter(')content(invalid)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_service_object) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Delegated)operator(::)constant(ContainerError)operator(\)) reserved(do) + instance_variable(@delegate_container)operator(.)ident(web_service_object)operator(()symbol(:nonexistent)operator(\)) + reserved(end) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(flag) operator(==) pre_constant(true)operator(\)) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(web_service_object)operator(()symbol(:immediate_service)operator(\)) operator(==) global_variable($immediate_service)operator(\)) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(previous_flag)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(flag) operator(==) pre_constant(true)operator(\)) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(web_service_object)operator(()symbol(:deferred_service)operator(\)) operator(==) global_variable($deferred_service)operator(\)) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(previous_flag) operator(==) pre_constant(true)operator(\)) + ident(assert)operator(()instance_variable(@delegate_container)operator(.)ident(flag) operator(==) pre_constant(false)operator(\)) + reserved(end) + + reserved(def) method(test_direct_container) + ident(assert)operator(()constant(DirectContainer)operator(.)ident(web_service_dispatching_mode) operator(==) symbol(:direct)operator(\)) + reserved(end) + + reserved(def) method(test_validity) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Direct)operator(::)constant(ContainerError)operator(\)) reserved(do) + constant(InvalidContainer)operator(.)ident(web_service_api) symbol(:test) + reserved(end) + ident(assert_raises)operator(()constant(ActionWebService)operator(::)constant(Container)operator(::)constant(Direct)operator(::)constant(ContainerError)operator(\)) reserved(do) + constant(InvalidContainer)operator(.)ident(web_service_api) float(50.0) + reserved(end) + reserved(end) +reserved(end) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/apis)delimiter(')>operator(\)) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_dispatcher)delimiter(')> +ident(require) string<delimiter(')content(wsdl/parser)delimiter(')> + +reserved(class) class(ActionController::Base) + reserved(class) operator(<<) class(self) + reserved(alias) symbol(:inherited_without_name_error) symbol(:inherited) + reserved(def) method(inherited)operator(()ident(child)operator(\)) + reserved(begin) + ident(inherited_without_name_error)operator(()ident(child)operator(\)) + reserved(rescue) constant(NameError) operator(=)operator(>) ident(e) + reserved(end) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(AutoLoadController) operator(<) constant(ActionController)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(FailingAutoLoadController) operator(<) constant(ActionController)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(BrokenAutoLoadController) operator(<) constant(ActionController)operator(::)constant(Base)operator(;) reserved(end) + +reserved(class) class(TC_DispatcherActionControllerSoap) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(DispatcherTest) + ident(include) constant(DispatcherCommonTests) + + reserved(def) method(setup) + instance_variable(@direct_controller) operator(=) constant(DirectController)operator(.)ident(new) + instance_variable(@delegated_controller) operator(=) constant(DelegatedController)operator(.)ident(new) + instance_variable(@virtual_controller) operator(=) constant(VirtualController)operator(.)ident(new) + instance_variable(@layered_controller) operator(=) constant(LayeredController)operator(.)ident(new) + instance_variable(@protocol) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(Soap)operator(::)constant(SoapProtocol)operator(.)ident(create)operator(()instance_variable(@direct_controller)operator(\)) + reserved(end) + + reserved(def) method(test_wsdl_generation) + ident(ensure_valid_wsdl_generation) constant(DelegatedController)operator(.)ident(new)operator(,) constant(DispatcherTest)operator(::)constant(WsdlNamespace) + ident(ensure_valid_wsdl_generation) constant(DirectController)operator(.)ident(new)operator(,) constant(DispatcherTest)operator(::)constant(WsdlNamespace) + reserved(end) + + reserved(def) method(test_wsdl_action) + ident(delegated_types) operator(=) ident(ensure_valid_wsdl_action) constant(DelegatedController)operator(.)ident(new) + ident(delegated_names) operator(=) ident(delegated_types)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(name)operator(.)ident(name)operator(}) + ident(assert)operator(()ident(delegated_names)operator(.)ident(include?)operator(()string<delimiter(')content(DispatcherTest..NodeArray)delimiter(')>operator(\))operator(\)) + ident(assert)operator(()ident(delegated_names)operator(.)ident(include?)operator(()string<delimiter(')content(DispatcherTest..Node)delimiter(')>operator(\))operator(\)) + ident(direct_types) operator(=) ident(ensure_valid_wsdl_action) constant(DirectController)operator(.)ident(new) + ident(direct_names) operator(=) ident(direct_types)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(name)operator(.)ident(name)operator(}) + ident(assert)operator(()ident(direct_names)operator(.)ident(include?)operator(()string<delimiter(')content(DispatcherTest..NodeArray)delimiter(')>operator(\))operator(\)) + ident(assert)operator(()ident(direct_names)operator(.)ident(include?)operator(()string<delimiter(')content(DispatcherTest..Node)delimiter(')>operator(\))operator(\)) + ident(assert)operator(()ident(direct_names)operator(.)ident(include?)operator(()string<delimiter(')content(IntegerArray)delimiter(')>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_autoloading) + ident(assert)operator(()operator(!)constant(AutoLoadController)operator(.)ident(web_service_api)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()constant(AutoLoadController)operator(.)ident(web_service_api)operator(.)ident(has_public_api_method?)operator(()string<delimiter(')content(Void)delimiter(')>operator(\))operator(\)) + ident(assert)operator(()constant(FailingAutoLoadController)operator(.)ident(web_service_api)operator(.)ident(nil?)operator(\)) + ident(assert_raises)operator(()constant(MissingSourceFile)operator(\)) reserved(do) + constant(FailingAutoLoadController)operator(.)ident(require_web_service_api) symbol(:blah) + reserved(end) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) reserved(do) + constant(FailingAutoLoadController)operator(.)ident(require_web_service_api) float(50.0) + reserved(end) + ident(assert)operator(()constant(BrokenAutoLoadController)operator(.)ident(web_service_api)operator(.)ident(nil?)operator(\)) + reserved(end) + + reserved(def) method(test_layered_dispatching) + ident(mt_cats) operator(=) ident(do_method_call)operator(()instance_variable(@layered_controller)operator(,) string<delimiter(')content(mt.getCategories)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(")content(mtCat1)delimiter(")>operator(,) string<delimiter(")content(mtCat2)delimiter(")>operator(])operator(,) ident(mt_cats)operator(\)) + ident(blogger_cats) operator(=) ident(do_method_call)operator(()instance_variable(@layered_controller)operator(,) string<delimiter(')content(blogger.getCategories)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(")content(bloggerCat1)delimiter(")>operator(,) string<delimiter(")content(bloggerCat2)delimiter(")>operator(])operator(,) ident(blogger_cats)operator(\)) + reserved(end) + + reserved(def) method(test_utf8) + instance_variable(@direct_controller)operator(.)ident(web_service_exception_reporting) operator(=) pre_constant(true) + global_variable($KCODE) operator(=) string<delimiter(')content(u)delimiter(')> + ident(assert_equal)operator(()constant(Utf8String)operator(,) ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(TestUtf8)delimiter(')>operator(\))operator(\)) + ident(retval) operator(=) constant(SOAP)operator(::)constant(Processor)operator(.)ident(unmarshal)operator(()instance_variable(@response_body)operator(\))operator(.)ident(body)operator(.)ident(response) + ident(assert) ident(retval)operator(.)ident(is_a?)operator(()constant(SOAP)operator(::)constant(SOAPString)operator(\)) + + comment(# If $KCODE is not set to UTF-8, any strings with non-ASCII UTF-8 data) + comment(# will be sent back as base64 by SOAP4R. By the time we get it here though,) + comment(# it will be decoded back into a string. So lets read the base64 value) + comment(# from the message body directly.) + global_variable($KCODE) operator(=) string<delimiter(')content(NONE)delimiter(')> + ident(do_method_call)operator(()instance_variable(@direct_controller)operator(,) string<delimiter(')content(TestUtf8)delimiter(')>operator(\)) + ident(retval) operator(=) constant(SOAP)operator(::)constant(Processor)operator(.)ident(unmarshal)operator(()instance_variable(@response_body)operator(\))operator(.)ident(body)operator(.)ident(response) + ident(assert) ident(retval)operator(.)ident(is_a?)operator(()constant(SOAP)operator(::)constant(SOAPBase64)operator(\)) + ident(assert_equal) string<delimiter(")content(T25lIFdvcmxkIENhZsOp)delimiter(")>operator(,) ident(retval)operator(.)ident(data)operator(.)ident(to_s) + reserved(end) + + ident(protected) + reserved(def) method(exception_message)operator(()ident(soap_fault_exception)operator(\)) + ident(soap_fault_exception)operator(.)ident(detail)operator(.)ident(cause)operator(.)ident(message) + reserved(end) + + reserved(def) method(is_exception?)operator(()ident(obj)operator(\)) + ident(obj)operator(.)ident(respond_to?)operator(()symbol(:detail)operator(\)) operator(&&) ident(obj)operator(.)ident(detail)operator(.)ident(respond_to?)operator(()symbol(:cause)operator(\)) operator(&&) \ + ident(obj)operator(.)ident(detail)operator(.)ident(cause)operator(.)ident(is_a?)operator(()constant(Exception)operator(\)) + reserved(end) + + reserved(def) method(service_name)operator(()ident(container)operator(\)) + ident(container)operator(.)ident(is_a?)operator(()constant(DelegatedController)operator(\)) operator(?) string<delimiter(')content(test_service)delimiter(')> operator(:) string<delimiter(')content(api)delimiter(')> + reserved(end) + + reserved(def) method(ensure_valid_wsdl_generation)operator(()ident(controller)operator(,) ident(expected_namespace)operator(\)) + ident(wsdl) operator(=) ident(controller)operator(.)ident(generate_wsdl) + ident(ensure_valid_wsdl)operator(()ident(controller)operator(,) ident(wsdl)operator(,) ident(expected_namespace)operator(\)) + reserved(end) + + reserved(def) method(ensure_valid_wsdl)operator(()ident(controller)operator(,) ident(wsdl)operator(,) ident(expected_namespace)operator(\)) + ident(definitions) operator(=) constant(WSDL)operator(::)constant(Parser)operator(.)ident(new)operator(.)ident(parse)operator(()ident(wsdl)operator(\)) + ident(assert)operator(()ident(definitions)operator(.)ident(is_a?)operator(()constant(WSDL)operator(::)constant(Definitions)operator(\))operator(\)) + ident(definitions)operator(.)ident(bindings)operator(.)ident(each) reserved(do) operator(|)ident(binding)operator(|) + ident(assert)operator(()ident(binding)operator(.)ident(name)operator(.)ident(name)operator(.)ident(index)operator(()string<delimiter(')content(:)delimiter(')>operator(\))operator(.)ident(nil?)operator(\)) + reserved(end) + ident(definitions)operator(.)ident(services)operator(.)ident(each) reserved(do) operator(|)ident(service)operator(|) + ident(service)operator(.)ident(ports)operator(.)ident(each) reserved(do) operator(|)ident(port)operator(|) + ident(assert)operator(()ident(port)operator(.)ident(name)operator(.)ident(name)operator(.)ident(index)operator(()string<delimiter(')content(:)delimiter(')>operator(\))operator(.)ident(nil?)operator(\)) + reserved(end) + reserved(end) + ident(types) operator(=) ident(definitions)operator(.)ident(collect_complextypes)operator(.)ident(map)operator({)operator(|)ident(x)operator(|) ident(x)operator(.)ident(name)operator(}) + ident(types)operator(.)ident(each) reserved(do) operator(|)ident(type)operator(|) + ident(assert)operator(()ident(type)operator(.)ident(namespace) operator(==) ident(expected_namespace)operator(\)) + reserved(end) + ident(location) operator(=) ident(definitions)operator(.)ident(services)operator([)integer(0)operator(])operator(.)ident(ports)operator([)integer(0)operator(])operator(.)ident(soap_address)operator(.)ident(location) + reserved(if) ident(controller)operator(.)ident(is_a?)operator(()constant(DelegatedController)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content(http://localhost/dispatcher_test/delegated/test_service$)delimiter(})>operator(,) ident(location) + reserved(elsif) ident(controller)operator(.)ident(is_a?)operator(()constant(DirectController)operator(\)) + ident(assert_match) regexp<delimiter(%r{)content(http://localhost/dispatcher_test/direct/api$)delimiter(})>operator(,) ident(location) + reserved(end) + ident(definitions)operator(.)ident(collect_complextypes) + reserved(end) + + reserved(def) method(ensure_valid_wsdl_action)operator(()ident(controller)operator(\)) + ident(test_request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new)operator(()operator({) string<delimiter(')content(action)delimiter(')> operator(=)operator(>) string<delimiter(')content(wsdl)delimiter(')> operator(})operator(\)) + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(REQUEST_METHOD)delimiter(')>operator(]) operator(=) string<delimiter(')content(GET)delimiter(')> + ident(test_request)operator(.)ident(env)operator([)string<delimiter(')content(HTTP_HOST)delimiter(')>operator(]) operator(=) string<delimiter(')content(localhost)delimiter(')> + ident(test_response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + ident(wsdl) operator(=) ident(controller)operator(.)ident(process)operator(()ident(test_request)operator(,) ident(test_response)operator(\))operator(.)ident(body) + ident(ensure_valid_wsdl)operator(()ident(controller)operator(,) ident(wsdl)operator(,) constant(DispatcherTest)operator(::)constant(WsdlNamespace)operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_dispatcher)delimiter(')> + +reserved(class) class(TC_DispatcherActionControllerXmlRpc) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(DispatcherTest) + ident(include) constant(DispatcherCommonTests) + + reserved(def) method(setup) + instance_variable(@direct_controller) operator(=) constant(DirectController)operator(.)ident(new) + instance_variable(@delegated_controller) operator(=) constant(DelegatedController)operator(.)ident(new) + instance_variable(@layered_controller) operator(=) constant(LayeredController)operator(.)ident(new) + instance_variable(@virtual_controller) operator(=) constant(VirtualController)operator(.)ident(new) + instance_variable(@protocol) operator(=) constant(ActionWebService)operator(::)constant(Protocol)operator(::)constant(XmlRpc)operator(::)constant(XmlRpcProtocol)operator(.)ident(create)operator(()instance_variable(@direct_controller)operator(\)) + reserved(end) + + reserved(def) method(test_layered_dispatching) + ident(mt_cats) operator(=) ident(do_method_call)operator(()instance_variable(@layered_controller)operator(,) string<delimiter(')content(mt.getCategories)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(")content(mtCat1)delimiter(")>operator(,) string<delimiter(")content(mtCat2)delimiter(")>operator(])operator(,) ident(mt_cats)operator(\)) + ident(blogger_cats) operator(=) ident(do_method_call)operator(()instance_variable(@layered_controller)operator(,) string<delimiter(')content(blogger.getCategories)delimiter(')>operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(")content(bloggerCat1)delimiter(")>operator(,) string<delimiter(")content(bloggerCat2)delimiter(")>operator(])operator(,) ident(blogger_cats)operator(\)) + reserved(end) + + reserved(def) method(test_multicall) + ident(response) operator(=) ident(do_method_call)operator(()instance_variable(@layered_controller)operator(,) string<delimiter(')content(system.multicall)delimiter(')>operator(,) operator([) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(mt.getCategories)delimiter(')>operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(blogger.getCategories)delimiter(')>operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(mt.bool)delimiter(')>operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(blogger.str)delimiter(')>operator(,) string<delimiter(')content(params)delimiter(')> operator(=)operator(>) operator([)string<delimiter(')content(2000)delimiter(')>operator(])operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(mt.alwaysFail)delimiter(')>operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(blogger.alwaysFail)delimiter(')>operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(mt.blah)delimiter(')>operator(})operator(,) + operator({)string<delimiter(')content(methodName)delimiter(')> operator(=)operator(>) string<delimiter(')content(blah.blah)delimiter(')>operator(}) + operator(])operator(\)) + ident(assert_equal) operator([) + operator([)operator([)string<delimiter(")content(mtCat1)delimiter(")>operator(,) string<delimiter(")content(mtCat2)delimiter(")>operator(])operator(])operator(,) + operator([)operator([)string<delimiter(")content(bloggerCat1)delimiter(")>operator(,) string<delimiter(")content(bloggerCat2)delimiter(")>operator(])operator(])operator(,) + operator([)pre_constant(true)operator(])operator(,) + operator([)string<delimiter(")content(2500)delimiter(")>operator(])operator(,) + operator({)string<delimiter(")content(faultCode)delimiter(")> operator(=)operator(>) integer(3)operator(,) string<delimiter(")content(faultString)delimiter(")> operator(=)operator(>) string<delimiter(")content(MT AlwaysFail)delimiter(")>operator(})operator(,) + operator({)string<delimiter(")content(faultCode)delimiter(")> operator(=)operator(>) integer(3)operator(,) string<delimiter(")content(faultString)delimiter(")> operator(=)operator(>) string<delimiter(")content(Blogger AlwaysFail)delimiter(")>operator(})operator(,) + operator({)string<delimiter(")content(faultCode)delimiter(")> operator(=)operator(>) integer(4)operator(,) string<delimiter(")content(faultMessage)delimiter(")> operator(=)operator(>) string<delimiter(")content(no such method 'blah' on API DispatcherTest::MTAPI)delimiter(")>operator(})operator(,) + operator({)string<delimiter(")content(faultCode)delimiter(")> operator(=)operator(>) integer(4)operator(,) string<delimiter(")content(faultMessage)delimiter(")> operator(=)operator(>) string<delimiter(")content(no such web service 'blah')delimiter(")>operator(}) + operator(])operator(,) ident(response) + reserved(end) + + ident(protected) + reserved(def) method(exception_message)operator(()ident(xmlrpc_fault_exception)operator(\)) + ident(xmlrpc_fault_exception)operator(.)ident(faultString) + reserved(end) + + reserved(def) method(is_exception?)operator(()ident(obj)operator(\)) + ident(obj)operator(.)ident(is_a?)operator(()constant(XMLRPC)operator(::)constant(FaultException)operator(\)) + reserved(end) + + reserved(def) method(service_name)operator(()ident(container)operator(\)) + ident(container)operator(.)ident(is_a?)operator(()constant(DelegatedController)operator(\)) operator(?) string<delimiter(')content(test_service)delimiter(')> operator(:) string<delimiter(')content(api)delimiter(')> + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +reserved(module) class(InvocationTest) + reserved(class) class(API) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:add)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(,) symbol(:int)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:transmogrify)operator(,) symbol(:expects_and_returns) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:fail_with_reason) + ident(api_method) symbol(:fail_generic) + ident(api_method) symbol(:no_before) + ident(api_method) symbol(:no_after) + ident(api_method) symbol(:only_one) + ident(api_method) symbol(:only_two) + reserved(end) + + reserved(class) class(Interceptor) + ident(attr) symbol(:args) + + reserved(def) method(initialize) + instance_variable(@args) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(intercept)operator(()operator(*)ident(args)operator(\)) + instance_variable(@args) operator(=) ident(args) + reserved(end) + reserved(end) + + constant(InterceptorClass) operator(=) constant(Interceptor)operator(.)ident(new) + + reserved(class) class(Service) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_service_api) constant(API) + + ident(before_invocation) symbol(:intercept_before)operator(,) symbol(:except) operator(=)operator(>) operator([)symbol(:no_before)operator(]) + ident(after_invocation) symbol(:intercept_after)operator(,) symbol(:except) operator(=)operator(>) operator([)symbol(:no_after)operator(]) + ident(prepend_after_invocation) symbol(:intercept_after_first)operator(,) symbol(:except) operator(=)operator(>) operator([)symbol(:no_after)operator(]) + ident(prepend_before_invocation) symbol(:intercept_only)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:only_one)operator(,) symbol(:only_two)operator(]) + ident(after_invocation)operator(()symbol(:only) operator(=)operator(>) operator([)symbol(:only_one)operator(])operator(\)) reserved(do) operator(|*)ident(args)operator(|) + ident(args)operator([)integer(0)operator(])operator(.)ident(instance_variable_set)operator(()string<delimiter(')content(@block_invoked)delimiter(')>operator(,) ident(args)operator([)integer(1)operator(])operator(\)) + reserved(end) + ident(after_invocation) constant(InterceptorClass)operator(,) symbol(:only) operator(=)operator(>) operator([)symbol(:only_one)operator(]) + + ident(attr_accessor) symbol(:before_invoked) + ident(attr_accessor) symbol(:after_invoked) + ident(attr_accessor) symbol(:after_first_invoked) + ident(attr_accessor) symbol(:only_invoked) + ident(attr_accessor) symbol(:block_invoked) + ident(attr_accessor) symbol(:invocation_result) + + reserved(def) method(initialize) + instance_variable(@before_invoked) operator(=) pre_constant(nil) + instance_variable(@after_invoked) operator(=) pre_constant(nil) + instance_variable(@after_first_invoked) operator(=) pre_constant(nil) + instance_variable(@only_invoked) operator(=) pre_constant(nil) + instance_variable(@invocation_result) operator(=) pre_constant(nil) + instance_variable(@block_invoked) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(add)operator(()ident(a)operator(,) ident(b)operator(\)) + ident(a) operator(+) ident(b) + reserved(end) + + reserved(def) method(transmogrify)operator(()ident(str)operator(\)) + ident(str)operator(.)ident(upcase) + reserved(end) + + reserved(def) method(fail_with_reason) + reserved(end) + + reserved(def) method(fail_generic) + reserved(end) + + reserved(def) method(no_before) + integer(5) + reserved(end) + + reserved(def) method(no_after) + reserved(end) + + reserved(def) method(only_one) + reserved(end) + + reserved(def) method(only_two) + reserved(end) + + ident(protected) + reserved(def) method(intercept_before)operator(()ident(name)operator(,) ident(args)operator(\)) + instance_variable(@before_invoked) operator(=) ident(name) + reserved(return) operator([)pre_constant(false)operator(,) string<delimiter(")content(permission denied)delimiter(")>operator(]) reserved(if) ident(name) operator(==) symbol(:fail_with_reason) + reserved(return) pre_constant(false) reserved(if) ident(name) operator(==) symbol(:fail_generic) + reserved(end) + + reserved(def) method(intercept_after)operator(()ident(name)operator(,) ident(args)operator(,) ident(result)operator(\)) + instance_variable(@after_invoked) operator(=) ident(name) + instance_variable(@invocation_result) operator(=) ident(result) + reserved(end) + + reserved(def) method(intercept_after_first)operator(()ident(name)operator(,) ident(args)operator(,) ident(result)operator(\)) + instance_variable(@after_first_invoked) operator(=) ident(name) + reserved(end) + + reserved(def) method(intercept_only)operator(()ident(name)operator(,) ident(args)operator(\)) + ident(raise) string<delimiter(")content(Interception error)delimiter(")> reserved(unless) ident(name) operator(==) symbol(:only_one) operator(||) ident(name) operator(==) symbol(:only_two) + instance_variable(@only_invoked) operator(=) ident(name) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(TC_Invocation) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(ActionWebService)operator(::)constant(Invocation) + + reserved(def) method(setup) + instance_variable(@service) operator(=) constant(InvocationTest)operator(::)constant(Service)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_invocation) + ident(assert)operator(()ident(perform_invocation)operator(()symbol(:add)operator(,) integer(5)operator(,) integer(10)operator(\)) operator(==) integer(15)operator(\)) + ident(assert)operator(()ident(perform_invocation)operator(()symbol(:transmogrify)operator(,) string<delimiter(")content(hello)delimiter(")>operator(\)) operator(==) string<delimiter(")content(HELLO)delimiter(")>operator(\)) + ident(assert_raises)operator(()constant(NoMethodError)operator(\)) reserved(do) + ident(perform_invocation)operator(()symbol(:nonexistent_method_xyzzy)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_interceptor_registration) + ident(assert)operator(()constant(InvocationTest)operator(::)constant(Service)operator(.)ident(before_invocation_interceptors)operator(.)ident(length) operator(==) integer(2)operator(\)) + ident(assert)operator(()constant(InvocationTest)operator(::)constant(Service)operator(.)ident(after_invocation_interceptors)operator(.)ident(length) operator(==) integer(4)operator(\)) + ident(assert_equal)operator(()symbol(:intercept_only)operator(,) constant(InvocationTest)operator(::)constant(Service)operator(.)ident(before_invocation_interceptors)operator([)integer(0)operator(])operator(\)) + ident(assert_equal)operator(()symbol(:intercept_after_first)operator(,) constant(InvocationTest)operator(::)constant(Service)operator(.)ident(after_invocation_interceptors)operator([)integer(0)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_interception) + ident(assert)operator(()instance_variable(@service)operator(.)ident(before_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(only_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(block_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(invocation_result)operator(.)ident(nil?)operator(\)) + ident(perform_invocation)operator(()symbol(:add)operator(,) integer(20)operator(,) integer(50)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(before_invoked) operator(==) symbol(:add)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_invoked) operator(==) symbol(:add)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(invocation_result) operator(==) integer(70)operator(\)) + reserved(end) + + reserved(def) method(test_interception_canceling) + ident(reason) operator(=) pre_constant(nil) + ident(perform_invocation)operator(()symbol(:fail_with_reason)operator(\))operator({)operator(|)ident(r)operator(|) ident(reason) operator(=) ident(r)operator(}) + ident(assert)operator(()instance_variable(@service)operator(.)ident(before_invoked) operator(==) symbol(:fail_with_reason)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(invocation_result)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()ident(reason) operator(==) string<delimiter(")content(permission denied)delimiter(")>operator(\)) + ident(reason) operator(=) pre_constant(true) + instance_variable(@service)operator(.)ident(before_invoked) operator(=) instance_variable(@service)operator(.)ident(after_invoked) operator(=) instance_variable(@service)operator(.)ident(invocation_result) operator(=) pre_constant(nil) + ident(perform_invocation)operator(()symbol(:fail_generic)operator(\))operator({)operator(|)ident(r)operator(|) ident(reason) operator(=) ident(r)operator(}) + ident(assert)operator(()instance_variable(@service)operator(.)ident(before_invoked) operator(==) symbol(:fail_generic)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(invocation_result)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()ident(reason) operator(==) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_interception_except_conditions) + ident(perform_invocation)operator(()symbol(:no_before)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(before_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_first_invoked) operator(==) symbol(:no_before)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_invoked) operator(==) symbol(:no_before)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(invocation_result) operator(==) integer(5)operator(\)) + instance_variable(@service)operator(.)ident(before_invoked) operator(=) instance_variable(@service)operator(.)ident(after_invoked) operator(=) instance_variable(@service)operator(.)ident(invocation_result) operator(=) pre_constant(nil) + ident(perform_invocation)operator(()symbol(:no_after)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(before_invoked) operator(==) symbol(:no_after)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(after_invoked)operator(.)ident(nil?)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(invocation_result)operator(.)ident(nil?)operator(\)) + reserved(end) + + reserved(def) method(test_interception_only_conditions) + ident(assert)operator(()instance_variable(@service)operator(.)ident(only_invoked)operator(.)ident(nil?)operator(\)) + ident(perform_invocation)operator(()symbol(:only_one)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(only_invoked) operator(==) symbol(:only_one)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(block_invoked) operator(==) symbol(:only_one)operator(\)) + ident(assert)operator(()constant(InvocationTest)operator(::)constant(InterceptorClass)operator(.)ident(args)operator([)integer(1)operator(]) operator(==) symbol(:only_one)operator(\)) + instance_variable(@service)operator(.)ident(only_invoked) operator(=) pre_constant(nil) + ident(perform_invocation)operator(()symbol(:only_two)operator(\)) + ident(assert)operator(()instance_variable(@service)operator(.)ident(only_invoked) operator(==) symbol(:only_two)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(perform_invocation)operator(()ident(method_name)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + instance_variable(@service)operator(.)ident(perform_invocation)operator(()ident(method_name)operator(,) ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +constant(ActionController)operator(::)constant(Routing)operator(::)constant(Routes)operator(.)ident(draw) reserved(do) operator(|)ident(map)operator(|) + ident(map)operator(.)ident(connect) string<delimiter(')delimiter(')>operator(,) symbol(:controller) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')> + ident(map)operator(.)ident(connect) string<delimiter(')content(:controller/:action/:id)delimiter(')> +reserved(end) + +constant(ActionController)operator(::)constant(Base)operator(.)ident(template_root) operator(=) string<delimiter(')content(.)delimiter(')> + +reserved(class) class(ScaffoldPerson) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:id)operator(,) symbol(:int) + ident(member) symbol(:name)operator(,) symbol(:string) + ident(member) symbol(:birth)operator(,) symbol(:date) + + reserved(def) method(==)operator(()ident(other)operator(\)) + pre_constant(self)operator(.)ident(id) operator(==) ident(other)operator(.)ident(id) operator(&&) pre_constant(self)operator(.)ident(name) operator(==) ident(other)operator(.)ident(name) + reserved(end) +reserved(end) + +reserved(class) class(ScaffoldedControllerTestAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:hello)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:integer)operator(=)operator(>)symbol(:int)operator(})operator(,) symbol(:string)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:bool)operator(]) + ident(api_method) symbol(:hello_struct_param)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:person) operator(=)operator(>) constant(ScaffoldPerson)operator(})operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:bool)operator(]) + ident(api_method) symbol(:date_of_birth)operator(,) symbol(:expects) operator(=)operator(>) operator([)constant(ScaffoldPerson)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:string)operator(]) + ident(api_method) symbol(:bye)operator(,) symbol(:returns) operator(=)operator(>) operator([)operator([)constant(ScaffoldPerson)operator(])operator(]) + ident(api_method) symbol(:date_diff)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:start_date) operator(=)operator(>) symbol(:date)operator(})operator(,) operator({)symbol(:end_date) operator(=)operator(>) symbol(:date)operator(})operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:time_diff)operator(,) symbol(:expects) operator(=)operator(>) operator([)operator({)symbol(:start_time) operator(=)operator(>) symbol(:time)operator(})operator(,) operator({)symbol(:end_time) operator(=)operator(>) symbol(:time)operator(})operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) + ident(api_method) symbol(:base64_upcase)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:base64)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:base64)operator(]) +reserved(end) + +reserved(class) class(ScaffoldedController) operator(<) constant(ActionController)operator(::)constant(Base) + ident(web_service_api) constant(ScaffoldedControllerTestAPI) + ident(web_service_scaffold) symbol(:scaffold_invoke) + + reserved(def) method(hello)operator(()ident(int)operator(,) ident(string)operator(\)) + integer(0) + reserved(end) + + reserved(def) method(hello_struct_param)operator(()ident(person)operator(\)) + integer(0) + reserved(end) + + reserved(def) method(date_of_birth)operator(()ident(person)operator(\)) + ident(person)operator(.)ident(birth)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(bye) + operator([)constant(ScaffoldPerson)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(1)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(leon)delimiter(")>operator(\))operator(,) constant(ScaffoldPerson)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(2)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(paul)delimiter(")>operator(\))operator(]) + reserved(end) + + reserved(def) method(rescue_action)operator(()ident(e)operator(\)) + ident(raise) ident(e) + reserved(end) + + reserved(def) method(date_diff)operator(()ident(start_date)operator(,) ident(end_date)operator(\)) + ident(end_date) operator(-) ident(start_date) + reserved(end) + + reserved(def) method(time_diff)operator(()ident(start_time)operator(,) ident(end_time)operator(\)) + ident(end_time) operator(-) ident(start_time) + reserved(end) + + reserved(def) method(base64_upcase)operator(()ident(data)operator(\)) + ident(data)operator(.)ident(upcase) + reserved(end) +reserved(end) + +reserved(class) class(ScaffoldedControllerTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@controller) operator(=) constant(ScaffoldedController)operator(.)ident(new) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_scaffold_invoke) + ident(get) symbol(:scaffold_invoke) + ident(assert_rendered_file) string<delimiter(')content(methods.rhtml)delimiter(')> + reserved(end) + + reserved(def) method(test_scaffold_invoke_method_params) + ident(get) symbol(:scaffold_invoke_method_params)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(Hello)delimiter(')> + ident(assert_rendered_file) string<delimiter(')content(parameters.rhtml)delimiter(')> + reserved(end) + + reserved(def) method(test_scaffold_invoke_method_params_with_struct) + ident(get) symbol(:scaffold_invoke_method_params)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(HelloStructParam)delimiter(')> + ident(assert_rendered_file) string<delimiter(')content(parameters.rhtml)delimiter(')> + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(')content(input)delimiter(')>operator(,) symbol(:attributes) operator(=)operator(>) operator({)symbol(:name) operator(=)operator(>) string<delimiter(")content(method_params[0][name])delimiter(")>operator(}) + reserved(end) + + reserved(def) method(test_scaffold_invoke_submit_hello) + ident(post) symbol(:scaffold_invoke_submit)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(Hello)delimiter(')>operator(,) symbol(:method_params) operator(=)operator(>) operator({)string<delimiter(')content(0)delimiter(')> operator(=)operator(>) string<delimiter(')content(5)delimiter(')>operator(,) string<delimiter(')content(1)delimiter(')> operator(=)operator(>) string<delimiter(')content(hello world)delimiter(')>operator(}) + ident(assert_rendered_file) string<delimiter(')content(result.rhtml)delimiter(')> + ident(assert_equal) pre_constant(false)operator(,) instance_variable(@controller)operator(.)ident(instance_eval)operator({) instance_variable(@method_return_value) operator(}) + reserved(end) + + reserved(def) method(test_scaffold_invoke_submit_bye) + ident(post) symbol(:scaffold_invoke_submit)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(Bye)delimiter(')> + ident(assert_rendered_file) string<delimiter(')content(result.rhtml)delimiter(')> + ident(persons) operator(=) operator([)constant(ScaffoldPerson)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(1)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(leon)delimiter(")>operator(\))operator(,) constant(ScaffoldPerson)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(2)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(paul)delimiter(")>operator(\))operator(]) + ident(assert_equal) ident(persons)operator(,) instance_variable(@controller)operator(.)ident(instance_eval)operator({) instance_variable(@method_return_value) operator(}) + reserved(end) + + reserved(def) method(test_scaffold_date_params) + ident(get) symbol(:scaffold_invoke_method_params)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(DateDiff)delimiter(')> + operator(()integer(0)operator(..)integer(1)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(param)operator(|) + operator(()integer(1)operator(..)integer(3)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(date_part)operator(|) + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(')content(select)delimiter(')>operator(,) symbol(:attributes) operator(=)operator(>) operator({)symbol(:name) operator(=)operator(>) string<delimiter(")content(method_params[)inline<inline_delimiter(#{)ident(param)inline_delimiter(})>content(][)inline<inline_delimiter(#{)ident(date_part)inline_delimiter(})>content(])delimiter(")>operator(})operator(,) + symbol(:children) operator(=)operator(>) operator({)symbol(:greater_than) operator(=)operator(>) integer(1)operator(,) symbol(:only) operator(=)operator(>) operator({)symbol(:tag) operator(=)operator(>) string<delimiter(')content(option)delimiter(')>operator(})operator(}) + reserved(end) + reserved(end) + + ident(post) symbol(:scaffold_invoke_submit)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(DateDiff)delimiter(')>operator(,) + symbol(:method_params) operator(=)operator(>) operator({)string<delimiter(')content(0)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(1)delimiter(')> operator(=)operator(>) string<delimiter(')content(2006)delimiter(')>operator(,) string<delimiter(')content(2)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(3)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(})operator(,) string<delimiter(')content(1)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(1)delimiter(')> operator(=)operator(>) string<delimiter(')content(2006)delimiter(')>operator(,) string<delimiter(')content(2)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(3)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(})operator(}) + ident(assert_equal) integer(1)operator(,) instance_variable(@controller)operator(.)ident(instance_eval)operator({) instance_variable(@method_return_value) operator(}) + reserved(end) + + reserved(def) method(test_scaffold_struct_date_params) + ident(post) symbol(:scaffold_invoke_submit)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(DateOfBirth)delimiter(')>operator(,) + symbol(:method_params) operator(=)operator(>) operator({)string<delimiter(')content(0)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(birth)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(1)delimiter(')> operator(=)operator(>) string<delimiter(')content(2006)delimiter(')>operator(,) string<delimiter(')content(2)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(3)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(})operator(,) string<delimiter(')content(id)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(person)delimiter(')>operator(})operator(}) + ident(assert_equal) string<delimiter(')content(2006-02-01)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(instance_eval)operator({) instance_variable(@method_return_value) operator(}) + reserved(end) + + reserved(def) method(test_scaffold_time_params) + ident(get) symbol(:scaffold_invoke_method_params)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(TimeDiff)delimiter(')> + operator(()integer(0)operator(..)integer(1)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(param)operator(|) + operator(()integer(1)operator(..)integer(6)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(date_part)operator(|) + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(')content(select)delimiter(')>operator(,) symbol(:attributes) operator(=)operator(>) operator({)symbol(:name) operator(=)operator(>) string<delimiter(")content(method_params[)inline<inline_delimiter(#{)ident(param)inline_delimiter(})>content(][)inline<inline_delimiter(#{)ident(date_part)inline_delimiter(})>content(])delimiter(")>operator(})operator(,) + symbol(:children) operator(=)operator(>) operator({)symbol(:greater_than) operator(=)operator(>) integer(1)operator(,) symbol(:only) operator(=)operator(>) operator({)symbol(:tag) operator(=)operator(>) string<delimiter(')content(option)delimiter(')>operator(})operator(}) + reserved(end) + reserved(end) + + ident(post) symbol(:scaffold_invoke_submit)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(TimeDiff)delimiter(')>operator(,) + symbol(:method_params) operator(=)operator(>) operator({)string<delimiter(')content(0)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(1)delimiter(')> operator(=)operator(>) string<delimiter(')content(2006)delimiter(')>operator(,) string<delimiter(')content(2)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(3)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(4)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(5)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(6)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(})operator(,) + string<delimiter(')content(1)delimiter(')> operator(=)operator(>) operator({)string<delimiter(')content(1)delimiter(')> operator(=)operator(>) string<delimiter(')content(2006)delimiter(')>operator(,) string<delimiter(')content(2)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(3)delimiter(')> operator(=)operator(>) string<delimiter(')content(2)delimiter(')>operator(,) string<delimiter(')content(4)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(5)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(,) string<delimiter(')content(6)delimiter(')> operator(=)operator(>) string<delimiter(')content(1)delimiter(')>operator(})operator(}) + ident(assert_equal) integer(86400)operator(,) instance_variable(@controller)operator(.)ident(instance_eval)operator({) instance_variable(@method_return_value) operator(}) + reserved(end) + + reserved(def) method(test_scaffold_base64) + ident(get) symbol(:scaffold_invoke_method_params)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(Base64Upcase)delimiter(')> + ident(assert_tag) symbol(:tag) operator(=)operator(>) string<delimiter(')content(textarea)delimiter(')>operator(,) symbol(:attributes) operator(=)operator(>) operator({)symbol(:name) operator(=)operator(>) string<delimiter(')content(method_params[0])delimiter(')>operator(}) + + ident(post) symbol(:scaffold_invoke_submit)operator(,) symbol(:service) operator(=)operator(>) string<delimiter(')content(scaffolded)delimiter(')>operator(,) symbol(:method) operator(=)operator(>) string<delimiter(')content(Base64Upcase)delimiter(')>operator(,) symbol(:method_params) operator(=)operator(>) operator({)string<delimiter(')content(0)delimiter(')> operator(=)operator(>) string<delimiter(')content(scaffold)delimiter(')>operator(}) + ident(assert_equal) string<delimiter(')content(SCAFFOLD)delimiter(')>operator(,) instance_variable(@controller)operator(.)ident(instance_eval)operator({) instance_variable(@method_return_value) operator(}) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> + +reserved(module) class(StructTest) + reserved(class) class(Struct) operator(<) constant(ActionWebService)operator(::)constant(Struct) + ident(member) symbol(:id)operator(,) constant(Integer) + ident(member) symbol(:name)operator(,) constant(String) + ident(member) symbol(:items)operator(,) operator([)constant(String)operator(]) + ident(member) symbol(:deleted)operator(,) symbol(:bool) + ident(member) symbol(:emails)operator(,) operator([)symbol(:string)operator(]) + reserved(end) +reserved(end) + +reserved(class) class(TC_Struct) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(include) constant(StructTest) + + reserved(def) method(setup) + instance_variable(@struct) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(5)operator(,) + symbol(:name) operator(=)operator(>) string<delimiter(')content(hello)delimiter(')>operator(,) + symbol(:items) operator(=)operator(>) operator([)string<delimiter(')content(one)delimiter(')>operator(,) string<delimiter(')content(two)delimiter(')>operator(])operator(,) + symbol(:deleted) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:emails) operator(=)operator(>) operator([)string<delimiter(')content(test@test.com)delimiter(')>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_members) + ident(assert_equal)operator(()integer(5)operator(,) constant(Struct)operator(.)ident(members)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()constant(Integer)operator(,) constant(Struct)operator(.)ident(members)operator([)symbol(:id)operator(])operator(.)ident(type_class)operator(\)) + ident(assert_equal)operator(()constant(String)operator(,) constant(Struct)operator(.)ident(members)operator([)symbol(:name)operator(])operator(.)ident(type_class)operator(\)) + ident(assert_equal)operator(()constant(String)operator(,) constant(Struct)operator(.)ident(members)operator([)symbol(:items)operator(])operator(.)ident(element_type)operator(.)ident(type_class)operator(\)) + ident(assert_equal)operator(()constant(TrueClass)operator(,) constant(Struct)operator(.)ident(members)operator([)symbol(:deleted)operator(])operator(.)ident(type_class)operator(\)) + ident(assert_equal)operator(()constant(String)operator(,) constant(Struct)operator(.)ident(members)operator([)symbol(:emails)operator(])operator(.)ident(element_type)operator(.)ident(type_class)operator(\)) + reserved(end) + + reserved(def) method(test_initializer_and_lookup) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@struct)operator(.)ident(id)operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(hello)delimiter(')>operator(,) instance_variable(@struct)operator(.)ident(name)operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(')content(one)delimiter(')>operator(,) string<delimiter(')content(two)delimiter(')>operator(])operator(,) instance_variable(@struct)operator(.)ident(items)operator(\)) + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@struct)operator(.)ident(deleted)operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(')content(test@test.com)delimiter(')>operator(])operator(,) instance_variable(@struct)operator(.)ident(emails)operator(\)) + ident(assert_equal)operator(()integer(5)operator(,) instance_variable(@struct)operator([)string<delimiter(')content(id)delimiter(')>operator(])operator(\)) + ident(assert_equal)operator(()string<delimiter(')content(hello)delimiter(')>operator(,) instance_variable(@struct)operator([)string<delimiter(')content(name)delimiter(')>operator(])operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(')content(one)delimiter(')>operator(,) string<delimiter(')content(two)delimiter(')>operator(])operator(,) instance_variable(@struct)operator([)string<delimiter(')content(items)delimiter(')>operator(])operator(\)) + ident(assert_equal)operator(()pre_constant(true)operator(,) instance_variable(@struct)operator([)string<delimiter(')content(deleted)delimiter(')>operator(])operator(\)) + ident(assert_equal)operator(()operator([)string<delimiter(')content(test@test.com)delimiter(')>operator(])operator(,) instance_variable(@struct)operator([)string<delimiter(')content(emails)delimiter(')>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_each_pair) + instance_variable(@struct)operator(.)ident(each_pair) reserved(do) operator(|)ident(name)operator(,) ident(value)operator(|) + ident(assert_equal) instance_variable(@struct)operator(.)ident(__send__)operator(()ident(name)operator(\))operator(,) ident(value) + ident(assert_equal) instance_variable(@struct)operator([)ident(name)operator(])operator(,) ident(value) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(action_web_service/test_invoke)delimiter(')> + +reserved(class) class(TestInvokeAPI) operator(<) constant(ActionWebService)operator(::)constant(API)operator(::)constant(Base) + ident(api_method) symbol(:add)operator(,) symbol(:expects) operator(=)operator(>) operator([)symbol(:int)operator(,) symbol(:int)operator(])operator(,) symbol(:returns) operator(=)operator(>) operator([)symbol(:int)operator(]) +reserved(end) + +reserved(class) class(TestInvokeService) operator(<) constant(ActionWebService)operator(::)constant(Base) + ident(web_service_api) constant(TestInvokeAPI) + + ident(attr) symbol(:invoked) + + reserved(def) method(add)operator(()ident(a)operator(,) ident(b)operator(\)) + instance_variable(@invoked) operator(=) pre_constant(true) + ident(a) operator(+) ident(b) + reserved(end) +reserved(end) + +reserved(class) class(TestController) operator(<) constant(ActionController)operator(::)constant(Base) + reserved(def) method(rescue_action)operator(()ident(e)operator(\))operator(;) ident(raise) ident(e)operator(;) reserved(end) +reserved(end) + +reserved(class) class(TestInvokeDirectController) operator(<) constant(TestController) + ident(web_service_api) constant(TestInvokeAPI) + + ident(attr) symbol(:invoked) + + reserved(def) method(add) + instance_variable(@invoked) operator(=) pre_constant(true) + instance_variable(@method_params)operator([)integer(0)operator(]) operator(+) instance_variable(@method_params)operator([)integer(1)operator(]) + reserved(end) +reserved(end) + +reserved(class) class(TestInvokeDelegatedController) operator(<) constant(TestController) + ident(web_service_dispatching_mode) symbol(:delegated) + ident(web_service) symbol(:service)operator(,) constant(TestInvokeService)operator(.)ident(new) +reserved(end) + +reserved(class) class(TestInvokeLayeredController) operator(<) constant(TestController) + ident(web_service_dispatching_mode) symbol(:layered) + ident(web_service)operator(()symbol(:one)operator(\)) operator({) instance_variable(@service_one) operator(||=) constant(TestInvokeService)operator(.)ident(new) operator(}) + ident(web_service)operator(()symbol(:two)operator(\)) operator({) instance_variable(@service_two) operator(||=) constant(TestInvokeService)operator(.)ident(new) operator(}) +reserved(end) + +reserved(class) class(TestInvokeTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@request) operator(=) constant(ActionController)operator(::)constant(TestRequest)operator(.)ident(new) + instance_variable(@response) operator(=) constant(ActionController)operator(::)constant(TestResponse)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_direct_add) + instance_variable(@controller) operator(=) constant(TestInvokeDirectController)operator(.)ident(new) + ident(assert_equal) pre_constant(nil)operator(,) instance_variable(@controller)operator(.)ident(invoked) + ident(result) operator(=) ident(invoke) symbol(:add)operator(,) integer(25)operator(,) integer(25) + ident(assert_equal) integer(50)operator(,) ident(result) + ident(assert_equal) pre_constant(true)operator(,) instance_variable(@controller)operator(.)ident(invoked) + reserved(end) + + reserved(def) method(test_delegated_add) + instance_variable(@controller) operator(=) constant(TestInvokeDelegatedController)operator(.)ident(new) + ident(assert_equal) pre_constant(nil)operator(,) instance_variable(@controller)operator(.)ident(web_service_object)operator(()symbol(:service)operator(\))operator(.)ident(invoked) + ident(result) operator(=) ident(invoke_delegated) symbol(:service)operator(,) symbol(:add)operator(,) integer(100)operator(,) integer(50) + ident(assert_equal) integer(150)operator(,) ident(result) + ident(assert_equal) pre_constant(true)operator(,) instance_variable(@controller)operator(.)ident(web_service_object)operator(()symbol(:service)operator(\))operator(.)ident(invoked) + reserved(end) + + reserved(def) method(test_layered_add) + operator([)symbol(:soap)operator(,) symbol(:xmlrpc)operator(])operator(.)ident(each) reserved(do) operator(|)ident(protocol)operator(|) + instance_variable(@protocol) operator(=) ident(protocol) + operator([)symbol(:one)operator(,) symbol(:two)operator(])operator(.)ident(each) reserved(do) operator(|)ident(service)operator(|) + instance_variable(@controller) operator(=) constant(TestInvokeLayeredController)operator(.)ident(new) + ident(assert_equal) pre_constant(nil)operator(,) instance_variable(@controller)operator(.)ident(web_service_object)operator(()ident(service)operator(\))operator(.)ident(invoked) + ident(result) operator(=) ident(invoke_layered) ident(service)operator(,) symbol(:add)operator(,) integer(200)operator(,) integer(-50) + ident(assert_equal) integer(150)operator(,) ident(result) + ident(assert_equal) pre_constant(true)operator(,) instance_variable(@controller)operator(.)ident(web_service_object)operator(()ident(service)operator(\))operator(.)ident(invoked) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_layered_fail_with_wrong_number_of_arguments) + operator([)symbol(:soap)operator(,) symbol(:xmlrpc)operator(])operator(.)ident(each) reserved(do) operator(|)ident(protocol)operator(|) + instance_variable(@protocol) operator(=) ident(protocol) + operator([)symbol(:one)operator(,) symbol(:two)operator(])operator(.)ident(each) reserved(do) operator(|)ident(service)operator(|) + instance_variable(@controller) operator(=) constant(TestInvokeLayeredController)operator(.)ident(new) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) ident(invoke_layered) ident(service)operator(,) symbol(:add)operator(,) integer(1) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_delegated_fail_with_wrong_number_of_arguments) + instance_variable(@controller) operator(=) constant(TestInvokeDelegatedController)operator(.)ident(new) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) ident(invoke_delegated) symbol(:service)operator(,) symbol(:add)operator(,) integer(1) operator(}) + reserved(end) + + reserved(def) method(test_direct_fail_with_wrong_number_of_arguments) + instance_variable(@controller) operator(=) constant(TestInvokeDirectController)operator(.)ident(new) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) ident(invoke) symbol(:add)operator(,) integer(1) operator(}) + reserved(end) + +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/shared_setup)delimiter(')> + +ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()constant(STDOUT)operator(\)) + +comment(# Database setup ---------------) + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Create tables)delimiter(")> + +operator([) string<delimiter(")content(DROP TABLE companies)delimiter(")>operator(,) string<delimiter(")content(DROP TABLE people)delimiter(")>operator(,) string<delimiter(")content(DROP TABLE people_companies)delimiter(")>operator(,) + string<delimiter(")content(CREATE TABLE companies (id int(11\) auto_increment, client_of int(11\), name varchar(255\), type varchar(100\), PRIMARY KEY (id\)\))delimiter(")>operator(,) + string<delimiter(")content(CREATE TABLE people (id int(11\) auto_increment, name varchar(100\), PRIMARY KEY (id\)\))delimiter(")>operator(,) + string<delimiter(")content(CREATE TABLE people_companies (person_id int(11\), company_id int(11\), PRIMARY KEY (person_id, company_id\)\))delimiter(")>operator(,) +operator(])operator(.)ident(each) operator({) operator(|)ident(statement)operator(|) + comment(# Tables doesn't necessarily already exist) + reserved(begin)operator(;) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(statement)operator(\))operator(;) reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(;) reserved(end) +operator(}) + + +comment(# Class setup ---------------) + +reserved(class) class(Company) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:people)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Person)delimiter(")>operator(,) symbol(:join_table) operator(=)operator(>) string<delimiter(")content(people_companies)delimiter(")>operator(,) symbol(:table_name) operator(=)operator(>) string<delimiter(")content(people)delimiter(")> +reserved(end) + +reserved(class) class(Firm) operator(<) constant(Company) + ident(has_many) symbol(:clients)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")> + + reserved(def) method(people_with_all_clients) + ident(clients)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) operator({) operator(|)ident(people)operator(,) ident(client)operator(|) ident(people) operator(+) ident(client)operator(.)ident(people) operator(}) + reserved(end) +reserved(end) + +reserved(class) class(Client) operator(<) constant(Company) + ident(belongs_to) symbol(:firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")> +reserved(end) + +reserved(class) class(Person) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:companies)operator(,) symbol(:join_table) operator(=)operator(>) string<delimiter(")content(people_companies)delimiter(")> + reserved(def) pre_constant(self)operator(.)ident(table_name)operator(()operator(\)) string<delimiter(")content(people)delimiter(")> reserved(end) +reserved(end) + + +comment(# Usage ---------------) + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Create fixtures)delimiter(")> + +constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Next Angle)delimiter(")>operator(\))operator(.)ident(save) +constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(37signals)delimiter(")>operator(,) string<delimiter(")content(client_of)delimiter(")> operator(=)operator(>) integer(1)operator(\))operator(.)ident(save) +constant(Person)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David)delimiter(")>operator(\))operator(.)ident(save) + + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Using Finders)delimiter(")> + +ident(next_angle) operator(=) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\)) +ident(next_angle) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) +ident(next_angle) operator(=) constant(Company)operator(.)ident(find_first) string<delimiter(")content(name = 'Next Angle')delimiter(")> +ident(next_angle) operator(=) constant(Firm)operator(.)ident(find_by_sql)operator(()string<delimiter(")content(SELECT * FROM companies WHERE id = 1)delimiter(")>operator(\))operator(.)ident(first) + +constant(Firm) operator(===) ident(next_angle) + + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Using has_many association)delimiter(")> + +ident(next_angle)operator(.)ident(has_clients?) +ident(next_angle)operator(.)ident(clients_count) +ident(all_clients) operator(=) ident(next_angle)operator(.)ident(clients) + +ident(thirty_seven_signals) operator(=) ident(next_angle)operator(.)ident(find_in_clients)operator(()integer(2)operator(\)) + + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Using belongs_to association)delimiter(")> + +ident(thirty_seven_signals)operator(.)ident(has_firm?) +ident(thirty_seven_signals)operator(.)ident(firm?)operator(()ident(next_angle)operator(\)) + + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Using has_and_belongs_to_many association)delimiter(")> + +ident(david) operator(=) constant(Person)operator(.)ident(find)operator(()integer(1)operator(\)) +ident(david)operator(.)ident(add_companies)operator(()ident(thirty_seven_signals)operator(,) ident(next_angle)operator(\)) +ident(david)operator(.)ident(companies)operator(.)ident(include?)operator(()ident(next_angle)operator(\)) +ident(david)operator(.)ident(companies_count) operator(==) integer(2) + +ident(david)operator(.)ident(remove_companies)operator(()ident(next_angle)operator(\)) +ident(david)operator(.)ident(companies_count) operator(==) integer(1) + +ident(thirty_seven_signals)operator(.)ident(people)operator(.)ident(include?)operator(()ident(david)operator(\))comment(# Be sure to change the mysql_connection details and create a database for the example) + +global_variable($:) operator(<<) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../lib)delimiter(')> + +ident(require) string<delimiter(')content(active_record)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')>operator(;) reserved(class) class(Logger)operator(;) reserved(def) method(format_message)operator(()ident(severity)operator(,) ident(timestamp)operator(,) ident(msg)operator(,) ident(progname)operator(\)) string<delimiter(")inline<inline_delimiter(#{)ident(msg)inline_delimiter(})>char(\\n)delimiter(")> reserved(end)operator(;) reserved(end) + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()constant(STDOUT)operator(\)) +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(mysql)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(root)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) string<delimiter(")content(activerecord_examples)delimiter(")> +operator(\)) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/shared_setup)delimiter(')> + +ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()constant(STDOUT)operator(\)) + +comment(# Database setup ---------------) + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Create tables)delimiter(")> + +operator([) string<delimiter(")content(DROP TABLE people)delimiter(")>operator(,) + string<delimiter(")content(CREATE TABLE people (id int(11\) auto_increment, name varchar(100\), pass varchar(100\), email varchar(100\), PRIMARY KEY (id\)\))delimiter(")> +operator(])operator(.)ident(each) operator({) operator(|)ident(statement)operator(|) + reserved(begin)operator(;) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(statement)operator(\))operator(;) reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(;) reserved(end) comment(# Tables doesn't necessarily already exist) +operator(}) + + +comment(# Class setup ---------------) + +reserved(class) class(Person) operator(<) constant(ActiveRecord)operator(::)constant(Base) + comment(# Using ) + reserved(def) pre_constant(self)operator(.)ident(authenticate)operator(()ident(name)operator(,) ident(pass)operator(\)) + comment(# find_first "name = '#{name}' AND pass = '#{pass}'" would be open to sql-injection (in a web-app scenario\)) + ident(find_first) operator([) string<delimiter(")content(name = '%s' AND pass = '%s')delimiter(")>operator(,) ident(name)operator(,) ident(pass) operator(]) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(name_exists?)operator(()ident(name)operator(,) ident(id) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(id)operator(.)ident(nil?) + ident(condition) operator(=) operator([) string<delimiter(")content(name = '%s')delimiter(")>operator(,) ident(name) operator(]) + reserved(else) + comment(# Check if anyone else than the person identified by person_id has that user_name) + ident(condition) operator(=) operator([) string<delimiter(")content(name = '%s' AND id <> %d)delimiter(")>operator(,) ident(name)operator(,) ident(id) operator(]) + reserved(end) + + operator(!)ident(find_first)operator(()ident(condition)operator(\))operator(.)ident(nil?) + reserved(end) + + reserved(def) method(email_address_with_name) + string<delimiter(")char(\\")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>char(\\")content( <)inline<inline_delimiter(#{)ident(email)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + ident(protected) + reserved(def) method(validate) + ident(errors)operator(.)ident(add_on_empty)operator(()string<delimiter(%w()content(name pass email)delimiter(\))>operator(\)) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(email)delimiter(")>operator(,) string<delimiter(")content(must be valid)delimiter(")>operator(\)) reserved(unless) ident(email_address_valid?) + reserved(end) + + reserved(def) method(validate_on_create) + reserved(if) ident(attribute_present?)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) operator(&&) constant(Person)operator(.)ident(name_exists?)operator(()ident(name)operator(\)) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(name)delimiter(")>operator(,) string<delimiter(")content(is already taken by another person)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(validate_on_update) + reserved(if) ident(attribute_present?)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) operator(&&) constant(Person)operator(.)ident(name_exists?)operator(()ident(name)operator(,) ident(id)operator(\)) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(name)delimiter(")>operator(,) string<delimiter(")content(is already taken by another person)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(email_address_valid?)operator(()operator(\)) ident(email) operator(=)operator(~) regexp<delimiter(/)char(\\w)content([-.)char(\\w)content(]*)char(\\@)content([-)char(\\w)content(]+[-.)char(\\w)content(]*)char(\\.)char(\\w)content(+)delimiter(/)> reserved(end) +reserved(end) + +comment(# Usage ---------------) + +ident(logger)operator(.)ident(info) string<delimiter(")char(\\n)content(Create fixtures)delimiter(")> +ident(david) operator(=) constant(Person)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(,) string<delimiter(")content(pass)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(email)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(\)) +reserved(unless) ident(david)operator(.)ident(save) + ident(puts) string<delimiter(")content(There was )inline<inline_delimiter(#{)ident(david)operator(.)ident(errors)operator(.)ident(count)inline_delimiter(})>content( error(s\))delimiter(")> + ident(david)operator(.)ident(errors)operator(.)ident(each_full) operator({) operator(|)ident(error)operator(|) ident(puts) ident(error) operator(}) +reserved(end) + +ident(david)operator(.)ident(pass) operator(=) string<delimiter(")content(something)delimiter(")> +ident(david)operator(.)ident(email) operator(=) string<delimiter(")content(invalid_address)delimiter(")> +reserved(unless) ident(david)operator(.)ident(save) + ident(puts) string<delimiter(")content(There was )inline<inline_delimiter(#{)ident(david)operator(.)ident(errors)operator(.)ident(count)inline_delimiter(})>content( error(s\))delimiter(")> + ident(puts) string<delimiter(")content(It was email with: )delimiter(")> operator(+) ident(david)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(email)delimiter(")>operator(\)) +reserved(end) + +ident(david)operator(.)ident(email) operator(=) string<delimiter(")content(david@loudthinking.com)delimiter(")> +reserved(if) ident(david)operator(.)ident(save) reserved(then) ident(puts) string<delimiter(")content(David finally made it!)delimiter(")> reserved(end) + + +ident(another_david) operator(=) constant(Person)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David Heinemeier Hansson)delimiter(")>operator(,) string<delimiter(")content(pass)delimiter(")> operator(=)operator(>) string<delimiter(")content(xc)delimiter(")>operator(,) string<delimiter(")content(email)delimiter(")> operator(=)operator(>) string<delimiter(")content(david@loudthinking)delimiter(")>operator(\)) +reserved(unless) ident(another_david)operator(.)ident(save) + ident(puts) string<delimiter(")content(Error on name: )delimiter(")> operator(+) ident(another_david)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) +ident(endrequire) string<delimiter(')content(rbconfig)delimiter(')> +ident(require) string<delimiter(')content(find)delimiter(')> +ident(require) string<delimiter(')content(ftools)delimiter(')> + +ident(include) constant(Config) + +comment(# this was adapted from rdoc's install.rb by ways of Log4r) + +global_variable($sitedir) operator(=) constant(CONFIG)operator([)string<delimiter(")content(sitelibdir)delimiter(")>operator(]) +reserved(unless) global_variable($sitedir) + ident(version) operator(=) constant(CONFIG)operator([)string<delimiter(")content(MAJOR)delimiter(")>operator(]) operator(+) string<delimiter(")content(.)delimiter(")> operator(+) constant(CONFIG)operator([)string<delimiter(")content(MINOR)delimiter(")>operator(]) + global_variable($libdir) operator(=) constant(File)operator(.)ident(join)operator(()constant(CONFIG)operator([)string<delimiter(")content(libdir)delimiter(")>operator(])operator(,) string<delimiter(")content(ruby)delimiter(")>operator(,) ident(version)operator(\)) + global_variable($sitedir) operator(=) global_variable($:)operator(.)ident(find) operator({)operator(|)ident(x)operator(|) ident(x) operator(=)operator(~) regexp<delimiter(/)content(site_ruby)delimiter(/)> operator(}) + reserved(if) operator(!)global_variable($sitedir) + global_variable($sitedir) operator(=) constant(File)operator(.)ident(join)operator(()global_variable($libdir)operator(,) string<delimiter(")content(site_ruby)delimiter(")>operator(\)) + reserved(elsif) global_variable($sitedir) operator(!)operator(~) constant(Regexp)operator(.)ident(quote)operator(()ident(version)operator(\)) + global_variable($sitedir) operator(=) constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) ident(version)operator(\)) + reserved(end) +reserved(end) + +comment(# the acual gruntwork) +constant(Dir)operator(.)ident(chdir)operator(()string<delimiter(")content(lib)delimiter(")>operator(\)) + +constant(Find)operator(.)ident(find)operator(()string<delimiter(")content(active_record)delimiter(")>operator(,) string<delimiter(")content(active_record.rb)delimiter(")>operator(\)) operator({) operator(|)ident(f)operator(|) + reserved(if) ident(f)operator([)integer(-3)operator(..)integer(-1)operator(]) operator(==) string<delimiter(")content(.rb)delimiter(")> + constant(File)operator(::)ident(install)operator(()ident(f)operator(,) constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) operator(*)ident(f)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator(\))operator(,) integer(0644)operator(,) pre_constant(true)operator(\)) + reserved(else) + constant(File)operator(::)ident(makedirs)operator(()constant(File)operator(.)ident(join)operator(()global_variable($sitedir)operator(,) operator(*)ident(f)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\/)delimiter(/)>operator(\))operator(\))operator(\)) + reserved(end) +operator(}) +reserved(module) class(ActiveRecord) + reserved(module) class(Acts) comment(#:nodoc:) + reserved(module) class(List) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# This act provides the capabilities for sorting and reordering a number of objects in a list.) + comment(# The class that has this specified needs to have a "position" column defined as an integer on) + comment(# the mapped database table.) + comment(#) + comment(# Todo list example:) + comment(#) + comment(# class TodoList < ActiveRecord::Base) + comment(# has_many :todo_items, :order => "position") + comment(# end) + comment(#) + comment(# class TodoItem < ActiveRecord::Base) + comment(# belongs_to :todo_list) + comment(# acts_as_list :scope => :todo_list) + comment(# end) + comment(#) + comment(# todo_list.first.move_to_bottom) + comment(# todo_list.last.move_higher) + reserved(module) class(ClassMethods) + comment(# Configuration options are:) + comment(#) + comment(# * +column+ - specifies the column name to use for keeping the position integer (default: position\)) + comment(# * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id" ) + comment(# (if that hasn't been already\) and use that as the foreign key restriction. It's also possible ) + comment(# to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.) + comment(# Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>) + reserved(def) method(acts_as_list)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(configuration) operator(=) operator({) symbol(:column) operator(=)operator(>) string<delimiter(")content(position)delimiter(")>operator(,) symbol(:scope) operator(=)operator(>) string<delimiter(")content(1 = 1)delimiter(")> operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(options)operator(\)) reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(configuration)operator([)symbol(:scope)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])inline_delimiter(})>content(_id)delimiter(")>operator(.)ident(intern) reserved(if) ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) operator(&&) ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s) operator(!)operator(~) regexp<delimiter(/)content(_id$)delimiter(/)> + + reserved(if) ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + ident(scope_condition_method) operator(=) string<delimiter(%()content( + def scope_condition + if )inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content(.nil? + ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content( IS NULL" + else + ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content( = )char(\\#)content({)inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content(}" + end + end + )delimiter(\))> + reserved(else) + ident(scope_condition_method) operator(=) string<delimiter(")content(def scope_condition(\) )char(\\")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])inline_delimiter(})>char(\\")content( end)delimiter(")> + reserved(end) + + ident(class_eval) string<delimiter(<<-EOV)>string<content( + include ActiveRecord::Acts::List::InstanceMethods + + def acts_as_list_class + ::)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(name)inline_delimiter(})>content( + end + + def position_column + ')inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:column)operator(])inline_delimiter(})>content(' + end + + )inline<inline_delimiter(#{)ident(scope_condition_method)inline_delimiter(})>content( + + after_destroy :remove_from_list + before_create :add_to_list_bottom)delimiter( + EOV)> + reserved(end) + reserved(end) + + comment(# All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works) + comment(# by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter) + comment(# lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return true if that chapter is) + comment(# the first in the list of all chapters.) + reserved(module) class(InstanceMethods) + reserved(def) method(insert_at)operator(()ident(position) operator(=) integer(1)operator(\)) + ident(insert_at_position)operator(()ident(position)operator(\)) + reserved(end) + + reserved(def) method(move_lower) + reserved(return) reserved(unless) ident(lower_item) + + ident(acts_as_list_class)operator(.)ident(transaction) reserved(do) + ident(lower_item)operator(.)ident(decrement_position) + ident(increment_position) + reserved(end) + reserved(end) + + reserved(def) method(move_higher) + reserved(return) reserved(unless) ident(higher_item) + + ident(acts_as_list_class)operator(.)ident(transaction) reserved(do) + ident(higher_item)operator(.)ident(increment_position) + ident(decrement_position) + reserved(end) + reserved(end) + + reserved(def) method(move_to_bottom) + reserved(return) reserved(unless) ident(in_list?) + ident(acts_as_list_class)operator(.)ident(transaction) reserved(do) + ident(decrement_positions_on_lower_items) + ident(assume_bottom_position) + reserved(end) + reserved(end) + + reserved(def) method(move_to_top) + reserved(return) reserved(unless) ident(in_list?) + ident(acts_as_list_class)operator(.)ident(transaction) reserved(do) + ident(increment_positions_on_higher_items) + ident(assume_top_position) + reserved(end) + reserved(end) + + reserved(def) method(remove_from_list) + ident(decrement_positions_on_lower_items) reserved(if) ident(in_list?) + reserved(end) + + reserved(def) method(increment_position) + reserved(return) reserved(unless) ident(in_list?) + ident(update_attribute) ident(position_column)operator(,) pre_constant(self)operator(.)ident(send)operator(()ident(position_column)operator(\))operator(.)ident(to_i) operator(+) integer(1) + reserved(end) + + reserved(def) method(decrement_position) + reserved(return) reserved(unless) ident(in_list?) + ident(update_attribute) ident(position_column)operator(,) pre_constant(self)operator(.)ident(send)operator(()ident(position_column)operator(\))operator(.)ident(to_i) operator(-) integer(1) + reserved(end) + + reserved(def) method(first?) + reserved(return) pre_constant(false) reserved(unless) ident(in_list?) + pre_constant(self)operator(.)ident(send)operator(()ident(position_column)operator(\)) operator(==) integer(1) + reserved(end) + + reserved(def) method(last?) + reserved(return) pre_constant(false) reserved(unless) ident(in_list?) + pre_constant(self)operator(.)ident(send)operator(()ident(position_column)operator(\)) operator(==) ident(bottom_position_in_list) + reserved(end) + + reserved(def) method(higher_item) + reserved(return) pre_constant(nil) reserved(unless) ident(in_list?) + ident(acts_as_list_class)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) + string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = )inline<inline_delimiter(#{)operator(()ident(send)operator(()ident(position_column)operator(\))operator(.)ident(to_i) operator(-) integer(1)operator(\))operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(lower_item) + reserved(return) pre_constant(nil) reserved(unless) ident(in_list?) + ident(acts_as_list_class)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) + string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = )inline<inline_delimiter(#{)operator(()ident(send)operator(()ident(position_column)operator(\))operator(.)ident(to_i) operator(+) integer(1)operator(\))operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(in_list?) + operator(!)ident(send)operator(()ident(position_column)operator(\))operator(.)ident(nil?) + reserved(end) + + ident(private) + reserved(def) method(add_to_list_top) + ident(increment_positions_on_all_items) + reserved(end) + + reserved(def) method(add_to_list_bottom) + pre_constant(self)operator([)ident(position_column)operator(]) operator(=) ident(bottom_position_in_list)operator(.)ident(to_i) operator(+) integer(1) + reserved(end) + + comment(# Overwrite this method to define the scope of the list changes) + reserved(def) method(scope_condition)operator(()operator(\)) string<delimiter(")content(1)delimiter(")> reserved(end) + + reserved(def) method(bottom_position_in_list)operator(()ident(except) operator(=) pre_constant(nil)operator(\)) + ident(item) operator(=) ident(bottom_item)operator(()ident(except)operator(\)) + ident(item) operator(?) ident(item)operator(.)ident(send)operator(()ident(position_column)operator(\)) operator(:) integer(0) + reserved(end) + + reserved(def) method(bottom_item)operator(()ident(except) operator(=) pre_constant(nil)operator(\)) + ident(conditions) operator(=) ident(scope_condition) + ident(conditions) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)inline_delimiter(})>content( != )inline<inline_delimiter(#{)ident(except)operator(.)ident(id)inline_delimiter(})>delimiter(")> reserved(if) ident(except) + ident(acts_as_list_class)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) ident(conditions)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( DESC)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(assume_bottom_position) + ident(update_attribute)operator(()ident(position_column)operator(,) ident(bottom_position_in_list)operator(()pre_constant(self)operator(\))operator(.)ident(to_i) operator(+) integer(1)operator(\)) + reserved(end) + + reserved(def) method(assume_top_position) + ident(update_attribute)operator(()ident(position_column)operator(,) integer(1)operator(\)) + reserved(end) + + comment(# This has the effect of moving all the higher items up one.) + reserved(def) method(decrement_positions_on_higher_items)operator(()ident(position)operator(\)) + ident(acts_as_list_class)operator(.)ident(update_all)operator(() + string<delimiter(")inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( - 1\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( <= )inline<inline_delimiter(#{)ident(position)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + comment(# This has the effect of moving all the lower items up one.) + reserved(def) method(decrement_positions_on_lower_items) + reserved(return) reserved(unless) ident(in_list?) + ident(acts_as_list_class)operator(.)ident(update_all)operator(() + string<delimiter(")inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( - 1\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( > )inline<inline_delimiter(#{)ident(send)operator(()ident(position_column)operator(\))operator(.)ident(to_i)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + comment(# This has the effect of moving all the higher items down one.) + reserved(def) method(increment_positions_on_higher_items) + reserved(return) reserved(unless) ident(in_list?) + ident(acts_as_list_class)operator(.)ident(update_all)operator(() + string<delimiter(")inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( + 1\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( < )inline<inline_delimiter(#{)ident(send)operator(()ident(position_column)operator(\))operator(.)ident(to_i)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + comment(# This has the effect of moving all the lower items down one.) + reserved(def) method(increment_positions_on_lower_items)operator(()ident(position)operator(\)) + ident(acts_as_list_class)operator(.)ident(update_all)operator(() + string<delimiter(")inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( + 1\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( >= )inline<inline_delimiter(#{)ident(position)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(increment_positions_on_all_items) + ident(acts_as_list_class)operator(.)ident(update_all)operator(() + string<delimiter(")inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(position_column)inline_delimiter(})>content( + 1\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(insert_at_position)operator(()ident(position)operator(\)) + ident(remove_from_list) + ident(increment_positions_on_lower_items)operator(()ident(position)operator(\)) + pre_constant(self)operator(.)ident(update_attribute)operator(()ident(position_column)operator(,) ident(position)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Acts) comment(#:nodoc:) + reserved(module) class(NestedSet) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# This acts provides Nested Set functionality. Nested Set is similiar to Tree, but with) + comment(# the added feature that you can select the children and all of their descendents with) + comment(# a single query. A good use case for this is a threaded post system, where you want) + comment(# to display every reply to a comment without multiple selects.) + comment(#) + comment(# A google search for "Nested Set" should point you in the direction to explain the) + comment(# database theory. I figured out a bunch of this from) + comment(# http://threebit.net/tutorials/nestedset/tutorial1.html) + comment(#) + comment(# Instead of picturing a leaf node structure with children pointing back to their parent,) + comment(# the best way to imagine how this works is to think of the parent entity surrounding all) + comment(# of its children, and its parent surrounding it, etc. Assuming that they are lined up) + comment(# horizontally, we store the left and right boundries in the database.) + comment(#) + comment(# Imagine:) + comment(# root) + comment(# |_ Child 1) + comment(# |_ Child 1.1) + comment(# |_ Child 1.2) + comment(# |_ Child 2) + comment(# |_ Child 2.1) + comment(# |_ Child 2.2) + comment(#) + comment(# If my cirlces in circles description didn't make sense, check out this sweet) + comment(# ASCII art:) + comment(#) + comment(# ___________________________________________________________________) + comment(# | Root |) + comment(# | ____________________________ ____________________________ |) + comment(# | | Child 1 | | Child 2 | |) + comment(# | | __________ _________ | | __________ _________ | |) + comment(# | | | C 1.1 | | C 1.2 | | | | C 2.1 | | C 2.2 | | |) + comment(# 1 2 3_________4 5________6 7 8 9_________10 11_______12 13 14) + comment(# | |___________________________| |___________________________| |) + comment(# |___________________________________________________________________| ) + comment(#) + comment(# The numbers represent the left and right boundries. The table then might) + comment(# look like this:) + comment(# ID | PARENT | LEFT | RIGHT | DATA) + comment(# 1 | 0 | 1 | 14 | root) + comment(# 2 | 1 | 2 | 7 | Child 1) + comment(# 3 | 2 | 3 | 4 | Child 1.1) + comment(# 4 | 2 | 5 | 6 | Child 1.2) + comment(# 5 | 1 | 8 | 13 | Child 2) + comment(# 6 | 5 | 9 | 10 | Child 2.1) + comment(# 7 | 5 | 11 | 12 | Child 2.2) + comment(#) + comment(# So, to get all children of an entry, you) + comment(# SELECT * WHERE CHILD.LEFT IS BETWEEN PARENT.LEFT AND PARENT.RIGHT) + comment(#) + comment(# To get the count, it's (LEFT - RIGHT + 1\)/2, etc.) + comment(#) + comment(# To get the direct parent, it falls back to using the PARENT_ID field. ) + comment(#) + comment(# There are instance methods for all of these.) + comment(#) + comment(# The structure is good if you need to group things together; the downside is that) + comment(# keeping data integrity is a pain, and both adding and removing an entry) + comment(# require a full table write. ) + comment(#) + comment(# This sets up a before_destroy trigger to prune the tree correctly if one of its) + comment(# elements gets deleted.) + comment(#) + reserved(module) class(ClassMethods) + comment(# Configuration options are:) + comment(#) + comment(# * +parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id\)) + comment(# * +left_column+ - column name for left boundry data, default "lft") + comment(# * +right_column+ - column name for right boundry data, default "rgt") + comment(# * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id" ) + comment(# (if that hasn't been already\) and use that as the foreign key restriction. It's also possible ) + comment(# to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.) + comment(# Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>) + reserved(def) method(acts_as_nested_set)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(configuration) operator(=) operator({) symbol(:parent_column) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")>operator(,) symbol(:left_column) operator(=)operator(>) string<delimiter(")content(lft)delimiter(")>operator(,) symbol(:right_column) operator(=)operator(>) string<delimiter(")content(rgt)delimiter(")>operator(,) symbol(:scope) operator(=)operator(>) string<delimiter(")content(1 = 1)delimiter(")> operator(}) + + ident(configuration)operator(.)ident(update)operator(()ident(options)operator(\)) reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(configuration)operator([)symbol(:scope)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])inline_delimiter(})>content(_id)delimiter(")>operator(.)ident(intern) reserved(if) ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) operator(&&) ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s) operator(!)operator(~) regexp<delimiter(/)content(_id$)delimiter(/)> + + reserved(if) ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + ident(scope_condition_method) operator(=) string<delimiter(%()content( + def scope_condition + if )inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content(.nil? + ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content( IS NULL" + else + ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content( = )char(\\#)content({)inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])operator(.)ident(to_s)inline_delimiter(})>content(}" + end + end + )delimiter(\))> + reserved(else) + ident(scope_condition_method) operator(=) string<delimiter(")content(def scope_condition(\) )char(\\")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:scope)operator(])inline_delimiter(})>char(\\")content( end)delimiter(")> + reserved(end) + + ident(class_eval) string<delimiter(<<-EOV)>string<content( + include ActiveRecord::Acts::NestedSet::InstanceMethods + + )inline<inline_delimiter(#{)ident(scope_condition_method)inline_delimiter(})>content( + + def left_col_name(\) ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:left_column)operator(])inline_delimiter(})>content(" end + + def right_col_name(\) ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:right_column)operator(])inline_delimiter(})>content(" end + + def parent_column(\) ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:parent_column)operator(])inline_delimiter(})>content(" end +)delimiter( + EOV)> + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) + comment(# Returns true is this is a root node. ) + reserved(def) method(root?) + ident(parent_id) operator(=) pre_constant(self)operator([)ident(parent_column)operator(]) + operator(()ident(parent_id) operator(==) integer(0) operator(||) ident(parent_id)operator(.)ident(nil?)operator(\)) operator(&&) operator(()pre_constant(self)operator([)ident(left_col_name)operator(]) operator(==) integer(1)operator(\)) operator(&&) operator(()pre_constant(self)operator([)ident(right_col_name)operator(]) operator(>) pre_constant(self)operator([)ident(left_col_name)operator(])operator(\)) + reserved(end) + + comment(# Returns true is this is a child node) + reserved(def) method(child?) + ident(parent_id) operator(=) pre_constant(self)operator([)ident(parent_column)operator(]) + operator(!)operator(()ident(parent_id) operator(==) integer(0) operator(||) ident(parent_id)operator(.)ident(nil?)operator(\)) operator(&&) operator(()pre_constant(self)operator([)ident(left_col_name)operator(]) operator(>) integer(1)operator(\)) operator(&&) operator(()pre_constant(self)operator([)ident(right_col_name)operator(]) operator(>) pre_constant(self)operator([)ident(left_col_name)operator(])operator(\)) + reserved(end) + + comment(# Returns true if we have no idea what this is) + reserved(def) method(unknown?) + operator(!)ident(root?) operator(&&) operator(!)ident(child?) + reserved(end) + + + comment(# Adds a child to this object in the tree. If this object hasn't been initialized,) + comment(# it gets set up as a root node. Otherwise, this method will update all of the) + comment(# other elements in the tree and shift them to the right, keeping everything) + comment(# balanced. ) + reserved(def) method(add_child)operator(() ident(child) operator(\)) + pre_constant(self)operator(.)ident(reload) + ident(child)operator(.)ident(reload) + + reserved(if) ident(child)operator(.)ident(root?) + ident(raise) string<delimiter(")content(Adding sub-tree isn)char(\\')content(t currently supported)delimiter(")> + reserved(else) + reserved(if) operator(() operator(()pre_constant(self)operator([)ident(left_col_name)operator(]) operator(==) pre_constant(nil)operator(\)) operator(||) operator(()pre_constant(self)operator([)ident(right_col_name)operator(]) operator(==) pre_constant(nil)operator(\)) operator(\)) + comment(# Looks like we're now the root node! Woo) + pre_constant(self)operator([)ident(left_col_name)operator(]) operator(=) integer(1) + pre_constant(self)operator([)ident(right_col_name)operator(]) operator(=) integer(4) + + comment(# What do to do about validation?) + reserved(return) pre_constant(nil) reserved(unless) pre_constant(self)operator(.)ident(save) + + ident(child)operator([)ident(parent_column)operator(]) operator(=) pre_constant(self)operator(.)ident(id) + ident(child)operator([)ident(left_col_name)operator(]) operator(=) integer(2) + ident(child)operator([)ident(right_col_name)operator(])operator(=) integer(3) + reserved(return) ident(child)operator(.)ident(save) + reserved(else) + comment(# OK, we need to add and shift everything else to the right) + ident(child)operator([)ident(parent_column)operator(]) operator(=) pre_constant(self)operator(.)ident(id) + ident(right_bound) operator(=) pre_constant(self)operator([)ident(right_col_name)operator(]) + ident(child)operator([)ident(left_col_name)operator(]) operator(=) ident(right_bound) + ident(child)operator([)ident(right_col_name)operator(]) operator(=) ident(right_bound) operator(+) integer(1) + pre_constant(self)operator([)ident(right_col_name)operator(]) operator(+=) integer(2) + pre_constant(self)operator(.)ident(class)operator(.)ident(transaction) operator({) + pre_constant(self)operator(.)ident(class)operator(.)ident(update_all)operator(() string<delimiter(")inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( + 2\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( >= )inline<inline_delimiter(#{)ident(right_bound)inline_delimiter(})>delimiter(")> operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(update_all)operator(() string<delimiter(")inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( + 2\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( >= )inline<inline_delimiter(#{)ident(right_bound)inline_delimiter(})>delimiter(")> operator(\)) + pre_constant(self)operator(.)ident(save) + ident(child)operator(.)ident(save) + operator(}) + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns the number of nested children of this object.) + reserved(def) method(children_count) + reserved(return) operator(()pre_constant(self)operator([)ident(right_col_name)operator(]) operator(-) pre_constant(self)operator([)ident(left_col_name)operator(]) operator(-) integer(1)operator(\))operator(/)integer(2) + reserved(end) + + comment(# Returns a set of itself and all of its nested children) + reserved(def) method(full_set) + pre_constant(self)operator(.)ident(class)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND ()inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( BETWEEN )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(left_col_name)operator(])inline_delimiter(})>content( and )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(right_col_name)operator(])inline_delimiter(})>content(\))delimiter(")> operator(\)) + reserved(end) + + comment(# Returns a set of all of its children and nested children) + reserved(def) method(all_children) + pre_constant(self)operator(.)ident(class)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND ()inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( > )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(left_col_name)operator(])inline_delimiter(})>content(\) and ()inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( < )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(right_col_name)operator(])inline_delimiter(})>content(\))delimiter(")> operator(\)) + reserved(end) + + comment(# Returns a set of only this entry's immediate children) + reserved(def) method(direct_children) + pre_constant(self)operator(.)ident(class)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( and )inline<inline_delimiter(#{)ident(parent_column)inline_delimiter(})>content( = )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + comment(# Prunes a branch off of the tree, shifting all of the elements on the right) + comment(# back to the left so the counts still work.) + reserved(def) method(before_destroy) + reserved(return) reserved(if) pre_constant(self)operator([)ident(right_col_name)operator(])operator(.)ident(nil?) operator(||) pre_constant(self)operator([)ident(left_col_name)operator(])operator(.)ident(nil?) + ident(dif) operator(=) pre_constant(self)operator([)ident(right_col_name)operator(]) operator(-) pre_constant(self)operator([)ident(left_col_name)operator(]) operator(+) integer(1) + + pre_constant(self)operator(.)ident(class)operator(.)ident(transaction) operator({) + pre_constant(self)operator(.)ident(class)operator(.)ident(delete_all)operator(() string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( and )inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( > )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(left_col_name)operator(])inline_delimiter(})>content( and )inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( < )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(right_col_name)operator(])inline_delimiter(})>delimiter(")> operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(update_all)operator(() string<delimiter(")inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( - )inline<inline_delimiter(#{)ident(dif)inline_delimiter(})>content(\))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(left_col_name)inline_delimiter(})>content( >= )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(right_col_name)operator(])inline_delimiter(})>delimiter(")> operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(update_all)operator(() string<delimiter(")inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( = ()inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( - )inline<inline_delimiter(#{)ident(dif)inline_delimiter(})>content( \))delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(scope_condition)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)ident(right_col_name)inline_delimiter(})>content( >= )inline<inline_delimiter(#{)pre_constant(self)operator([)ident(right_col_name)operator(])inline_delimiter(})>delimiter(")> operator(\)) + operator(}) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Acts) comment(#:nodoc:) + reserved(module) class(Tree) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Specify this act if you want to model a tree structure by providing a parent association and a children ) + comment(# association. This act requires that you have a foreign key column, which by default is called parent_id.) + comment(# ) + comment(# class Category < ActiveRecord::Base) + comment(# acts_as_tree :order => "name") + comment(# end) + comment(# ) + comment(# Example : ) + comment(# root) + comment(# \\_ child1 ) + comment(# \\_ subchild1) + comment(# \\_ subchild2) + comment(#) + comment(# root = Category.create("name" => "root"\)) + comment(# child1 = root.children.create("name" => "child1"\)) + comment(# subchild1 = child1.children.create("name" => "subchild1"\)) + comment(#) + comment(# root.parent # => nil) + comment(# child1.parent # => root) + comment(# root.children # => [child1]) + comment(# root.children.first.children.first # => subchild1) + comment(#) + comment(# In addition to the parent and children associations, the following instance methods are added to the class ) + comment(# after specifying the act:) + comment(# * siblings : Returns all the children of the parent, excluding the current node ([ subchild2 ] when called from subchild1\)) + comment(# * self_and_siblings : Returns all the children of the parent, including the current node ([ subchild1, subchild2 ] when called from subchild1\)) + comment(# * ancestors : Returns all the ancestors of the current node ([child1, root] when called from subchild2\)) + comment(# * root : Returns the root of the current node (root when called from subchild2\)) + reserved(module) class(ClassMethods) + comment(# Configuration options are:) + comment(#) + comment(# * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: parent_id\)) + comment(# * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.) + comment(# * <tt>counter_cache</tt> - keeps a count in a children_count column if set to true (default: false\).) + reserved(def) method(acts_as_tree)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(configuration) operator(=) operator({) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) pre_constant(nil)operator(,) symbol(:counter_cache) operator(=)operator(>) pre_constant(nil) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(options)operator(\)) reserved(if) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(belongs_to) symbol(:parent)operator(,) symbol(:class_name) operator(=)operator(>) ident(name)operator(,) symbol(:foreign_key) operator(=)operator(>) ident(configuration)operator([)symbol(:foreign_key)operator(])operator(,) symbol(:counter_cache) operator(=)operator(>) ident(configuration)operator([)symbol(:counter_cache)operator(]) + ident(has_many) symbol(:children)operator(,) symbol(:class_name) operator(=)operator(>) ident(name)operator(,) symbol(:foreign_key) operator(=)operator(>) ident(configuration)operator([)symbol(:foreign_key)operator(])operator(,) symbol(:order) operator(=)operator(>) ident(configuration)operator([)symbol(:order)operator(])operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) + + ident(class_eval) string<delimiter(<<-EOV)>string<content( + include ActiveRecord::Acts::Tree::InstanceMethods + + def self.roots + find(:all, :conditions => ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:foreign_key)operator(])inline_delimiter(})>content( IS NULL", :order => )inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:order)operator(])operator(.)ident(nil?) operator(?) string<delimiter(")content(nil)delimiter(")> operator(:) string<delimiter(%Q{)content(")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:order)operator(])inline_delimiter(})>content(")delimiter(})>inline_delimiter(})>content(\) + end + + def self.root + find(:first, :conditions => ")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:foreign_key)operator(])inline_delimiter(})>content( IS NULL", :order => )inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:order)operator(])operator(.)ident(nil?) operator(?) string<delimiter(")content(nil)delimiter(")> operator(:) string<delimiter(%Q{)content(")inline<inline_delimiter(#{)ident(configuration)operator([)symbol(:order)operator(])inline_delimiter(})>content(")delimiter(})>inline_delimiter(})>content(\) + end)delimiter( + EOV)> + reserved(end) + reserved(end) + + reserved(module) class(InstanceMethods) + comment(# Returns list of ancestors, starting from parent until root.) + comment(#) + comment(# subchild1.ancestors # => [child1, root]) + reserved(def) method(ancestors) + ident(node)operator(,) ident(nodes) operator(=) pre_constant(self)operator(,) operator([)operator(]) + ident(nodes) operator(<<) ident(node) operator(=) ident(node)operator(.)ident(parent) reserved(until) reserved(not) ident(node)operator(.)ident(has_parent?) + ident(nodes) + reserved(end) + + reserved(def) method(root) + ident(node) operator(=) pre_constant(self) + ident(node) operator(=) ident(node)operator(.)ident(parent) reserved(until) reserved(not) ident(node)operator(.)ident(has_parent?) + ident(node) + reserved(end) + + reserved(def) method(siblings) + ident(self_and_siblings) operator(-) operator([)pre_constant(self)operator(]) + reserved(end) + + reserved(def) method(self_and_siblings) + ident(has_parent?) operator(?) ident(parent)operator(.)ident(children) operator(:) pre_constant(self)operator(.)ident(class)operator(.)ident(roots) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Aggregations) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(def) method(clear_aggregation_cache) comment(#:nodoc:) + pre_constant(self)operator(.)ident(class)operator(.)ident(reflect_on_all_aggregations)operator(.)ident(to_a)operator(.)ident(each) reserved(do) operator(|)ident(assoc)operator(|) + ident(instance_variable_set) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(assoc)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) pre_constant(nil) + reserved(end) reserved(unless) pre_constant(self)operator(.)ident(new_record?) + reserved(end) + + comment(# Active Record implements aggregation through a macro-like class method called +composed_of+ for representing attributes ) + comment(# as value objects. It expresses relationships like "Account [is] composed of Money [among other things]" or "Person [is]) + comment(# composed of [an] address". Each call to the macro adds a description of how the value objects are created from the ) + comment(# attributes of the entity object (when the entity is initialized either as a new object or from finding an existing object\) ) + comment(# and how it can be turned back into attributes (when the entity is saved to the database\). Example:) + comment(#) + comment(# class Customer < ActiveRecord::Base) + comment(# composed_of :balance, :class_name => "Money", :mapping => %w(balance amount\)) + comment(# composed_of :address, :mapping => [ %w(address_street street\), %w(address_city city\) ]) + comment(# end) + comment(#) + comment(# The customer class now has the following methods to manipulate the value objects:) + comment(# * <tt>Customer#balance, Customer#balance=(money\)</tt>) + comment(# * <tt>Customer#address, Customer#address=(address\)</tt>) + comment(#) + comment(# These methods will operate with value objects like the ones described below:) + comment(#) + comment(# class Money) + comment(# include Comparable) + comment(# attr_reader :amount, :currency) + comment(# EXCHANGE_RATES = { "USD_TO_DKK" => 6 } ) + comment(# ) + comment(# def initialize(amount, currency = "USD"\) ) + comment(# @amount, @currency = amount, currency ) + comment(# end) + comment(#) + comment(# def exchange_to(other_currency\)) + comment(# exchanged_amount = (amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]\).floor) + comment(# Money.new(exchanged_amount, other_currency\)) + comment(# end) + comment(#) + comment(# def ==(other_money\)) + comment(# amount == other_money.amount && currency == other_money.currency) + comment(# end) + comment(#) + comment(# def <=>(other_money\)) + comment(# if currency == other_money.currency) + comment(# amount <=> amount) + comment(# else) + comment(# amount <=> other_money.exchange_to(currency\).amount) + comment(# end) + comment(# end) + comment(# end) + comment(#) + comment(# class Address) + comment(# attr_reader :street, :city) + comment(# def initialize(street, city\) ) + comment(# @street, @city = street, city ) + comment(# end) + comment(#) + comment(# def close_to?(other_address\) ) + comment(# city == other_address.city ) + comment(# end) + comment(#) + comment(# def ==(other_address\)) + comment(# city == other_address.city && street == other_address.street) + comment(# end) + comment(# end) + comment(# ) + comment(# Now it's possible to access attributes from the database through the value objects instead. If you choose to name the) + comment(# composition the same as the attributes name, it will be the only way to access that attribute. That's the case with our) + comment(# +balance+ attribute. You interact with the value objects just like you would any other attribute, though:) + comment(#) + comment(# customer.balance = Money.new(20\) # sets the Money value object and the attribute) + comment(# customer.balance # => Money value object) + comment(# customer.balance.exchanged_to("DKK"\) # => Money.new(120, "DKK"\)) + comment(# customer.balance > Money.new(10\) # => true) + comment(# customer.balance == Money.new(20\) # => true) + comment(# customer.balance < Money.new(5\) # => false) + comment(#) + comment(# Value objects can also be composed of multiple attributes, such as the case of Address. The order of the mappings will) + comment(# determine the order of the parameters. Example:) + comment(#) + comment(# customer.address_street = "Hyancintvej") + comment(# customer.address_city = "Copenhagen") + comment(# customer.address # => Address.new("Hyancintvej", "Copenhagen"\)) + comment(# customer.address = Address.new("May Street", "Chicago"\)) + comment(# customer.address_street # => "May Street" ) + comment(# customer.address_city # => "Chicago" ) + comment(#) + comment(# == Writing value objects) + comment(#) + comment(# Value objects are immutable and interchangeable objects that represent a given value, such as a Money object representing) + comment(# $5. Two Money objects both representing $5 should be equal (through methods such as == and <=> from Comparable if ranking) + comment(# makes sense\). This is unlike entity objects where equality is determined by identity. An entity class such as Customer can) + comment(# easily have two different objects that both have an address on Hyancintvej. Entity identity is determined by object or) + comment(# relational unique identifiers (such as primary keys\). Normal ActiveRecord::Base classes are entity objects.) + comment(#) + comment(# It's also important to treat the value objects as immutable. Don't allow the Money object to have its amount changed after) + comment(# creation. Create a new money object with the new value instead. This is exemplified by the Money#exchanged_to method that) + comment(# returns a new value object instead of changing its own values. Active Record won't persist value objects that have been) + comment(# changed through other means than the writer method.) + comment(#) + comment(# The immutable requirement is enforced by Active Record by freezing any object assigned as a value object. Attempting to ) + comment(# change it afterwards will result in a TypeError.) + comment(# ) + comment(# Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not keeping value objects) + comment(# immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable) + reserved(module) class(ClassMethods) + comment(# Adds the a reader and writer method for manipulating a value object, so) + comment(# <tt>composed_of :address</tt> would add <tt>address</tt> and <tt>address=(new_address\)</tt>.) + comment(#) + comment(# Options are:) + comment(# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred) + comment(# from the part id. So <tt>composed_of :address</tt> will by default be linked to the +Address+ class, but) + comment(# if the real class name is +CompanyAddress+, you'll have to specify it with this option.) + comment(# * <tt>:mapping</tt> - specifies a number of mapping arrays (attribute, parameter\) that bind an attribute name) + comment(# to a constructor parameter on the value class.) + comment(#) + comment(# Option examples:) + comment(# composed_of :temperature, :mapping => %w(reading celsius\)) + comment(# composed_of :balance, :class_name => "Money", :mapping => %w(balance amount\)) + comment(# composed_of :address, :mapping => [ %w(address_street street\), %w(address_city city\) ]) + comment(# composed_of :gps_location) + reserved(def) method(composed_of)operator(()ident(part_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(()symbol(:class_name)operator(,) symbol(:mapping)operator(\)) + + ident(name) operator(=) ident(part_id)operator(.)ident(id2name) + ident(class_name) operator(=) ident(options)operator([)symbol(:class_name)operator(]) operator(||) ident(name_to_class_name)operator(()ident(name)operator(\)) + ident(mapping) operator(=) ident(options)operator([)symbol(:mapping)operator(]) operator(||) operator([) ident(name)operator(,) ident(name) operator(]) + + ident(reader_method)operator(()ident(name)operator(,) ident(class_name)operator(,) ident(mapping)operator(\)) + ident(writer_method)operator(()ident(name)operator(,) ident(class_name)operator(,) ident(mapping)operator(\)) + + ident(create_reflection)operator(()symbol(:composed_of)operator(,) ident(part_id)operator(,) ident(options)operator(,) pre_constant(self)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(name_to_class_name)operator(()ident(name)operator(\)) + ident(name)operator(.)ident(capitalize)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(_(.\))delimiter(/)>operator(\)) operator({) operator(|)ident(s)operator(|) global_variable($1)operator(.)ident(capitalize) operator(}) + reserved(end) + + reserved(def) method(reader_method)operator(()ident(name)operator(,) ident(class_name)operator(,) ident(mapping)operator(\)) + ident(module_eval) string<delimiter(<<-end_eval)>string<content( + def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content((force_reload = false\) + if @)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(.nil? || force_reload + @)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(class_name)inline_delimiter(})>content(.new()inline<inline_delimiter(#{)operator(()constant(Array) operator(===) ident(mapping)operator(.)ident(first) operator(?) ident(mapping) operator(:) operator([) ident(mapping) operator(])operator(\))operator(.)ident(collect)operator({) operator(|)ident(pair)operator(|) string<delimiter(")content(read_attribute()char(\\")inline<inline_delimiter(#{)ident(pair)operator(.)ident(first)inline_delimiter(})>char(\\")content(\))delimiter(")>operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))inline_delimiter(})>content(\) + end + + return @)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(writer_method)operator(()ident(name)operator(,) ident(class_name)operator(,) ident(mapping)operator(\)) + ident(module_eval) string<delimiter(<<-end_eval)>string<content( + def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(=(part\) + @)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( = part.freeze + )inline<inline_delimiter(#{)operator(()constant(Array) operator(===) ident(mapping)operator(.)ident(first) operator(?) ident(mapping) operator(:) operator([) ident(mapping) operator(])operator(\))operator(.)ident(collect)operator({) operator(|)ident(pair)operator(|) string<delimiter(")content(@attributes[)char(\\")inline<inline_delimiter(#{)ident(pair)operator(.)ident(first)inline_delimiter(})>char(\\")content(] = part.)inline<inline_delimiter(#{)ident(pair)operator(.)ident(last)inline_delimiter(})>delimiter(")> operator(})operator(.)ident(join)operator(()string<delimiter(")char(\\n)delimiter(")>operator(\))inline_delimiter(})>content( + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(set)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(AssociationCollection) operator(<) constant(AssociationProxy) comment(#:nodoc:) + reserved(def) method(to_ary) + ident(load_target) + instance_variable(@target)operator(.)ident(to_ary) + reserved(end) + + reserved(def) method(reset) + instance_variable(@target) operator(=) operator([)operator(]) + instance_variable(@loaded) operator(=) pre_constant(false) + reserved(end) + + comment(# Add +records+ to this association. Returns +self+ so method calls may be chained. ) + comment(# Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically.) + reserved(def) method(<<)operator(()operator(*)ident(records)operator(\)) + ident(result) operator(=) pre_constant(true) + ident(load_target) + + instance_variable(@owner)operator(.)ident(transaction) reserved(do) + ident(flatten_deeper)operator(()ident(records)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(record)operator(|) + ident(raise_on_type_mismatch)operator(()ident(record)operator(\)) + ident(callback)operator(()symbol(:before_add)operator(,) ident(record)operator(\)) + ident(result) operator(&&=) ident(insert_record)operator(()ident(record)operator(\)) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) + instance_variable(@target) operator(<<) ident(record) + ident(callback)operator(()symbol(:after_add)operator(,) ident(record)operator(\)) + reserved(end) + reserved(end) + + ident(result) operator(&&) pre_constant(self) + reserved(end) + + ident(alias_method) symbol(:push)operator(,) symbol(:<<) + ident(alias_method) symbol(:concat)operator(,) symbol(:<<) + + comment(# Remove all records from this association) + reserved(def) method(delete_all) + ident(load_target) + ident(delete)operator(()instance_variable(@target)operator(\)) + instance_variable(@target) operator(=) operator([)operator(]) + reserved(end) + + comment(# Remove +records+ from this association. Does not destroy +records+.) + reserved(def) method(delete)operator(()operator(*)ident(records)operator(\)) + ident(records) operator(=) ident(flatten_deeper)operator(()ident(records)operator(\)) + ident(records)operator(.)ident(each) operator({) operator(|)ident(record)operator(|) ident(raise_on_type_mismatch)operator(()ident(record)operator(\)) operator(}) + ident(records)operator(.)ident(reject!) operator({) operator(|)ident(record)operator(|) instance_variable(@target)operator(.)ident(delete)operator(()ident(record)operator(\)) reserved(if) ident(record)operator(.)ident(new_record?) operator(}) + reserved(return) reserved(if) ident(records)operator(.)ident(empty?) + + instance_variable(@owner)operator(.)ident(transaction) reserved(do) + ident(records)operator(.)ident(each) operator({) operator(|)ident(record)operator(|) ident(callback)operator(()symbol(:before_remove)operator(,) ident(record)operator(\)) operator(}) + ident(delete_records)operator(()ident(records)operator(\)) + ident(records)operator(.)ident(each) reserved(do) operator(|)ident(record)operator(|) + instance_variable(@target)operator(.)ident(delete)operator(()ident(record)operator(\)) + ident(callback)operator(()symbol(:after_remove)operator(,) ident(record)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Removes all records from this association. Returns +self+ so method calls may be chained.) + reserved(def) method(clear) + reserved(return) pre_constant(self) reserved(if) ident(length)operator(.)ident(zero?) comment(# forces load_target if hasn't happened already) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) operator(&&) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) operator(==) symbol(:delete_all) + ident(destroy_all) + reserved(else) + ident(delete_all) + reserved(end) + + pre_constant(self) + reserved(end) + + reserved(def) method(destroy_all) + instance_variable(@owner)operator(.)ident(transaction) reserved(do) + ident(each) operator({) operator(|)ident(record)operator(|) ident(record)operator(.)ident(destroy) operator(}) + reserved(end) + + instance_variable(@target) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(create)operator(()ident(attributes) operator(=) operator({)operator(})operator(\)) + comment(# Can't use Base.create since the foreign key may be a protected attribute.) + reserved(if) ident(attributes)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(attributes)operator(.)ident(collect) operator({) operator(|)ident(attr)operator(|) ident(create)operator(()ident(attr)operator(\)) operator(}) + reserved(else) + ident(record) operator(=) ident(build)operator(()ident(attributes)operator(\)) + ident(record)operator(.)ident(save) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) + ident(record) + reserved(end) + reserved(end) + + comment(# Returns the size of the collection by executing a SELECT COUNT(*\) query if the collection hasn't been loaded and) + comment(# calling collection.size if it has. If it's more likely than not that the collection does have a size larger than zero) + comment(# and you need to fetch that collection afterwards, it'll take one less SELECT query if you use length.) + reserved(def) method(size) + reserved(if) ident(loaded?) reserved(then) instance_variable(@target)operator(.)ident(size) reserved(else) ident(count_records) reserved(end) + reserved(end) + + comment(# Returns the size of the collection by loading it and calling size on the array. If you want to use this method to check) + comment(# whether the collection is empty, use collection.length.zero? instead of collection.empty?) + reserved(def) method(length) + ident(load_target)operator(.)ident(size) + reserved(end) + + reserved(def) method(empty?) + ident(size)operator(.)ident(zero?) + reserved(end) + + reserved(def) method(uniq)operator(()ident(collection) operator(=) pre_constant(self)operator(\)) + ident(collection)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) operator({) operator(|)ident(uniq_records)operator(,) ident(record)operator(|) ident(uniq_records) operator(<<) ident(record) reserved(unless) ident(uniq_records)operator(.)ident(include?)operator(()ident(record)operator(\))operator(;) ident(uniq_records) operator(}) + reserved(end) + + comment(# Replace this collection with +other_array+) + comment(# This will perform a diff and delete/add only records that have changed.) + reserved(def) method(replace)operator(()ident(other_array)operator(\)) + ident(other_array)operator(.)ident(each) operator({) operator(|)ident(val)operator(|) ident(raise_on_type_mismatch)operator(()ident(val)operator(\)) operator(}) + + ident(load_target) + ident(other) operator(=) ident(other_array)operator(.)ident(size) operator(<) integer(100) operator(?) ident(other_array) operator(:) ident(other_array)operator(.)ident(to_set) + ident(current) operator(=) instance_variable(@target)operator(.)ident(size) operator(<) integer(100) operator(?) instance_variable(@target) operator(:) instance_variable(@target)operator(.)ident(to_set) + + instance_variable(@owner)operator(.)ident(transaction) reserved(do) + ident(delete)operator(()instance_variable(@target)operator(.)ident(select) operator({) operator(|)ident(v)operator(|) operator(!)ident(other)operator(.)ident(include?)operator(()ident(v)operator(\)) operator(})operator(\)) + ident(concat)operator(()ident(other_array)operator(.)ident(select) operator({) operator(|)ident(v)operator(|) operator(!)ident(current)operator(.)ident(include?)operator(()ident(v)operator(\)) operator(})operator(\)) + reserved(end) + reserved(end) + + ident(private) + comment(# Array#flatten has problems with recursive arrays. Going one level deeper solves the majority of the problems.) + reserved(def) method(flatten_deeper)operator(()ident(array)operator(\)) + ident(array)operator(.)ident(collect) operator({) operator(|)ident(element)operator(|) ident(element)operator(.)ident(respond_to?)operator(()symbol(:flatten)operator(\)) operator(?) ident(element)operator(.)ident(flatten) operator(:) ident(element) operator(})operator(.)ident(flatten) + reserved(end) + + reserved(def) method(callback)operator(()ident(method)operator(,) ident(record)operator(\)) + ident(callbacks_for)operator(()ident(method)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(callback)operator(|) + reserved(case) ident(callback) + reserved(when) constant(Symbol) + instance_variable(@owner)operator(.)ident(send)operator(()ident(callback)operator(,) ident(record)operator(\)) + reserved(when) constant(Proc)operator(,) constant(Method) + ident(callback)operator(.)ident(call)operator(()instance_variable(@owner)operator(,) ident(record)operator(\)) + reserved(else) + reserved(if) ident(callback)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) + ident(callback)operator(.)ident(send)operator(()ident(method)operator(,) instance_variable(@owner)operator(,) ident(record)operator(\)) + reserved(else) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")content(Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method.)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(callbacks_for)operator(()ident(callback_name)operator(\)) + ident(full_callback_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(callback_name)inline_delimiter(})>content(_for_)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")> + instance_variable(@owner)operator(.)ident(class)operator(.)ident(read_inheritable_attribute)operator(()ident(full_callback_name)operator(.)ident(to_sym)operator(\)) operator(||) operator([)operator(]) + reserved(end) + + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(AssociationProxy) comment(#:nodoc:) + ident(attr_reader) symbol(:reflection) + ident(alias_method) symbol(:proxy_respond_to?)operator(,) symbol(:respond_to?) + ident(alias_method) symbol(:proxy_extend)operator(,) symbol(:extend) + ident(instance_methods)operator(.)ident(each) operator({) operator(|)ident(m)operator(|) ident(undef_method) ident(m) reserved(unless) ident(m) operator(=)operator(~) regexp<delimiter(/)content((^__|^nil)char(\\?)content(|^proxy_respond_to)char(\\?)content(|^proxy_extend|^send\))delimiter(/)> operator(}) + + reserved(def) method(initialize)operator(()ident(owner)operator(,) ident(reflection)operator(\)) + instance_variable(@owner)operator(,) instance_variable(@reflection) operator(=) ident(owner)operator(,) ident(reflection) + ident(proxy_extend)operator(()ident(reflection)operator(.)ident(options)operator([)symbol(:extend)operator(])operator(\)) reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:extend)operator(]) + ident(reset) + reserved(end) + + reserved(def) method(respond_to?)operator(()ident(symbol)operator(,) ident(include_priv) operator(=) pre_constant(false)operator(\)) + ident(proxy_respond_to?)operator(()ident(symbol)operator(,) ident(include_priv)operator(\)) operator(||) operator(()ident(load_target) operator(&&) instance_variable(@target)operator(.)ident(respond_to?)operator(()ident(symbol)operator(,) ident(include_priv)operator(\))operator(\)) + reserved(end) + + comment(# Explicitly proxy === because the instance method removal above) + comment(# doesn't catch it.) + reserved(def) method(===)operator(()ident(other)operator(\)) + ident(load_target) + ident(other) operator(===) instance_variable(@target) + reserved(end) + + reserved(def) method(aliased_table_name) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(conditions) + instance_variable(@conditions) operator(||=) ident(eval)operator(()string<delimiter(")content(%()inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(active_record)operator(.)ident(send) symbol(:sanitize_sql)operator(,) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])inline_delimiter(})>content(\))delimiter(")>operator(\)) reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(]) + reserved(end) + reserved(alias) symbol(:sql_conditions) symbol(:conditions) + + reserved(def) method(reset) + instance_variable(@target) operator(=) pre_constant(nil) + instance_variable(@loaded) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(reload) + ident(reset) + ident(load_target) + reserved(end) + + reserved(def) method(loaded?) + instance_variable(@loaded) + reserved(end) + + reserved(def) method(loaded) + instance_variable(@loaded) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(target) + instance_variable(@target) + reserved(end) + + reserved(def) method(target=)operator(()ident(target)operator(\)) + instance_variable(@target) operator(=) ident(target) + ident(loaded) + reserved(end) + + ident(protected) + reserved(def) method(dependent?) + instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) operator(||) pre_constant(false) + reserved(end) + + reserved(def) method(quoted_record_ids)operator(()ident(records)operator(\)) + ident(records)operator(.)ident(map) operator({) operator(|)ident(record)operator(|) ident(record)operator(.)ident(quoted_id) operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(interpolate_sql_options!)operator(()ident(options)operator(,) operator(*)ident(keys)operator(\)) + ident(keys)operator(.)ident(each) operator({) operator(|)ident(key)operator(|) ident(options)operator([)ident(key)operator(]) operator(&&=) ident(interpolate_sql)operator(()ident(options)operator([)ident(key)operator(])operator(\)) operator(}) + reserved(end) + + reserved(def) method(interpolate_sql)operator(()ident(sql)operator(,) ident(record) operator(=) pre_constant(nil)operator(\)) + instance_variable(@owner)operator(.)ident(send)operator(()symbol(:interpolate_sql)operator(,) ident(sql)operator(,) ident(record)operator(\)) + reserved(end) + + reserved(def) method(sanitize_sql)operator(()ident(sql)operator(\)) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(send)operator(()symbol(:sanitize_sql)operator(,) ident(sql)operator(\)) + reserved(end) + + reserved(def) method(extract_options_from_args!)operator(()ident(args)operator(\)) + instance_variable(@owner)operator(.)ident(send)operator(()symbol(:extract_options_from_args!)operator(,) ident(args)operator(\)) + reserved(end) + + reserved(def) method(set_belongs_to_association_for)operator(()ident(record)operator(\)) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + ident(record)operator([)string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id)delimiter(")>operator(]) operator(=) instance_variable(@owner)operator(.)ident(id) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) + ident(record)operator([)string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type)delimiter(")>operator(]) operator(=) instance_variable(@owner)operator(.)ident(class)operator(.)ident(base_class)operator(.)ident(name)operator(.)ident(to_s) + reserved(else) + ident(record)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) instance_variable(@owner)operator(.)ident(id) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) + reserved(end) + reserved(end) + + reserved(def) method(merge_options_from_reflection!)operator(()ident(options)operator(\)) + ident(options)operator(.)ident(reverse_merge!)operator(() + symbol(:group) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:group)operator(])operator(,) + symbol(:limit) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:limit)operator(])operator(,) + symbol(:offset) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:offset)operator(])operator(,) + symbol(:joins) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:joins)operator(])operator(,) + symbol(:include) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:include)operator(])operator(,) + symbol(:select) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:select)operator(]) + operator(\)) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(load_target) + instance_variable(@target)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(load_target) + reserved(if) operator(!)instance_variable(@owner)operator(.)ident(new_record?) operator(||) ident(foreign_key_present) + reserved(begin) + instance_variable(@target) operator(=) ident(find_target) reserved(if) operator(!)ident(loaded?) + reserved(rescue) constant(ActiveRecord)operator(::)constant(RecordNotFound) + ident(reset) + reserved(end) + reserved(end) + + ident(loaded) reserved(if) ident(target) + ident(target) + reserved(end) + + comment(# Can be overwritten by associations that might have the foreign key available for an association without) + comment(# having the object itself (and still being a new record\). Currently, only belongs_to present this scenario.) + reserved(def) method(foreign_key_present) + pre_constant(false) + reserved(end) + + reserved(def) method(raise_on_type_mismatch)operator(()ident(record)operator(\)) + reserved(unless) ident(record)operator(.)ident(is_a?)operator(()instance_variable(@reflection)operator(.)ident(klass)operator(\)) + ident(raise) constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(,) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(class_name)inline_delimiter(})>content( expected, got )inline<inline_delimiter(#{)ident(record)operator(.)ident(class)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(BelongsToAssociation) operator(<) constant(AssociationProxy) comment(#:nodoc:) + reserved(def) method(create)operator(()ident(attributes) operator(=) operator({)operator(})operator(\)) + ident(replace)operator(()instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(create)operator(()ident(attributes)operator(\))operator(\)) + reserved(end) + + reserved(def) method(build)operator(()ident(attributes) operator(=) operator({)operator(})operator(\)) + ident(replace)operator(()instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(new)operator(()ident(attributes)operator(\))operator(\)) + reserved(end) + + reserved(def) method(replace)operator(()ident(record)operator(\)) + ident(counter_cache_name) operator(=) instance_variable(@reflection)operator(.)ident(counter_cache_column) + + reserved(if) ident(record)operator(.)ident(nil?) + reserved(if) ident(counter_cache_name) operator(&&) instance_variable(@owner)operator([)ident(counter_cache_name)operator(]) operator(&&) operator(!)instance_variable(@owner)operator(.)ident(new_record?) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(decrement_counter)operator(()ident(counter_cache_name)operator(,) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(\)) reserved(if) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) + reserved(end) + + instance_variable(@target) operator(=) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) pre_constant(nil) + reserved(else) + ident(raise_on_type_mismatch)operator(()ident(record)operator(\)) + + reserved(if) ident(counter_cache_name) operator(&&) operator(!)instance_variable(@owner)operator(.)ident(new_record?) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(increment_counter)operator(()ident(counter_cache_name)operator(,) ident(record)operator(.)ident(id)operator(\)) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(decrement_counter)operator(()ident(counter_cache_name)operator(,) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(\)) reserved(if) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) + reserved(end) + + instance_variable(@target) operator(=) operator(()constant(AssociationProxy) operator(===) ident(record) operator(?) ident(record)operator(.)ident(target) operator(:) ident(record)operator(\)) + instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) ident(record)operator(.)ident(id) reserved(unless) ident(record)operator(.)ident(new_record?) + instance_variable(@updated) operator(=) pre_constant(true) + reserved(end) + + ident(loaded) + ident(record) + reserved(end) + + reserved(def) method(updated?) + instance_variable(@updated) + reserved(end) + + ident(private) + reserved(def) method(find_target) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find)operator(() + instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(,) + symbol(:conditions) operator(=)operator(>) ident(conditions)operator(,) + symbol(:include) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:include)operator(]) + operator(\)) + reserved(end) + + reserved(def) method(foreign_key_present) + operator(!)instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(.)ident(nil?) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(BelongsToPolymorphicAssociation) operator(<) constant(AssociationProxy) comment(#:nodoc:) + reserved(def) method(replace)operator(()ident(record)operator(\)) + reserved(if) ident(record)operator(.)ident(nil?) + instance_variable(@target) operator(=) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:foreign_type)operator(])operator(]) operator(=) pre_constant(nil) + reserved(else) + instance_variable(@target) operator(=) operator(()constant(AssociationProxy) operator(===) ident(record) operator(?) ident(record)operator(.)ident(target) operator(:) ident(record)operator(\)) + + reserved(unless) ident(record)operator(.)ident(new_record?) + instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) ident(record)operator(.)ident(id) + instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:foreign_type)operator(])operator(]) operator(=) ident(record)operator(.)ident(class)operator(.)ident(base_class)operator(.)ident(name)operator(.)ident(to_s) + reserved(end) + + instance_variable(@updated) operator(=) pre_constant(true) + reserved(end) + + ident(loaded) + ident(record) + reserved(end) + + reserved(def) method(updated?) + instance_variable(@updated) + reserved(end) + + ident(private) + reserved(def) method(find_target) + reserved(return) pre_constant(nil) reserved(if) ident(association_class)operator(.)ident(nil?) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(]) + ident(association_class)operator(.)ident(find)operator(() + instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(,) + symbol(:conditions) operator(=)operator(>) ident(conditions)operator(,) + symbol(:include) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:include)operator(]) + operator(\)) + reserved(else) + ident(association_class)operator(.)ident(find)operator(()instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(,) symbol(:include) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:include)operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(foreign_key_present) + operator(!)instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(])operator(.)ident(nil?) + reserved(end) + + reserved(def) method(association_class) + instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:foreign_type)operator(])operator(]) operator(?) instance_variable(@owner)operator([)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:foreign_type)operator(])operator(])operator(.)ident(constantize) operator(:) pre_constant(nil) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(HasAndBelongsToManyAssociation) operator(<) constant(AssociationCollection) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(owner)operator(,) ident(reflection)operator(\)) + reserved(super) + ident(construct_sql) + reserved(end) + + reserved(def) method(build)operator(()ident(attributes) operator(=) operator({)operator(})operator(\)) + ident(load_target) + ident(record) operator(=) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(new)operator(()ident(attributes)operator(\)) + instance_variable(@target) operator(<<) ident(record) + ident(record) + reserved(end) + + reserved(def) method(find_first) + ident(load_target)operator(.)ident(first) + reserved(end) + + reserved(def) method(find)operator(()operator(*)ident(args)operator(\)) + ident(options) operator(=) constant(Base)operator(.)ident(send)operator(()symbol(:extract_options_from_args!)operator(,) ident(args)operator(\)) + + comment(# If using a custom finder_sql, scan the entire collection.) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + ident(expects_array) operator(=) ident(args)operator(.)ident(first)operator(.)ident(kind_of?)operator(()constant(Array)operator(\)) + ident(ids) operator(=) ident(args)operator(.)ident(flatten)operator(.)ident(compact)operator(.)ident(uniq) + + reserved(if) ident(ids)operator(.)ident(size) operator(==) integer(1) + ident(id) operator(=) ident(ids)operator(.)ident(first)operator(.)ident(to_i) + ident(record) operator(=) ident(load_target)operator(.)ident(detect) operator({) operator(|)ident(record)operator(|) ident(id) operator(==) ident(record)operator(.)ident(id) operator(}) + ident(expects_array) operator(?) operator([)ident(record)operator(]) operator(:) ident(record) + reserved(else) + ident(load_target)operator(.)ident(select) operator({) operator(|)ident(record)operator(|) ident(ids)operator(.)ident(include?)operator(()ident(record)operator(.)ident(id)operator(\)) operator(}) + reserved(end) + reserved(else) + ident(conditions) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@finder_sql)inline_delimiter(})>delimiter(")> + + reserved(if) ident(sanitized_conditions) operator(=) ident(sanitize_sql)operator(()ident(options)operator([)symbol(:conditions)operator(])operator(\)) + ident(conditions) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitized_conditions)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + ident(options)operator([)symbol(:conditions)operator(]) operator(=) ident(conditions) + ident(options)operator([)symbol(:joins)operator(]) operator(=) instance_variable(@join_sql) + ident(options)operator([)symbol(:readonly)operator(]) operator(=) ident(finding_with_ambigious_select?)operator(()ident(options)operator([)symbol(:select)operator(])operator(\)) + + reserved(if) ident(options)operator([)symbol(:order)operator(]) operator(&&) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>delimiter(")> + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + reserved(end) + + ident(merge_options_from_reflection!)operator(()ident(options)operator(\)) + + comment(# Pass through args exactly as we received them.) + ident(args) operator(<<) ident(options) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(push_with_attributes)operator(()ident(record)operator(,) ident(join_attributes) operator(=) operator({)operator(})operator(\)) + ident(raise_on_type_mismatch)operator(()ident(record)operator(\)) + ident(join_attributes)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) ident(record)operator([)ident(key)operator(.)ident(to_s)operator(]) operator(=) ident(value) operator(}) + + ident(callback)operator(()symbol(:before_add)operator(,) ident(record)operator(\)) + ident(insert_record)operator(()ident(record)operator(\)) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) + instance_variable(@target) operator(<<) ident(record) + ident(callback)operator(()symbol(:after_add)operator(,) ident(record)operator(\)) + + pre_constant(self) + reserved(end) + + reserved(alias) symbol(:concat_with_attributes) symbol(:push_with_attributes) + + reserved(def) method(size) + instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:uniq)operator(]) operator(?) ident(count_records) operator(:) reserved(super) + reserved(end) + + ident(protected) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(if) instance_variable(@target)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) operator(||) operator(()operator(!)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) operator(&&) constant(Class)operator(.)ident(respond_to?)operator(()ident(method)operator(\))operator(\)) + reserved(super) + reserved(else) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) instance_variable(@finder_sql)operator(,) symbol(:joins) operator(=)operator(>) instance_variable(@join_sql)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false) operator(})operator(\)) reserved(do) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(find_target) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + ident(records) operator(=) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find_by_sql)operator(()instance_variable(@finder_sql)operator(\)) + reserved(else) + ident(records) operator(=) ident(find)operator(()symbol(:all)operator(\)) + reserved(end) + + instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:uniq)operator(]) operator(?) ident(uniq)operator(()ident(records)operator(\)) operator(:) ident(records) + reserved(end) + + reserved(def) method(count_records) + ident(load_target)operator(.)ident(size) + reserved(end) + + reserved(def) method(insert_record)operator(()ident(record)operator(\)) + reserved(if) ident(record)operator(.)ident(new_record?) + reserved(return) pre_constant(false) reserved(unless) ident(record)operator(.)ident(save) + reserved(end) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:insert_sql)operator(]) + instance_variable(@owner)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:insert_sql)operator(])operator(,) ident(record)operator(\))operator(\)) + reserved(else) + ident(columns) operator(=) instance_variable(@owner)operator(.)ident(connection)operator(.)ident(columns)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])operator(,) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])inline_delimiter(})>content( Columns)delimiter(")>operator(\)) + + ident(attributes) operator(=) ident(columns)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(attributes)operator(,) ident(column)operator(|) + reserved(case) ident(column)operator(.)ident(name) + reserved(when) instance_variable(@reflection)operator(.)ident(primary_key_name) + ident(attributes)operator([)ident(column)operator(.)ident(name)operator(]) operator(=) instance_variable(@owner)operator(.)ident(quoted_id) + reserved(when) instance_variable(@reflection)operator(.)ident(association_foreign_key) + ident(attributes)operator([)ident(column)operator(.)ident(name)operator(]) operator(=) ident(record)operator(.)ident(quoted_id) + reserved(else) + reserved(if) ident(record)operator(.)ident(attributes)operator(.)ident(has_key?)operator(()ident(column)operator(.)ident(name)operator(\)) + ident(value) operator(=) instance_variable(@owner)operator(.)ident(send)operator(()symbol(:quote)operator(,) ident(record)operator([)ident(column)operator(.)ident(name)operator(])operator(,) ident(column)operator(\)) + ident(attributes)operator([)ident(column)operator(.)ident(name)operator(]) operator(=) ident(value) reserved(unless) ident(value)operator(.)ident(nil?) + reserved(end) + reserved(end) + ident(attributes) + reserved(end) + + ident(sql) operator(=) + string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])inline_delimiter(})>content( ()inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(send)operator(()symbol(:quoted_column_names)operator(,) ident(attributes)operator(\))operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>content(\) )delimiter(")> operator(+) + string<delimiter(")content(VALUES ()inline<inline_delimiter(#{)ident(attributes)operator(.)ident(values)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>content(\))delimiter(")> + + instance_variable(@owner)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) + reserved(end) + + reserved(return) pre_constant(true) + reserved(end) + + reserved(def) method(delete_records)operator(()ident(records)operator(\)) + reserved(if) ident(sql) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:delete_sql)operator(]) + ident(records)operator(.)ident(each) operator({) operator(|)ident(record)operator(|) instance_variable(@owner)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(interpolate_sql)operator(()ident(sql)operator(,) ident(record)operator(\))operator(\)) operator(}) + reserved(else) + ident(ids) operator(=) ident(quoted_record_ids)operator(()ident(records)operator(\)) + ident(sql) operator(=) string<delimiter(")content(DELETE FROM )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])inline_delimiter(})>content( WHERE )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(association_foreign_key)inline_delimiter(})>content( IN ()inline<inline_delimiter(#{)ident(ids)inline_delimiter(})>content(\))delimiter(")> + instance_variable(@owner)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(construct_sql) + ident(interpolate_sql_options!)operator(()instance_variable(@reflection)operator(.)ident(options)operator(,) symbol(:finder_sql)operator(\)) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + instance_variable(@finder_sql) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + reserved(else) + instance_variable(@finder_sql) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>content( )delimiter(")> + instance_variable(@finder_sql) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(conditions) + reserved(end) + + instance_variable(@join_sql) operator(=) string<delimiter(")content(INNER JOIN )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])inline_delimiter(})>content( ON )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(association_foreign_key)inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Join tables with additional columns on top of the two foreign keys must be considered ambigious unless a select) + comment(# clause has been explicitly defined. Otherwise you can get broken records back, if, say, the join column also has) + comment(# and id column, which will then overwrite the id column of the records coming back.) + reserved(def) method(finding_with_ambigious_select?)operator(()ident(select_clause)operator(\)) + operator(!)ident(select_clause) operator(&&) instance_variable(@owner)operator(.)ident(connection)operator(.)ident(columns)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(])operator(,) string<delimiter(")content(Join Table Columns)delimiter(")>operator(\))operator(.)ident(size) operator(!=) integer(2) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(HasManyAssociation) operator(<) constant(AssociationCollection) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(owner)operator(,) ident(reflection)operator(\)) + reserved(super) + ident(construct_sql) + reserved(end) + + reserved(def) method(build)operator(()ident(attributes) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(attributes)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(attributes)operator(.)ident(collect) operator({) operator(|)ident(attr)operator(|) ident(build)operator(()ident(attr)operator(\)) operator(}) + reserved(else) + ident(load_target) + ident(record) operator(=) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(new)operator(()ident(attributes)operator(\)) + ident(set_belongs_to_association_for)operator(()ident(record)operator(\)) + instance_variable(@target) operator(<<) ident(record) + ident(record) + reserved(end) + reserved(end) + + comment(# DEPRECATED.) + reserved(def) method(find_all)operator(()ident(runtime_conditions) operator(=) pre_constant(nil)operator(,) ident(orderings) operator(=) pre_constant(nil)operator(,) ident(limit) operator(=) pre_constant(nil)operator(,) ident(joins) operator(=) pre_constant(nil)operator(\)) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find_by_sql)operator(()instance_variable(@finder_sql)operator(\)) + reserved(else) + ident(conditions) operator(=) instance_variable(@finder_sql) + ident(conditions) operator(+=) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitize_sql)operator(()ident(runtime_conditions)operator(\))inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(runtime_conditions) + ident(orderings) operator(||=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find_all)operator(()ident(conditions)operator(,) ident(orderings)operator(,) ident(limit)operator(,) ident(joins)operator(\)) + reserved(end) + reserved(end) + + comment(# DEPRECATED. Find the first associated record. All arguments are optional.) + reserved(def) method(find_first)operator(()ident(conditions) operator(=) pre_constant(nil)operator(,) ident(orderings) operator(=) pre_constant(nil)operator(\)) + ident(find_all)operator(()ident(conditions)operator(,) ident(orderings)operator(,) integer(1)operator(\))operator(.)ident(first) + reserved(end) + + comment(# Count the number of associated records. All arguments are optional.) + reserved(def) method(count)operator(()ident(runtime_conditions) operator(=) pre_constant(nil)operator(\)) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(]) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(count_by_sql)operator(()instance_variable(@counter_sql)operator(\)) + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(count_by_sql)operator(()instance_variable(@finder_sql)operator(\)) + reserved(else) + ident(sql) operator(=) instance_variable(@finder_sql) + ident(sql) operator(+=) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitize_sql)operator(()ident(runtime_conditions)operator(\))inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(runtime_conditions) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(count)operator(()ident(sql)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(find)operator(()operator(*)ident(args)operator(\)) + ident(options) operator(=) constant(Base)operator(.)ident(send)operator(()symbol(:extract_options_from_args!)operator(,) ident(args)operator(\)) + + comment(# If using a custom finder_sql, scan the entire collection.) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + ident(expects_array) operator(=) ident(args)operator(.)ident(first)operator(.)ident(kind_of?)operator(()constant(Array)operator(\)) + ident(ids) operator(=) ident(args)operator(.)ident(flatten)operator(.)ident(compact)operator(.)ident(uniq) + + reserved(if) ident(ids)operator(.)ident(size) operator(==) integer(1) + ident(id) operator(=) ident(ids)operator(.)ident(first) + ident(record) operator(=) ident(load_target)operator(.)ident(detect) operator({) operator(|)ident(record)operator(|) ident(id) operator(==) ident(record)operator(.)ident(id) operator(}) + ident(expects_array) operator(?) operator([) ident(record) operator(]) operator(:) ident(record) + reserved(else) + ident(load_target)operator(.)ident(select) operator({) operator(|)ident(record)operator(|) ident(ids)operator(.)ident(include?)operator(()ident(record)operator(.)ident(id)operator(\)) operator(}) + reserved(end) + reserved(else) + ident(conditions) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@finder_sql)inline_delimiter(})>delimiter(")> + reserved(if) ident(sanitized_conditions) operator(=) ident(sanitize_sql)operator(()ident(options)operator([)symbol(:conditions)operator(])operator(\)) + ident(conditions) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitized_conditions)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + ident(options)operator([)symbol(:conditions)operator(]) operator(=) ident(conditions) + + reserved(if) ident(options)operator([)symbol(:order)operator(]) operator(&&) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>delimiter(")> + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + reserved(end) + + ident(merge_options_from_reflection!)operator(()ident(options)operator(\)) + + comment(# Pass through args exactly as we received them.) + ident(args) operator(<<) ident(options) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(if) instance_variable(@target)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) operator(||) operator(()operator(!)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) operator(&&) constant(Class)operator(.)ident(respond_to?)operator(()ident(method)operator(\))operator(\)) + reserved(super) + reserved(else) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(with_scope)operator(() + symbol(:find) operator(=)operator(>) operator({) + symbol(:conditions) operator(=)operator(>) instance_variable(@finder_sql)operator(,) + symbol(:joins) operator(=)operator(>) instance_variable(@join_sql)operator(,) + symbol(:readonly) operator(=)operator(>) pre_constant(false) + operator(})operator(,) + symbol(:create) operator(=)operator(>) operator({) + instance_variable(@reflection)operator(.)ident(primary_key_name) operator(=)operator(>) instance_variable(@owner)operator(.)ident(id) + operator(}) + operator(\)) reserved(do) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(find_target) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find_by_sql)operator(()instance_variable(@finder_sql)operator(\)) + reserved(else) + ident(find)operator(()symbol(:all)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(count_records) + ident(count) operator(=) reserved(if) ident(has_cached_counter?) + instance_variable(@owner)operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) ident(cached_counter_attribute_name)operator(\)) + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(]) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(count_by_sql)operator(()instance_variable(@counter_sql)operator(\)) + reserved(else) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(count)operator(()instance_variable(@counter_sql)operator(\)) + reserved(end) + + instance_variable(@target) operator(=) operator([)operator(]) reserved(and) ident(loaded) reserved(if) ident(count) operator(==) integer(0) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:limit)operator(]) + ident(count) operator(=) operator([) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:limit)operator(])operator(,) ident(count) operator(])operator(.)ident(min) + reserved(end) + + reserved(return) ident(count) + reserved(end) + + reserved(def) method(has_cached_counter?) + instance_variable(@owner)operator(.)ident(attribute_present?)operator(()ident(cached_counter_attribute_name)operator(\)) + reserved(end) + + reserved(def) method(cached_counter_attribute_name) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(name)inline_delimiter(})>content(_count)delimiter(")> + reserved(end) + + reserved(def) method(insert_record)operator(()ident(record)operator(\)) + ident(set_belongs_to_association_for)operator(()ident(record)operator(\)) + ident(record)operator(.)ident(save) + reserved(end) + + reserved(def) method(delete_records)operator(()ident(records)operator(\)) + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) + ident(records)operator(.)ident(each) operator({) operator(|)ident(r)operator(|) ident(r)operator(.)ident(destroy) operator(}) + reserved(else) + ident(ids) operator(=) ident(quoted_record_ids)operator(()ident(records)operator(\)) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(update_all)operator(() + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = NULL)delimiter(")>operator(,) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>content( AND )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(primary_key)inline_delimiter(})>content( IN ()inline<inline_delimiter(#{)ident(ids)inline_delimiter(})>content(\))delimiter(")> + operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(target_obsolete?) + pre_constant(false) + reserved(end) + + reserved(def) method(construct_sql) + reserved(case) + reserved(when) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + instance_variable(@finder_sql) operator(=) ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(])operator(\)) + + reserved(when) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + instance_variable(@finder_sql) operator(=) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>content( AND )delimiter(")> operator(+) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(class)operator(.)ident(quote) instance_variable(@owner)operator(.)ident(class)operator(.)ident(base_class)operator(.)ident(name)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + instance_variable(@finder_sql) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(conditions) + + reserved(else) + instance_variable(@finder_sql) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>delimiter(")> + instance_variable(@finder_sql) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(conditions) + reserved(end) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(]) + instance_variable(@counter_sql) operator(=) ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(])operator(\)) + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + comment(# replace the SELECT clause with COUNT(*\), preserving any hints within /* ... */) + instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(]) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(])operator(.)ident(sub)operator(()regexp<delimiter(/)content(SELECT ()char(\\/)char(\\*)content(.*?)char(\\*)char(\\/)content( \)?(.*\))char(\\b)content(FROM)char(\\b)delimiter(/)modifier(im)>operator(\)) operator({) string<delimiter(")content(SELECT )inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content(COUNT(*\) FROM)delimiter(")> operator(}) + instance_variable(@counter_sql) operator(=) ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(])operator(\)) + reserved(else) + instance_variable(@counter_sql) operator(=) instance_variable(@finder_sql) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(HasManyThroughAssociation) operator(<) constant(AssociationProxy) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(owner)operator(,) ident(reflection)operator(\)) + reserved(super) + ident(reflection)operator(.)ident(check_validity!) + instance_variable(@finder_sql) operator(=) ident(construct_conditions) + ident(construct_sql) + reserved(end) + + + reserved(def) method(find)operator(()operator(*)ident(args)operator(\)) + ident(options) operator(=) constant(Base)operator(.)ident(send)operator(()symbol(:extract_options_from_args!)operator(,) ident(args)operator(\)) + + ident(conditions) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@finder_sql)inline_delimiter(})>delimiter(")> + reserved(if) ident(sanitized_conditions) operator(=) ident(sanitize_sql)operator(()ident(options)operator([)symbol(:conditions)operator(])operator(\)) + ident(conditions) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitized_conditions)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + ident(options)operator([)symbol(:conditions)operator(]) operator(=) ident(conditions) + + reserved(if) ident(options)operator([)symbol(:order)operator(]) operator(&&) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>content(, )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>delimiter(")> + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(]) + reserved(end) + + ident(options)operator([)symbol(:select)operator(]) operator(=) ident(construct_select)operator(()ident(options)operator([)symbol(:select)operator(])operator(\)) + ident(options)operator([)symbol(:from)operator(]) operator(||=) ident(construct_from) + ident(options)operator([)symbol(:joins)operator(]) operator(=) ident(construct_joins)operator(()ident(options)operator([)symbol(:joins)operator(])operator(\)) + ident(options)operator([)symbol(:include)operator(]) operator(=) instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(options)operator([)symbol(:include)operator(]) reserved(if) ident(options)operator([)symbol(:include)operator(])operator(.)ident(nil?) + + ident(merge_options_from_reflection!)operator(()ident(options)operator(\)) + + comment(# Pass through args exactly as we received them.) + ident(args) operator(<<) ident(options) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find)operator(()operator(*)ident(args)operator(\)) + reserved(end) + + reserved(def) method(reset) + instance_variable(@target) operator(=) operator([)operator(]) + instance_variable(@loaded) operator(=) pre_constant(false) + reserved(end) + + ident(protected) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(if) instance_variable(@target)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) operator(||) operator(()operator(!)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) operator(&&) constant(Class)operator(.)ident(respond_to?)operator(()ident(method)operator(\))operator(\)) + reserved(super) + reserved(else) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(with_scope)operator(()ident(construct_scope)operator(\)) operator({) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(find_target) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find)operator(()symbol(:all)operator(,) + symbol(:select) operator(=)operator(>) ident(construct_select)operator(,) + symbol(:conditions) operator(=)operator(>) ident(construct_conditions)operator(,) + symbol(:from) operator(=)operator(>) ident(construct_from)operator(,) + symbol(:joins) operator(=)operator(>) ident(construct_joins)operator(,) + symbol(:order) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(])operator(,) + symbol(:limit) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:limit)operator(])operator(,) + symbol(:group) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:group)operator(])operator(,) + symbol(:include) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:include)operator(]) operator(||) instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(options)operator([)symbol(:include)operator(]) + operator(\)) + reserved(end) + + reserved(def) method(construct_conditions) + ident(conditions) operator(=) reserved(if) instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>content( )delimiter(")> operator(+) + string<delimiter(")content(AND )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(class)operator(.)ident(quote) instance_variable(@owner)operator(.)ident(class)operator(.)ident(base_class)operator(.)ident(name)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + reserved(else) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>delimiter(")> + reserved(end) + ident(conditions) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sql_conditions)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(sql_conditions) + + reserved(return) ident(conditions) + reserved(end) + + reserved(def) method(construct_from) + instance_variable(@reflection)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(construct_select)operator(()ident(custom_select) operator(=) pre_constant(nil)operator(\)) + ident(selected) operator(=) ident(custom_select) operator(||) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:select)operator(]) operator(||) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(table_name)inline_delimiter(})>content(.*)delimiter(")> + reserved(end) + + reserved(def) method(construct_joins)operator(()ident(custom_joins) operator(=) pre_constant(nil)operator(\)) + ident(polymorphic_join) operator(=) pre_constant(nil) + reserved(if) instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) operator(||) instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(macro) operator(==) symbol(:belongs_to) + ident(reflection_primary_key) operator(=) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(primary_key) + ident(source_primary_key) operator(=) instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(primary_key_name) + reserved(else) + ident(reflection_primary_key) operator(=) instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(primary_key_name) + ident(source_primary_key) operator(=) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(primary_key) + reserved(if) instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + ident(polymorphic_join) operator(=) string<delimiter(")content(AND %s.%s = %s)delimiter(")> operator(%) operator([) + instance_variable(@reflection)operator(.)ident(table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(source_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type)delimiter(")>operator(,) + instance_variable(@owner)operator(.)ident(class)operator(.)ident(quote)operator(()instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(klass)operator(.)ident(name)operator(\)) + operator(]) + reserved(end) + reserved(end) + + string<delimiter(")content(INNER JOIN %s ON %s.%s = %s.%s %s )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:joins)operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(custom_joins)inline_delimiter(})>delimiter(")> operator(%) operator([) + instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(table_name)operator(,) + instance_variable(@reflection)operator(.)ident(table_name)operator(,) ident(reflection_primary_key)operator(,) + instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(table_name)operator(,) ident(source_primary_key)operator(,) + ident(polymorphic_join) + operator(]) + reserved(end) + + reserved(def) method(construct_scope) + operator({) + symbol(:find) operator(=)operator(>) operator({) symbol(:from) operator(=)operator(>) ident(construct_from)operator(,) symbol(:conditions) operator(=)operator(>) ident(construct_conditions)operator(,) symbol(:joins) operator(=)operator(>) ident(construct_joins)operator(,) symbol(:select) operator(=)operator(>) ident(construct_select) operator(})operator(,) + symbol(:create) operator(=)operator(>) operator({) instance_variable(@reflection)operator(.)ident(primary_key_name) operator(=)operator(>) instance_variable(@owner)operator(.)ident(id) operator(}) + operator(}) + reserved(end) + + reserved(def) method(construct_sql) + reserved(case) + reserved(when) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + instance_variable(@finder_sql) operator(=) ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(])operator(\)) + + instance_variable(@finder_sql) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>delimiter(")> + instance_variable(@finder_sql) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(conditions) + reserved(end) + + reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(]) + instance_variable(@counter_sql) operator(=) ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(])operator(\)) + reserved(elsif) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(]) + comment(# replace the SELECT clause with COUNT(*\), preserving any hints within /* ... */) + instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(]) operator(=) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:finder_sql)operator(])operator(.)ident(sub)operator(()regexp<delimiter(/)content(SELECT ()char(\\/)char(\\*)content(.*?)char(\\*)char(\\/)content( \)?(.*\))char(\\b)content(FROM)char(\\b)delimiter(/)modifier(im)>operator(\)) operator({) string<delimiter(")content(SELECT )inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content(COUNT(*\) FROM)delimiter(")> operator(}) + instance_variable(@counter_sql) operator(=) ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:counter_sql)operator(])operator(\)) + reserved(else) + instance_variable(@counter_sql) operator(=) instance_variable(@finder_sql) + reserved(end) + reserved(end) + + reserved(def) method(conditions) + instance_variable(@conditions) operator(||=) operator([) + operator(()ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(active_record)operator(.)ident(send)operator(()symbol(:sanitize_sql)operator(,) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\))operator(\)) reserved(if) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\))operator(,) + operator(()ident(interpolate_sql)operator(()instance_variable(@reflection)operator(.)ident(active_record)operator(.)ident(send)operator(()symbol(:sanitize_sql)operator(,) instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\))operator(\)) reserved(if) instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\)) + operator(])operator(.)ident(compact)operator(.)ident(collect) operator({) operator(|)ident(condition)operator(|) string<delimiter(")content(()inline<inline_delimiter(#{)ident(condition)inline_delimiter(})>content(\))delimiter(")> operator(})operator(.)ident(join)operator(()string<delimiter(')content( AND )delimiter(')>operator(\)) reserved(unless) operator(()operator(!)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(]) operator(&&) operator(!)instance_variable(@reflection)operator(.)ident(through_reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\)) + reserved(end) + + ident(alias_method) symbol(:sql_conditions)operator(,) symbol(:conditions) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Associations) + reserved(class) class(HasOneAssociation) operator(<) constant(BelongsToAssociation) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(owner)operator(,) ident(reflection)operator(\)) + reserved(super) + ident(construct_sql) + reserved(end) + + reserved(def) method(create)operator(()ident(attributes) operator(=) operator({)operator(})operator(,) ident(replace_existing) operator(=) pre_constant(true)operator(\)) + ident(record) operator(=) ident(build)operator(()ident(attributes)operator(,) ident(replace_existing)operator(\)) + ident(record)operator(.)ident(save) + ident(record) + reserved(end) + + reserved(def) method(build)operator(()ident(attributes) operator(=) operator({)operator(})operator(,) ident(replace_existing) operator(=) pre_constant(true)operator(\)) + ident(record) operator(=) instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(new)operator(()ident(attributes)operator(\)) + + reserved(if) ident(replace_existing) + ident(replace)operator(()ident(record)operator(,) pre_constant(true)operator(\)) + reserved(else) + ident(record)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) instance_variable(@owner)operator(.)ident(id) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) + pre_constant(self)operator(.)ident(target) operator(=) ident(record) + reserved(end) + + ident(record) + reserved(end) + + reserved(def) method(replace)operator(()ident(obj)operator(,) ident(dont_save) operator(=) pre_constant(false)operator(\)) + ident(load_target) + + reserved(unless) instance_variable(@target)operator(.)ident(nil?) + reserved(if) ident(dependent?) operator(&&) operator(!)ident(dont_save) operator(&&) instance_variable(@target) operator(!=) ident(obj) + instance_variable(@target)operator(.)ident(destroy) reserved(unless) instance_variable(@target)operator(.)ident(new_record?) + instance_variable(@owner)operator(.)ident(clear_association_cache) + reserved(else) + instance_variable(@target)operator([)instance_variable(@reflection)operator(.)ident(primary_key_name)operator(]) operator(=) pre_constant(nil) + instance_variable(@target)operator(.)ident(save) reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) operator(||) instance_variable(@target)operator(.)ident(new_record?) + reserved(end) + reserved(end) + + reserved(if) ident(obj)operator(.)ident(nil?) + instance_variable(@target) operator(=) pre_constant(nil) + reserved(else) + ident(raise_on_type_mismatch)operator(()ident(obj)operator(\)) + ident(set_belongs_to_association_for)operator(()ident(obj)operator(\)) + instance_variable(@target) operator(=) operator(()constant(AssociationProxy) operator(===) ident(obj) operator(?) ident(obj)operator(.)ident(target) operator(:) ident(obj)operator(\)) + reserved(end) + + instance_variable(@loaded) operator(=) pre_constant(true) + + reserved(unless) instance_variable(@owner)operator(.)ident(new_record?) reserved(or) ident(obj)operator(.)ident(nil?) reserved(or) ident(dont_save) + reserved(return) operator(()ident(obj)operator(.)ident(save) operator(?) pre_constant(self) operator(:) pre_constant(false)operator(\)) + reserved(else) + reserved(return) operator(()ident(obj)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) pre_constant(self)operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(find_target) + instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(find)operator(()symbol(:first)operator(,) + symbol(:conditions) operator(=)operator(>) instance_variable(@finder_sql)operator(,) + symbol(:order) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:order)operator(])operator(,) + symbol(:include) operator(=)operator(>) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:include)operator(]) + operator(\)) + reserved(end) + + reserved(def) method(construct_sql) + reserved(case) + reserved(when) instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + instance_variable(@finder_sql) operator(=) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>content( AND )delimiter(")> operator(+) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(class)operator(.)ident(quote) instance_variable(@owner)operator(.)ident(class)operator(.)ident(base_class)operator(.)ident(name)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + reserved(else) + instance_variable(@finder_sql) operator(=) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)instance_variable(@owner)operator(.)ident(quoted_id)inline_delimiter(})>delimiter(")> + reserved(end) + instance_variable(@finder_sql) operator(<<) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(conditions) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(active_record/associations/association_proxy)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/association_collection)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/belongs_to_association)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/belongs_to_polymorphic_association)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/has_one_association)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/has_many_association)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/has_many_through_association)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations/has_and_belongs_to_many_association)delimiter(')> +ident(require) string<delimiter(')content(active_record/deprecated_associations)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(HasManyThroughAssociationNotFoundError) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(reflection)operator(\)) + instance_variable(@reflection) operator(=) ident(reflection) + reserved(end) + + reserved(def) method(message) + string<delimiter(")content(Could not find the association )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(options)operator([)symbol(:through)operator(])operator(.)ident(inspect)inline_delimiter(})>content( in model )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(klass)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(HasManyThroughAssociationPolymorphicError) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(owner_class_name)operator(,) ident(reflection)operator(,) ident(source_reflection)operator(\)) + instance_variable(@owner_class_name) operator(=) ident(owner_class_name) + instance_variable(@reflection) operator(=) ident(reflection) + instance_variable(@source_reflection) operator(=) ident(source_reflection) + reserved(end) + + reserved(def) method(message) + string<delimiter(")content(Cannot have a has_many :through association ')inline<inline_delimiter(#{)instance_variable(@owner_class_name)inline_delimiter(})>content(#)inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(name)inline_delimiter(})>content(' on the polymorphic object ')inline<inline_delimiter(#{)instance_variable(@source_reflection)operator(.)ident(class_name)inline_delimiter(})>content(#)inline<inline_delimiter(#{)instance_variable(@source_reflection)operator(.)ident(name)inline_delimiter(})>content('.)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(HasManyThroughSourceAssociationNotFoundError) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(reflection)operator(\)) + instance_variable(@reflection) operator(=) ident(reflection) + instance_variable(@through_reflection) operator(=) ident(reflection)operator(.)ident(through_reflection) + instance_variable(@source_reflection_names) operator(=) ident(reflection)operator(.)ident(source_reflection_names) + instance_variable(@source_associations) operator(=) ident(reflection)operator(.)ident(through_reflection)operator(.)ident(klass)operator(.)ident(reflect_on_all_associations)operator(.)ident(collect) operator({) operator(|)ident(a)operator(|) ident(a)operator(.)ident(name)operator(.)ident(inspect) operator(}) + reserved(end) + + reserved(def) method(message) + string<delimiter(")content(Could not find the source association(s\) )inline<inline_delimiter(#{)instance_variable(@source_reflection_names)operator(.)ident(collect)operator(()operator(&)symbol(:inspect)operator(\))operator(.)ident(to_sentence) symbol(:connector) operator(=)operator(>) string<delimiter(')content(or)delimiter(')>inline_delimiter(})>content( in model )inline<inline_delimiter(#{)instance_variable(@through_reflection)operator(.)ident(klass)inline_delimiter(})>content(. Try 'has_many )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(, :through => )inline<inline_delimiter(#{)instance_variable(@through_reflection)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(, :source => <name>'. Is it one of )inline<inline_delimiter(#{)instance_variable(@source_associations)operator(.)ident(to_sentence) symbol(:connector) operator(=)operator(>) string<delimiter(')content(or)delimiter(')>inline_delimiter(})>content(?)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(HasManyThroughSourceAssociationMacroError) operator(<) constant(ActiveRecordError) comment(#:nodoc) + reserved(def) method(initialize)operator(()ident(reflection)operator(\)) + instance_variable(@reflection) operator(=) ident(reflection) + instance_variable(@through_reflection) operator(=) ident(reflection)operator(.)ident(through_reflection) + instance_variable(@source_reflection) operator(=) ident(reflection)operator(.)ident(source_reflection) + reserved(end) + + reserved(def) method(message) + string<delimiter(")content(Invalid source reflection macro :)inline<inline_delimiter(#{)instance_variable(@source_reflection)operator(.)ident(macro)inline_delimiter(})>inline<inline_delimiter(#{)string<delimiter(")content( :through)delimiter(")> reserved(if) instance_variable(@source_reflection)operator(.)ident(options)operator([)symbol(:through)operator(])inline_delimiter(})>content( for has_many )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(, :through => )inline<inline_delimiter(#{)instance_variable(@through_reflection)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(. Use :source to specify the source reflection.)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(EagerLoadPolymorphicError) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(reflection)operator(\)) + instance_variable(@reflection) operator(=) ident(reflection) + reserved(end) + + reserved(def) method(message) + string<delimiter(")content(Can not eagerly load the polymorphic association )inline<inline_delimiter(#{)instance_variable(@reflection)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(module) class(Associations) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Clears out the association cache ) + reserved(def) method(clear_association_cache) comment(#:nodoc:) + pre_constant(self)operator(.)ident(class)operator(.)ident(reflect_on_all_associations)operator(.)ident(to_a)operator(.)ident(each) reserved(do) operator(|)ident(assoc)operator(|) + ident(instance_variable_set) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(assoc)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) pre_constant(nil) + reserved(end) reserved(unless) pre_constant(self)operator(.)ident(new_record?) + reserved(end) + + comment(# Associations are a set of macro-like class methods for tying objects together through foreign keys. They express relationships like ) + comment(# "Project has one Project Manager" or "Project belongs to a Portfolio". Each macro adds a number of methods to the class which are ) + comment(# specialized according to the collection or association symbol and the options hash. It works much the same way as Ruby's own attr* ) + comment(# methods. Example:) + comment(#) + comment(# class Project < ActiveRecord::Base) + comment(# belongs_to :portfolio) + comment(# has_one :project_manager ) + comment(# has_many :milestones) + comment(# has_and_belongs_to_many :categories) + comment(# end) + comment(#) + comment(# The project class now has the following methods (and more\) to ease the traversal and manipulation of its relationships:) + comment(# * <tt>Project#portfolio, Project#portfolio=(portfolio\), Project#portfolio.nil?</tt>) + comment(# * <tt>Project#project_manager, Project#project_manager=(project_manager\), Project#project_manager.nil?,</tt>) + comment(# * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone\),</tt>) + comment(# <tt>Project#milestones.delete(milestone\), Project#milestones.find(milestone_id\), Project#milestones.find_all(conditions\),</tt>) + comment(# <tt>Project#milestones.build, Project#milestones.create</tt>) + comment(# * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1\),</tt>) + comment(# <tt>Project#categories.delete(category1\)</tt>) + comment(#) + comment(# == Example) + comment(#) + comment(# link:files/examples/associations.png) + comment(#) + comment(# == Is it belongs_to or has_one?) + comment(#) + comment(# Both express a 1-1 relationship, the difference is mostly where to place the foreign key, which goes on the table for the class) + comment(# saying belongs_to. Example:) + comment(#) + comment(# class Post < ActiveRecord::Base) + comment(# has_one :author) + comment(# end) + comment(#) + comment(# class Author < ActiveRecord::Base) + comment(# belongs_to :post) + comment(# end) + comment(#) + comment(# The tables for these classes could look something like:) + comment(#) + comment(# CREATE TABLE posts () + comment(# id int(11\) NOT NULL auto_increment,) + comment(# title varchar default NULL,) + comment(# PRIMARY KEY (id\)) + comment(# \)) + comment(#) + comment(# CREATE TABLE authors () + comment(# id int(11\) NOT NULL auto_increment,) + comment(# post_id int(11\) default NULL,) + comment(# name varchar default NULL,) + comment(# PRIMARY KEY (id\)) + comment(# \)) + comment(#) + comment(# == Unsaved objects and associations) + comment(#) + comment(# You can manipulate objects and associations before they are saved to the database, but there is some special behaviour you should be) + comment(# aware of, mostly involving the saving of associated objects.) + comment(#) + comment(# === One-to-one associations) + comment(#) + comment(# * Assigning an object to a has_one association automatically saves that object and the object being replaced (if there is one\), in) + comment(# order to update their primary keys - except if the parent object is unsaved (new_record? == true\).) + comment(# * If either of these saves fail (due to one of the objects being invalid\) the assignment statement returns false and the assignment) + comment(# is cancelled.) + comment(# * If you wish to assign an object to a has_one association without saving it, use the #association.build method (documented below\).) + comment(# * Assigning an object to a belongs_to association does not save the object, since the foreign key field belongs on the parent. It does) + comment(# not save the parent either.) + comment(#) + comment(# === Collections) + comment(#) + comment(# * Adding an object to a collection (has_many or has_and_belongs_to_many\) automatically saves that object, except if the parent object) + comment(# (the owner of the collection\) is not yet stored in the database.) + comment(# * If saving any of the objects being added to a collection (via #push or similar\) fails, then #push returns false.) + comment(# * You can add an object to a collection without automatically saving it by using the #collection.build method (documented below\).) + comment(# * All unsaved (new_record? == true\) members of the collection are automatically saved when the parent is saved.) + comment(#) + comment(# === Association callbacks) + comment(#) + comment(# Similiar to the normal callbacks that hook into the lifecycle of an Active Record object, you can also define callbacks that get) + comment(# trigged when you add an object to or removing an object from a association collection. Example:) + comment(#) + comment(# class Project) + comment(# has_and_belongs_to_many :developers, :after_add => :evaluate_velocity) + comment(#) + comment(# def evaluate_velocity(developer\)) + comment(# ...) + comment(# end) + comment(# end ) + comment(#) + comment(# It's possible to stack callbacks by passing them as an array. Example:) + comment(# ) + comment(# class Project) + comment(# has_and_belongs_to_many :developers, :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]) + comment(# end) + comment(#) + comment(# Possible callbacks are: before_add, after_add, before_remove and after_remove.) + comment(#) + comment(# Should any of the before_add callbacks throw an exception, the object does not get added to the collection. Same with) + comment(# the before_remove callbacks, if an exception is thrown the object doesn't get removed.) + comment(#) + comment(# === Association extensions) + comment(#) + comment(# The proxy objects that controls the access to associations can be extended through anonymous modules. This is especially) + comment(# beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association.) + comment(# Example:) + comment(#) + comment(# class Account < ActiveRecord::Base) + comment(# has_many :people do) + comment(# def find_or_create_by_name(name\)) + comment(# first_name, last_name = name.split(" ", 2\)) + comment(# find_or_create_by_first_name_and_last_name(first_name, last_name\)) + comment(# end) + comment(# end) + comment(# end) + comment(#) + comment(# person = Account.find(:first\).people.find_or_create_by_name("David Heinemeier Hansson"\)) + comment(# person.first_name # => "David") + comment(# person.last_name # => "Heinemeier Hansson") + comment(#) + comment(# If you need to share the same extensions between many associations, you can use a named extension module. Example:) + comment(#) + comment(# module FindOrCreateByNameExtension) + comment(# def find_or_create_by_name(name\)) + comment(# first_name, last_name = name.split(" ", 2\)) + comment(# find_or_create_by_first_name_and_last_name(first_name, last_name\)) + comment(# end) + comment(# end) + comment(#) + comment(# class Account < ActiveRecord::Base) + comment(# has_many :people, :extend => FindOrCreateByNameExtension) + comment(# end) + comment(#) + comment(# class Company < ActiveRecord::Base) + comment(# has_many :people, :extend => FindOrCreateByNameExtension) + comment(# end) + comment(#) + comment(# === Association Join Models) + comment(# ) + comment(# Has Many associations can be configured with the :through option to use an explicit join model to retrieve the data. This) + comment(# operates similarly to a <tt>has_and_belongs_to_many</tt> association. The advantage is that you're able to add validations,) + comment(# callbacks, and extra attributes on the join model. Consider the following schema:) + comment(# ) + comment(# class Author < ActiveRecord::Base) + comment(# has_many :authorships) + comment(# has_many :books, :through => :authorships) + comment(# end) + comment(# ) + comment(# class Authorship < ActiveRecord::Base) + comment(# belongs_to :author) + comment(# belongs_to :book) + comment(# end) + comment(# ) + comment(# @author = Author.find :first) + comment(# @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to.) + comment(# @author.books # selects all books by using the Authorship join model) + comment(# ) + comment(# You can also go through a has_many association on the join model:) + comment(# ) + comment(# class Firm < ActiveRecord::Base) + comment(# has_many :clients) + comment(# has_many :invoices, :through => :clients) + comment(# end) + comment(# ) + comment(# class Client < ActiveRecord::Base) + comment(# belongs_to :firm) + comment(# has_many :invoices) + comment(# end) + comment(# ) + comment(# class Invoice < ActiveRecord::Base) + comment(# belongs_to :client) + comment(# end) + comment(#) + comment(# @firm = Firm.find :first) + comment(# @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm) + comment(# @firm.invoices # selects all invoices by going through the Client join model.) + comment(#) + comment(# === Polymorphic Associations) + comment(# ) + comment(# Polymorphic associations on models are not restricted on what types of models they can be associated with. Rather, they ) + comment(# specify an interface that a has_many association must adhere to.) + comment(# ) + comment(# class Asset < ActiveRecord::Base) + comment(# belongs_to :attachable, :polymorphic => true) + comment(# end) + comment(# ) + comment(# class Post < ActiveRecord::Base) + comment(# has_many :assets, :as => :attachable # The <tt>:as</tt> option specifies the polymorphic interface to use.) + comment(# end) + comment(#) + comment(# @asset.attachable = @post) + comment(# ) + comment(# This works by using a type column in addition to a foreign key to specify the associated record. In the Asset example, you'd need) + comment(# an attachable_id integer column and an attachable_type string column.) + comment(#) + comment(# == Caching) + comment(#) + comment(# All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically) + comment(# instructed not to. The cache is even shared across methods to make it even cheaper to use the macro-added methods without ) + comment(# worrying too much about performance at the first go. Example:) + comment(#) + comment(# project.milestones # fetches milestones from the database) + comment(# project.milestones.size # uses the milestone cache) + comment(# project.milestones.empty? # uses the milestone cache) + comment(# project.milestones(true\).size # fetches milestones from the database) + comment(# project.milestones # uses the milestone cache) + comment(#) + comment(# == Eager loading of associations) + comment(#) + comment(# Eager loading is a way to find objects of a certain class and a number of named associations along with it in a single SQL call. This is) + comment(# one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100 posts that each needs to display their author) + comment(# triggers 101 database queries. Through the use of eager loading, the 101 queries can be reduced to 1. Example:) + comment(#) + comment(# class Post < ActiveRecord::Base) + comment(# belongs_to :author) + comment(# has_many :comments) + comment(# end) + comment(#) + comment(# Consider the following loop using the class above:) + comment(#) + comment(# for post in Post.find(:all\)) + comment(# puts "Post: " + post.title) + comment(# puts "Written by: " + post.author.name) + comment(# puts "Last comment on: " + post.comments.first.created_on) + comment(# end ) + comment(#) + comment(# To iterate over these one hundred posts, we'll generate 201 database queries. Let's first just optimize it for retrieving the author:) + comment(#) + comment(# for post in Post.find(:all, :include => :author\)) + comment(#) + comment(# This references the name of the belongs_to association that also used the :author symbol, so the find will now weave in a join something) + comment(# like this: LEFT OUTER JOIN authors ON authors.id = posts.author_id. Doing so will cut down the number of queries from 201 to 101.) + comment(#) + comment(# We can improve upon the situation further by referencing both associations in the finder with:) + comment(#) + comment(# for post in Post.find(:all, :include => [ :author, :comments ]\)) + comment(#) + comment(# That'll add another join along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id. And we'll be down to 1 query.) + comment(# But that shouldn't fool you to think that you can pull out huge amounts of data with no performance penalty just because you've reduced) + comment(# the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no) + comment(# catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above.) + comment(#) + comment(# Please note that limited eager loading with has_many and has_and_belongs_to_many associations is not compatible with describing conditions) + comment(# on these eager tables. This will work:) + comment(#) + comment(# Post.find(:all, :include => :comments, :conditions => "posts.title = 'magic forest'", :limit => 2\)) + comment(#) + comment(# ...but this will not (and an ArgumentError will be raised\):) + comment(#) + comment(# Post.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%'", :limit => 2\)) + comment(#) + comment(# Also have in mind that since the eager loading is pulling from multiple tables, you'll have to disambiguate any column references) + comment(# in both conditions and orders. So :order => "posts.id DESC" will work while :order => "id DESC" will not. This may require that) + comment(# you alter the :order and :conditions on the association definitions themselves.) + comment(#) + comment(# It's currently not possible to use eager loading on multiple associations from the same table. Eager loading will not pull) + comment(# additional attributes on join tables, so "rich associations" with has_and_belongs_to_many is not a good fit for eager loading.) + comment(# ) + comment(# == Table Aliasing) + comment(#) + comment(# ActiveRecord uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once,) + comment(# the standard table name is used. The second time, the table is aliased as #{reflection_name}_#{parent_table_name}. Indexes are appended) + comment(# for any more successive uses of the table name.) + comment(# ) + comment(# Post.find :all, :include => :comments) + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ...) + comment(# Post.find :all, :include => :special_comments # STI) + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... AND comments.type = 'SpecialComment') + comment(# Post.find :all, :include => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name) + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... LEFT OUTER JOIN comments special_comments_posts) + comment(# ) + comment(# Acts as tree example:) + comment(# ) + comment(# TreeMixin.find :all, :include => :children) + comment(# # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ...) + comment(# TreeMixin.find :all, :include => {:children => :parent} # using cascading eager includes) + comment(# # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... ) + comment(# LEFT OUTER JOIN parents_mixins ...) + comment(# TreeMixin.find :all, :include => {:children => {:parent => :children}} ) + comment(# # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... ) + comment(# LEFT OUTER JOIN parents_mixins ... ) + comment(# LEFT OUTER JOIN mixins childrens_mixins_2) + comment(# ) + comment(# Has and Belongs to Many join tables use the same idea, but add a _join suffix:) + comment(# ) + comment(# Post.find :all, :include => :categories) + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ...) + comment(# Post.find :all, :include => {:categories => :posts}) + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ...) + comment(# LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories) + comment(# Post.find :all, :include => {:categories => {:posts => :categories}}) + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ...) + comment(# LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories) + comment(# LEFT OUTER JOIN categories_posts categories_posts_join LEFT OUTER JOIN categories categories_posts) + comment(# ) + comment(# If you wish to specify your own custom joins using a :joins option, those table names will take precedence over the eager associations..) + comment(# ) + comment(# Post.find :all, :include => :comments, :joins => "inner join comments ...") + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN comments_posts ON ... INNER JOIN comments ...) + comment(# Post.find :all, :include => [:comments, :special_comments], :joins => "inner join comments ...") + comment(# # => SELECT ... FROM posts LEFT OUTER JOIN comments comments_posts ON ... ) + comment(# LEFT OUTER JOIN comments special_comments_posts ...) + comment(# INNER JOIN comments ...) + comment(# ) + comment(# Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database.) + comment(# ) + comment(# == Modules) + comment(#) + comment(# By default, associations will look for objects within the current module scope. Consider:) + comment(#) + comment(# module MyApplication) + comment(# module Business) + comment(# class Firm < ActiveRecord::Base) + comment(# has_many :clients) + comment(# end) + comment(#) + comment(# class Company < ActiveRecord::Base; end) + comment(# end) + comment(# end) + comment(#) + comment(# When Firm#clients is called, it'll in turn call <tt>MyApplication::Business::Company.find(firm.id\)</tt>. If you want to associate) + comment(# with a class in another module scope this can be done by specifying the complete class name, such as:) + comment(#) + comment(# module MyApplication) + comment(# module Business) + comment(# class Firm < ActiveRecord::Base; end) + comment(# end) + comment(#) + comment(# module Billing) + comment(# class Account < ActiveRecord::Base) + comment(# belongs_to :firm, :class_name => "MyApplication::Business::Firm") + comment(# end) + comment(# end) + comment(# end) + comment(#) + comment(# == Type safety with ActiveRecord::AssociationTypeMismatch) + comment(#) + comment(# If you attempt to assign an object to an association that doesn't match the inferred or specified <tt>:class_name</tt>, you'll) + comment(# get a ActiveRecord::AssociationTypeMismatch.) + comment(#) + comment(# == Options) + comment(#) + comment(# All of the association macros can be specialized through options which makes more complex cases than the simple and guessable ones) + comment(# possible.) + reserved(module) class(ClassMethods) + comment(# Adds the following methods for retrieval and query of collections of associated objects.) + comment(# +collection+ is replaced with the symbol passed as the first argument, so ) + comment(# <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.) + comment(# * <tt>collection(force_reload = false\)</tt> - returns an array of all the associated objects.) + comment(# An empty array is returned if none are found.) + comment(# * <tt>collection<<(object, ...\)</tt> - adds one or more objects to the collection by setting their foreign keys to the collection's primary key.) + comment(# * <tt>collection.delete(object, ...\)</tt> - removes one or more objects from the collection by setting their foreign keys to NULL. ) + comment(# This will also destroy the objects if they're declared as belongs_to and dependent on this model.) + comment(# * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate.) + comment(# * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+) + comment(# * <tt>collection.clear</tt> - removes every object from the collection. This destroys the associated objects if they) + comment(# are <tt>:dependent</tt>, deletes them directly from the database if they are <tt>:dependent => :delete_all</tt>,) + comment(# and sets their foreign keys to NULL otherwise.) + comment(# * <tt>collection.empty?</tt> - returns true if there are no associated objects.) + comment(# * <tt>collection.size</tt> - returns the number of associated objects.) + comment(# * <tt>collection.find</tt> - finds an associated object according to the same rules as Base.find.) + comment(# * <tt>collection.build(attributes = {}\)</tt> - returns a new object of the collection type that has been instantiated) + comment(# with +attributes+ and linked to this object through a foreign key but has not yet been saved. *Note:* This only works if an ) + comment(# associated object already exists, not if it's nil!) + comment(# * <tt>collection.create(attributes = {}\)</tt> - returns a new object of the collection type that has been instantiated) + comment(# with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation\).) + comment(# *Note:* This only works if an associated object already exists, not if it's nil!) + comment(#) + comment(# Example: A Firm class declares <tt>has_many :clients</tt>, which will add:) + comment(# * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => "firm_id = #{id}"</tt>\)) + comment(# * <tt>Firm#clients<<</tt>) + comment(# * <tt>Firm#clients.delete</tt>) + comment(# * <tt>Firm#clients=</tt>) + comment(# * <tt>Firm#client_ids=</tt>) + comment(# * <tt>Firm#clients.clear</tt>) + comment(# * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>\)) + comment(# * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>\)) + comment(# * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}"\)</tt>\)) + comment(# * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id\)</tt>\)) + comment(# * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id\); c.save; c</tt>\)) + comment(# The declaration can also include an options hash to specialize the behavior of the association.) + comment(# ) + comment(# Options are:) + comment(# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred) + comment(# from the association name. So <tt>has_many :products</tt> will by default be linked to the +Product+ class, but) + comment(# if the real class name is +SpecialProduct+, you'll have to specify it with this option.) + comment(# * <tt>:conditions</tt> - specify the conditions that the associated objects must meet in order to be included as a "WHERE") + comment(# sql fragment, such as "price > 5 AND name LIKE 'B%'".) + comment(# * <tt>:order</tt> - specify the order in which the associated objects are returned as a "ORDER BY" sql fragment,) + comment(# such as "last_name, first_name DESC") + comment(# * <tt>:group</tt> - specify the attribute by which the associated objects are returned as a "GROUP BY" sql fragment,) + comment(# such as "category" ) + comment(# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name) + comment(# of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_many association will use "person_id") + comment(# as the default foreign_key.) + comment(# * <tt>:dependent</tt> - if set to :destroy all the associated objects are destroyed) + comment(# alongside this object by calling their destroy method. If set to :delete_all all associated) + comment(# objects are deleted *without* calling their destroy method. If set to :nullify all associated) + comment(# objects' foreign keys are set to NULL *without* calling their save callbacks.) + comment(# NOTE: :dependent => true is deprecated and has been replaced with :dependent => :destroy. ) + comment(# May not be set if :exclusively_dependent is also set.) + comment(# * <tt>:exclusively_dependent</tt> - Deprecated; equivalent to :dependent => :delete_all. If set to true all) + comment(# the associated object are deleted in one SQL statement without having their) + comment(# before_destroy callback run. This should only be used on associations that depend solely on this class and don't need to do any) + comment(# clean-up in before_destroy. The upside is that it's much faster, especially if there's a counter_cache involved.) + comment(# May not be set if :dependent is also set.) + comment(# * <tt>:finder_sql</tt> - specify a complete SQL statement to fetch the association. This is a good way to go for complex) + comment(# associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added.) + comment(# * <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If +:finder_sql+ is) + comment(# specified but +:counter_sql+, +:counter_sql+ will be generated by replacing SELECT ... FROM with SELECT COUNT(*\) FROM.) + comment(# * <tt>:extend</tt> - specify a named module for extending the proxy, see "Association extensions".) + comment(# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded.) + comment(# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.) + comment(# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned.) + comment(# * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.) + comment(# * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not) + comment(# include the joined columns.) + comment(# * <tt>:as</tt>: Specifies a polymorphic interface (See #belongs_to\).) + comment(# * <tt>:through</tt>: Specifies a Join Model to perform the query through. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt> ) + comment(# are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt>) + comment(# or <tt>has_many</tt> association.) + comment(# * <tt>:source</tt>: Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be ) + comment(# inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either +:subscribers+ or) + comment(# +:subscriber+ on +Subscription+, unless a +:source+ is given.) + comment(#) + comment(# Option examples:) + comment(# has_many :comments, :order => "posted_on") + comment(# has_many :comments, :include => :author) + comment(# has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name") + comment(# has_many :tracks, :order => "position", :dependent => :destroy) + comment(# has_many :comments, :dependent => :nullify) + comment(# has_many :tags, :as => :taggable) + comment(# has_many :subscribers, :through => :subscriptions, :source => :user) + comment(# has_many :subscribers, :class_name => "Person", :finder_sql =>) + comment(# 'SELECT DISTINCT people.* ' +) + comment(# 'FROM people p, post_subscriptions ps ' +) + comment(# 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' +) + comment(# 'ORDER BY p.first_name') + reserved(def) method(has_many)operator(()ident(association_id)operator(,) ident(options) operator(=) operator({)operator(})operator(,) operator(&)ident(extension)operator(\)) + ident(reflection) operator(=) ident(create_has_many_reflection)operator(()ident(association_id)operator(,) ident(options)operator(,) operator(&)ident(extension)operator(\)) + + ident(configure_dependency_for_has_many)operator(()ident(reflection)operator(\)) + + reserved(if) ident(options)operator([)symbol(:through)operator(]) + ident(collection_reader_method)operator(()ident(reflection)operator(,) constant(HasManyThroughAssociation)operator(\)) + reserved(else) + ident(add_multiple_associated_save_callbacks)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(add_association_callbacks)operator(()ident(reflection)operator(.)ident(name)operator(,) ident(reflection)operator(.)ident(options)operator(\)) + ident(collection_accessor_methods)operator(()ident(reflection)operator(,) constant(HasManyAssociation)operator(\)) + reserved(end) + + ident(add_deprecated_api_for_has_many)operator(()ident(reflection)operator(.)ident(name)operator(\)) + reserved(end) + + comment(# Adds the following methods for retrieval and query of a single associated object.) + comment(# +association+ is replaced with the symbol passed as the first argument, so ) + comment(# <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.) + comment(# * <tt>association(force_reload = false\)</tt> - returns the associated object. Nil is returned if none is found.) + comment(# * <tt>association=(associate\)</tt> - assigns the associate object, extracts the primary key, sets it as the foreign key, ) + comment(# and saves the associate object.) + comment(# * <tt>association.nil?</tt> - returns true if there is no associated object.) + comment(# * <tt>build_association(attributes = {}\)</tt> - returns a new object of the associated type that has been instantiated) + comment(# with +attributes+ and linked to this object through a foreign key but has not yet been saved. Note: This ONLY works if) + comment(# an association already exists. It will NOT work if the association is nil.) + comment(# * <tt>create_association(attributes = {}\)</tt> - returns a new object of the associated type that has been instantiated) + comment(# with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation\).) + comment(#) + comment(# Example: An Account class declares <tt>has_one :beneficiary</tt>, which will add:) + comment(# * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}"\)</tt>\)) + comment(# * <tt>Account#beneficiary=(beneficiary\)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>\)) + comment(# * <tt>Account#beneficiary.nil?</tt>) + comment(# * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id\)</tt>\)) + comment(# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id\); b.save; b</tt>\)) + comment(#) + comment(# The declaration can also include an options hash to specialize the behavior of the association.) + comment(# ) + comment(# Options are:) + comment(# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred) + comment(# from the association name. So <tt>has_one :manager</tt> will by default be linked to the +Manager+ class, but) + comment(# if the real class name is +Person+, you'll have to specify it with this option.) + comment(# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE") + comment(# sql fragment, such as "rank = 5".) + comment(# * <tt>:order</tt> - specify the order from which the associated object will be picked at the top. Specified as) + comment(# an "ORDER BY" sql fragment, such as "last_name, first_name DESC") + comment(# * <tt>:dependent</tt> - if set to :destroy (or true\) all the associated objects are destroyed when this object is. Also,) + comment(# association is assigned.) + comment(# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name) + comment(# of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_one association will use "person_id") + comment(# as the default foreign_key.) + comment(# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded.) + comment(#) + comment(# Option examples:) + comment(# has_one :credit_card, :dependent => :destroy # destroys the associated credit card) + comment(# has_one :credit_card, :dependent => :nullify # updates the associated records foriegn key value to null rather than destroying it) + comment(# has_one :last_comment, :class_name => "Comment", :order => "posted_on") + comment(# has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'") + reserved(def) method(has_one)operator(()ident(association_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(reflection) operator(=) ident(create_has_one_reflection)operator(()ident(association_id)operator(,) ident(options)operator(\)) + + ident(module_eval) reserved(do) + ident(after_save) string<delimiter(<<-EOF)>string<content( + association = instance_variable_get("@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content("\) + unless association.nil? + association[")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content("] = id + association.save(true\) + end)delimiter( + EOF)> + reserved(end) + + ident(association_accessor_methods)operator(()ident(reflection)operator(,) constant(HasOneAssociation)operator(\)) + ident(association_constructor_method)operator(()symbol(:build)operator(,) ident(reflection)operator(,) constant(HasOneAssociation)operator(\)) + ident(association_constructor_method)operator(()symbol(:create)operator(,) ident(reflection)operator(,) constant(HasOneAssociation)operator(\)) + + ident(configure_dependency_for_has_one)operator(()ident(reflection)operator(\)) + + comment(# deprecated api) + ident(deprecated_has_association_method)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(deprecated_association_comparison_method)operator(()ident(reflection)operator(.)ident(name)operator(,) ident(reflection)operator(.)ident(class_name)operator(\)) + reserved(end) + + comment(# Adds the following methods for retrieval and query for a single associated object that this object holds an id to.) + comment(# +association+ is replaced with the symbol passed as the first argument, so ) + comment(# <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.) + comment(# * <tt>association(force_reload = false\)</tt> - returns the associated object. Nil is returned if none is found.) + comment(# * <tt>association=(associate\)</tt> - assigns the associate object, extracts the primary key, and sets it as the foreign key.) + comment(# * <tt>association.nil?</tt> - returns true if there is no associated object.) + comment(# * <tt>build_association(attributes = {}\)</tt> - returns a new object of the associated type that has been instantiated) + comment(# with +attributes+ and linked to this object through a foreign key but has not yet been saved.) + comment(# * <tt>create_association(attributes = {}\)</tt> - returns a new object of the associated type that has been instantiated) + comment(# with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation\).) + comment(#) + comment(# Example: A Post class declares <tt>belongs_to :author</tt>, which will add:) + comment(# * <tt>Post#author</tt> (similar to <tt>Author.find(author_id\)</tt>\)) + comment(# * <tt>Post#author=(author\)</tt> (similar to <tt>post.author_id = author.id</tt>\)) + comment(# * <tt>Post#author?</tt> (similar to <tt>post.author == some_author</tt>\)) + comment(# * <tt>Post#author.nil?</tt>) + comment(# * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>\)) + comment(# * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>\)) + comment(# The declaration can also include an options hash to specialize the behavior of the association.) + comment(# ) + comment(# Options are:) + comment(# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred) + comment(# from the association name. So <tt>has_one :author</tt> will by default be linked to the +Author+ class, but) + comment(# if the real class name is +Person+, you'll have to specify it with this option.) + comment(# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE") + comment(# sql fragment, such as "authorized = 1".) + comment(# * <tt>:order</tt> - specify the order from which the associated object will be picked at the top. Specified as) + comment(# an "ORDER BY" sql fragment, such as "last_name, first_name DESC") + comment(# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name) + comment(# of the associated class in lower-case and "_id" suffixed. So a +Person+ class that makes a belongs_to association to a) + comment(# +Boss+ class will use "boss_id" as the default foreign_key.) + comment(# * <tt>:counter_cache</tt> - caches the number of belonging objects on the associate class through use of increment_counter ) + comment(# and decrement_counter. The counter cache is incremented when an object of this class is created and decremented when it's) + comment(# destroyed. This requires that a column named "#{table_name}_count" (such as comments_count for a belonging Comment class\)) + comment(# is used on the associate class (such as a Post class\). You can also specify a custom counter cache column by given that) + comment(# name instead of a true/false value to this option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.\)) + comment(# * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded.) + comment(# * <tt>:polymorphic</tt> - specify this association is a polymorphic association by passing true.) + comment(#) + comment(# Option examples:) + comment(# belongs_to :firm, :foreign_key => "client_of") + comment(# belongs_to :author, :class_name => "Person", :foreign_key => "author_id") + comment(# belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", ) + comment(# :conditions => 'discounts > #{payments_count}') + comment(# belongs_to :attachable, :polymorphic => true) + reserved(def) method(belongs_to)operator(()ident(association_id)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(reflection) operator(=) ident(create_belongs_to_reflection)operator(()ident(association_id)operator(,) ident(options)operator(\)) + + reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:polymorphic)operator(]) + ident(association_accessor_methods)operator(()ident(reflection)operator(,) constant(BelongsToPolymorphicAssociation)operator(\)) + + ident(module_eval) reserved(do) + ident(before_save) string<delimiter(<<-EOF)>string<content( + association = instance_variable_get("@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content("\) + if !association.nil? + if association.new_record? + association.save(true\) + end + + if association.updated? + self[")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content("] = association.id + self[")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(options)operator([)symbol(:foreign_type)operator(])inline_delimiter(})>content("] = association.class.base_class.name.to_s + end + end)delimiter( + EOF)> + reserved(end) + reserved(else) + ident(association_accessor_methods)operator(()ident(reflection)operator(,) constant(BelongsToAssociation)operator(\)) + ident(association_constructor_method)operator(()symbol(:build)operator(,) ident(reflection)operator(,) constant(BelongsToAssociation)operator(\)) + ident(association_constructor_method)operator(()symbol(:create)operator(,) ident(reflection)operator(,) constant(BelongsToAssociation)operator(\)) + + ident(module_eval) reserved(do) + ident(before_save) string<delimiter(<<-EOF)>string<content( + association = instance_variable_get("@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content("\) + if !association.nil? + if association.new_record? + association.save(true\) + end + + if association.updated? + self[")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content("] = association.id + end + end )delimiter( + EOF)> + reserved(end) + + comment(# deprecated api) + ident(deprecated_has_association_method)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(deprecated_association_comparison_method)operator(()ident(reflection)operator(.)ident(name)operator(,) ident(reflection)operator(.)ident(class_name)operator(\)) + reserved(end) + + reserved(if) ident(options)operator([)symbol(:counter_cache)operator(]) + ident(cache_column) operator(=) ident(options)operator([)symbol(:counter_cache)operator(]) operator(==) pre_constant(true) operator(?) + string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(to_s)operator(.)ident(underscore)operator(.)ident(pluralize)inline_delimiter(})>content(_count)delimiter(")> operator(:) + ident(options)operator([)symbol(:counter_cache)operator(]) + + ident(module_eval)operator(() + string<delimiter(")content(after_create ')inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.class.increment_counter()char(\\")inline<inline_delimiter(#{)ident(cache_column)inline_delimiter(})>char(\\")content(, )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content(\))delimiter(")> operator(+) + string<delimiter(")content( unless )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.nil?')delimiter(")> + operator(\)) + + ident(module_eval)operator(() + string<delimiter(")content(before_destroy ')inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.class.decrement_counter()char(\\")inline<inline_delimiter(#{)ident(cache_column)inline_delimiter(})>char(\\")content(, )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content(\))delimiter(")> operator(+) + string<delimiter(")content( unless )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.nil?')delimiter(")> + operator(\)) + reserved(end) + reserved(end) + + comment(# Associates two classes via an intermediate join table. Unless the join table is explicitly specified as) + comment(# an option, it is guessed using the lexical order of the class names. So a join between Developer and Project) + comment(# will give the default join table name of "developers_projects" because "D" outranks "P".) + comment(#) + comment(# Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through) + comment(# has_and_belongs_to_many associations. Records returned from join tables with additional attributes will be marked as) + comment(# ReadOnly (because we can't save changes to the additional attrbutes\). It's strongly recommended that you upgrade any) + comment(# associations with attributes to a real join model (see introduction\).) + comment(#) + comment(# Adds the following methods for retrieval and query.) + comment(# +collection+ is replaced with the symbol passed as the first argument, so ) + comment(# <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.) + comment(# * <tt>collection(force_reload = false\)</tt> - returns an array of all the associated objects.) + comment(# An empty array is returned if none is found.) + comment(# * <tt>collection<<(object, ...\)</tt> - adds one or more objects to the collection by creating associations in the join table ) + comment(# (collection.push and collection.concat are aliases to this method\).) + comment(# * <tt>collection.push_with_attributes(object, join_attributes\)</tt> - adds one to the collection by creating an association in the join table that) + comment(# also holds the attributes from <tt>join_attributes</tt> (should be a hash with the column names as keys\). This can be used to have additional) + comment(# attributes on the join, which will be injected into the associated objects when they are retrieved through the collection.) + comment(# (collection.concat_with_attributes is an alias to this method\). This method is now deprecated.) + comment(# * <tt>collection.delete(object, ...\)</tt> - removes one or more objects from the collection by removing their associations from the join table. ) + comment(# This does not destroy the objects.) + comment(# * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate.) + comment(# * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+) + comment(# * <tt>collection.clear</tt> - removes every object from the collection. This does not destroy the objects.) + comment(# * <tt>collection.empty?</tt> - returns true if there are no associated objects.) + comment(# * <tt>collection.size</tt> - returns the number of associated objects.) + comment(# * <tt>collection.find(id\)</tt> - finds an associated object responding to the +id+ and that) + comment(# meets the condition that it has to be associated with this object.) + comment(#) + comment(# Example: An Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:) + comment(# * <tt>Developer#projects</tt>) + comment(# * <tt>Developer#projects<<</tt>) + comment(# * <tt>Developer#projects.push_with_attributes</tt>) + comment(# * <tt>Developer#projects.delete</tt>) + comment(# * <tt>Developer#projects=</tt>) + comment(# * <tt>Developer#project_ids=</tt>) + comment(# * <tt>Developer#projects.clear</tt>) + comment(# * <tt>Developer#projects.empty?</tt>) + comment(# * <tt>Developer#projects.size</tt>) + comment(# * <tt>Developer#projects.find(id\)</tt>) + comment(# The declaration may include an options hash to specialize the behavior of the association.) + comment(# ) + comment(# Options are:) + comment(# * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred) + comment(# from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the ) + comment(# +Project+ class, but if the real class name is +SuperProject+, you'll have to specify it with this option.) + comment(# * <tt>:join_table</tt> - specify the name of the join table if the default based on lexical order isn't what you want.) + comment(# WARNING: If you're overwriting the table name of either class, the table_name method MUST be declared underneath any) + comment(# has_and_belongs_to_many declaration in order to work.) + comment(# * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name) + comment(# of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_and_belongs_to_many association) + comment(# will use "person_id" as the default foreign_key.) + comment(# * <tt>:association_foreign_key</tt> - specify the association foreign key used for the association. By default this is) + comment(# guessed to be the name of the associated class in lower-case and "_id" suffixed. So if the associated class is +Project+,) + comment(# the has_and_belongs_to_many association will use "project_id" as the default association foreign_key.) + comment(# * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE") + comment(# sql fragment, such as "authorized = 1".) + comment(# * <tt>:order</tt> - specify the order in which the associated objects are returned as a "ORDER BY" sql fragment, such as "last_name, first_name DESC") + comment(# * <tt>:uniq</tt> - if set to true, duplicate associated objects will be ignored by accessors and query methods) + comment(# * <tt>:finder_sql</tt> - overwrite the default generated SQL used to fetch the association with a manual one) + comment(# * <tt>:delete_sql</tt> - overwrite the default generated SQL used to remove links between the associated ) + comment(# classes with a manual one) + comment(# * <tt>:insert_sql</tt> - overwrite the default generated SQL used to add links between the associated classes) + comment(# with a manual one) + comment(# * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions".) + comment(# * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded.) + comment(# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.) + comment(# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned.) + comment(# * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.) + comment(# * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not) + comment(# include the joined columns.) + comment(#) + comment(# Option examples:) + comment(# has_and_belongs_to_many :projects) + comment(# has_and_belongs_to_many :projects, :include => [ :milestones, :manager ]) + comment(# has_and_belongs_to_many :nations, :class_name => "Country") + comment(# has_and_belongs_to_many :categories, :join_table => "prods_cats") + comment(# has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql => ) + comment(# 'DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}') + reserved(def) method(has_and_belongs_to_many)operator(()ident(association_id)operator(,) ident(options) operator(=) operator({)operator(})operator(,) operator(&)ident(extension)operator(\)) + ident(reflection) operator(=) ident(create_has_and_belongs_to_many_reflection)operator(()ident(association_id)operator(,) ident(options)operator(,) operator(&)ident(extension)operator(\)) + + ident(add_multiple_associated_save_callbacks)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(collection_accessor_methods)operator(()ident(reflection)operator(,) constant(HasAndBelongsToManyAssociation)operator(\)) + + comment(# Don't use a before_destroy callback since users' before_destroy) + comment(# callbacks will be executed after the association is wiped out.) + ident(old_method) operator(=) string<delimiter(")content(destroy_without_habtm_shim_for_)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")> + ident(class_eval) string<delimiter(<<-end_eval)>string<content( + alias_method :)inline<inline_delimiter(#{)ident(old_method)inline_delimiter(})>content(, :destroy_without_callbacks + def destroy_without_callbacks + )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.clear + )inline<inline_delimiter(#{)ident(old_method)inline_delimiter(})>content( + end)delimiter( + end_eval)> + + ident(add_association_callbacks)operator(()ident(reflection)operator(.)ident(name)operator(,) ident(options)operator(\)) + + comment(# deprecated api) + ident(deprecated_collection_count_method)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(deprecated_add_association_relation)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(deprecated_remove_association_relation)operator(()ident(reflection)operator(.)ident(name)operator(\)) + ident(deprecated_has_collection_method)operator(()ident(reflection)operator(.)ident(name)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(join_table_name)operator(()ident(first_table_name)operator(,) ident(second_table_name)operator(\)) + reserved(if) ident(first_table_name) operator(<) ident(second_table_name) + ident(join_table) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(first_table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(second_table_name)inline_delimiter(})>delimiter(")> + reserved(else) + ident(join_table) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(second_table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(first_table_name)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(table_name_prefix) operator(+) ident(join_table) operator(+) ident(table_name_suffix) + reserved(end) + + reserved(def) method(association_accessor_methods)operator(()ident(reflection)operator(,) ident(association_proxy_class)operator(\)) + ident(define_method)operator(()ident(reflection)operator(.)ident(name)operator(\)) reserved(do) operator(|*)ident(params)operator(|) + ident(force_reload) operator(=) ident(params)operator(.)ident(first) reserved(unless) ident(params)operator(.)ident(empty?) + ident(association) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(\)) + + reserved(if) ident(association)operator(.)ident(nil?) operator(||) ident(force_reload) + ident(association) operator(=) ident(association_proxy_class)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(reflection)operator(\)) + ident(retval) operator(=) ident(association)operator(.)ident(reload) + reserved(unless) ident(retval)operator(.)ident(nil?) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(association)operator(\)) + reserved(else) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) pre_constant(nil)operator(\)) + reserved(return) pre_constant(nil) + reserved(end) + reserved(end) + ident(association) + reserved(end) + + ident(define_method)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(=)delimiter(")>operator(\)) reserved(do) operator(|)ident(new_value)operator(|) + ident(association) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(if) ident(association)operator(.)ident(nil?) + ident(association) operator(=) ident(association_proxy_class)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(reflection)operator(\)) + reserved(end) + + ident(association)operator(.)ident(replace)operator(()ident(new_value)operator(\)) + + reserved(unless) ident(new_value)operator(.)ident(nil?) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(association)operator(\)) + reserved(else) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) pre_constant(nil)operator(\)) + reserved(return) pre_constant(nil) + reserved(end) + + ident(association) + reserved(end) + + ident(define_method)operator(()string<delimiter(")content(set_)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(_target)delimiter(")>operator(\)) reserved(do) operator(|)ident(target)operator(|) + reserved(return) reserved(if) ident(target)operator(.)ident(nil?) + ident(association) operator(=) ident(association_proxy_class)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(reflection)operator(\)) + ident(association)operator(.)ident(target) operator(=) ident(target) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(association)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(collection_reader_method)operator(()ident(reflection)operator(,) ident(association_proxy_class)operator(\)) + ident(define_method)operator(()ident(reflection)operator(.)ident(name)operator(\)) reserved(do) operator(|*)ident(params)operator(|) + ident(force_reload) operator(=) ident(params)operator(.)ident(first) reserved(unless) ident(params)operator(.)ident(empty?) + ident(association) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(\)) + + reserved(unless) ident(association)operator(.)ident(respond_to?)operator(()symbol(:loaded?)operator(\)) + ident(association) operator(=) ident(association_proxy_class)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(reflection)operator(\)) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(association)operator(\)) + reserved(end) + + ident(association)operator(.)ident(reload) reserved(if) ident(force_reload) + + ident(association) + reserved(end) + reserved(end) + + reserved(def) method(collection_accessor_methods)operator(()ident(reflection)operator(,) ident(association_proxy_class)operator(\)) + ident(collection_reader_method)operator(()ident(reflection)operator(,) ident(association_proxy_class)operator(\)) + + ident(define_method)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(=)delimiter(")>operator(\)) reserved(do) operator(|)ident(new_value)operator(|) + ident(association) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(unless) ident(association)operator(.)ident(respond_to?)operator(()symbol(:loaded?)operator(\)) + ident(association) operator(=) ident(association_proxy_class)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(reflection)operator(\)) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(association)operator(\)) + reserved(end) + ident(association)operator(.)ident(replace)operator(()ident(new_value)operator(\)) + ident(association) + reserved(end) + + ident(define_method)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)operator(.)ident(to_s)operator(.)ident(singularize)inline_delimiter(})>content(_ids=)delimiter(")>operator(\)) reserved(do) operator(|)ident(new_value)operator(|) + ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(=)delimiter(")>operator(,) ident(reflection)operator(.)ident(class_name)operator(.)ident(constantize)operator(.)ident(find)operator(()ident(new_value)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(require_association_class)operator(()ident(class_name)operator(\)) + ident(require_association)operator(()constant(Inflector)operator(.)ident(underscore)operator(()ident(class_name)operator(\))operator(\)) reserved(if) ident(class_name) + reserved(end) + + reserved(def) method(add_multiple_associated_save_callbacks)operator(()ident(association_name)operator(\)) + ident(method_name) operator(=) string<delimiter(")content(validate_associated_records_for_)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>delimiter(")>operator(.)ident(to_sym) + ident(define_method)operator(()ident(method_name)operator(\)) reserved(do) + ident(association) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>delimiter(")>operator(\)) + reserved(if) ident(association)operator(.)ident(respond_to?)operator(()symbol(:loaded?)operator(\)) + reserved(if) ident(new_record?) + ident(association) + reserved(else) + ident(association)operator(.)ident(select) operator({) operator(|)ident(record)operator(|) ident(record)operator(.)ident(new_record?) operator(}) + reserved(end)operator(.)ident(each) reserved(do) operator(|)ident(record)operator(|) + ident(errors)operator(.)ident(add) string<delimiter(")inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>delimiter(")> reserved(unless) ident(record)operator(.)ident(valid?) + reserved(end) + reserved(end) + reserved(end) + + ident(validate) ident(method_name) + ident(before_save)operator(()string<delimiter(")content(@new_record_before_save = new_record?; true)delimiter(")>operator(\)) + + ident(after_callback) operator(=) string<delimiter(<<-end_eval)>string<content( + association = instance_variable_get("@)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content("\) + + if association.respond_to?(:loaded?\) + if @new_record_before_save + records_to_save = association + else + records_to_save = association.select { |record| record.new_record? } + end + records_to_save.each { |record| association.send(:insert_record, record\) } + association.send(:construct_sql\) # reconstruct the SQL queries now that we know the owner's id + end)delimiter( + end_eval)> + + comment(# Doesn't use after_save as that would save associations added in after_create/after_update twice) + ident(after_create)operator(()ident(after_callback)operator(\)) + ident(after_update)operator(()ident(after_callback)operator(\)) + reserved(end) + + reserved(def) method(association_constructor_method)operator(()ident(constructor)operator(,) ident(reflection)operator(,) ident(association_proxy_class)operator(\)) + ident(define_method)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(constructor)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(\)) reserved(do) operator(|*)ident(params)operator(|) + ident(attributees) operator(=) ident(params)operator(.)ident(first) reserved(unless) ident(params)operator(.)ident(empty?) + ident(replace_existing) operator(=) ident(params)operator([)integer(1)operator(])operator(.)ident(nil?) operator(?) pre_constant(true) operator(:) ident(params)operator([)integer(1)operator(]) + ident(association) operator(=) ident(instance_variable_get)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(\)) + + reserved(if) ident(association)operator(.)ident(nil?) + ident(association) operator(=) ident(association_proxy_class)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(reflection)operator(\)) + ident(instance_variable_set)operator(()string<delimiter(")content(@)inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(association)operator(\)) + reserved(end) + + reserved(if) ident(association_proxy_class) operator(==) constant(HasOneAssociation) + ident(association)operator(.)ident(send)operator(()ident(constructor)operator(,) ident(attributees)operator(,) ident(replace_existing)operator(\)) + reserved(else) + ident(association)operator(.)ident(send)operator(()ident(constructor)operator(,) ident(attributees)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(count_with_associations)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(catch) symbol(:invalid_query) reserved(do) + ident(join_dependency) operator(=) constant(JoinDependency)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(merge_includes)operator(()ident(scope)operator(()symbol(:find)operator(,) symbol(:include)operator(\))operator(,) ident(options)operator([)symbol(:include)operator(])operator(\))operator(,) ident(options)operator([)symbol(:joins)operator(])operator(\)) + reserved(return) ident(count_by_sql)operator(()ident(construct_counter_sql_with_included_associations)operator(()ident(options)operator(,) ident(join_dependency)operator(\))operator(\)) + reserved(end) + integer(0) + reserved(end) + + reserved(def) method(find_with_associations)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(catch) symbol(:invalid_query) reserved(do) + ident(join_dependency) operator(=) constant(JoinDependency)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(merge_includes)operator(()ident(scope)operator(()symbol(:find)operator(,) symbol(:include)operator(\))operator(,) ident(options)operator([)symbol(:include)operator(])operator(\))operator(,) ident(options)operator([)symbol(:joins)operator(])operator(\)) + ident(rows) operator(=) ident(select_all_rows)operator(()ident(options)operator(,) ident(join_dependency)operator(\)) + reserved(return) ident(join_dependency)operator(.)ident(instantiate)operator(()ident(rows)operator(\)) + reserved(end) + operator([)operator(]) + reserved(end) + + reserved(def) method(configure_dependency_for_has_many)operator(()ident(reflection)operator(\)) + reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) operator(&&) ident(reflection)operator(.)ident(options)operator([)symbol(:exclusively_dependent)operator(]) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(:dependent and :exclusively_dependent are mutually exclusive options. You may specify one or the other.)delimiter(')> + reserved(end) + + reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:exclusively_dependent)operator(]) + ident(reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) operator(=) symbol(:delete_all) + comment(#warn "The :exclusively_dependent option is deprecated. Please use :dependent => :delete_all instead."\)) + reserved(end) + + comment(# See HasManyAssociation#delete_records. Dependent associations) + comment(# delete children, otherwise foreign key is set to NULL.) + + comment(# Add polymorphic type if the :as option is present) + ident(dependent_conditions) operator(=) string<delimiter(%()inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = )char(\\#)content({record.quoted_id})delimiter(\))> + reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + ident(dependent_conditions) operator(+=) string<delimiter(")content( AND )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type = ')inline<inline_delimiter(#{)ident(base_class)operator(.)ident(name)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(case) ident(reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) + reserved(when) symbol(:destroy)operator(,) pre_constant(true) + ident(module_eval) string<delimiter(")content(before_destroy ')inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.each { |o| o.destroy }')delimiter(")> + reserved(when) symbol(:delete_all) + ident(module_eval) string<delimiter(")content(before_destroy { |record| )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(class_name)inline_delimiter(})>content(.delete_all(%()inline<inline_delimiter(#{)ident(dependent_conditions)inline_delimiter(})>content(\)\) })delimiter(")> + reserved(when) symbol(:nullify) + ident(module_eval) string<delimiter(")content(before_destroy { |record| )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(class_name)inline_delimiter(})>content(.update_all(%()inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>content( = NULL\), %()inline<inline_delimiter(#{)ident(dependent_conditions)inline_delimiter(})>content(\)\) })delimiter(")> + reserved(when) pre_constant(nil)operator(,) pre_constant(false) + comment(# pass) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(The :dependent option expects either :destroy, :delete_all, or :nullify)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(configure_dependency_for_has_one)operator(()ident(reflection)operator(\)) + reserved(case) ident(reflection)operator(.)ident(options)operator([)symbol(:dependent)operator(]) + reserved(when) symbol(:destroy)operator(,) pre_constant(true) + ident(module_eval) string<delimiter(")content(before_destroy ')inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.destroy unless )inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.nil?')delimiter(")> + reserved(when) symbol(:nullify) + ident(module_eval) string<delimiter(")content(before_destroy ')inline<inline_delimiter(#{)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(.update_attribute()char(\\")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(primary_key_name)inline_delimiter(})>char(\\")content(, nil\)')delimiter(")> + reserved(when) pre_constant(nil)operator(,) pre_constant(false) + comment(# pass) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(The :dependent option expects either :destroy or :nullify.)delimiter(")> + reserved(end) + reserved(end) + + + reserved(def) method(add_deprecated_api_for_has_many)operator(()ident(association_name)operator(\)) + ident(deprecated_collection_count_method)operator(()ident(association_name)operator(\)) + ident(deprecated_add_association_relation)operator(()ident(association_name)operator(\)) + ident(deprecated_remove_association_relation)operator(()ident(association_name)operator(\)) + ident(deprecated_has_collection_method)operator(()ident(association_name)operator(\)) + ident(deprecated_find_in_collection_method)operator(()ident(association_name)operator(\)) + ident(deprecated_find_all_in_collection_method)operator(()ident(association_name)operator(\)) + ident(deprecated_collection_create_method)operator(()ident(association_name)operator(\)) + ident(deprecated_collection_build_method)operator(()ident(association_name)operator(\)) + reserved(end) + + reserved(def) method(create_has_many_reflection)operator(()ident(association_id)operator(,) ident(options)operator(,) operator(&)ident(extension)operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(() + symbol(:class_name)operator(,) symbol(:table_name)operator(,) symbol(:foreign_key)operator(,) + symbol(:exclusively_dependent)operator(,) symbol(:dependent)operator(,) + symbol(:select)operator(,) symbol(:conditions)operator(,) symbol(:include)operator(,) symbol(:order)operator(,) symbol(:group)operator(,) symbol(:limit)operator(,) symbol(:offset)operator(,) + symbol(:as)operator(,) symbol(:through)operator(,) symbol(:source)operator(,) + symbol(:finder_sql)operator(,) symbol(:counter_sql)operator(,) + symbol(:before_add)operator(,) symbol(:after_add)operator(,) symbol(:before_remove)operator(,) symbol(:after_remove)operator(,) + symbol(:extend) + operator(\)) + + ident(options)operator([)symbol(:extend)operator(]) operator(=) ident(create_extension_module)operator(()ident(association_id)operator(,) ident(extension)operator(\)) reserved(if) ident(block_given?) + + ident(create_reflection)operator(()symbol(:has_many)operator(,) ident(association_id)operator(,) ident(options)operator(,) pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(create_has_one_reflection)operator(()ident(association_id)operator(,) ident(options)operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(() + symbol(:class_name)operator(,) symbol(:foreign_key)operator(,) symbol(:remote)operator(,) symbol(:conditions)operator(,) symbol(:order)operator(,) symbol(:include)operator(,) symbol(:dependent)operator(,) symbol(:counter_cache)operator(,) symbol(:extend)operator(,) symbol(:as) + operator(\)) + + ident(create_reflection)operator(()symbol(:has_one)operator(,) ident(association_id)operator(,) ident(options)operator(,) pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(create_belongs_to_reflection)operator(()ident(association_id)operator(,) ident(options)operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(() + symbol(:class_name)operator(,) symbol(:foreign_key)operator(,) symbol(:foreign_type)operator(,) symbol(:remote)operator(,) symbol(:conditions)operator(,) symbol(:order)operator(,) symbol(:include)operator(,) symbol(:dependent)operator(,) + symbol(:counter_cache)operator(,) symbol(:extend)operator(,) symbol(:polymorphic) + operator(\)) + + ident(reflection) operator(=) ident(create_reflection)operator(()symbol(:belongs_to)operator(,) ident(association_id)operator(,) ident(options)operator(,) pre_constant(self)operator(\)) + + reserved(if) ident(options)operator([)symbol(:polymorphic)operator(]) + ident(reflection)operator(.)ident(options)operator([)symbol(:foreign_type)operator(]) operator(||=) ident(reflection)operator(.)ident(class_name)operator(.)ident(underscore) operator(+) string<delimiter(")content(_type)delimiter(")> + reserved(end) + + ident(reflection) + reserved(end) + + reserved(def) method(create_has_and_belongs_to_many_reflection)operator(()ident(association_id)operator(,) ident(options)operator(,) operator(&)ident(extension)operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(() + symbol(:class_name)operator(,) symbol(:table_name)operator(,) symbol(:join_table)operator(,) symbol(:foreign_key)operator(,) symbol(:association_foreign_key)operator(,) + symbol(:select)operator(,) symbol(:conditions)operator(,) symbol(:include)operator(,) symbol(:order)operator(,) symbol(:group)operator(,) symbol(:limit)operator(,) symbol(:offset)operator(,) + symbol(:finder_sql)operator(,) symbol(:delete_sql)operator(,) symbol(:insert_sql)operator(,) symbol(:uniq)operator(,) + symbol(:before_add)operator(,) symbol(:after_add)operator(,) symbol(:before_remove)operator(,) symbol(:after_remove)operator(,) + symbol(:extend) + operator(\)) + + ident(options)operator([)symbol(:extend)operator(]) operator(=) ident(create_extension_module)operator(()ident(association_id)operator(,) ident(extension)operator(\)) reserved(if) ident(block_given?) + + ident(reflection) operator(=) ident(create_reflection)operator(()symbol(:has_and_belongs_to_many)operator(,) ident(association_id)operator(,) ident(options)operator(,) pre_constant(self)operator(\)) + + ident(reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(]) operator(||=) ident(join_table_name)operator(()ident(undecorated_table_name)operator(()pre_constant(self)operator(.)ident(to_s)operator(\))operator(,) ident(undecorated_table_name)operator(()ident(reflection)operator(.)ident(class_name)operator(\))operator(\)) + + ident(reflection) + reserved(end) + + reserved(def) method(reflect_on_included_associations)operator(()ident(associations)operator(\)) + operator([) ident(associations) operator(])operator(.)ident(flatten)operator(.)ident(collect) operator({) operator(|)ident(association)operator(|) ident(reflect_on_association)operator(()ident(association)operator(.)ident(to_s)operator(.)ident(intern)operator(\)) operator(}) + reserved(end) + + reserved(def) method(guard_against_unlimitable_reflections)operator(()ident(reflections)operator(,) ident(options)operator(\)) + reserved(if) operator(()ident(options)operator([)symbol(:offset)operator(]) operator(||) ident(options)operator([)symbol(:limit)operator(])operator(\)) operator(&&) operator(!)ident(using_limitable_reflections?)operator(()ident(reflections)operator(\)) + ident(raise)operator(() + constant(ConfigurationError)operator(,) + string<delimiter(")content(You can not use offset and limit together with has_many or has_and_belongs_to_many associations)delimiter(")> + operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(select_all_rows)operator(()ident(options)operator(,) ident(join_dependency)operator(\)) + ident(connection)operator(.)ident(select_all)operator(() + ident(construct_finder_sql_with_included_associations)operator(()ident(options)operator(,) ident(join_dependency)operator(\))operator(,) + string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Load Including Associations)delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(construct_counter_sql_with_included_associations)operator(()ident(options)operator(,) ident(join_dependency)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) + ident(sql) operator(=) string<delimiter(")content(SELECT COUNT(DISTINCT )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content(\))delimiter(")> + + comment(# A (slower\) workaround if we're using a backend, like sqlite, that doesn't support COUNT DISTINCT.) + reserved(if) operator(!)constant(Base)operator(.)ident(connection)operator(.)ident(supports_count_distinct?) + ident(sql) operator(=) string<delimiter(")content(SELECT COUNT(*\) FROM (SELECT DISTINCT )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>delimiter(")> + reserved(end) + + ident(sql) operator(<<) string<delimiter(")content( FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )delimiter(")> + ident(sql) operator(<<) ident(join_dependency)operator(.)ident(join_associations)operator(.)ident(collect)operator({)operator(|)ident(join)operator(|) ident(join)operator(.)ident(association_join) operator(})operator(.)ident(join) + + ident(add_joins!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + ident(add_conditions!)operator(()ident(sql)operator(,) ident(options)operator([)symbol(:conditions)operator(])operator(,) ident(scope)operator(\)) + ident(add_limited_ids_condition!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(join_dependency)operator(\)) reserved(if) operator(!)ident(using_limitable_reflections?)operator(()ident(join_dependency)operator(.)ident(reflections)operator(\)) operator(&&) operator(()operator(()ident(scope) operator(&&) ident(scope)operator([)symbol(:limit)operator(])operator(\)) operator(||) ident(options)operator([)symbol(:limit)operator(])operator(\)) + + ident(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) reserved(if) ident(using_limitable_reflections?)operator(()ident(join_dependency)operator(.)ident(reflections)operator(\)) + + reserved(if) operator(!)constant(Base)operator(.)ident(connection)operator(.)ident(supports_count_distinct?) + ident(sql) operator(<<) string<delimiter(")content(\))delimiter(")> + reserved(end) + + reserved(return) ident(sanitize_sql)operator(()ident(sql)operator(\)) + reserved(end) + + reserved(def) method(construct_finder_sql_with_included_associations)operator(()ident(options)operator(,) ident(join_dependency)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) + ident(sql) operator(=) string<delimiter(")content(SELECT )inline<inline_delimiter(#{)ident(column_aliases)operator(()ident(join_dependency)operator(\))inline_delimiter(})>content( FROM )inline<inline_delimiter(#{)operator(()ident(scope) operator(&&) ident(scope)operator([)symbol(:from)operator(])operator(\)) operator(||) ident(options)operator([)symbol(:from)operator(]) operator(||) ident(table_name)inline_delimiter(})>content( )delimiter(")> + ident(sql) operator(<<) ident(join_dependency)operator(.)ident(join_associations)operator(.)ident(collect)operator({)operator(|)ident(join)operator(|) ident(join)operator(.)ident(association_join) operator(})operator(.)ident(join) + + ident(add_joins!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + ident(add_conditions!)operator(()ident(sql)operator(,) ident(options)operator([)symbol(:conditions)operator(])operator(,) ident(scope)operator(\)) + ident(add_limited_ids_condition!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(join_dependency)operator(\)) reserved(if) operator(!)ident(using_limitable_reflections?)operator(()ident(join_dependency)operator(.)ident(reflections)operator(\)) operator(&&) ident(options)operator([)symbol(:limit)operator(]) + + ident(sql) operator(<<) string<delimiter(")content(ORDER BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>content( )delimiter(")> reserved(if) ident(options)operator([)symbol(:order)operator(]) + + ident(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) reserved(if) ident(using_limitable_reflections?)operator(()ident(join_dependency)operator(.)ident(reflections)operator(\)) + + reserved(return) ident(sanitize_sql)operator(()ident(sql)operator(\)) + reserved(end) + + reserved(def) method(add_limited_ids_condition!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(join_dependency)operator(\)) + reserved(unless) operator(()ident(id_list) operator(=) ident(select_limited_ids_list)operator(()ident(options)operator(,) ident(join_dependency)operator(\))operator(\))operator(.)ident(empty?) + ident(sql) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(condition_word)operator(()ident(sql)operator(\))inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( IN ()inline<inline_delimiter(#{)ident(id_list)inline_delimiter(})>content(\) )delimiter(")> + reserved(else) + ident(throw) symbol(:invalid_query) + reserved(end) + reserved(end) + + reserved(def) method(select_limited_ids_list)operator(()ident(options)operator(,) ident(join_dependency)operator(\)) + ident(connection)operator(.)ident(select_all)operator(() + ident(construct_finder_sql_for_association_limiting)operator(()ident(options)operator(,) ident(join_dependency)operator(\))operator(,) + string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Load IDs For Limited Eager Loading)delimiter(")> + operator(\))operator(.)ident(collect) operator({) operator(|)ident(row)operator(|) ident(connection)operator(.)ident(quote)operator(()ident(row)operator([)ident(primary_key)operator(])operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(construct_finder_sql_for_association_limiting)operator(()ident(options)operator(,) ident(join_dependency)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) + ident(sql) operator(=) string<delimiter(")content(SELECT )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(DISTINCT )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)delimiter(")> reserved(if) ident(include_eager_conditions?)operator(()ident(options)operator(\)) operator(||) ident(include_eager_order?)operator(()ident(options)operator(\)) + ident(sql) operator(<<) ident(primary_key) + ident(sql) operator(<<) string<delimiter(")content(, )inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\))operator(.)ident(collect) operator({) operator(|)ident(s)operator(|) ident(s)operator(.)ident(split)operator(.)ident(first) operator(}) operator(*) string<delimiter(')content(, )delimiter(')>inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:order)operator(]) operator(&&) operator(()ident(include_eager_conditions?)operator(()ident(options)operator(\)) operator(||) ident(include_eager_order?)operator(()ident(options)operator(\))operator(\)) + ident(sql) operator(<<) string<delimiter(")content( FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )delimiter(")> + + reserved(if) ident(include_eager_conditions?)operator(()ident(options)operator(\)) operator(||) ident(include_eager_order?)operator(()ident(options)operator(\)) + ident(sql) operator(<<) ident(join_dependency)operator(.)ident(join_associations)operator(.)ident(collect)operator({)operator(|)ident(join)operator(|) ident(join)operator(.)ident(association_join) operator(})operator(.)ident(join) + ident(add_joins!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + reserved(end) + + ident(add_conditions!)operator(()ident(sql)operator(,) ident(options)operator([)symbol(:conditions)operator(])operator(,) ident(scope)operator(\)) + ident(sql) operator(<<) string<delimiter(")content(ORDER BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>content( )delimiter(")> reserved(if) ident(options)operator([)symbol(:order)operator(]) + ident(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + reserved(return) ident(sanitize_sql)operator(()ident(sql)operator(\)) + reserved(end) + + comment(# Checks if the conditions reference a table other than the current model table) + reserved(def) method(include_eager_conditions?)operator(()ident(options)operator(\)) + comment(# look in both sets of conditions) + ident(conditions) operator(=) operator([)ident(scope)operator(()symbol(:find)operator(,) symbol(:conditions)operator(\))operator(,) ident(options)operator([)symbol(:conditions)operator(])operator(])operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(all)operator(,) ident(cond)operator(|) + reserved(case) ident(cond) + reserved(when) pre_constant(nil) reserved(then) ident(all) + reserved(when) constant(Array) reserved(then) ident(all) operator(<<) ident(cond)operator(.)ident(first) + reserved(else) ident(all) operator(<<) ident(cond) + reserved(end) + reserved(end) + reserved(return) pre_constant(false) reserved(unless) ident(conditions)operator(.)ident(any?) + ident(conditions)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))operator(.)ident(scan)operator(()regexp<delimiter(/)content(()char(\\w)content(+\))char(\\.)char(\\w)content(+)delimiter(/)>operator(\))operator(.)ident(flatten)operator(.)ident(any?) reserved(do) operator(|)ident(condition_table_name)operator(|) + ident(condition_table_name) operator(!=) ident(table_name) + reserved(end) + reserved(end) + + comment(# Checks if the query order references a table other than the current model's table.) + reserved(def) method(include_eager_order?)operator(()ident(options)operator(\)) + ident(order) operator(=) ident(options)operator([)symbol(:order)operator(]) + reserved(return) pre_constant(false) reserved(unless) ident(order) + ident(order)operator(.)ident(scan)operator(()regexp<delimiter(/)content(()char(\\w)content(+\))char(\\.)char(\\w)content(+)delimiter(/)>operator(\))operator(.)ident(flatten)operator(.)ident(any?) reserved(do) operator(|)ident(order_table_name)operator(|) + ident(order_table_name) operator(!=) ident(table_name) + reserved(end) + reserved(end) + + reserved(def) method(using_limitable_reflections?)operator(()ident(reflections)operator(\)) + ident(reflections)operator(.)ident(reject) operator({) operator(|)ident(r)operator(|) operator([) symbol(:belongs_to)operator(,) symbol(:has_one) operator(])operator(.)ident(include?)operator(()ident(r)operator(.)ident(macro)operator(\)) operator(})operator(.)ident(length)operator(.)ident(zero?) + reserved(end) + + reserved(def) method(column_aliases)operator(()ident(join_dependency)operator(\)) + ident(join_dependency)operator(.)ident(joins)operator(.)ident(collect)operator({)operator(|)ident(join)operator(|) ident(join)operator(.)ident(column_names_with_alias)operator(.)ident(collect)operator({)operator(|)ident(column_name)operator(,) ident(aliased_name)operator(|) + string<delimiter(")inline<inline_delimiter(#{)ident(join)operator(.)ident(aliased_table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(connection)operator(.)ident(quote_column_name) ident(column_name)inline_delimiter(})>content( AS )inline<inline_delimiter(#{)ident(aliased_name)inline_delimiter(})>delimiter(")>operator(})operator(})operator(.)ident(flatten)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(add_association_callbacks)operator(()ident(association_name)operator(,) ident(options)operator(\)) + ident(callbacks) operator(=) string<delimiter(%w()content(before_add after_add before_remove after_remove)delimiter(\))> + ident(callbacks)operator(.)ident(each) reserved(do) operator(|)ident(callback_name)operator(|) + ident(full_callback_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(callback_name)operator(.)ident(to_s)inline_delimiter(})>content(_for_)inline<inline_delimiter(#{)ident(association_name)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + ident(defined_callbacks) operator(=) ident(options)operator([)ident(callback_name)operator(.)ident(to_sym)operator(]) + reserved(if) ident(options)operator(.)ident(has_key?)operator(()ident(callback_name)operator(.)ident(to_sym)operator(\)) + ident(class_inheritable_reader) ident(full_callback_name)operator(.)ident(to_sym) + ident(write_inheritable_array)operator(()ident(full_callback_name)operator(.)ident(to_sym)operator(,) operator([)ident(defined_callbacks)operator(])operator(.)ident(flatten)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(condition_word)operator(()ident(sql)operator(\)) + ident(sql) operator(=)operator(~) regexp<delimiter(/)content(where)delimiter(/)modifier(i)> operator(?) string<delimiter(")content( AND )delimiter(")> operator(:) string<delimiter(")content(WHERE )delimiter(")> + reserved(end) + + reserved(def) method(create_extension_module)operator(()ident(association_id)operator(,) ident(extension)operator(\)) + ident(extension_module_name) operator(=) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(to_s)inline_delimiter(})>inline<inline_delimiter(#{)ident(association_id)operator(.)ident(to_s)operator(.)ident(camelize)inline_delimiter(})>content(AssociationExtension)delimiter(")> + + ident(silence_warnings) reserved(do) + constant(Object)operator(.)ident(const_set)operator(()ident(extension_module_name)operator(,) constant(Module)operator(.)ident(new)operator(()operator(&)ident(extension)operator(\))operator(\)) + reserved(end) + + ident(extension_module_name)operator(.)ident(constantize) + reserved(end) + + reserved(class) class(JoinDependency) + ident(attr_reader) symbol(:joins)operator(,) symbol(:reflections)operator(,) symbol(:table_aliases) + + reserved(def) method(initialize)operator(()ident(base)operator(,) ident(associations)operator(,) ident(joins)operator(\)) + instance_variable(@joins) operator(=) operator([)constant(JoinBase)operator(.)ident(new)operator(()ident(base)operator(,) ident(joins)operator(\))operator(]) + instance_variable(@associations) operator(=) ident(associations) + instance_variable(@reflections) operator(=) operator([)operator(]) + instance_variable(@base_records_hash) operator(=) operator({)operator(}) + instance_variable(@base_records_in_order) operator(=) operator([)operator(]) + instance_variable(@table_aliases) operator(=) constant(Hash)operator(.)ident(new) operator({) operator(|)ident(aliases)operator(,) ident(table)operator(|) ident(aliases)operator([)ident(table)operator(]) operator(=) integer(0) operator(}) + instance_variable(@table_aliases)operator([)ident(base)operator(.)ident(table_name)operator(]) operator(=) integer(1) + ident(build)operator(()ident(associations)operator(\)) + reserved(end) + + reserved(def) method(join_associations) + instance_variable(@joins)operator([)integer(1)operator(..)integer(-1)operator(])operator(.)ident(to_a) + reserved(end) + + reserved(def) method(join_base) + instance_variable(@joins)operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(instantiate)operator(()ident(rows)operator(\)) + ident(rows)operator(.)ident(each_with_index) reserved(do) operator(|)ident(row)operator(,) ident(i)operator(|) + ident(primary_id) operator(=) ident(join_base)operator(.)ident(record_id)operator(()ident(row)operator(\)) + reserved(unless) instance_variable(@base_records_hash)operator([)ident(primary_id)operator(]) + instance_variable(@base_records_in_order) operator(<<) operator(()instance_variable(@base_records_hash)operator([)ident(primary_id)operator(]) operator(=) ident(join_base)operator(.)ident(instantiate)operator(()ident(row)operator(\))operator(\)) + reserved(end) + ident(construct)operator(()instance_variable(@base_records_hash)operator([)ident(primary_id)operator(])operator(,) instance_variable(@associations)operator(,) ident(join_associations)operator(.)ident(dup)operator(,) ident(row)operator(\)) + reserved(end) + reserved(return) instance_variable(@base_records_in_order) + reserved(end) + + reserved(def) method(aliased_table_names_for)operator(()ident(table_name)operator(\)) + ident(joins)operator(.)ident(select)operator({)operator(|)ident(join)operator(|) ident(join)operator(.)ident(table_name) operator(==) ident(table_name) operator(})operator(.)ident(collect)operator({)operator(|)ident(join)operator(|) ident(join)operator(.)ident(aliased_table_name)operator(}) + reserved(end) + + ident(protected) + reserved(def) method(build)operator(()ident(associations)operator(,) ident(parent) operator(=) pre_constant(nil)operator(\)) + ident(parent) operator(||=) instance_variable(@joins)operator(.)ident(last) + reserved(case) ident(associations) + reserved(when) constant(Symbol)operator(,) constant(String) + ident(reflection) operator(=) ident(parent)operator(.)ident(reflections)operator([)ident(associations)operator(.)ident(to_s)operator(.)ident(intern)operator(]) reserved(or) + ident(raise) constant(ConfigurationError)operator(,) string<delimiter(")content(Association named ')inline<inline_delimiter(#{) ident(associations) inline_delimiter(})>content(' was not found; perhaps you misspelled it?)delimiter(")> + instance_variable(@reflections) operator(<<) ident(reflection) + instance_variable(@joins) operator(<<) constant(JoinAssociation)operator(.)ident(new)operator(()ident(reflection)operator(,) pre_constant(self)operator(,) ident(parent)operator(\)) + reserved(when) constant(Array) + ident(associations)operator(.)ident(each) reserved(do) operator(|)ident(association)operator(|) + ident(build)operator(()ident(association)operator(,) ident(parent)operator(\)) + reserved(end) + reserved(when) constant(Hash) + ident(associations)operator(.)ident(keys)operator(.)ident(sort)operator({)operator(|)ident(a)operator(,)ident(b)operator(|)ident(a)operator(.)ident(to_s)operator(<=>)ident(b)operator(.)ident(to_s)operator(})operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(build)operator(()ident(name)operator(,) ident(parent)operator(\)) + ident(build)operator(()ident(associations)operator([)ident(name)operator(])operator(\)) + reserved(end) + reserved(else) + ident(raise) constant(ConfigurationError)operator(,) ident(associations)operator(.)ident(inspect) + reserved(end) + reserved(end) + + reserved(def) method(construct)operator(()ident(parent)operator(,) ident(associations)operator(,) ident(joins)operator(,) ident(row)operator(\)) + reserved(case) ident(associations) + reserved(when) constant(Symbol)operator(,) constant(String) + reserved(while) operator(()ident(join) operator(=) ident(joins)operator(.)ident(shift)operator(\))operator(.)ident(reflection)operator(.)ident(name)operator(.)ident(to_s) operator(!=) ident(associations)operator(.)ident(to_s) + ident(raise) constant(ConfigurationError)operator(,) string<delimiter(")content(Not Enough Associations)delimiter(")> reserved(if) ident(joins)operator(.)ident(empty?) + reserved(end) + ident(construct_association)operator(()ident(parent)operator(,) ident(join)operator(,) ident(row)operator(\)) + reserved(when) constant(Array) + ident(associations)operator(.)ident(each) reserved(do) operator(|)ident(association)operator(|) + ident(construct)operator(()ident(parent)operator(,) ident(association)operator(,) ident(joins)operator(,) ident(row)operator(\)) + reserved(end) + reserved(when) constant(Hash) + ident(associations)operator(.)ident(keys)operator(.)ident(sort)operator({)operator(|)ident(a)operator(,)ident(b)operator(|)ident(a)operator(.)ident(to_s)operator(<=>)ident(b)operator(.)ident(to_s)operator(})operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(association) operator(=) ident(construct_association)operator(()ident(parent)operator(,) ident(joins)operator(.)ident(shift)operator(,) ident(row)operator(\)) + ident(construct)operator(()ident(association)operator(,) ident(associations)operator([)ident(name)operator(])operator(,) ident(joins)operator(,) ident(row)operator(\)) reserved(if) ident(association) + reserved(end) + reserved(else) + ident(raise) constant(ConfigurationError)operator(,) ident(associations)operator(.)ident(inspect) + reserved(end) + reserved(end) + + reserved(def) method(construct_association)operator(()ident(record)operator(,) ident(join)operator(,) ident(row)operator(\)) + reserved(case) ident(join)operator(.)ident(reflection)operator(.)ident(macro) + reserved(when) symbol(:has_many)operator(,) symbol(:has_and_belongs_to_many) + ident(collection) operator(=) ident(record)operator(.)ident(send)operator(()ident(join)operator(.)ident(reflection)operator(.)ident(name)operator(\)) + ident(collection)operator(.)ident(loaded) + + reserved(return) pre_constant(nil) reserved(if) ident(record)operator(.)ident(id)operator(.)ident(to_s) operator(!=) ident(join)operator(.)ident(parent)operator(.)ident(record_id)operator(()ident(row)operator(\))operator(.)ident(to_s) reserved(or) ident(row)operator([)ident(join)operator(.)ident(aliased_primary_key)operator(])operator(.)ident(nil?) + ident(association) operator(=) ident(join)operator(.)ident(instantiate)operator(()ident(row)operator(\)) + ident(collection)operator(.)ident(target)operator(.)ident(push)operator(()ident(association)operator(\)) reserved(unless) ident(collection)operator(.)ident(target)operator(.)ident(include?)operator(()ident(association)operator(\)) + reserved(when) symbol(:has_one)operator(,) symbol(:belongs_to) + reserved(return) reserved(if) ident(record)operator(.)ident(id)operator(.)ident(to_s) operator(!=) ident(join)operator(.)ident(parent)operator(.)ident(record_id)operator(()ident(row)operator(\))operator(.)ident(to_s) reserved(or) ident(row)operator([)ident(join)operator(.)ident(aliased_primary_key)operator(])operator(.)ident(nil?) + ident(association) operator(=) ident(join)operator(.)ident(instantiate)operator(()ident(row)operator(\)) + ident(record)operator(.)ident(send)operator(()string<delimiter(")content(set_)inline<inline_delimiter(#{)ident(join)operator(.)ident(reflection)operator(.)ident(name)inline_delimiter(})>content(_target)delimiter(")>operator(,) ident(association)operator(\)) + reserved(else) + ident(raise) constant(ConfigurationError)operator(,) string<delimiter(")content(unknown macro: )inline<inline_delimiter(#{)ident(join)operator(.)ident(reflection)operator(.)ident(macro)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(return) ident(association) + reserved(end) + + reserved(class) class(JoinBase) + ident(attr_reader) symbol(:active_record)operator(,) symbol(:table_joins) + ident(delegate) symbol(:table_name)operator(,) symbol(:column_names)operator(,) symbol(:primary_key)operator(,) symbol(:reflections)operator(,) symbol(:sanitize_sql)operator(,) symbol(:to) operator(=)operator(>) symbol(:active_record) + + reserved(def) method(initialize)operator(()ident(active_record)operator(,) ident(joins) operator(=) pre_constant(nil)operator(\)) + instance_variable(@active_record) operator(=) ident(active_record) + instance_variable(@cached_record) operator(=) operator({)operator(}) + instance_variable(@table_joins) operator(=) ident(joins) + reserved(end) + + reserved(def) method(aliased_prefix) + string<delimiter(")content(t0)delimiter(")> + reserved(end) + + reserved(def) method(aliased_primary_key) + string<delimiter(")inline<inline_delimiter(#{) ident(aliased_prefix) inline_delimiter(})>content(_r0)delimiter(")> + reserved(end) + + reserved(def) method(aliased_table_name) + ident(active_record)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(column_names_with_alias) + reserved(unless) instance_variable(@column_names_with_alias) + instance_variable(@column_names_with_alias) operator(=) operator([)operator(]) + operator(()operator([)ident(primary_key)operator(]) operator(+) operator(()ident(column_names) operator(-) operator([)ident(primary_key)operator(])operator(\))operator(\))operator(.)ident(each_with_index) reserved(do) operator(|)ident(column_name)operator(,) ident(i)operator(|) + instance_variable(@column_names_with_alias) operator(<<) operator([)ident(column_name)operator(,) string<delimiter(")inline<inline_delimiter(#{) ident(aliased_prefix) inline_delimiter(})>content(_r)inline<inline_delimiter(#{) ident(i) inline_delimiter(})>delimiter(")>operator(]) + reserved(end) + reserved(end) + reserved(return) instance_variable(@column_names_with_alias) + reserved(end) + + reserved(def) method(extract_record)operator(()ident(row)operator(\)) + ident(column_names_with_alias)operator(.)ident(inject)operator(()operator({)operator(})operator(\))operator({)operator(|)ident(record)operator(,) operator(()ident(cn)operator(,) ident(an)operator(\))operator(|) ident(record)operator([)ident(cn)operator(]) operator(=) ident(row)operator([)ident(an)operator(])operator(;) ident(record)operator(}) + reserved(end) + + reserved(def) method(record_id)operator(()ident(row)operator(\)) + ident(row)operator([)ident(aliased_primary_key)operator(]) + reserved(end) + + reserved(def) method(instantiate)operator(()ident(row)operator(\)) + instance_variable(@cached_record)operator([)ident(record_id)operator(()ident(row)operator(\))operator(]) operator(||=) ident(active_record)operator(.)ident(instantiate)operator(()ident(extract_record)operator(()ident(row)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(JoinAssociation) operator(<) constant(JoinBase) + ident(attr_reader) symbol(:reflection)operator(,) symbol(:parent)operator(,) symbol(:aliased_table_name)operator(,) symbol(:aliased_prefix)operator(,) symbol(:aliased_join_table_name)operator(,) symbol(:parent_table_name) + ident(delegate) symbol(:options)operator(,) symbol(:klass)operator(,) symbol(:through_reflection)operator(,) symbol(:source_reflection)operator(,) symbol(:to) operator(=)operator(>) symbol(:reflection) + + reserved(def) method(initialize)operator(()ident(reflection)operator(,) ident(join_dependency)operator(,) ident(parent) operator(=) pre_constant(nil)operator(\)) + ident(reflection)operator(.)ident(check_validity!) + reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:polymorphic)operator(]) + ident(raise) constant(EagerLoadPolymorphicError)operator(.)ident(new)operator(()ident(reflection)operator(\)) + reserved(end) + + reserved(super)operator(()ident(reflection)operator(.)ident(klass)operator(\)) + instance_variable(@parent) operator(=) ident(parent) + instance_variable(@reflection) operator(=) ident(reflection) + instance_variable(@aliased_prefix) operator(=) string<delimiter(")content(t)inline<inline_delimiter(#{) ident(join_dependency)operator(.)ident(joins)operator(.)ident(size) inline_delimiter(})>delimiter(")> + instance_variable(@aliased_table_name) operator(=) ident(table_name) comment(# start with the table name) + instance_variable(@parent_table_name) operator(=) ident(parent)operator(.)ident(active_record)operator(.)ident(table_name) + + reserved(if) operator(!)ident(parent)operator(.)ident(table_joins)operator(.)ident(blank?) operator(&&) ident(parent)operator(.)ident(table_joins)operator(.)ident(to_s)operator(.)ident(downcase) operator(=)operator(~) regexp<delimiter(%r{)content(join()char(\\s)content(+)char(\\w)content(+\)?)char(\\s)content(+)inline<inline_delimiter(#{)ident(aliased_table_name)operator(.)ident(downcase)inline_delimiter(})>char(\\s)content(on)delimiter(})> + ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_table_name)operator(]) operator(+=) integer(1) + reserved(end) + + reserved(unless) ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_table_name)operator(])operator(.)ident(zero?) + comment(# if the table name has been used, then use an alias) + instance_variable(@aliased_table_name) operator(=) ident(active_record)operator(.)ident(connection)operator(.)ident(table_alias_for) string<delimiter(")inline<inline_delimiter(#{)ident(pluralize)operator(()ident(reflection)operator(.)ident(name)operator(\))inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(parent_table_name)inline_delimiter(})>delimiter(")> + ident(table_index) operator(=) ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_table_name)operator(]) + instance_variable(@aliased_table_name) operator(=) instance_variable(@aliased_table_name)operator([)integer(0)operator(..)ident(active_record)operator(.)ident(connection)operator(.)ident(table_alias_length)operator(-)integer(3)operator(]) operator(+) string<delimiter(")content(_)inline<inline_delimiter(#{)ident(table_index)operator(+)integer(1)inline_delimiter(})>delimiter(")> reserved(if) ident(table_index) operator(>) integer(0) + reserved(end) + ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_table_name)operator(]) operator(+=) integer(1) + + reserved(if) ident(reflection)operator(.)ident(macro) operator(==) symbol(:has_and_belongs_to_many) operator(||) operator(()ident(reflection)operator(.)ident(macro) operator(==) symbol(:has_many) operator(&&) ident(reflection)operator(.)ident(options)operator([)symbol(:through)operator(])operator(\)) + instance_variable(@aliased_join_table_name) operator(=) ident(reflection)operator(.)ident(macro) operator(==) symbol(:has_and_belongs_to_many) operator(?) ident(reflection)operator(.)ident(options)operator([)symbol(:join_table)operator(]) operator(:) ident(reflection)operator(.)ident(through_reflection)operator(.)ident(klass)operator(.)ident(table_name) + reserved(unless) ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_join_table_name)operator(])operator(.)ident(zero?) + instance_variable(@aliased_join_table_name) operator(=) ident(active_record)operator(.)ident(connection)operator(.)ident(table_alias_for) string<delimiter(")inline<inline_delimiter(#{)ident(pluralize)operator(()ident(reflection)operator(.)ident(name)operator(\))inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(parent_table_name)inline_delimiter(})>content(_join)delimiter(")> + ident(table_index) operator(=) ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_join_table_name)operator(]) + instance_variable(@aliased_join_table_name) operator(=) instance_variable(@aliased_join_table_name)operator([)integer(0)operator(..)ident(active_record)operator(.)ident(connection)operator(.)ident(table_alias_length)operator(-)integer(3)operator(]) operator(+) string<delimiter(")content(_)inline<inline_delimiter(#{)ident(table_index)operator(+)integer(1)inline_delimiter(})>delimiter(")> reserved(if) ident(table_index) operator(>) integer(0) + reserved(end) + ident(join_dependency)operator(.)ident(table_aliases)operator([)ident(aliased_join_table_name)operator(]) operator(+=) integer(1) + reserved(end) + reserved(end) + + reserved(def) method(association_join) + ident(join) operator(=) reserved(case) ident(reflection)operator(.)ident(macro) + reserved(when) symbol(:has_and_belongs_to_many) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_alias_for)operator(()ident(options)operator([)symbol(:join_table)operator(])operator(,) ident(aliased_join_table_name)operator(\))operator(,) + ident(aliased_join_table_name)operator(,) + ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(reflection)operator(.)ident(active_record)operator(.)ident(to_s)operator(.)ident(classify)operator(.)ident(foreign_key)operator(,) + ident(reflection)operator(.)ident(active_record)operator(.)ident(table_name)operator(,) ident(reflection)operator(.)ident(active_record)operator(.)ident(primary_key)operator(]) operator(+) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) ident(aliased_table_name)operator(,) ident(klass)operator(.)ident(primary_key)operator(,) + ident(aliased_join_table_name)operator(,) ident(options)operator([)symbol(:association_foreign_key)operator(]) operator(||) ident(klass)operator(.)ident(table_name)operator(.)ident(classify)operator(.)ident(foreign_key) + operator(]) + reserved(when) symbol(:has_many)operator(,) symbol(:has_one) + reserved(case) + reserved(when) ident(reflection)operator(.)ident(macro) operator(==) symbol(:has_many) operator(&&) ident(reflection)operator(.)ident(options)operator([)symbol(:through)operator(]) + ident(through_conditions) operator(=) ident(through_reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(]) operator(?) string<delimiter(")content(AND )inline<inline_delimiter(#{)ident(interpolate_sql)operator(()ident(sanitize_sql)operator(()ident(through_reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\))operator(\))inline_delimiter(})>delimiter(")> operator(:) string<delimiter(')delimiter(')> + reserved(if) ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) comment(# has_many :through against a polymorphic join) + ident(polymorphic_foreign_key) operator(=) ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])operator(.)ident(to_s) operator(+) string<delimiter(')content(_id)delimiter(')> + ident(polymorphic_foreign_type) operator(=) ident(through_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])operator(.)ident(to_s) operator(+) string<delimiter(')content(_type)delimiter(')> + + string<delimiter(")content( LEFT OUTER JOIN %s ON (%s.%s = %s.%s AND %s.%s = %s\) )delimiter(")> operator(%) operator([) + ident(table_alias_for)operator(()ident(through_reflection)operator(.)ident(klass)operator(.)ident(table_name)operator(,) ident(aliased_join_table_name)operator(\))operator(,) + ident(aliased_join_table_name)operator(,) ident(polymorphic_foreign_key)operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(parent)operator(.)ident(primary_key)operator(,) + ident(aliased_join_table_name)operator(,) ident(polymorphic_foreign_type)operator(,) ident(klass)operator(.)ident(quote)operator(()ident(parent)operator(.)ident(active_record)operator(.)ident(base_class)operator(.)ident(name)operator(\))operator(]) operator(+) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([)ident(table_name_and_alias)operator(,) + ident(aliased_table_name)operator(,) ident(primary_key)operator(,) ident(aliased_join_table_name)operator(,) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(reflection)operator(.)ident(klass)operator(.)ident(to_s)operator(.)ident(classify)operator(.)ident(foreign_key) + operator(]) + reserved(else) + reserved(if) ident(source_reflection)operator(.)ident(macro) operator(==) symbol(:has_many) operator(&&) ident(source_reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_alias_for)operator(()ident(through_reflection)operator(.)ident(klass)operator(.)ident(table_name)operator(,) ident(aliased_join_table_name)operator(\))operator(,) ident(aliased_join_table_name)operator(,) + ident(through_reflection)operator(.)ident(primary_key_name)operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(parent)operator(.)ident(primary_key)operator(]) operator(+) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s )delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) + ident(aliased_table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(source_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id)delimiter(")>operator(,) + ident(aliased_join_table_name)operator(,) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(primary_key)operator(,) + ident(aliased_table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(source_reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type)delimiter(")>operator(,) + ident(klass)operator(.)ident(quote)operator(()ident(source_reflection)operator(.)ident(active_record)operator(.)ident(base_class)operator(.)ident(name)operator(\)) + operator(]) + reserved(else) + reserved(case) ident(source_reflection)operator(.)ident(macro) + reserved(when) symbol(:belongs_to) + ident(first_key) operator(=) ident(primary_key) + ident(second_key) operator(=) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(klass)operator(.)ident(to_s)operator(.)ident(classify)operator(.)ident(foreign_key) + reserved(when) symbol(:has_many) + ident(first_key) operator(=) ident(through_reflection)operator(.)ident(klass)operator(.)ident(to_s)operator(.)ident(classify)operator(.)ident(foreign_key) + ident(second_key) operator(=) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(primary_key) + reserved(end) + + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_alias_for)operator(()ident(through_reflection)operator(.)ident(klass)operator(.)ident(table_name)operator(,) ident(aliased_join_table_name)operator(\))operator(,) ident(aliased_join_table_name)operator(,) + ident(through_reflection)operator(.)ident(primary_key_name)operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(parent)operator(.)ident(primary_key)operator(]) operator(+) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) + ident(aliased_table_name)operator(,) ident(first_key)operator(,) + ident(aliased_join_table_name)operator(,) ident(second_key) + operator(]) + reserved(end) + reserved(end) + + reserved(when) ident(reflection)operator(.)ident(macro) operator(==) symbol(:has_many) operator(&&) ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s)delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) + ident(aliased_table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id)delimiter(")>operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(parent)operator(.)ident(primary_key)operator(,) + ident(aliased_table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type)delimiter(")>operator(,) + ident(klass)operator(.)ident(quote)operator(()ident(parent)operator(.)ident(active_record)operator(.)ident(base_class)operator(.)ident(name)operator(\)) + operator(]) + reserved(when) ident(reflection)operator(.)ident(macro) operator(==) symbol(:has_one) operator(&&) ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(]) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s )delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) + ident(aliased_table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id)delimiter(")>operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(parent)operator(.)ident(primary_key)operator(,) + ident(aliased_table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(reflection)operator(.)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_type)delimiter(")>operator(,) + ident(klass)operator(.)ident(quote)operator(()ident(reflection)operator(.)ident(active_record)operator(.)ident(base_class)operator(.)ident(name)operator(\)) + operator(]) + reserved(else) + ident(foreign_key) operator(=) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(reflection)operator(.)ident(active_record)operator(.)ident(name)operator(.)ident(foreign_key) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) + ident(aliased_table_name)operator(,) ident(foreign_key)operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(parent)operator(.)ident(primary_key) + operator(]) + reserved(end) + reserved(when) symbol(:belongs_to) + string<delimiter(")content( LEFT OUTER JOIN %s ON %s.%s = %s.%s )delimiter(")> operator(%) operator([) + ident(table_name_and_alias)operator(,) ident(aliased_table_name)operator(,) ident(reflection)operator(.)ident(klass)operator(.)ident(primary_key)operator(,) + ident(parent)operator(.)ident(aliased_table_name)operator(,) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(klass)operator(.)ident(to_s)operator(.)ident(foreign_key) + operator(]) + reserved(else) + string<delimiter(")delimiter(")> + reserved(end) operator(||) string<delimiter(')delimiter(')> + ident(join) operator(<<) string<delimiter(%()content(AND %s.%s = %s )delimiter(\))> operator(%) operator([) + ident(aliased_table_name)operator(,) + ident(reflection)operator(.)ident(active_record)operator(.)ident(connection)operator(.)ident(quote_column_name)operator(()ident(reflection)operator(.)ident(active_record)operator(.)ident(inheritance_column)operator(\))operator(,) + ident(klass)operator(.)ident(quote)operator(()ident(klass)operator(.)ident(name)operator(\))operator(]) reserved(unless) ident(klass)operator(.)ident(descends_from_active_record?) + ident(join) operator(<<) string<delimiter(")content(AND )inline<inline_delimiter(#{)ident(interpolate_sql)operator(()ident(sanitize_sql)operator(()ident(reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(])operator(\))operator(\))inline_delimiter(})>content( )delimiter(")> reserved(if) ident(reflection)operator(.)ident(options)operator([)symbol(:conditions)operator(]) + ident(join) + reserved(end) + + ident(protected) + reserved(def) method(pluralize)operator(()ident(table_name)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(?) ident(table_name)operator(.)ident(to_s)operator(.)ident(pluralize) operator(:) ident(table_name) + reserved(end) + + reserved(def) method(table_alias_for)operator(()ident(table_name)operator(,) ident(table_alias)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(table_alias) reserved(if) ident(table_name) operator(!=) ident(table_alias)inline_delimiter(})>delimiter(")>operator(.)ident(strip) + reserved(end) + + reserved(def) method(table_name_and_alias) + ident(table_alias_for) ident(table_name)operator(,) instance_variable(@aliased_table_name) + reserved(end) + + reserved(def) method(interpolate_sql)operator(()ident(sql)operator(\)) + ident(instance_eval)operator(()string<delimiter(")content(%@)inline<inline_delimiter(#{)ident(sql)operator(.)ident(gsub)operator(()string<delimiter(')content(@)delimiter(')>operator(,) string<delimiter(')content(\\@)delimiter(')>operator(\))inline_delimiter(})>content(@)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(yaml)delimiter(')> +ident(require) string<delimiter(')content(set)delimiter(')> +ident(require) string<delimiter(')content(active_record/deprecated_finders)delimiter(')> + +reserved(module) class(ActiveRecord) comment(#:nodoc:) + reserved(class) class(ActiveRecordError) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + reserved(class) class(SubclassNotFound) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(AssociationTypeMismatch) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(SerializationTypeMismatch) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(AdapterNotSpecified) operator(<) constant(ActiveRecordError) comment(# :nodoc:) + reserved(end) + reserved(class) class(AdapterNotFound) operator(<) constant(ActiveRecordError) comment(# :nodoc:) + reserved(end) + reserved(class) class(ConnectionNotEstablished) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(ConnectionFailed) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(RecordNotFound) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(RecordNotSaved) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(StatementInvalid) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(PreparedStatementInvalid) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(StaleObjectError) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + reserved(end) + reserved(class) class(ConfigurationError) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + reserved(class) class(ReadOnlyRecord) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + + reserved(class) class(AttributeAssignmentError) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + ident(attr_reader) symbol(:exception)operator(,) symbol(:attribute) + reserved(def) method(initialize)operator(()ident(message)operator(,) ident(exception)operator(,) ident(attribute)operator(\)) + instance_variable(@exception) operator(=) ident(exception) + instance_variable(@attribute) operator(=) ident(attribute) + instance_variable(@message) operator(=) ident(message) + reserved(end) + reserved(end) + + reserved(class) class(MultiparameterAssignmentErrors) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + ident(attr_reader) symbol(:errors) + reserved(def) method(initialize)operator(()ident(errors)operator(\)) + instance_variable(@errors) operator(=) ident(errors) + reserved(end) + reserved(end) + + comment(# Active Record objects don't specify their attributes directly, but rather infer them from the table definition with) + comment(# which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change) + comment(# is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain) + comment(# database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.) + comment(#) + comment(# See the mapping rules in table_name and the full example in link:files/README.html for more insight.) + comment(#) + comment(# == Creation) + comment(#) + comment(# Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when) + comment(# you're receiving the data from somewhere else, like a HTTP request. It works like this:) + comment(#) + comment(# user = User.new(:name => "David", :occupation => "Code Artist"\)) + comment(# user.name # => "David") + comment(#) + comment(# You can also use block initialization:) + comment(#) + comment(# user = User.new do |u|) + comment(# u.name = "David") + comment(# u.occupation = "Code Artist") + comment(# end) + comment(#) + comment(# And of course you can just create a bare object and specify the attributes after the fact:) + comment(#) + comment(# user = User.new) + comment(# user.name = "David") + comment(# user.occupation = "Code Artist") + comment(#) + comment(# == Conditions) + comment(#) + comment(# Conditions can either be specified as a string or an array representing the WHERE-part of an SQL statement.) + comment(# The array form is to be used when the condition input is tainted and requires sanitization. The string form can) + comment(# be used for statements that don't involve tainted data. Examples:) + comment(#) + comment(# User < ActiveRecord::Base) + comment(# def self.authenticate_unsafely(user_name, password\)) + comment(# find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'"\)) + comment(# end) + comment(#) + comment(# def self.authenticate_safely(user_name, password\)) + comment(# find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ]\)) + comment(# end) + comment(# end) + comment(#) + comment(# The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query and is thus susceptible to SQL-injection) + comment(# attacks if the <tt>user_name</tt> and +password+ parameters come directly from a HTTP request. The <tt>authenticate_safely</tt> method,) + comment(# on the other hand, will sanitize the <tt>user_name</tt> and +password+ before inserting them in the query, which will ensure that) + comment(# an attacker can't escape the query and fake the login (or worse\).) + comment(#) + comment(# When using multiple parameters in the conditions, it can easily become hard to read exactly what the fourth or fifth) + comment(# question mark is supposed to represent. In those cases, you can resort to named bind variables instead. That's done by replacing) + comment(# the question marks with symbols and supplying a hash with values for the matching symbol keys:) + comment(#) + comment(# Company.find(:first, [) + comment(# "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",) + comment(# { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }) + comment(# ]\)) + comment(#) + comment(# == Overwriting default accessors) + comment(#) + comment(# All column values are automatically available through basic accessors on the Active Record object, but some times you) + comment(# want to specialize this behavior. This can be done by either by overwriting the default accessors (using the same) + comment(# name as the attribute\) calling read_attribute(attr_name\) and write_attribute(attr_name, value\) to actually change things.) + comment(# Example:) + comment(#) + comment(# class Song < ActiveRecord::Base) + comment(# # Uses an integer of seconds to hold the length of the song) + comment(#) + comment(# def length=(minutes\)) + comment(# write_attribute(:length, minutes * 60\)) + comment(# end) + comment(#) + comment(# def length) + comment(# read_attribute(:length\) / 60) + comment(# end) + comment(# end) + comment(#) + comment(# You can alternatively use self[:attribute]=(value\) and self[:attribute] instead of write_attribute(:attribute, vaule\) and) + comment(# read_attribute(:attribute\) as a shorter form.) + comment(#) + comment(# == Accessing attributes before they have been typecasted) + comment(#) + comment(# Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first.) + comment(# That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model) + comment(# has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast.) + comment(#) + comment(# This is especially useful in validation situations where the user might supply a string for an integer field and you want to display) + comment(# the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you) + comment(# want.) + comment(#) + comment(# == Dynamic attribute-based finders) + comment(#) + comment(# Dynamic attribute-based finders are a cleaner way of getting (and/or creating\) objects by simple queries without turning to SQL. They work by) + comment(# appending the name of an attribute to <tt>find_by_</tt> or <tt>find_all_by_</tt>, so you get finders like Person.find_by_user_name,) + comment(# Person.find_all_by_last_name, Payment.find_by_transaction_id. So instead of writing) + comment(# <tt>Person.find(:first, ["user_name = ?", user_name]\)</tt>, you just do <tt>Person.find_by_user_name(user_name\)</tt>.) + comment(# And instead of writing <tt>Person.find(:all, ["last_name = ?", last_name]\)</tt>, you just do <tt>Person.find_all_by_last_name(last_name\)</tt>.) + comment(#) + comment(# It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like) + comment(# <tt>Person.find_by_user_name_and_password</tt> or even <tt>Payment.find_by_purchaser_and_state_and_country</tt>. So instead of writing) + comment(# <tt>Person.find(:first, ["user_name = ? AND password = ?", user_name, password]\)</tt>, you just do) + comment(# <tt>Person.find_by_user_name_and_password(user_name, password\)</tt>.) + comment(#) + comment(# It's even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount) + comment(# is actually Payment.find_all_by_amount(amount, options\). And the full interface to Person.find_by_user_name is) + comment(# actually Person.find_by_user_name(user_name, options\). So you could call <tt>Payment.find_all_by_amount(50, :order => "created_on"\)</tt>.) + comment(#) + comment(# The same dynamic finder style can be used to create the object if it doesn't already exist. This dynamic finder is called with) + comment(# <tt>find_or_create_by_</tt> and will return the object if it already exists and otherwise creates it, then returns it. Example:) + comment(#) + comment(# # No 'Summer' tag exists) + comment(# Tag.find_or_create_by_name("Summer"\) # equal to Tag.create(:name => "Summer"\)) + comment(# ) + comment(# # Now the 'Summer' tag does exist) + comment(# Tag.find_or_create_by_name("Summer"\) # equal to Tag.find_by_name("Summer"\)) + comment(#) + comment(# == Saving arrays, hashes, and other non-mappable objects in text columns) + comment(#) + comment(# Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method +serialize+.) + comment(# This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work. Example:) + comment(#) + comment(# class User < ActiveRecord::Base) + comment(# serialize :preferences) + comment(# end) + comment(#) + comment(# user = User.create(:preferences => { "background" => "black", "display" => large }\)) + comment(# User.find(user.id\).preferences # => { "background" => "black", "display" => large }) + comment(#) + comment(# You can also specify a class option as the second parameter that'll raise an exception if a serialized object is retrieved as a) + comment(# descendent of a class not in the hierarchy. Example:) + comment(#) + comment(# class User < ActiveRecord::Base) + comment(# serialize :preferences, Hash) + comment(# end) + comment(#) + comment(# user = User.create(:preferences => %w( one two three \)\)) + comment(# User.find(user.id\).preferences # raises SerializationTypeMismatch) + comment(#) + comment(# == Single table inheritance) + comment(#) + comment(# Active Record allows inheritance by storing the name of the class in a column that by default is called "type" (can be changed) + comment(# by overwriting <tt>Base.inheritance_column</tt>\). This means that an inheritance looking like this:) + comment(#) + comment(# class Company < ActiveRecord::Base; end) + comment(# class Firm < Company; end) + comment(# class Client < Company; end) + comment(# class PriorityClient < Client; end) + comment(#) + comment(# When you do Firm.create(:name => "37signals"\), this record will be saved in the companies table with type = "Firm". You can then) + comment(# fetch this row again using Company.find(:first, "name = '37signals'"\) and it will return a Firm object.) + comment(#) + comment(# If you don't have a type column defined in your table, single-table inheritance won't be triggered. In that case, it'll work just) + comment(# like normal subclasses with no special magic for differentiating between them or reloading the right type with find.) + comment(#) + comment(# Note, all the attributes for all the cases are kept in the same table. Read more:) + comment(# http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html) + comment(#) + comment(# == Connection to multiple databases in different models) + comment(#) + comment(# Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection.) + comment(# All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection.) + comment(# For example, if Course is a ActiveRecord::Base, but resides in a different database you can just say Course.establish_connection) + comment(# and Course *and all its subclasses* will use this connection instead.) + comment(#) + comment(# This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is) + comment(# requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool.) + comment(#) + comment(# == Exceptions) + comment(#) + comment(# * +ActiveRecordError+ -- generic error class and superclass of all other errors raised by Active Record) + comment(# * +AdapterNotSpecified+ -- the configuration hash used in <tt>establish_connection</tt> didn't include a) + comment(# <tt>:adapter</tt> key.) + comment(# * +AdapterNotFound+ -- the <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified an non-existent adapter) + comment(# (or a bad spelling of an existing one\).) + comment(# * +AssociationTypeMismatch+ -- the object assigned to the association wasn't of the type specified in the association definition.) + comment(# * +SerializationTypeMismatch+ -- the object serialized wasn't of the class specified as the second parameter.) + comment(# * +ConnectionNotEstablished+ -- no connection has been established. Use <tt>establish_connection</tt> before querying.) + comment(# * +RecordNotFound+ -- no record responded to the find* method.) + comment(# Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.) + comment(# * +StatementInvalid+ -- the database server rejected the SQL statement. The precise error is added in the message.) + comment(# Either the record with the given ID doesn't exist or the record didn't meet the additional restrictions.) + comment(# * +MultiparameterAssignmentErrors+ -- collection of errors that occurred during a mass assignment using the) + comment(# +attributes=+ method. The +errors+ property of this exception contains an array of +AttributeAssignmentError+) + comment(# objects that should be inspected to determine which attributes triggered the errors.) + comment(# * +AttributeAssignmentError+ -- an error occurred while doing a mass assignment through the +attributes=+ method.) + comment(# You can inspect the +attribute+ property of the exception object to determine which attribute triggered the error.) + comment(#) + comment(# *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level\).) + comment(# So it's possible to assign a logger to the class through Base.logger= which will then be used by all) + comment(# instances in the current object space.) + reserved(class) class(Base) + comment(# Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed) + comment(# on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+.) + ident(cattr_accessor) symbol(:logger) + + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + reserved(def) pre_constant(self)operator(.)ident(inherited)operator(()ident(child)operator(\)) comment(#:nodoc:) + class_variable(@@subclasses)operator([)pre_constant(self)operator(]) operator(||=) operator([)operator(]) + class_variable(@@subclasses)operator([)pre_constant(self)operator(]) operator(<<) ident(child) + reserved(super) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(reset_subclasses) comment(#:nodoc:) + ident(nonreloadables) operator(=) operator([)operator(]) + ident(subclasses)operator(.)ident(each) reserved(do) operator(|)ident(klass)operator(|) + reserved(unless) ident(klass)operator(.)ident(reloadable?) + ident(nonreloadables) operator(<<) ident(klass) + reserved(next) + reserved(end) + ident(klass)operator(.)ident(instance_variables)operator(.)ident(each) operator({) operator(|)ident(var)operator(|) ident(klass)operator(.)ident(send)operator(()symbol(:remove_instance_variable)operator(,) ident(var)operator(\)) operator(}) + ident(klass)operator(.)ident(instance_methods)operator(()pre_constant(false)operator(\))operator(.)ident(each) operator({) operator(|)ident(m)operator(|) ident(klass)operator(.)ident(send) symbol(:undef_method)operator(,) ident(m) operator(}) + reserved(end) + class_variable(@@subclasses) operator(=) operator({)operator(}) + ident(nonreloadables)operator(.)ident(each) operator({) operator(|)ident(klass)operator(|) operator(()class_variable(@@subclasses)operator([)ident(klass)operator(.)ident(superclass)operator(]) operator(||=) operator([)operator(])operator(\)) operator(<<) ident(klass) operator(}) + reserved(end) + + class_variable(@@subclasses) operator(=) operator({)operator(}) + + ident(cattr_accessor) symbol(:configurations) + class_variable(@@configurations) operator(=) operator({)operator(}) + + comment(# Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and) + comment(# :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as) + comment(# the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember) + comment(# that this is a global setting for all Active Records.) + ident(cattr_accessor) symbol(:primary_key_prefix_type) + class_variable(@@primary_key_prefix_type) operator(=) pre_constant(nil) + + comment(# Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all) + comment(# table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace) + comment(# for tables in a shared database. By default, the prefix is the empty string.) + ident(cattr_accessor) symbol(:table_name_prefix) + class_variable(@@table_name_prefix) operator(=) string<delimiter(")delimiter(")> + + comment(# Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",) + comment(# "people_basecamp"\). By default, the suffix is the empty string.) + ident(cattr_accessor) symbol(:table_name_suffix) + class_variable(@@table_name_suffix) operator(=) string<delimiter(")delimiter(")> + + comment(# Indicates whether or not table names should be the pluralized versions of the corresponding class names.) + comment(# If true, the default table name for a +Product+ class will be +products+. If false, it would just be +product+.) + comment(# See table_name for the full rules on table/class naming. This is true, by default.) + ident(cattr_accessor) symbol(:pluralize_table_names) + class_variable(@@pluralize_table_names) operator(=) pre_constant(true) + + comment(# Determines whether or not to use ANSI codes to colorize the logging statements committed by the connection adapter. These colors) + comment(# make it much easier to overview things during debugging (when used through a reader like +tail+ and on a black background\), but) + comment(# may complicate matters if you use software like syslog. This is true, by default.) + ident(cattr_accessor) symbol(:colorize_logging) + class_variable(@@colorize_logging) operator(=) pre_constant(true) + + comment(# Determines whether to use Time.local (using :local\) or Time.utc (using :utc\) when pulling dates and times from the database.) + comment(# This is set to :local by default.) + ident(cattr_accessor) symbol(:default_timezone) + class_variable(@@default_timezone) operator(=) symbol(:local) + + comment(# Determines whether or not to use a connection for each thread, or a single shared connection for all threads.) + comment(# Defaults to false. Set to true if you're writing a threaded application.) + ident(cattr_accessor) symbol(:allow_concurrency) + class_variable(@@allow_concurrency) operator(=) pre_constant(false) + + comment(# Determines whether to speed up access by generating optimized reader) + comment(# methods to avoid expensive calls to method_missing when accessing) + comment(# attributes by name. You might want to set this to false in development) + comment(# mode, because the methods would be regenerated on each request.) + ident(cattr_accessor) symbol(:generate_read_methods) + class_variable(@@generate_read_methods) operator(=) pre_constant(true) + + comment(# Specifies the format to use when dumping the database schema with Rails') + comment(# Rakefile. If :sql, the schema is dumped as (potentially database-) + comment(# specific\) SQL statements. If :ruby, the schema is dumped as an ) + comment(# ActiveRecord::Schema file which can be loaded into any database that) + comment(# supports migrations. Use :ruby if you want to have different database) + comment(# adapters for, e.g., your development and test environments.) + ident(cattr_accessor) symbol(:schema_format) + class_variable(@@schema_format) operator(=) symbol(:ruby) + + reserved(class) operator(<<) class(self) comment(# Class methods) + comment(# Find operates with three different retrieval approaches:) + comment(#) + comment(# * Find by id: This can either be a specific id (1\), a list of ids (1, 5, 6\), or an array of ids ([5, 6, 10]\).) + comment(# If no record can be found for all of the listed ids, then RecordNotFound will be raised.) + comment(# * Find first: This will return the first record matched by the options used. These options can either be specific) + comment(# conditions or merely an order. If no record can matched, nil is returned.) + comment(# * Find all: This will return all the records matched by the options used. If no records are found, an empty array is returned.) + comment(#) + comment(# All approaches accept an option hash as their last parameter. The options are:) + comment(#) + comment(# * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.) + comment(# * <tt>:order</tt>: An SQL fragment like "created_at DESC, name".) + comment(# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.) + comment(# * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned.) + comment(# * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows.) + comment(# * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed\).) + comment(# The records will be returned read-only since they will have attributes that do not correspond to the table's columns.) + comment(# Pass :readonly => false to override.) + comment(# * <tt>:include</tt>: Names associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer) + comment(# to already defined associations. See eager loading under Associations.) + comment(# * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not) + comment(# include the joined columns.) + comment(# * <tt>:readonly</tt>: Mark the returned records read-only so they cannot be saved or updated.) + comment(#) + comment(# Examples for find by id:) + comment(# Person.find(1\) # returns the object for ID = 1) + comment(# Person.find(1, 2, 6\) # returns an array for objects with IDs in (1, 2, 6\)) + comment(# Person.find([7, 17]\) # returns an array for objects with IDs in (7, 17\)) + comment(# Person.find([1]\) # returns an array for objects the object with ID = 1) + comment(# Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC"\)) + comment(#) + comment(# Examples for find first:) + comment(# Person.find(:first\) # returns the first object fetched by SELECT * FROM people) + comment(# Person.find(:first, :conditions => [ "user_name = ?", user_name]\)) + comment(# Person.find(:first, :order => "created_on DESC", :offset => 5\)) + comment(#) + comment(# Examples for find all:) + comment(# Person.find(:all\) # returns an array of objects for all the rows fetched by SELECT * FROM people) + comment(# Person.find(:all, :conditions => [ "category IN (?\)", categories], :limit => 50\)) + comment(# Person.find(:all, :offset => 10, :limit => 10\)) + comment(# Person.find(:all, :include => [ :account, :friends ]\)) + comment(# Person.find(:all, :group => "category"\)) + reserved(def) method(find)operator(()operator(*)ident(args)operator(\)) + ident(options) operator(=) ident(extract_options_from_args!)operator(()ident(args)operator(\)) + ident(validate_find_options)operator(()ident(options)operator(\)) + ident(set_readonly_option!)operator(()ident(options)operator(\)) + + reserved(case) ident(args)operator(.)ident(first) + reserved(when) symbol(:first) reserved(then) ident(find_initial)operator(()ident(options)operator(\)) + reserved(when) symbol(:all) reserved(then) ident(find_every)operator(()ident(options)operator(\)) + reserved(else) ident(find_from_ids)operator(()ident(args)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + comment(# Works like find(:all\), but requires a complete SQL string. Examples:) + comment(# Post.find_by_sql "SELECT p.*, c.author FROM posts p, comments c WHERE p.id = c.post_id") + comment(# Post.find_by_sql ["SELECT * FROM posts WHERE author = ? AND created > ?", author_id, start_date]) + reserved(def) method(find_by_sql)operator(()ident(sql)operator(\)) + ident(connection)operator(.)ident(select_all)operator(()ident(sanitize_sql)operator(()ident(sql)operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Load)delimiter(")>operator(\))operator(.)ident(collect!) operator({) operator(|)ident(record)operator(|) ident(instantiate)operator(()ident(record)operator(\)) operator(}) + reserved(end) + + comment(# Returns true if the given +id+ represents the primary key of a record in the database, false otherwise.) + comment(# Example:) + comment(# Person.exists?(5\)) + reserved(def) method(exists?)operator(()ident(id)operator(\)) + operator(!)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( = ?)delimiter(")>operator(,) ident(id)operator(])operator(\))operator(.)ident(nil?) reserved(rescue) pre_constant(false) + reserved(end) + + comment(# Creates an object, instantly saves it as a record (if the validation permits it\), and returns it. If the save) + comment(# fails under validations, the unsaved object is still returned.) + reserved(def) method(create)operator(()ident(attributes) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(attributes)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(attributes)operator(.)ident(collect) operator({) operator(|)ident(attr)operator(|) ident(create)operator(()ident(attr)operator(\)) operator(}) + reserved(else) + ident(object) operator(=) ident(new)operator(()ident(attributes)operator(\)) + ident(scope)operator(()symbol(:create)operator(\))operator(.)ident(each) operator({) operator(|)ident(att)operator(,)ident(value)operator(|) ident(object)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(att)inline_delimiter(})>content(=)delimiter(")>operator(,) ident(value)operator(\)) operator(}) reserved(if) ident(scoped?)operator(()symbol(:create)operator(\)) + ident(object)operator(.)ident(save) + ident(object) + reserved(end) + reserved(end) + + comment(# Finds the record from the passed +id+, instantly saves it with the passed +attributes+ (if the validation permits it\),) + comment(# and returns it. If the save fails under validations, the unsaved object is still returned.) + comment(#) + comment(# The arguments may also be given as arrays in which case the update method is called for each pair of +id+ and ) + comment(# +attributes+ and an array of objects is returned.) + comment(#) + comment(# Example of updating one record:) + comment(# Person.update(15, {:user_name => 'Samuel', :group => 'expert'}\)) + comment(# ) + comment(# Example of updating multiple records:) + comment(# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} } ) + comment(# Person.update(people.keys, people.values\)) + reserved(def) method(update)operator(()ident(id)operator(,) ident(attributes)operator(\)) + reserved(if) ident(id)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(idx) operator(=) integer(-1) + ident(id)operator(.)ident(collect) operator({) operator(|)ident(id)operator(|) ident(idx) operator(+=) integer(1)operator(;) ident(update)operator(()ident(id)operator(,) ident(attributes)operator([)ident(idx)operator(])operator(\)) operator(}) + reserved(else) + ident(object) operator(=) ident(find)operator(()ident(id)operator(\)) + ident(object)operator(.)ident(update_attributes)operator(()ident(attributes)operator(\)) + ident(object) + reserved(end) + reserved(end) + + comment(# Deletes the record with the given +id+ without instantiating an object first. If an array of ids is provided, all of them) + comment(# are deleted.) + reserved(def) method(delete)operator(()ident(id)operator(\)) + ident(delete_all)operator(()operator([) string<delimiter(")inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( IN (?\))delimiter(")>operator(,) ident(id) operator(])operator(\)) + reserved(end) + + comment(# Destroys the record with the given +id+ by instantiating the object and calling #destroy (all the callbacks are the triggered\).) + comment(# If an array of ids is provided, all of them are destroyed.) + reserved(def) method(destroy)operator(()ident(id)operator(\)) + ident(id)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(?) ident(id)operator(.)ident(each) operator({) operator(|)ident(id)operator(|) ident(destroy)operator(()ident(id)operator(\)) operator(}) operator(:) ident(find)operator(()ident(id)operator(\))operator(.)ident(destroy) + reserved(end) + + comment(# Updates all records with the SET-part of an SQL update statement in +updates+ and returns an integer with the number of rows updated.) + comment(# A subset of the records can be selected by specifying +conditions+. Example:) + comment(# Billing.update_all "category = 'authorized', approved = 1", "author = 'David'") + reserved(def) method(update_all)operator(()ident(updates)operator(,) ident(conditions) operator(=) pre_constant(nil)operator(\)) + ident(sql) operator(=) string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( SET )inline<inline_delimiter(#{)ident(sanitize_sql)operator(()ident(updates)operator(\))inline_delimiter(})>content( )delimiter(")> + ident(add_conditions!)operator(()ident(sql)operator(,) ident(conditions)operator(,) ident(scope)operator(()symbol(:find)operator(\))operator(\)) + ident(connection)operator(.)ident(update)operator(()ident(sql)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Update)delimiter(")>operator(\)) + reserved(end) + + comment(# Destroys the objects for all the records that match the +condition+ by instantiating each object and calling) + comment(# the destroy method. Example:) + comment(# Person.destroy_all "last_login < '2004-04-04'") + reserved(def) method(destroy_all)operator(()ident(conditions) operator(=) pre_constant(nil)operator(\)) + ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) ident(conditions)operator(\))operator(.)ident(each) operator({) operator(|)ident(object)operator(|) ident(object)operator(.)ident(destroy) operator(}) + reserved(end) + + comment(# Deletes all the records that match the +condition+ without instantiating the objects first (and hence not) + comment(# calling the destroy method\). Example:) + comment(# Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else'\)") + reserved(def) method(delete_all)operator(()ident(conditions) operator(=) pre_constant(nil)operator(\)) + ident(sql) operator(=) string<delimiter(")content(DELETE FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )delimiter(")> + ident(add_conditions!)operator(()ident(sql)operator(,) ident(conditions)operator(,) ident(scope)operator(()symbol(:find)operator(\))operator(\)) + ident(connection)operator(.)ident(delete)operator(()ident(sql)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Delete all)delimiter(")>operator(\)) + reserved(end) + + comment(# Returns the result of an SQL statement that should only include a COUNT(*\) in the SELECT part.) + comment(# Product.count_by_sql "SELECT COUNT(*\) FROM sales s, customers c WHERE s.customer_id = c.id") + reserved(def) method(count_by_sql)operator(()ident(sql)operator(\)) + ident(sql) operator(=) ident(sanitize_conditions)operator(()ident(sql)operator(\)) + ident(connection)operator(.)ident(select_value)operator(()ident(sql)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Count)delimiter(")>operator(\))operator(.)ident(to_i) + reserved(end) + + comment(# Increments the specified counter by one. So <tt>DiscussionBoard.increment_counter("post_count",) + comment(# discussion_board_id\)</tt> would increment the "post_count" counter on the board responding to discussion_board_id.) + comment(# This is used for caching aggregate values, so that they don't need to be computed every time. Especially important) + comment(# for looping over a collection where each element require a number of aggregate values. Like the DiscussionBoard) + comment(# that needs to list both the number of posts and comments.) + reserved(def) method(increment_counter)operator(()ident(counter_name)operator(,) ident(id)operator(\)) + ident(update_all) string<delimiter(")inline<inline_delimiter(#{)ident(counter_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(counter_name)inline_delimiter(})>content( + 1)delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quote)operator(()ident(id)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Works like increment_counter, but decrements instead.) + reserved(def) method(decrement_counter)operator(()ident(counter_name)operator(,) ident(id)operator(\)) + ident(update_all) string<delimiter(")inline<inline_delimiter(#{)ident(counter_name)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(counter_name)inline_delimiter(})>content( - 1)delimiter(")>operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quote)operator(()ident(id)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + + comment(# Attributes named in this macro are protected from mass-assignment, such as <tt>new(attributes\)</tt> and) + comment(# <tt>attributes=(attributes\)</tt>. Their assignment will simply be ignored. Instead, you can use the direct writer) + comment(# methods to do assignment. This is meant to protect sensitive attributes from being overwritten by URL/form hackers. Example:) + comment(#) + comment(# class Customer < ActiveRecord::Base) + comment(# attr_protected :credit_rating) + comment(# end) + comment(#) + comment(# customer = Customer.new("name" => David, "credit_rating" => "Excellent"\)) + comment(# customer.credit_rating # => nil) + comment(# customer.attributes = { "description" => "Jolly fellow", "credit_rating" => "Superb" }) + comment(# customer.credit_rating # => nil) + comment(#) + comment(# customer.credit_rating = "Average") + comment(# customer.credit_rating # => "Average") + reserved(def) method(attr_protected)operator(()operator(*)ident(attributes)operator(\)) + ident(write_inheritable_array)operator(()string<delimiter(")content(attr_protected)delimiter(")>operator(,) ident(attributes) operator(-) operator(()ident(protected_attributes) operator(||) operator([)operator(])operator(\))operator(\)) + reserved(end) + + comment(# Returns an array of all the attributes that have been protected from mass-assignment.) + reserved(def) method(protected_attributes) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(attr_protected)delimiter(")>operator(\)) + reserved(end) + + comment(# If this macro is used, only those attributes named in it will be accessible for mass-assignment, such as) + comment(# <tt>new(attributes\)</tt> and <tt>attributes=(attributes\)</tt>. This is the more conservative choice for mass-assignment) + comment(# protection. If you'd rather start from an all-open default and restrict attributes as needed, have a look at) + comment(# attr_protected.) + reserved(def) method(attr_accessible)operator(()operator(*)ident(attributes)operator(\)) + ident(write_inheritable_array)operator(()string<delimiter(")content(attr_accessible)delimiter(")>operator(,) ident(attributes) operator(-) operator(()ident(accessible_attributes) operator(||) operator([)operator(])operator(\))operator(\)) + reserved(end) + + comment(# Returns an array of all the attributes that have been made accessible to mass-assignment.) + reserved(def) method(accessible_attributes) comment(# :nodoc:) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(attr_accessible)delimiter(")>operator(\)) + reserved(end) + + + comment(# Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized) + comment(# after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized) + comment(# object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised.) + reserved(def) method(serialize)operator(()ident(attr_name)operator(,) ident(class_name) operator(=) constant(Object)operator(\)) + ident(serialized_attributes)operator([)ident(attr_name)operator(.)ident(to_s)operator(]) operator(=) ident(class_name) + reserved(end) + + comment(# Returns a hash of all the attributes that have been specified for serialization as keys and their class restriction as values.) + reserved(def) method(serialized_attributes) + ident(read_inheritable_attribute)operator(()string<delimiter(")content(attr_serialized)delimiter(")>operator(\)) reserved(or) ident(write_inheritable_attribute)operator(()string<delimiter(")content(attr_serialized)delimiter(")>operator(,) operator({)operator(})operator(\)) + reserved(end) + + + comment(# Guesses the table name (in forced lower-case\) based on the name of the class in the inheritance hierarchy descending) + comment(# directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used) + comment(# to guess the table name from even when called on Reply. The rules used to do the guess are handled by the Inflector class) + comment(# in Active Support, which knows almost all common English inflections (report a bug if your inflection isn't covered\).) + comment(#) + comment(# Additionally, the class-level table_name_prefix is prepended to the table_name and the table_name_suffix is appended.) + comment(# So if you have "myapp_" as a prefix, the table name guess for an Account class becomes "myapp_accounts".) + comment(#) + comment(# You can also overwrite this class method to allow for unguessable links, such as a Mouse class with a link to a) + comment(# "mice" table. Example:) + comment(#) + comment(# class Mouse < ActiveRecord::Base) + comment(# set_table_name "mice") + comment(# end) + reserved(def) method(table_name) + ident(reset_table_name) + reserved(end) + + reserved(def) method(reset_table_name) comment(#:nodoc:) + ident(name) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(table_name_prefix)inline_delimiter(})>inline<inline_delimiter(#{)ident(undecorated_table_name)operator(()ident(base_class)operator(.)ident(name)operator(\))inline_delimiter(})>inline<inline_delimiter(#{)ident(table_name_suffix)inline_delimiter(})>delimiter(")> + ident(set_table_name)operator(()ident(name)operator(\)) + ident(name) + reserved(end) + + comment(# Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the) + comment(# primary_key_prefix_type setting, though.) + reserved(def) method(primary_key) + ident(reset_primary_key) + reserved(end) + + reserved(def) method(reset_primary_key) comment(#:nodoc:) + ident(key) operator(=) string<delimiter(')content(id)delimiter(')> + reserved(case) ident(primary_key_prefix_type) + reserved(when) symbol(:table_name) + ident(key) operator(=) constant(Inflector)operator(.)ident(foreign_key)operator(()ident(base_class)operator(.)ident(name)operator(,) pre_constant(false)operator(\)) + reserved(when) symbol(:table_name_with_underscore) + ident(key) operator(=) constant(Inflector)operator(.)ident(foreign_key)operator(()ident(base_class)operator(.)ident(name)operator(\)) + reserved(end) + ident(set_primary_key)operator(()ident(key)operator(\)) + ident(key) + reserved(end) + + comment(# Defines the column name for use with single table inheritance -- can be overridden in subclasses.) + reserved(def) method(inheritance_column) + string<delimiter(")content(type)delimiter(")> + reserved(end) + + comment(# Lazy-set the sequence name to the connection's default. This method) + comment(# is only ever called once since set_sequence_name overrides it.) + reserved(def) method(sequence_name) comment(#:nodoc:) + ident(reset_sequence_name) + reserved(end) + + reserved(def) method(reset_sequence_name) comment(#:nodoc:) + ident(default) operator(=) ident(connection)operator(.)ident(default_sequence_name)operator(()ident(table_name)operator(,) ident(primary_key)operator(\)) + ident(set_sequence_name)operator(()ident(default)operator(\)) + ident(default) + reserved(end) + + comment(# Sets the table name to use to the given value, or (if the value) + comment(# is nil or false\) to the value returned by the given block.) + comment(#) + comment(# Example:) + comment(#) + comment(# class Project < ActiveRecord::Base) + comment(# set_table_name "project") + comment(# end) + reserved(def) method(set_table_name)operator(()ident(value) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(define_attr_method) symbol(:table_name)operator(,) ident(value)operator(,) operator(&)ident(block) + reserved(end) + reserved(alias) symbol(:table_name=) symbol(:set_table_name) + + comment(# Sets the name of the primary key column to use to the given value,) + comment(# or (if the value is nil or false\) to the value returned by the given) + comment(# block.) + comment(#) + comment(# Example:) + comment(#) + comment(# class Project < ActiveRecord::Base) + comment(# set_primary_key "sysid") + comment(# end) + reserved(def) method(set_primary_key)operator(()ident(value) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(define_attr_method) symbol(:primary_key)operator(,) ident(value)operator(,) operator(&)ident(block) + reserved(end) + reserved(alias) symbol(:primary_key=) symbol(:set_primary_key) + + comment(# Sets the name of the inheritance column to use to the given value,) + comment(# or (if the value # is nil or false\) to the value returned by the) + comment(# given block.) + comment(#) + comment(# Example:) + comment(#) + comment(# class Project < ActiveRecord::Base) + comment(# set_inheritance_column do) + comment(# original_inheritance_column + "_id") + comment(# end) + comment(# end) + reserved(def) method(set_inheritance_column)operator(()ident(value) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(define_attr_method) symbol(:inheritance_column)operator(,) ident(value)operator(,) operator(&)ident(block) + reserved(end) + reserved(alias) symbol(:inheritance_column=) symbol(:set_inheritance_column) + + comment(# Sets the name of the sequence to use when generating ids to the given) + comment(# value, or (if the value is nil or false\) to the value returned by the) + comment(# given block. This is required for Oracle and is useful for any) + comment(# database which relies on sequences for primary key generation.) + comment(#) + comment(# If a sequence name is not explicitly set when using Oracle or Firebird,) + comment(# it will default to the commonly used pattern of: #{table_name}_seq) + comment(#) + comment(# If a sequence name is not explicitly set when using PostgreSQL, it) + comment(# will discover the sequence corresponding to your primary key for you.) + comment(#) + comment(# Example:) + comment(#) + comment(# class Project < ActiveRecord::Base) + comment(# set_sequence_name "projectseq" # default would have been "project_seq") + comment(# end) + reserved(def) method(set_sequence_name)operator(()ident(value) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(define_attr_method) symbol(:sequence_name)operator(,) ident(value)operator(,) operator(&)ident(block) + reserved(end) + reserved(alias) symbol(:sequence_name=) symbol(:set_sequence_name) + + comment(# Turns the +table_name+ back into a class name following the reverse rules of +table_name+.) + reserved(def) method(class_name)operator(()ident(table_name) operator(=) ident(table_name)operator(\)) comment(# :nodoc:) + comment(# remove any prefix and/or suffix from the table name) + ident(class_name) operator(=) ident(table_name)operator([)ident(table_name_prefix)operator(.)ident(length)operator(..)operator(-)operator(()ident(table_name_suffix)operator(.)ident(length) operator(+) integer(1)operator(\))operator(])operator(.)ident(camelize) + ident(class_name) operator(=) ident(class_name)operator(.)ident(singularize) reserved(if) ident(pluralize_table_names) + ident(class_name) + reserved(end) + + comment(# Indicates whether the table associated with this class exists) + reserved(def) method(table_exists?) + reserved(if) ident(connection)operator(.)ident(respond_to?)operator(()symbol(:tables)operator(\)) + ident(connection)operator(.)ident(tables)operator(.)ident(include?) ident(table_name) + reserved(else) + comment(# if the connection adapter hasn't implemented tables, there are two crude tests that can be) + comment(# used - see if getting column info raises an error, or if the number of columns returned is zero) + reserved(begin) + ident(reset_column_information) + ident(columns)operator(.)ident(size) operator(>) integer(0) + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) + pre_constant(false) + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns an array of column objects for the table associated with this class.) + reserved(def) method(columns) + reserved(unless) instance_variable(@columns) + instance_variable(@columns) operator(=) ident(connection)operator(.)ident(columns)operator(()ident(table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Columns)delimiter(")>operator(\)) + instance_variable(@columns)operator(.)ident(each) operator({)operator(|)ident(column)operator(|) ident(column)operator(.)ident(primary) operator(=) ident(column)operator(.)ident(name) operator(==) ident(primary_key)operator(}) + reserved(end) + instance_variable(@columns) + reserved(end) + + comment(# Returns an array of column objects for the table associated with this class.) + reserved(def) method(columns_hash) + instance_variable(@columns_hash) operator(||=) ident(columns)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(hash)operator(,) ident(column)operator(|) ident(hash)operator([)ident(column)operator(.)ident(name)operator(]) operator(=) ident(column)operator(;) ident(hash) operator(}) + reserved(end) + + comment(# Returns an array of column names as strings.) + reserved(def) method(column_names) + instance_variable(@column_names) operator(||=) ident(columns)operator(.)ident(map) operator({) operator(|)ident(column)operator(|) ident(column)operator(.)ident(name) operator(}) + reserved(end) + + comment(# Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",) + comment(# and columns used for single table inheritance have been removed.) + reserved(def) method(content_columns) + instance_variable(@content_columns) operator(||=) ident(columns)operator(.)ident(reject) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(primary) operator(||) ident(c)operator(.)ident(name) operator(=)operator(~) regexp<delimiter(/)content((_id|_count\)$)delimiter(/)> operator(||) ident(c)operator(.)ident(name) operator(==) ident(inheritance_column) operator(}) + reserved(end) + + comment(# Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key) + comment(# and true as the value. This makes it possible to do O(1\) lookups in respond_to? to check if a given method for attribute) + comment(# is available.) + reserved(def) method(column_methods_hash) comment(#:nodoc:) + instance_variable(@dynamic_methods_hash) operator(||=) ident(column_names)operator(.)ident(inject)operator(()constant(Hash)operator(.)ident(new)operator(()pre_constant(false)operator(\))operator(\)) reserved(do) operator(|)ident(methods)operator(,) ident(attr)operator(|) + ident(attr_name) operator(=) ident(attr)operator(.)ident(to_s) + ident(methods)operator([)ident(attr)operator(.)ident(to_sym)operator(]) operator(=) ident(attr_name) + ident(methods)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(attr)inline_delimiter(})>content(=)delimiter(")>operator(.)ident(to_sym)operator(]) operator(=) ident(attr_name) + ident(methods)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(attr)inline_delimiter(})>content(?)delimiter(")>operator(.)ident(to_sym)operator(]) operator(=) ident(attr_name) + ident(methods)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(attr)inline_delimiter(})>content(_before_type_cast)delimiter(")>operator(.)ident(to_sym)operator(]) operator(=) ident(attr_name) + ident(methods) + reserved(end) + reserved(end) + + comment(# Contains the names of the generated reader methods.) + reserved(def) method(read_methods) comment(#:nodoc:) + instance_variable(@read_methods) operator(||=) constant(Set)operator(.)ident(new) + reserved(end) + + comment(# Resets all the cached information about columns, which will cause them to be reloaded on the next request.) + reserved(def) method(reset_column_information) + ident(read_methods)operator(.)ident(each) operator({) operator(|)ident(name)operator(|) ident(undef_method)operator(()ident(name)operator(\)) operator(}) + instance_variable(@column_names) operator(=) instance_variable(@columns) operator(=) instance_variable(@columns_hash) operator(=) instance_variable(@content_columns) operator(=) instance_variable(@dynamic_methods_hash) operator(=) instance_variable(@read_methods) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(reset_column_information_and_inheritable_attributes_for_all_subclasses)comment(#:nodoc:) + ident(subclasses)operator(.)ident(each) operator({) operator(|)ident(klass)operator(|) ident(klass)operator(.)ident(reset_inheritable_attributes)operator(;) ident(klass)operator(.)ident(reset_column_information) operator(}) + reserved(end) + + comment(# Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example:) + comment(# Person.human_attribute_name("first_name"\) # => "First name") + comment(# Deprecated in favor of just calling "first_name".humanize) + reserved(def) method(human_attribute_name)operator(()ident(attribute_key_name)operator(\)) comment(#:nodoc:) + ident(attribute_key_name)operator(.)ident(humanize) + reserved(end) + + reserved(def) method(descends_from_active_record?) comment(# :nodoc:) + ident(superclass) operator(==) constant(Base) operator(||) operator(!)ident(columns_hash)operator(.)ident(include?)operator(()ident(inheritance_column)operator(\)) + reserved(end) + + reserved(def) method(quote)operator(()ident(object)operator(\)) comment(#:nodoc:) + ident(connection)operator(.)ident(quote)operator(()ident(object)operator(\)) + reserved(end) + + comment(# Used to sanitize objects before they're used in an SELECT SQL-statement. Delegates to <tt>connection.quote</tt>.) + reserved(def) method(sanitize)operator(()ident(object)operator(\)) comment(#:nodoc:) + ident(connection)operator(.)ident(quote)operator(()ident(object)operator(\)) + reserved(end) + + comment(# Log and benchmark multiple statements in a single block. Example:) + comment(#) + comment(# Project.benchmark("Creating project"\) do) + comment(# project = Project.create("name" => "stuff"\)) + comment(# project.create_manager("name" => "David"\)) + comment(# project.milestones << Milestone.find(:all\)) + comment(# end) + comment(#) + comment(# The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it) + comment(# easy to include benchmarking statements in production software that will remain inexpensive because the benchmark) + comment(# will only be conducted if the log level is low enough.) + comment(#) + comment(# The logging of the multiple statements is turned off unless <tt>use_silence</tt> is set to false.) + reserved(def) method(benchmark)operator(()ident(title)operator(,) ident(log_level) operator(=) constant(Logger)operator(::)constant(DEBUG)operator(,) ident(use_silence) operator(=) pre_constant(true)operator(\)) + reserved(if) ident(logger) operator(&&) ident(logger)operator(.)ident(level) operator(==) ident(log_level) + ident(result) operator(=) pre_constant(nil) + ident(seconds) operator(=) constant(Benchmark)operator(.)ident(realtime) operator({) ident(result) operator(=) ident(use_silence) operator(?) ident(silence) operator({) reserved(yield) operator(}) operator(:) reserved(yield) operator(}) + ident(logger)operator(.)ident(add)operator(()ident(log_level)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(title)inline_delimiter(})>content( ()inline<inline_delimiter(#{)string<delimiter(')content(%.5f)delimiter(')> operator(%) ident(seconds)inline_delimiter(})>content(\))delimiter(")>operator(\)) + ident(result) + reserved(else) + reserved(yield) + reserved(end) + reserved(end) + + comment(# Silences the logger for the duration of the block.) + reserved(def) method(silence) + ident(old_logger_level)operator(,) ident(logger)operator(.)ident(level) operator(=) ident(logger)operator(.)ident(level)operator(,) constant(Logger)operator(::)constant(ERROR) reserved(if) ident(logger) + reserved(yield) + reserved(ensure) + ident(logger)operator(.)ident(level) operator(=) ident(old_logger_level) reserved(if) ident(logger) + reserved(end) + + comment(# Scope parameters to method calls within the block. Takes a hash of method_name => parameters hash.) + comment(# method_name may be :find or :create. :find parameters may include the <tt>:conditions</tt>, <tt>:joins</tt>,) + comment(# <tt>:include</tt>, <tt>:offset</tt>, <tt>:limit</tt>, and <tt>:readonly</tt> options. :create parameters are an attributes hash.) + comment(#) + comment(# Article.with_scope(:find => { :conditions => "blog_id = 1" }, :create => { :blog_id => 1 }\) do) + comment(# Article.find(1\) # => SELECT * from articles WHERE blog_id = 1 AND id = 1) + comment(# a = Article.create(1\)) + comment(# a.blog_id # => 1) + comment(# end) + comment(#) + comment(# In nested scopings, all previous parameters are overwritten by inner rule) + comment(# except :conditions in :find, that are merged as hash.) + comment(#) + comment(# Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }\) do) + comment(# Article.with_scope(:find => { :limit => 10}\)) + comment(# Article.find(:all\) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10) + comment(# end) + comment(# Article.with_scope(:find => { :conditions => "author_id = 3" }\)) + comment(# Article.find(:all\) # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1) + comment(# end) + comment(# end) + comment(#) + comment(# You can ignore any previous scopings by using <tt>with_exclusive_scope</tt> method.) + comment(#) + comment(# Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }\) do) + comment(# Article.with_exclusive_scope(:find => { :limit => 10 }\)) + comment(# Article.find(:all\) # => SELECT * from articles LIMIT 10) + comment(# end) + comment(# end) + reserved(def) method(with_scope)operator(()ident(method_scoping) operator(=) operator({)operator(})operator(,) ident(action) operator(=) symbol(:merge)operator(,) operator(&)ident(block)operator(\)) + ident(method_scoping) operator(=) ident(method_scoping)operator(.)ident(method_scoping) reserved(if) ident(method_scoping)operator(.)ident(respond_to?)operator(()symbol(:method_scoping)operator(\)) + + comment(# Dup first and second level of hash (method and params\).) + ident(method_scoping) operator(=) ident(method_scoping)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(hash)operator(,) operator(()ident(method)operator(,) ident(params)operator(\))operator(|) + ident(hash)operator([)ident(method)operator(]) operator(=) operator(()ident(params) operator(==) pre_constant(true)operator(\)) operator(?) ident(params) operator(:) ident(params)operator(.)ident(dup) + ident(hash) + reserved(end) + + ident(method_scoping)operator(.)ident(assert_valid_keys)operator(()operator([) symbol(:find)operator(,) symbol(:create) operator(])operator(\)) + + reserved(if) ident(f) operator(=) ident(method_scoping)operator([)symbol(:find)operator(]) + ident(f)operator(.)ident(assert_valid_keys)operator(()operator([) symbol(:conditions)operator(,) symbol(:joins)operator(,) symbol(:select)operator(,) symbol(:include)operator(,) symbol(:from)operator(,) symbol(:offset)operator(,) symbol(:limit)operator(,) symbol(:readonly) operator(])operator(\)) + ident(f)operator([)symbol(:readonly)operator(]) operator(=) pre_constant(true) reserved(if) operator(!)ident(f)operator([)symbol(:joins)operator(])operator(.)ident(blank?) operator(&&) operator(!)ident(f)operator(.)ident(has_key?)operator(()symbol(:readonly)operator(\)) + reserved(end) + + comment(# Merge scopings) + reserved(if) ident(action) operator(==) symbol(:merge) operator(&&) ident(current_scoped_methods) + ident(method_scoping) operator(=) ident(current_scoped_methods)operator(.)ident(inject)operator(()ident(method_scoping)operator(\)) reserved(do) operator(|)ident(hash)operator(,) operator(()ident(method)operator(,) ident(params)operator(\))operator(|) + reserved(case) ident(hash)operator([)ident(method)operator(]) + reserved(when) constant(Hash) + reserved(if) ident(method) operator(==) symbol(:find) + operator(()ident(hash)operator([)ident(method)operator(])operator(.)ident(keys) operator(+) ident(params)operator(.)ident(keys)operator(\))operator(.)ident(uniq)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + ident(merge) operator(=) ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(]) operator(&&) ident(params)operator([)ident(key)operator(]) comment(# merge if both scopes have the same key) + reserved(if) ident(key) operator(==) symbol(:conditions) operator(&&) ident(merge) + ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(]) operator(=) operator([)ident(params)operator([)ident(key)operator(])operator(,) ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(])operator(])operator(.)ident(collect)operator({) operator(|)ident(sql)operator(|) string<delimiter(")content(( %s \))delimiter(")> operator(%) ident(sanitize_sql)operator(()ident(sql)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content( AND )delimiter(")>operator(\)) + reserved(elsif) ident(key) operator(==) symbol(:include) operator(&&) ident(merge) + ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(]) operator(=) ident(merge_includes)operator(()ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(])operator(,) ident(params)operator([)ident(key)operator(])operator(\))operator(.)ident(uniq) + reserved(else) + ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(]) operator(=) ident(hash)operator([)ident(method)operator(])operator([)ident(key)operator(]) operator(||) ident(params)operator([)ident(key)operator(]) + reserved(end) + reserved(end) + reserved(else) + ident(hash)operator([)ident(method)operator(]) operator(=) ident(params)operator(.)ident(merge)operator(()ident(hash)operator([)ident(method)operator(])operator(\)) + reserved(end) + reserved(else) + ident(hash)operator([)ident(method)operator(]) operator(=) ident(params) + reserved(end) + ident(hash) + reserved(end) + reserved(end) + + pre_constant(self)operator(.)ident(scoped_methods) operator(<<) ident(method_scoping) + + reserved(begin) + reserved(yield) + reserved(ensure) + pre_constant(self)operator(.)ident(scoped_methods)operator(.)ident(pop) + reserved(end) + reserved(end) + + comment(# Works like with_scope, but discards any nested properties.) + reserved(def) method(with_exclusive_scope)operator(()ident(method_scoping) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + ident(with_scope)operator(()ident(method_scoping)operator(,) symbol(:overwrite)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + comment(# Overwrite the default class equality method to provide support for association proxies.) + reserved(def) method(===)operator(()ident(object)operator(\)) + ident(object)operator(.)ident(is_a?)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Deprecated ) + reserved(def) method(threaded_connections) comment(#:nodoc:) + ident(allow_concurrency) + reserved(end) + + comment(# Deprecated ) + reserved(def) method(threaded_connections=)operator(()ident(value)operator(\)) comment(#:nodoc:) + pre_constant(self)operator(.)ident(allow_concurrency) operator(=) ident(value) + reserved(end) + + comment(# Returns the base AR subclass that this class descends from. If A) + comment(# extends AR::Base, A.base_class will return A. If B descends from A) + comment(# through some arbitrarily deep hierarchy, B.base_class will return A.) + reserved(def) method(base_class) + ident(class_of_active_record_descendant)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Set this to true if this is an abstract class (see #abstract_class?\).) + ident(attr_accessor) symbol(:abstract_class) + + comment(# Returns whether this class is a base AR class. If A is a base class and) + comment(# B descends from A, then B.base_class will return B.) + reserved(def) method(abstract_class?) + ident(abstract_class) operator(==) pre_constant(true) + reserved(end) + + ident(private) + reserved(def) method(find_initial)operator(()ident(options)operator(\)) + ident(options)operator(.)ident(update)operator(()symbol(:limit) operator(=)operator(>) integer(1)operator(\)) reserved(unless) ident(options)operator([)symbol(:include)operator(]) + ident(find_every)operator(()ident(options)operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(find_every)operator(()ident(options)operator(\)) + ident(records) operator(=) ident(scoped?)operator(()symbol(:find)operator(,) symbol(:include)operator(\)) operator(||) ident(options)operator([)symbol(:include)operator(]) operator(?) + ident(find_with_associations)operator(()ident(options)operator(\)) operator(:) + ident(find_by_sql)operator(()ident(construct_finder_sql)operator(()ident(options)operator(\))operator(\)) + + ident(records)operator(.)ident(each) operator({) operator(|)ident(record)operator(|) ident(record)operator(.)ident(readonly!) operator(}) reserved(if) ident(options)operator([)symbol(:readonly)operator(]) + + ident(records) + reserved(end) + + reserved(def) method(find_from_ids)operator(()ident(ids)operator(,) ident(options)operator(\)) + ident(expects_array) operator(=) ident(ids)operator(.)ident(first)operator(.)ident(kind_of?)operator(()constant(Array)operator(\)) + reserved(return) ident(ids)operator(.)ident(first) reserved(if) ident(expects_array) operator(&&) ident(ids)operator(.)ident(first)operator(.)ident(empty?) + + ident(ids) operator(=) ident(ids)operator(.)ident(flatten)operator(.)ident(compact)operator(.)ident(uniq) + + reserved(case) ident(ids)operator(.)ident(size) + reserved(when) integer(0) + ident(raise) constant(RecordNotFound)operator(,) string<delimiter(")content(Couldn't find )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( without an ID)delimiter(")> + reserved(when) integer(1) + ident(result) operator(=) ident(find_one)operator(()ident(ids)operator(.)ident(first)operator(,) ident(options)operator(\)) + ident(expects_array) operator(?) operator([) ident(result) operator(]) operator(:) ident(result) + reserved(else) + ident(find_some)operator(()ident(ids)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(find_one)operator(()ident(id)operator(,) ident(options)operator(\)) + ident(conditions) operator(=) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitize_sql)operator(()ident(options)operator([)symbol(:conditions)operator(])operator(\))inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(options)operator([)symbol(:conditions)operator(]) + ident(options)operator(.)ident(update) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(sanitize)operator(()ident(id)operator(\))inline_delimiter(})>inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>delimiter(")> + + reserved(if) ident(result) operator(=) ident(find_initial)operator(()ident(options)operator(\)) + ident(result) + reserved(else) + ident(raise) constant(RecordNotFound)operator(,) string<delimiter(")content(Couldn't find )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( with ID=)inline<inline_delimiter(#{)ident(id)inline_delimiter(})>inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(find_some)operator(()ident(ids)operator(,) ident(options)operator(\)) + ident(conditions) operator(=) string<delimiter(")content( AND ()inline<inline_delimiter(#{)ident(sanitize_sql)operator(()ident(options)operator([)symbol(:conditions)operator(])operator(\))inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(options)operator([)symbol(:conditions)operator(]) + ident(ids_list) operator(=) ident(ids)operator(.)ident(map) operator({) operator(|)ident(id)operator(|) ident(sanitize)operator(()ident(id)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + ident(options)operator(.)ident(update) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>content( IN ()inline<inline_delimiter(#{)ident(ids_list)inline_delimiter(})>content(\))inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>delimiter(")> + + ident(result) operator(=) ident(find_every)operator(()ident(options)operator(\)) + + reserved(if) ident(result)operator(.)ident(size) operator(==) ident(ids)operator(.)ident(size) + ident(result) + reserved(else) + ident(raise) constant(RecordNotFound)operator(,) string<delimiter(")content(Couldn't find all )inline<inline_delimiter(#{)ident(name)operator(.)ident(pluralize)inline_delimiter(})>content( with IDs ()inline<inline_delimiter(#{)ident(ids_list)inline_delimiter(})>content(\))inline<inline_delimiter(#{)ident(conditions)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# Finder methods must instantiate through this method to work with the single-table inheritance model) + comment(# that makes it possible to create objects of different types from the same table.) + reserved(def) method(instantiate)operator(()ident(record)operator(\)) + ident(object) operator(=) + reserved(if) ident(subclass_name) operator(=) ident(record)operator([)ident(inheritance_column)operator(]) + reserved(if) ident(subclass_name)operator(.)ident(empty?) + ident(allocate) + reserved(else) + ident(require_association_class)operator(()ident(subclass_name)operator(\)) + reserved(begin) + ident(compute_type)operator(()ident(subclass_name)operator(\))operator(.)ident(allocate) + reserved(rescue) constant(NameError) + ident(raise) constant(SubclassNotFound)operator(,) + string<delimiter(")content(The single-table inheritance mechanism failed to locate the subclass: ')inline<inline_delimiter(#{)ident(record)operator([)ident(inheritance_column)operator(])inline_delimiter(})>content('. )delimiter(")> operator(+) + string<delimiter(")content(This error is raised because the column ')inline<inline_delimiter(#{)ident(inheritance_column)inline_delimiter(})>content(' is reserved for storing the class in case of inheritance. )delimiter(")> operator(+) + string<delimiter(")content(Please rename this column if you didn't intend it to be used for storing the inheritance class )delimiter(")> operator(+) + string<delimiter(")content(or overwrite )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(to_s)inline_delimiter(})>content(.inheritance_column to use another column for that information.)delimiter(")> + reserved(end) + reserved(end) + reserved(else) + ident(allocate) + reserved(end) + + ident(object)operator(.)ident(instance_variable_set)operator(()string<delimiter(")content(@attributes)delimiter(")>operator(,) ident(record)operator(\)) + ident(object) + reserved(end) + + comment(# Nest the type name in the same module as this class.) + comment(# Bar is "MyApp::Business::Bar" relative to MyApp::Business::Foo) + reserved(def) method(type_name_with_module)operator(()ident(type_name)operator(\)) + operator(()regexp<delimiter(/)content(^::)delimiter(/)> operator(=)operator(~) ident(type_name)operator(\)) operator(?) ident(type_name) operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(parent)operator(.)ident(name)inline_delimiter(})>content(::)inline<inline_delimiter(#{)ident(type_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(construct_finder_sql)operator(()ident(options)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) + ident(sql) operator(=) string<delimiter(")content(SELECT )inline<inline_delimiter(#{)operator(()ident(scope) operator(&&) ident(scope)operator([)symbol(:select)operator(])operator(\)) operator(||) ident(options)operator([)symbol(:select)operator(]) operator(||) string<delimiter(')content(*)delimiter(')>inline_delimiter(})>content( )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(FROM )inline<inline_delimiter(#{)operator(()ident(scope) operator(&&) ident(scope)operator([)symbol(:from)operator(])operator(\)) operator(||) ident(options)operator([)symbol(:from)operator(]) operator(||) ident(table_name)inline_delimiter(})>content( )delimiter(")> + + ident(add_joins!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + ident(add_conditions!)operator(()ident(sql)operator(,) ident(options)operator([)symbol(:conditions)operator(])operator(,) ident(scope)operator(\)) + + ident(sql) operator(<<) string<delimiter(")content( GROUP BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:group)operator(])inline_delimiter(})>content( )delimiter(")> reserved(if) ident(options)operator([)symbol(:group)operator(]) + ident(sql) operator(<<) string<delimiter(")content( ORDER BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>content( )delimiter(")> reserved(if) ident(options)operator([)symbol(:order)operator(]) + + ident(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + + ident(sql) + reserved(end) + + comment(# Merges includes so that the result is a valid +include+) + reserved(def) method(merge_includes)operator(()ident(first)operator(,) ident(second)operator(\)) + ident(safe_to_array)operator(()ident(first)operator(\)) operator(+) ident(safe_to_array)operator(()ident(second)operator(\)) + reserved(end) + + comment(# Object#to_a is deprecated, though it does have the desired behaviour) + reserved(def) method(safe_to_array)operator(()ident(o)operator(\)) + reserved(case) ident(o) + reserved(when) constant(NilClass) + operator([)operator(]) + reserved(when) constant(Array) + ident(o) + reserved(else) + operator([)ident(o)operator(]) + reserved(end) + reserved(end) + + comment(# The optional scope argument is for the current :find scope.) + reserved(def) method(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope) operator(=) symbol(:auto)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) reserved(if) symbol(:auto) operator(==) ident(scope) + reserved(if) ident(scope) + ident(options)operator([)symbol(:limit)operator(]) operator(||=) ident(scope)operator([)symbol(:limit)operator(]) + ident(options)operator([)symbol(:offset)operator(]) operator(||=) ident(scope)operator([)symbol(:offset)operator(]) + reserved(end) + ident(connection)operator(.)ident(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# The optional scope argument is for the current :find scope.) + reserved(def) method(add_joins!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope) operator(=) symbol(:auto)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) reserved(if) symbol(:auto) operator(==) ident(scope) + ident(join) operator(=) operator(()ident(scope) operator(&&) ident(scope)operator([)symbol(:joins)operator(])operator(\)) operator(||) ident(options)operator([)symbol(:joins)operator(]) + ident(sql) operator(<<) string<delimiter(")content( )inline<inline_delimiter(#{)ident(join)inline_delimiter(})>content( )delimiter(")> reserved(if) ident(join) + reserved(end) + + comment(# Adds a sanitized version of +conditions+ to the +sql+ string. Note that the passed-in +sql+ string is changed.) + comment(# The optional scope argument is for the current :find scope.) + reserved(def) method(add_conditions!)operator(()ident(sql)operator(,) ident(conditions)operator(,) ident(scope) operator(=) symbol(:auto)operator(\)) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) reserved(if) symbol(:auto) operator(==) ident(scope) + ident(segments) operator(=) operator([)operator(]) + ident(segments) operator(<<) ident(sanitize_sql)operator(()ident(scope)operator([)symbol(:conditions)operator(])operator(\)) reserved(if) ident(scope) operator(&&) ident(scope)operator([)symbol(:conditions)operator(]) + ident(segments) operator(<<) ident(sanitize_sql)operator(()ident(conditions)operator(\)) reserved(unless) ident(conditions)operator(.)ident(nil?) + ident(segments) operator(<<) ident(type_condition) reserved(unless) ident(descends_from_active_record?) + ident(segments)operator(.)ident(compact!) + ident(sql) operator(<<) string<delimiter(")content(WHERE ()inline<inline_delimiter(#{)ident(segments)operator(.)ident(join)operator(()string<delimiter(")content(\) AND ()delimiter(")>operator(\))inline_delimiter(})>content(\) )delimiter(")> reserved(unless) ident(segments)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(type_condition) + ident(quoted_inheritance_column) operator(=) ident(connection)operator(.)ident(quote_column_name)operator(()ident(inheritance_column)operator(\)) + ident(type_condition) operator(=) ident(subclasses)operator(.)ident(inject)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(quoted_inheritance_column)inline_delimiter(})>content( = ')inline<inline_delimiter(#{)ident(name)operator(.)ident(demodulize)inline_delimiter(})>content(' )delimiter(")>operator(\)) reserved(do) operator(|)ident(condition)operator(,) ident(subclass)operator(|) + ident(condition) operator(<<) string<delimiter(")content(OR )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(quoted_inheritance_column)inline_delimiter(})>content( = ')inline<inline_delimiter(#{)ident(subclass)operator(.)ident(name)operator(.)ident(demodulize)inline_delimiter(})>content(' )delimiter(")> + reserved(end) + + string<delimiter(")content( ()inline<inline_delimiter(#{)ident(type_condition)inline_delimiter(})>content(\) )delimiter(")> + reserved(end) + + comment(# Guesses the table name, but does not decorate it with prefix and suffix information.) + reserved(def) method(undecorated_table_name)operator(()ident(class_name) operator(=) ident(base_class)operator(.)ident(name)operator(\)) + ident(table_name) operator(=) constant(Inflector)operator(.)ident(underscore)operator(()constant(Inflector)operator(.)ident(demodulize)operator(()ident(class_name)operator(\))operator(\)) + ident(table_name) operator(=) constant(Inflector)operator(.)ident(pluralize)operator(()ident(table_name)operator(\)) reserved(if) ident(pluralize_table_names) + ident(table_name) + reserved(end) + + comment(# Enables dynamic finders like find_by_user_name(user_name\) and find_by_user_name_and_password(user_name, password\) that are turned into) + comment(# find(:first, :conditions => ["user_name = ?", user_name]\) and find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password]\)) + comment(# respectively. Also works for find(:all\), but using find_all_by_amount(50\) that are turned into find(:all, :conditions => ["amount = ?", 50]\).) + comment(#) + comment(# It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount) + comment(# is actually find_all_by_amount(amount, options\).) + reserved(def) method(method_missing)operator(()ident(method_id)operator(,) operator(*)ident(arguments)operator(\)) + reserved(if) ident(match) operator(=) regexp<delimiter(/)content(find_(all_by|by\)_([_a-zA-Z])char(\\w)content(*\))delimiter(/)>operator(.)ident(match)operator(()ident(method_id)operator(.)ident(to_s)operator(\)) + ident(finder)operator(,) ident(deprecated_finder) operator(=) ident(determine_finder)operator(()ident(match)operator(\))operator(,) ident(determine_deprecated_finder)operator(()ident(match)operator(\)) + + ident(attribute_names) operator(=) ident(extract_attribute_names_from_match)operator(()ident(match)operator(\)) + reserved(super) reserved(unless) ident(all_attributes_exists?)operator(()ident(attribute_names)operator(\)) + + ident(conditions) operator(=) ident(construct_conditions_from_arguments)operator(()ident(attribute_names)operator(,) ident(arguments)operator(\)) + + reserved(case) ident(extra_options) operator(=) ident(arguments)operator([)ident(attribute_names)operator(.)ident(size)operator(]) + reserved(when) pre_constant(nil) + ident(options) operator(=) operator({) symbol(:conditions) operator(=)operator(>) ident(conditions) operator(}) + ident(set_readonly_option!)operator(()ident(options)operator(\)) + ident(send)operator(()ident(finder)operator(,) ident(options)operator(\)) + + reserved(when) constant(Hash) + ident(finder_options) operator(=) ident(extra_options)operator(.)ident(merge)operator(()symbol(:conditions) operator(=)operator(>) ident(conditions)operator(\)) + ident(validate_find_options)operator(()ident(finder_options)operator(\)) + ident(set_readonly_option!)operator(()ident(finder_options)operator(\)) + + reserved(if) ident(extra_options)operator([)symbol(:conditions)operator(]) + ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) ident(extra_options)operator([)symbol(:conditions)operator(]) operator(})operator(\)) reserved(do) + ident(send)operator(()ident(finder)operator(,) ident(finder_options)operator(\)) + reserved(end) + reserved(else) + ident(send)operator(()ident(finder)operator(,) ident(finder_options)operator(\)) + reserved(end) + + reserved(else) + ident(send)operator(()ident(deprecated_finder)operator(,) ident(conditions)operator(,) operator(*)ident(arguments)operator([)ident(attribute_names)operator(.)ident(length)operator(..)integer(-1)operator(])operator(\)) comment(# deprecated API) + reserved(end) + reserved(elsif) ident(match) operator(=) regexp<delimiter(/)content(find_or_create_by_([_a-zA-Z])char(\\w)content(*\))delimiter(/)>operator(.)ident(match)operator(()ident(method_id)operator(.)ident(to_s)operator(\)) + ident(attribute_names) operator(=) ident(extract_attribute_names_from_match)operator(()ident(match)operator(\)) + reserved(super) reserved(unless) ident(all_attributes_exists?)operator(()ident(attribute_names)operator(\)) + + ident(options) operator(=) operator({) symbol(:conditions) operator(=)operator(>) ident(construct_conditions_from_arguments)operator(()ident(attribute_names)operator(,) ident(arguments)operator(\)) operator(}) + ident(set_readonly_option!)operator(()ident(options)operator(\)) + ident(find_initial)operator(()ident(options)operator(\)) operator(||) ident(create)operator(()ident(construct_attributes_from_arguments)operator(()ident(attribute_names)operator(,) ident(arguments)operator(\))operator(\)) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(def) method(determine_finder)operator(()ident(match)operator(\)) + ident(match)operator(.)ident(captures)operator(.)ident(first) operator(==) string<delimiter(')content(all_by)delimiter(')> operator(?) symbol(:find_every) operator(:) symbol(:find_initial) + reserved(end) + + reserved(def) method(determine_deprecated_finder)operator(()ident(match)operator(\)) + ident(match)operator(.)ident(captures)operator(.)ident(first) operator(==) string<delimiter(')content(all_by)delimiter(')> operator(?) symbol(:find_all) operator(:) symbol(:find_first) + reserved(end) + + reserved(def) method(extract_attribute_names_from_match)operator(()ident(match)operator(\)) + ident(match)operator(.)ident(captures)operator(.)ident(last)operator(.)ident(split)operator(()string<delimiter(')content(_and_)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(construct_conditions_from_arguments)operator(()ident(attribute_names)operator(,) ident(arguments)operator(\)) + ident(conditions) operator(=) operator([)operator(]) + ident(attribute_names)operator(.)ident(each_with_index) operator({) operator(|)ident(name)operator(,) ident(idx)operator(|) ident(conditions) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(connection)operator(.)ident(quote_column_name)operator(()ident(name)operator(\))inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(attribute_condition)operator(()ident(arguments)operator([)ident(idx)operator(])operator(\))inline_delimiter(})>content( )delimiter(")> operator(}) + operator([) ident(conditions)operator(.)ident(join)operator(()string<delimiter(")content( AND )delimiter(")>operator(\))operator(,) operator(*)ident(arguments)operator([)integer(0)operator(...)ident(attribute_names)operator(.)ident(length)operator(]) operator(]) + reserved(end) + + reserved(def) method(construct_attributes_from_arguments)operator(()ident(attribute_names)operator(,) ident(arguments)operator(\)) + ident(attributes) operator(=) operator({)operator(}) + ident(attribute_names)operator(.)ident(each_with_index) operator({) operator(|)ident(name)operator(,) ident(idx)operator(|) ident(attributes)operator([)ident(name)operator(]) operator(=) ident(arguments)operator([)ident(idx)operator(]) operator(}) + ident(attributes) + reserved(end) + + reserved(def) method(all_attributes_exists?)operator(()ident(attribute_names)operator(\)) + ident(attribute_names)operator(.)ident(all?) operator({) operator(|)ident(name)operator(|) ident(column_methods_hash)operator(.)ident(include?)operator(()ident(name)operator(.)ident(to_sym)operator(\)) operator(}) + reserved(end) + + reserved(def) method(attribute_condition)operator(()ident(argument)operator(\)) + reserved(case) ident(argument) + reserved(when) pre_constant(nil) reserved(then) string<delimiter(")content(IS ?)delimiter(")> + reserved(when) constant(Array) reserved(then) string<delimiter(")content(IN (?\))delimiter(")> + reserved(else) string<delimiter(")content(= ?)delimiter(")> + reserved(end) + reserved(end) + + comment(# Defines an "attribute" method (like #inheritance_column or) + comment(# #table_name\). A new (class\) method will be created with the) + comment(# given name. If a value is specified, the new method will) + comment(# return that value (as a string\). Otherwise, the given block) + comment(# will be used to compute the value of the method.) + comment(#) + comment(# The original method will be aliased, with the new name being) + comment(# prefixed with "original_". This allows the new method to) + comment(# access the original value.) + comment(#) + comment(# Example:) + comment(#) + comment(# class A < ActiveRecord::Base) + comment(# define_attr_method :primary_key, "sysid") + comment(# define_attr_method( :inheritance_column \) do) + comment(# original_inheritance_column + "_id") + comment(# end) + comment(# end) + reserved(def) method(define_attr_method)operator(()ident(name)operator(,) ident(value)operator(=)pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(sing) operator(=) reserved(class) operator(<<) class(self)operator(;) pre_constant(self)operator(;) reserved(end) + ident(sing)operator(.)ident(send) symbol(:alias_method)operator(,) string<delimiter(")content(original_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(name) + reserved(if) ident(block_given?) + ident(sing)operator(.)ident(send) symbol(:define_method)operator(,) ident(name)operator(,) operator(&)ident(block) + reserved(else) + comment(# use eval instead of a block to work around a memory leak in dev) + comment(# mode in fcgi) + ident(sing)operator(.)ident(class_eval) string<delimiter(")content(def )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(; )inline<inline_delimiter(#{)ident(value)operator(.)ident(to_s)operator(.)ident(inspect)inline_delimiter(})>content(; end)delimiter(")> + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(subclasses) comment(#:nodoc:) + class_variable(@@subclasses)operator([)pre_constant(self)operator(]) operator(||=) operator([)operator(]) + class_variable(@@subclasses)operator([)pre_constant(self)operator(]) operator(+) ident(extra) operator(=) class_variable(@@subclasses)operator([)pre_constant(self)operator(])operator(.)ident(inject)operator(()operator([)operator(])operator(\)) operator({)operator(|)ident(list)operator(,) ident(subclass)operator(|) ident(list) operator(+) ident(subclass)operator(.)ident(subclasses) operator(}) + reserved(end) + + comment(# Test whether the given method and optional key are scoped.) + reserved(def) method(scoped?)operator(()ident(method)operator(,) ident(key) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + reserved(if) ident(current_scoped_methods) operator(&&) operator(()ident(scope) operator(=) ident(current_scoped_methods)operator([)ident(method)operator(])operator(\)) + operator(!)ident(key) operator(||) ident(scope)operator(.)ident(has_key?)operator(()ident(key)operator(\)) + reserved(end) + reserved(end) + + comment(# Retrieve the scope for the given method and optional key.) + reserved(def) method(scope)operator(()ident(method)operator(,) ident(key) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + reserved(if) ident(current_scoped_methods) operator(&&) operator(()ident(scope) operator(=) ident(current_scoped_methods)operator([)ident(method)operator(])operator(\)) + ident(key) operator(?) ident(scope)operator([)ident(key)operator(]) operator(:) ident(scope) + reserved(end) + reserved(end) + + reserved(def) method(thread_safe_scoped_methods) comment(#:nodoc:) + ident(scoped_methods) operator(=) operator(()constant(Thread)operator(.)ident(current)operator([)symbol(:scoped_methods)operator(]) operator(||=) operator({)operator(})operator(\)) + ident(scoped_methods)operator([)pre_constant(self)operator(]) operator(||=) operator([)operator(]) + reserved(end) + + reserved(def) method(single_threaded_scoped_methods) comment(#:nodoc:) + instance_variable(@scoped_methods) operator(||=) operator([)operator(]) + reserved(end) + + comment(# pick up the correct scoped_methods version from @@allow_concurrency) + reserved(if) class_variable(@@allow_concurrency) + ident(alias_method) symbol(:scoped_methods)operator(,) symbol(:thread_safe_scoped_methods) + reserved(else) + ident(alias_method) symbol(:scoped_methods)operator(,) symbol(:single_threaded_scoped_methods) + reserved(end) + + reserved(def) method(current_scoped_methods) comment(#:nodoc:) + ident(scoped_methods)operator(.)ident(last) + reserved(end) + + comment(# Returns the class type of the record using the current module as a prefix. So descendents of) + comment(# MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.) + reserved(def) method(compute_type)operator(()ident(type_name)operator(\)) + ident(modularized_name) operator(=) ident(type_name_with_module)operator(()ident(type_name)operator(\)) + reserved(begin) + ident(instance_eval)operator(()ident(modularized_name)operator(\)) + reserved(rescue) constant(NameError) operator(=)operator(>) ident(e) + ident(instance_eval)operator(()ident(type_name)operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the class descending directly from ActiveRecord in the inheritance hierarchy.) + reserved(def) method(class_of_active_record_descendant)operator(()ident(klass)operator(\)) + reserved(if) ident(klass)operator(.)ident(superclass) operator(==) constant(Base) operator(||) ident(klass)operator(.)ident(superclass)operator(.)ident(abstract_class?) + ident(klass) + reserved(elsif) ident(klass)operator(.)ident(superclass)operator(.)ident(nil?) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( doesn't belong in a hierarchy descending from ActiveRecord)delimiter(")> + reserved(else) + ident(class_of_active_record_descendant)operator(()ident(klass)operator(.)ident(superclass)operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the name of the class descending directly from ActiveRecord in the inheritance hierarchy.) + reserved(def) method(class_name_of_active_record_descendant)operator(()ident(klass)operator(\)) comment(#:nodoc:) + ident(klass)operator(.)ident(base_class)operator(.)ident(name) + reserved(end) + + comment(# Accepts an array or string. The string is returned untouched, but the array has each value) + comment(# sanitized and interpolated into the sql statement.) + comment(# ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'") + reserved(def) method(sanitize_sql)operator(()ident(ary)operator(\)) + reserved(return) ident(ary) reserved(unless) ident(ary)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + + ident(statement)operator(,) operator(*)ident(values) operator(=) ident(ary) + reserved(if) ident(values)operator(.)ident(first)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) reserved(and) ident(statement) operator(=)operator(~) regexp<delimiter(/)content(:)char(\\w)content(+)delimiter(/)> + ident(replace_named_bind_variables)operator(()ident(statement)operator(,) ident(values)operator(.)ident(first)operator(\)) + reserved(elsif) ident(statement)operator(.)ident(include?)operator(()string<delimiter(')content(?)delimiter(')>operator(\)) + ident(replace_bind_variables)operator(()ident(statement)operator(,) ident(values)operator(\)) + reserved(else) + ident(statement) operator(%) ident(values)operator(.)ident(collect) operator({) operator(|)ident(value)operator(|) ident(connection)operator(.)ident(quote_string)operator(()ident(value)operator(.)ident(to_s)operator(\)) operator(}) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:sanitize_conditions)operator(,) symbol(:sanitize_sql) + + reserved(def) method(replace_bind_variables)operator(()ident(statement)operator(,) ident(values)operator(\)) comment(#:nodoc:) + ident(raise_if_bind_arity_mismatch)operator(()ident(statement)operator(,) ident(statement)operator(.)ident(count)operator(()string<delimiter(')content(?)delimiter(')>operator(\))operator(,) ident(values)operator(.)ident(size)operator(\)) + ident(bound) operator(=) ident(values)operator(.)ident(dup) + ident(statement)operator(.)ident(gsub)operator(()string<delimiter(')content(?)delimiter(')>operator(\)) operator({) ident(quote_bound_value)operator(()ident(bound)operator(.)ident(shift)operator(\)) operator(}) + reserved(end) + + reserved(def) method(replace_named_bind_variables)operator(()ident(statement)operator(,) ident(bind_vars)operator(\)) comment(#:nodoc:) + ident(statement)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(:()char(\\w)content(+\))delimiter(/)>operator(\)) reserved(do) + ident(match) operator(=) global_variable($1)operator(.)ident(to_sym) + reserved(if) ident(bind_vars)operator(.)ident(include?)operator(()ident(match)operator(\)) + ident(quote_bound_value)operator(()ident(bind_vars)operator([)ident(match)operator(])operator(\)) + reserved(else) + ident(raise) constant(PreparedStatementInvalid)operator(,) string<delimiter(")content(missing value for :)inline<inline_delimiter(#{)ident(match)inline_delimiter(})>content( in )inline<inline_delimiter(#{)ident(statement)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(quote_bound_value)operator(()ident(value)operator(\)) comment(#:nodoc:) + reserved(if) operator(()ident(value)operator(.)ident(respond_to?)operator(()symbol(:map)operator(\)) operator(&&) operator(!)ident(value)operator(.)ident(is_a?)operator(()constant(String)operator(\))operator(\)) + ident(value)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) ident(connection)operator(.)ident(quote)operator(()ident(v)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + reserved(else) + ident(connection)operator(.)ident(quote)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(raise_if_bind_arity_mismatch)operator(()ident(statement)operator(,) ident(expected)operator(,) ident(provided)operator(\)) comment(#:nodoc:) + reserved(unless) ident(expected) operator(==) ident(provided) + ident(raise) constant(PreparedStatementInvalid)operator(,) string<delimiter(")content(wrong number of bind variables ()inline<inline_delimiter(#{)ident(provided)inline_delimiter(})>content( for )inline<inline_delimiter(#{)ident(expected)inline_delimiter(})>content(\) in: )inline<inline_delimiter(#{)ident(statement)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(extract_options_from_args!)operator(()ident(args)operator(\)) comment(#:nodoc:) + ident(args)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(args)operator(.)ident(pop) operator(:) operator({)operator(}) + reserved(end) + + constant(VALID_FIND_OPTIONS) operator(=) operator([) symbol(:conditions)operator(,) symbol(:include)operator(,) symbol(:joins)operator(,) symbol(:limit)operator(,) symbol(:offset)operator(,) + symbol(:order)operator(,) symbol(:select)operator(,) symbol(:readonly)operator(,) symbol(:group)operator(,) symbol(:from) operator(]) + + reserved(def) method(validate_find_options)operator(()ident(options)operator(\)) comment(#:nodoc:) + ident(options)operator(.)ident(assert_valid_keys)operator(()constant(VALID_FIND_OPTIONS)operator(\)) + reserved(end) + + reserved(def) method(set_readonly_option!)operator(()ident(options)operator(\)) comment(#:nodoc:) + comment(# Inherit :readonly from finder scope if set. Otherwise,) + comment(# if :joins is not blank then :readonly defaults to true.) + reserved(unless) ident(options)operator(.)ident(has_key?)operator(()symbol(:readonly)operator(\)) + reserved(if) ident(scoped?)operator(()symbol(:find)operator(,) symbol(:readonly)operator(\)) + ident(options)operator([)symbol(:readonly)operator(]) operator(=) ident(scope)operator(()symbol(:find)operator(,) symbol(:readonly)operator(\)) + reserved(elsif) operator(!)ident(options)operator([)symbol(:joins)operator(])operator(.)ident(blank?) operator(&&) operator(!)ident(options)operator([)symbol(:select)operator(]) + ident(options)operator([)symbol(:readonly)operator(]) operator(=) pre_constant(true) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(encode_quoted_value)operator(()ident(value)operator(\)) comment(#:nodoc:) + ident(quoted_value) operator(=) ident(connection)operator(.)ident(quote)operator(()ident(value)operator(\)) + ident(quoted_value) operator(=) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quoted_value)operator([)integer(1)operator(..)integer(-2)operator(])operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\')delimiter(/)>operator(,) string<delimiter(")char(\\\\)char(\\\\)content(')delimiter(")>operator(\))inline_delimiter(})>content(')delimiter(")> reserved(if) ident(quoted_value)operator(.)ident(include?)operator(()string<delimiter(")char(\\\\)char(\\')delimiter(")>operator(\)) comment(# (for ruby mode\) " ) + ident(quoted_value) + reserved(end) + reserved(end) + + ident(public) + comment(# New objects can be instantiated as either empty (pass no construction parameter\) or pre-set with) + comment(# attributes but not yet saved (pass a hash with key names matching the associated table column names\).) + comment(# In both instances, valid attribute keys are determined by the column names of the associated table --) + comment(# hence you can't have attributes that aren't part of the table columns.) + reserved(def) method(initialize)operator(()ident(attributes) operator(=) pre_constant(nil)operator(\)) + instance_variable(@attributes) operator(=) ident(attributes_from_column_definition) + instance_variable(@new_record) operator(=) pre_constant(true) + ident(ensure_proper_type) + pre_constant(self)operator(.)ident(attributes) operator(=) ident(attributes) reserved(unless) ident(attributes)operator(.)ident(nil?) + reserved(yield) pre_constant(self) reserved(if) ident(block_given?) + reserved(end) + + comment(# A model instance's primary key is always available as model.id) + comment(# whether you name it the default 'id' or set it to something else.) + reserved(def) method(id) + ident(attr_name) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key) + ident(column) operator(=) ident(column_for_attribute)operator(()ident(attr_name)operator(\)) + ident(define_read_method)operator(()symbol(:id)operator(,) ident(attr_name)operator(,) ident(column)operator(\)) reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(generate_read_methods) + ident(read_attribute)operator(()ident(attr_name)operator(\)) + reserved(end) + + comment(# Enables Active Record objects to be used as URL parameters in Action Pack automatically.) + ident(alias_method) symbol(:to_param)operator(,) symbol(:id) + + reserved(def) method(id_before_type_cast) comment(#:nodoc:) + ident(read_attribute_before_type_cast)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(\)) + reserved(end) + + reserved(def) method(quoted_id) comment(#:nodoc:) + ident(quote)operator(()ident(id)operator(,) ident(column_for_attribute)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(\))operator(\)) + reserved(end) + + comment(# Sets the primary ID.) + reserved(def) method(id=)operator(()ident(value)operator(\)) + ident(write_attribute)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(,) ident(value)operator(\)) + reserved(end) + + comment(# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet.) + reserved(def) method(new_record?) + instance_variable(@new_record) + reserved(end) + + comment(# * No record exists: Creates a new record with values matching those of the object attributes.) + comment(# * A record does exist: Updates the record with values matching those of the object attributes.) + reserved(def) method(save) + ident(raise) constant(ReadOnlyRecord) reserved(if) ident(readonly?) + ident(create_or_update) + reserved(end) + + comment(# Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a ) + comment(# RecordNotSaved exception) + reserved(def) method(save!) + ident(save) operator(||) ident(raise)operator(()constant(RecordNotSaved)operator(\)) + reserved(end) + + comment(# Deletes the record in the database and freezes this instance to reflect that no changes should) + comment(# be made (since they can't be persisted\).) + reserved(def) method(destroy) + reserved(unless) ident(new_record?) + ident(connection)operator(.)ident(delete) string<delimiter(<<-end_sql)>operator(,) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content( Destroy)delimiter(")>string<content( + DELETE FROM )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content( + WHERE )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quoted_id)inline_delimiter(})>delimiter( + end_sql)> + reserved(end) + + ident(freeze) + reserved(end) + + comment(# Returns a clone of the record that hasn't been assigned an id yet and) + comment(# is treated as a new record. Note that this is a "shallow" clone:) + comment(# it copies the object's attributes only, not its associations.) + comment(# The extent of a "deep" clone is application-specific and is therefore) + comment(# left to the application to implement according to its need.) + reserved(def) method(clone) + ident(attrs) operator(=) pre_constant(self)operator(.)ident(attributes_before_type_cast) + ident(attrs)operator(.)ident(delete)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(new) reserved(do) operator(|)ident(record)operator(|) + ident(record)operator(.)ident(send) symbol(:instance_variable_set)operator(,) string<delimiter(')content(@attributes)delimiter(')>operator(,) ident(attrs) + reserved(end) + reserved(end) + + comment(# Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records.) + comment(# Note: This method is overwritten by the Validation module that'll make sure that updates made with this method) + comment(# doesn't get subjected to validation checks. Hence, attributes can be updated even if the full object isn't valid.) + reserved(def) method(update_attribute)operator(()ident(name)operator(,) ident(value)operator(\)) + ident(send)operator(()ident(name)operator(.)ident(to_s) operator(+) string<delimiter(')content(=)delimiter(')>operator(,) ident(value)operator(\)) + ident(save) + reserved(end) + + comment(# Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will) + comment(# fail and false will be returned.) + reserved(def) method(update_attributes)operator(()ident(attributes)operator(\)) + pre_constant(self)operator(.)ident(attributes) operator(=) ident(attributes) + ident(save) + reserved(end) + + comment(# Initializes the +attribute+ to zero if nil and adds one. Only makes sense for number-based attributes. Returns self.) + reserved(def) method(increment)operator(()ident(attribute)operator(\)) + pre_constant(self)operator([)ident(attribute)operator(]) operator(||=) integer(0) + pre_constant(self)operator([)ident(attribute)operator(]) operator(+=) integer(1) + pre_constant(self) + reserved(end) + + comment(# Increments the +attribute+ and saves the record.) + reserved(def) method(increment!)operator(()ident(attribute)operator(\)) + ident(increment)operator(()ident(attribute)operator(\))operator(.)ident(update_attribute)operator(()ident(attribute)operator(,) pre_constant(self)operator([)ident(attribute)operator(])operator(\)) + reserved(end) + + comment(# Initializes the +attribute+ to zero if nil and subtracts one. Only makes sense for number-based attributes. Returns self.) + reserved(def) method(decrement)operator(()ident(attribute)operator(\)) + pre_constant(self)operator([)ident(attribute)operator(]) operator(||=) integer(0) + pre_constant(self)operator([)ident(attribute)operator(]) operator(-=) integer(1) + pre_constant(self) + reserved(end) + + comment(# Decrements the +attribute+ and saves the record.) + reserved(def) method(decrement!)operator(()ident(attribute)operator(\)) + ident(decrement)operator(()ident(attribute)operator(\))operator(.)ident(update_attribute)operator(()ident(attribute)operator(,) pre_constant(self)operator([)ident(attribute)operator(])operator(\)) + reserved(end) + + comment(# Turns an +attribute+ that's currently true into false and vice versa. Returns self.) + reserved(def) method(toggle)operator(()ident(attribute)operator(\)) + pre_constant(self)operator([)ident(attribute)operator(]) operator(=) operator(!)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(attribute)inline_delimiter(})>content(?)delimiter(")>operator(\)) + pre_constant(self) + reserved(end) + + comment(# Toggles the +attribute+ and saves the record.) + reserved(def) method(toggle!)operator(()ident(attribute)operator(\)) + ident(toggle)operator(()ident(attribute)operator(\))operator(.)ident(update_attribute)operator(()ident(attribute)operator(,) pre_constant(self)operator([)ident(attribute)operator(])operator(\)) + reserved(end) + + comment(# Reloads the attributes of this object from the database.) + reserved(def) method(reload) + ident(clear_aggregation_cache) + ident(clear_association_cache) + instance_variable(@attributes)operator(.)ident(update)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(find)operator(()pre_constant(self)operator(.)ident(id)operator(\))operator(.)ident(instance_variable_get)operator(()string<delimiter(')content(@attributes)delimiter(')>operator(\))operator(\)) + pre_constant(self) + reserved(end) + + comment(# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,) + comment(# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12\)\).) + comment(# (Alias for the protected read_attribute method\).) + reserved(def) method([])operator(()ident(attr_name)operator(\)) + ident(read_attribute)operator(()ident(attr_name)operator(\)) + reserved(end) + + comment(# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.) + comment(# (Alias for the protected write_attribute method\).) + reserved(def) method([]=)operator(()ident(attr_name)operator(,) ident(value)operator(\)) + ident(write_attribute)operator(()ident(attr_name)operator(,) ident(value)operator(\)) + reserved(end) + + comment(# Allows you to set all the attributes at once by passing in a hash with keys) + comment(# matching the attribute names (which again matches the column names\). Sensitive attributes can be protected) + comment(# from this form of mass-assignment by using the +attr_protected+ macro. Or you can alternatively) + comment(# specify which attributes *can* be accessed in with the +attr_accessible+ macro. Then all the) + comment(# attributes not included in that won't be allowed to be mass-assigned.) + reserved(def) method(attributes=)operator(()ident(new_attributes)operator(\)) + reserved(return) reserved(if) ident(new_attributes)operator(.)ident(nil?) + ident(attributes) operator(=) ident(new_attributes)operator(.)ident(dup) + ident(attributes)operator(.)ident(stringify_keys!) + + ident(multi_parameter_attributes) operator(=) operator([)operator(]) + ident(remove_attributes_protected_from_mass_assignment)operator(()ident(attributes)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,) ident(v)operator(|) + ident(k)operator(.)ident(include?)operator(()string<delimiter(")content(()delimiter(")>operator(\)) operator(?) ident(multi_parameter_attributes) operator(<<) operator([) ident(k)operator(,) ident(v) operator(]) operator(:) ident(send)operator(()ident(k) operator(+) string<delimiter(")content(=)delimiter(")>operator(,) ident(v)operator(\)) + reserved(end) + + ident(assign_multiparameter_attributes)operator(()ident(multi_parameter_attributes)operator(\)) + reserved(end) + + + comment(# Returns a hash of all the attributes with their names as keys and clones of their objects as values.) + reserved(def) method(attributes)operator(()ident(options) operator(=) pre_constant(nil)operator(\)) + ident(attributes) operator(=) ident(clone_attributes) symbol(:read_attribute) + + reserved(if) ident(options)operator(.)ident(nil?) + ident(attributes) + reserved(else) + reserved(if) ident(except) operator(=) ident(options)operator([)symbol(:except)operator(]) + ident(except) operator(=) ident(Array)operator(()ident(except)operator(\))operator(.)ident(collect) operator({) operator(|)ident(attribute)operator(|) ident(attribute)operator(.)ident(to_s) operator(}) + ident(except)operator(.)ident(each) operator({) operator(|)ident(attribute_name)operator(|) ident(attributes)operator(.)ident(delete)operator(()ident(attribute_name)operator(\)) operator(}) + ident(attributes) + reserved(elsif) ident(only) operator(=) ident(options)operator([)symbol(:only)operator(]) + ident(only) operator(=) ident(Array)operator(()ident(only)operator(\))operator(.)ident(collect) operator({) operator(|)ident(attribute)operator(|) ident(attribute)operator(.)ident(to_s) operator(}) + ident(attributes)operator(.)ident(delete_if) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) operator(!)ident(only)operator(.)ident(include?)operator(()ident(key)operator(\)) operator(}) + ident(attributes) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Options does not specify :except or :only ()inline<inline_delimiter(#{)ident(options)operator(.)ident(keys)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns a hash of cloned attributes before typecasting and deserialization.) + reserved(def) method(attributes_before_type_cast) + ident(clone_attributes) symbol(:read_attribute_before_type_cast) + reserved(end) + + comment(# Returns true if the specified +attribute+ has been set by the user or by a database load and is neither) + comment(# nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings\).) + reserved(def) method(attribute_present?)operator(()ident(attribute)operator(\)) + ident(value) operator(=) ident(read_attribute)operator(()ident(attribute)operator(\)) + operator(!)ident(value)operator(.)ident(blank?) reserved(or) ident(value) operator(==) integer(0) + reserved(end) + + comment(# Returns true if the given attribute is in the attributes hash) + reserved(def) method(has_attribute?)operator(()ident(attr_name)operator(\)) + instance_variable(@attributes)operator(.)ident(has_key?)operator(()ident(attr_name)operator(.)ident(to_s)operator(\)) + reserved(end) + + comment(# Returns an array of names for the attributes available on this object sorted alphabetically.) + reserved(def) method(attribute_names) + instance_variable(@attributes)operator(.)ident(keys)operator(.)ident(sort) + reserved(end) + + comment(# Returns the column object for the named attribute.) + reserved(def) method(column_for_attribute)operator(()ident(name)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(columns_hash)operator([)ident(name)operator(.)ident(to_s)operator(]) + reserved(end) + + comment(# Returns true if the +comparison_object+ is the same object, or is of the same type and has the same id.) + reserved(def) method(==)operator(()ident(comparison_object)operator(\)) + ident(comparison_object)operator(.)ident(equal?)operator(()pre_constant(self)operator(\)) operator(||) + operator(()ident(comparison_object)operator(.)ident(instance_of?)operator(()pre_constant(self)operator(.)ident(class)operator(\)) operator(&&) + ident(comparison_object)operator(.)ident(id) operator(==) ident(id) operator(&&) + operator(!)ident(comparison_object)operator(.)ident(new_record?)operator(\)) + reserved(end) + + comment(# Delegates to ==) + reserved(def) method(eql?)operator(()ident(comparison_object)operator(\)) + pre_constant(self) operator(==) operator(()ident(comparison_object)operator(\)) + reserved(end) + + comment(# Delegates to id in order to allow two records of the same type and id to work with something like:) + comment(# [ Person.find(1\), Person.find(2\), Person.find(3\) ] & [ Person.find(1\), Person.find(4\) ] # => [ Person.find(1\) ]) + reserved(def) method(hash) + ident(id)operator(.)ident(hash) + reserved(end) + + comment(# For checking respond_to? without searching the attributes (which is faster\).) + ident(alias_method) symbol(:respond_to_without_attributes?)operator(,) symbol(:respond_to?) + + comment(# A Person object with a name attribute can ask person.respond_to?("name"\), person.respond_to?("name="\), and) + comment(# person.respond_to?("name?"\) which will all return true.) + reserved(def) method(respond_to?)operator(()ident(method)operator(,) ident(include_priv) operator(=) pre_constant(false)operator(\)) + reserved(if) instance_variable(@attributes)operator(.)ident(nil?) + reserved(return) reserved(super) + reserved(elsif) ident(attr_name) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(column_methods_hash)operator([)ident(method)operator(.)ident(to_sym)operator(]) + reserved(return) pre_constant(true) reserved(if) instance_variable(@attributes)operator(.)ident(include?)operator(()ident(attr_name)operator(\)) operator(||) ident(attr_name) operator(==) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key) + reserved(return) pre_constant(false) reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(read_methods)operator(.)ident(include?)operator(()ident(attr_name)operator(\)) + reserved(elsif) instance_variable(@attributes)operator(.)ident(include?)operator(()ident(method_name) operator(=) ident(method)operator(.)ident(to_s)operator(\)) + reserved(return) pre_constant(true) + reserved(elsif) ident(md) operator(=) regexp<delimiter(/)content((=|)char(\\?)content(|_before_type_cast\)$)delimiter(/)>operator(.)ident(match)operator(()ident(method_name)operator(\)) + reserved(return) pre_constant(true) reserved(if) instance_variable(@attributes)operator(.)ident(include?)operator(()ident(md)operator(.)ident(pre_match)operator(\)) + reserved(end) + comment(# super must be called at the end of the method, because the inherited respond_to?) + comment(# would return true for generated readers, even if the attribute wasn't present) + reserved(super) + reserved(end) + + comment(# Just freeze the attributes hash, such that associations are still accessible even on destroyed records.) + reserved(def) method(freeze) + instance_variable(@attributes)operator(.)ident(freeze)operator(;) pre_constant(self) + reserved(end) + + reserved(def) method(frozen?) + instance_variable(@attributes)operator(.)ident(frozen?) + reserved(end) + + comment(# Records loaded through joins with piggy-back attributes will be marked as read only as they cannot be saved and return true to this query.) + reserved(def) method(readonly?) + instance_variable(@readonly) operator(==) pre_constant(true) + reserved(end) + + reserved(def) method(readonly!) comment(#:nodoc:) + instance_variable(@readonly) operator(=) pre_constant(true) + reserved(end) + + comment(# Builds an XML document to represent the model. Some configuration is) + comment(# availble through +options+, however more complicated cases should use ) + comment(# Builder.) + comment(#) + comment(# By default the generated XML document will include the processing ) + comment(# instruction and all object's attributes. For example:) + comment(# ) + comment(# <?xml version="1.0" encoding="UTF-8"?>) + comment(# <topic>) + comment(# <title>The First Topic</title>) + comment(# <author-name>David</author-name>) + comment(# <id type="integer">1</id>) + comment(# <approved type="boolean">false</approved>) + comment(# <replies-count type="integer">0</replies-count>) + comment(# <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time>) + comment(# <written-on type="datetime">2003-07-16T09:28:00+1200</written-on>) + comment(# <content>Have a nice day</content>) + comment(# <author-email-address>david@loudthinking.com</author-email-address>) + comment(# <parent-id></parent-id>) + comment(# <last-read type="date">2004-04-15</last-read>) + comment(# </topic>) + comment(#) + comment(# This behaviour can be controlled with :only, :except, and :skip_instruct ) + comment(# for instance:) + comment(#) + comment(# topic.to_xml(:skip_instruct => true, :except => [ :id, bonus_time, :written_on, replies_count ]\)) + comment(#) + comment(# <topic>) + comment(# <title>The First Topic</title>) + comment(# <author-name>David</author-name>) + comment(# <approved type="boolean">false</approved>) + comment(# <content>Have a nice day</content>) + comment(# <author-email-address>david@loudthinking.com</author-email-address>) + comment(# <parent-id></parent-id>) + comment(# <last-read type="date">2004-04-15</last-read>) + comment(# </topic>) + comment(# ) + comment(# To include first level associations use :include) + comment(#) + comment(# firm.to_xml :include => [ :account, :clients ]) + comment(#) + comment(# <?xml version="1.0" encoding="UTF-8"?>) + comment(# <firm>) + comment(# <id type="integer">1</id>) + comment(# <rating type="integer">1</rating>) + comment(# <name>37signals</name>) + comment(# <clients>) + comment(# <client>) + comment(# <rating type="integer">1</rating>) + comment(# <name>Summit</name>) + comment(# </client>) + comment(# <client>) + comment(# <rating type="integer">1</rating>) + comment(# <name>Microsoft</name>) + comment(# </client>) + comment(# </clients>) + comment(# <account>) + comment(# <id type="integer">1</id>) + comment(# <credit-limit type="integer">50</credit-limit>) + comment(# </account>) + comment(# </firm>) + reserved(def) method(to_xml)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator([)symbol(:root)operator(]) operator(||=) pre_constant(self)operator(.)ident(class)operator(.)ident(to_s)operator(.)ident(underscore) + ident(options)operator([)symbol(:except)operator(]) operator(=) ident(Array)operator(()ident(options)operator([)symbol(:except)operator(])operator(\)) operator(<<) pre_constant(self)operator(.)ident(class)operator(.)ident(inheritance_column) reserved(unless) ident(options)operator([)symbol(:only)operator(]) comment(# skip type column) + ident(root_only_or_except) operator(=) operator({) symbol(:only) operator(=)operator(>) ident(options)operator([)symbol(:only)operator(])operator(,) symbol(:except) operator(=)operator(>) ident(options)operator([)symbol(:except)operator(]) operator(}) + + ident(attributes_for_xml) operator(=) ident(attributes)operator(()ident(root_only_or_except)operator(\)) + + reserved(if) ident(include_associations) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:include)operator(\)) + ident(include_has_options) operator(=) ident(include_associations)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + reserved(for) ident(association) reserved(in) ident(include_has_options) operator(?) ident(include_associations)operator(.)ident(keys) operator(:) ident(Array)operator(()ident(include_associations)operator(\)) + ident(association_options) operator(=) ident(include_has_options) operator(?) ident(include_associations)operator([)ident(association)operator(]) operator(:) ident(root_only_or_except) + + reserved(case) pre_constant(self)operator(.)ident(class)operator(.)ident(reflect_on_association)operator(()ident(association)operator(\))operator(.)ident(macro) + reserved(when) symbol(:has_many)operator(,) symbol(:has_and_belongs_to_many) + ident(records) operator(=) ident(send)operator(()ident(association)operator(\))operator(.)ident(to_a) + reserved(unless) ident(records)operator(.)ident(empty?) + ident(attributes_for_xml)operator([)ident(association)operator(]) operator(=) ident(records)operator(.)ident(collect) reserved(do) operator(|)ident(record)operator(|) + ident(record)operator(.)ident(attributes)operator(()ident(association_options)operator(\)) + reserved(end) + reserved(end) + reserved(when) symbol(:has_one)operator(,) symbol(:belongs_to) + reserved(if) ident(record) operator(=) ident(send)operator(()ident(association)operator(\)) + ident(attributes_for_xml)operator([)ident(association)operator(]) operator(=) ident(record)operator(.)ident(attributes)operator(()ident(association_options)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + ident(attributes_for_xml)operator(.)ident(to_xml)operator(()ident(options)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(create_or_update) + reserved(if) ident(new_record?) reserved(then) ident(create) reserved(else) ident(update) reserved(end) + reserved(end) + + comment(# Updates the associated record with values matching those of the instance attributes.) + reserved(def) method(update) + ident(connection)operator(.)ident(update)operator(() + string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content( )delimiter(")> operator(+) + string<delimiter(")content(SET )inline<inline_delimiter(#{)ident(quoted_comma_pair_list)operator(()ident(connection)operator(,) ident(attributes_with_quotes)operator(()pre_constant(false)operator(\))operator(\))inline_delimiter(})>content( )delimiter(")> operator(+) + string<delimiter(")content(WHERE )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quote)operator(()ident(id)operator(\))inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content( Update)delimiter(")> + operator(\)) + + reserved(return) pre_constant(true) + reserved(end) + + comment(# Creates a new record with values matching those of the instance attributes.) + reserved(def) method(create) + reserved(if) pre_constant(self)operator(.)ident(id)operator(.)ident(nil?) operator(&&) ident(connection)operator(.)ident(prefetch_primary_key?)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(table_name)operator(\)) + pre_constant(self)operator(.)ident(id) operator(=) ident(connection)operator(.)ident(next_sequence_value)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(sequence_name)operator(\)) + reserved(end) + + pre_constant(self)operator(.)ident(id) operator(=) ident(connection)operator(.)ident(insert)operator(() + string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content( )delimiter(")> operator(+) + string<delimiter(")content(()inline<inline_delimiter(#{)ident(quoted_column_names)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>content(\) )delimiter(")> operator(+) + string<delimiter(")content(VALUES()inline<inline_delimiter(#{)ident(attributes_with_quotes)operator(.)ident(values)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>content(\))delimiter(")>operator(,) + string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content( Create)delimiter(")>operator(,) + pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(,) pre_constant(self)operator(.)ident(id)operator(,) pre_constant(self)operator(.)ident(class)operator(.)ident(sequence_name) + operator(\)) + + instance_variable(@new_record) operator(=) pre_constant(false) + + reserved(return) pre_constant(true) + reserved(end) + + comment(# Sets the attribute used for single table inheritance to this class name if this is not the ActiveRecord descendent.) + comment(# Considering the hierarchy Reply < Message < ActiveRecord, this makes it possible to do Reply.new without having to) + comment(# set Reply[Reply.inheritance_column] = "Reply" yourself. No such attribute would be set for objects of the) + comment(# Message class in that example.) + reserved(def) method(ensure_proper_type) + reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(descends_from_active_record?) + ident(write_attribute)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(inheritance_column)operator(,) constant(Inflector)operator(.)ident(demodulize)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(name)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Allows access to the object attributes, which are held in the @attributes hash, as were) + comment(# they first-class methods. So a Person class with a name attribute can use Person#name and) + comment(# Person#name= and never directly use the attributes hash -- except for multiple assigns with) + comment(# ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that) + comment(# the completed attribute is not nil or 0.) + comment(#) + comment(# It's also possible to instantiate related objects, so a Client class belonging to the clients) + comment(# table with a master_id foreign key can instantiate master through Client#master.) + reserved(def) method(method_missing)operator(()ident(method_id)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(method_name) operator(=) ident(method_id)operator(.)ident(to_s) + reserved(if) instance_variable(@attributes)operator(.)ident(include?)operator(()ident(method_name)operator(\)) reserved(or) + operator(()ident(md) operator(=) regexp<delimiter(/)char(\\?)content($)delimiter(/)>operator(.)ident(match)operator(()ident(method_name)operator(\)) reserved(and) + instance_variable(@attributes)operator(.)ident(include?)operator(()ident(method_name) operator(=) ident(md)operator(.)ident(pre_match)operator(\))operator(\)) + ident(define_read_methods) reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(read_methods)operator(.)ident(empty?) operator(&&) pre_constant(self)operator(.)ident(class)operator(.)ident(generate_read_methods) + ident(md) operator(?) ident(query_attribute)operator(()ident(method_name)operator(\)) operator(:) ident(read_attribute)operator(()ident(method_name)operator(\)) + reserved(elsif) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(.)ident(to_s) operator(==) ident(method_name) + ident(id) + reserved(elsif) ident(md) operator(=) regexp<delimiter(/)content((=|_before_type_cast\)$)delimiter(/)>operator(.)ident(match)operator(()ident(method_name)operator(\)) + ident(attribute_name)operator(,) ident(method_type) operator(=) ident(md)operator(.)ident(pre_match)operator(,) ident(md)operator(.)ident(to_s) + reserved(if) instance_variable(@attributes)operator(.)ident(include?)operator(()ident(attribute_name)operator(\)) + reserved(case) ident(method_type) + reserved(when) string<delimiter(')content(=)delimiter(')> + ident(write_attribute)operator(()ident(attribute_name)operator(,) ident(args)operator(.)ident(first)operator(\)) + reserved(when) string<delimiter(')content(_before_type_cast)delimiter(')> + ident(read_attribute_before_type_cast)operator(()ident(attribute_name)operator(\)) + reserved(end) + reserved(else) + reserved(super) + reserved(end) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + comment(# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,) + comment(# "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12\)\).) + reserved(def) method(read_attribute)operator(()ident(attr_name)operator(\)) + ident(attr_name) operator(=) ident(attr_name)operator(.)ident(to_s) + reserved(if) operator(!)operator(()ident(value) operator(=) instance_variable(@attributes)operator([)ident(attr_name)operator(])operator(\))operator(.)ident(nil?) + reserved(if) ident(column) operator(=) ident(column_for_attribute)operator(()ident(attr_name)operator(\)) + reserved(if) ident(unserializable_attribute?)operator(()ident(attr_name)operator(,) ident(column)operator(\)) + ident(unserialize_attribute)operator(()ident(attr_name)operator(\)) + reserved(else) + ident(column)operator(.)ident(type_cast)operator(()ident(value)operator(\)) + reserved(end) + reserved(else) + ident(value) + reserved(end) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(read_attribute_before_type_cast)operator(()ident(attr_name)operator(\)) + instance_variable(@attributes)operator([)ident(attr_name)operator(]) + reserved(end) + + comment(# Called on first read access to any given column and generates reader) + comment(# methods for all columns in the columns_hash if) + comment(# ActiveRecord::Base.generate_read_methods is set to true.) + reserved(def) method(define_read_methods) + pre_constant(self)operator(.)ident(class)operator(.)ident(columns_hash)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(column)operator(|) + reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(serialized_attributes)operator([)ident(name)operator(]) + ident(define_read_method)operator(()ident(name)operator(.)ident(to_sym)operator(,) ident(name)operator(,) ident(column)operator(\)) reserved(unless) ident(respond_to_without_attributes?)operator(()ident(name)operator(\)) + ident(define_question_method)operator(()ident(name)operator(\)) reserved(unless) ident(respond_to_without_attributes?)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(?)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Define an attribute reader method. Cope with nil column.) + reserved(def) method(define_read_method)operator(()ident(symbol)operator(,) ident(attr_name)operator(,) ident(column)operator(\)) + ident(cast_code) operator(=) ident(column)operator(.)ident(type_cast_code)operator(()string<delimiter(')content(v)delimiter(')>operator(\)) reserved(if) ident(column) + ident(access_code) operator(=) ident(cast_code) operator(?) string<delimiter(")content((v=@attributes[')inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(']\) && )inline<inline_delimiter(#{)ident(cast_code)inline_delimiter(})>delimiter(")> operator(:) string<delimiter(")content(@attributes[')inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content('])delimiter(")> + + reserved(unless) ident(attr_name)operator(.)ident(to_s) operator(==) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(.)ident(to_s) + ident(access_code) operator(=) ident(access_code)operator(.)ident(insert)operator(()integer(0)operator(,) string<delimiter(")content(raise NoMethodError, 'missing attribute: )inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(', caller unless @attributes.has_key?(')inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content('\); )delimiter(")>operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(read_methods) operator(<<) ident(attr_name) + reserved(end) + + ident(evaluate_read_method) ident(attr_name)operator(,) string<delimiter(")content(def )inline<inline_delimiter(#{)ident(symbol)inline_delimiter(})>content(; )inline<inline_delimiter(#{)ident(access_code)inline_delimiter(})>content(; end)delimiter(")> + reserved(end) + + comment(# Define an attribute ? method.) + reserved(def) method(define_question_method)operator(()ident(attr_name)operator(\)) + reserved(unless) ident(attr_name)operator(.)ident(to_s) operator(==) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(.)ident(to_s) + pre_constant(self)operator(.)ident(class)operator(.)ident(read_methods) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(?)delimiter(")> + reserved(end) + + ident(evaluate_read_method) ident(attr_name)operator(,) string<delimiter(")content(def )inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(?; query_attribute(')inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content('\); end)delimiter(")> + reserved(end) + + comment(# Evaluate the definition for an attribute reader or ? method) + reserved(def) method(evaluate_read_method)operator(()ident(attr_name)operator(,) ident(method_definition)operator(\)) + reserved(begin) + pre_constant(self)operator(.)ident(class)operator(.)ident(class_eval)operator(()ident(method_definition)operator(\)) + reserved(rescue) constant(SyntaxError) operator(=)operator(>) ident(err) + pre_constant(self)operator(.)ident(class)operator(.)ident(read_methods)operator(.)ident(delete)operator(()ident(attr_name)operator(\)) + reserved(if) ident(logger) + ident(logger)operator(.)ident(warn) string<delimiter(")content(Exception occured during reader method compilation.)delimiter(")> + ident(logger)operator(.)ident(warn) string<delimiter(")content(Maybe )inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content( is not a valid Ruby identifier?)delimiter(")> + ident(logger)operator(.)ident(warn) string<delimiter(")inline<inline_delimiter(#{)ident(err)operator(.)ident(message)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + comment(# Returns true if the attribute is of a text column and marked for serialization.) + reserved(def) method(unserializable_attribute?)operator(()ident(attr_name)operator(,) ident(column)operator(\)) + ident(column)operator(.)ident(text?) operator(&&) pre_constant(self)operator(.)ident(class)operator(.)ident(serialized_attributes)operator([)ident(attr_name)operator(]) + reserved(end) + + comment(# Returns the unserialized object of the attribute.) + reserved(def) method(unserialize_attribute)operator(()ident(attr_name)operator(\)) + ident(unserialized_object) operator(=) ident(object_from_yaml)operator(()instance_variable(@attributes)operator([)ident(attr_name)operator(])operator(\)) + + reserved(if) ident(unserialized_object)operator(.)ident(is_a?)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(serialized_attributes)operator([)ident(attr_name)operator(])operator(\)) + instance_variable(@attributes)operator([)ident(attr_name)operator(]) operator(=) ident(unserialized_object) + reserved(else) + ident(raise) constant(SerializationTypeMismatch)operator(,) + string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content( was supposed to be a )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(serialized_attributes)operator([)ident(attr_name)operator(])inline_delimiter(})>content(, but was a )inline<inline_delimiter(#{)ident(unserialized_object)operator(.)ident(class)operator(.)ident(to_s)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float) + comment(# columns are turned into nil.) + reserved(def) method(write_attribute)operator(()ident(attr_name)operator(,) ident(value)operator(\)) + ident(attr_name) operator(=) ident(attr_name)operator(.)ident(to_s) + reserved(if) operator(()ident(column) operator(=) ident(column_for_attribute)operator(()ident(attr_name)operator(\))operator(\)) operator(&&) ident(column)operator(.)ident(number?) + instance_variable(@attributes)operator([)ident(attr_name)operator(]) operator(=) ident(convert_number_column_value)operator(()ident(value)operator(\)) + reserved(else) + instance_variable(@attributes)operator([)ident(attr_name)operator(]) operator(=) ident(value) + reserved(end) + reserved(end) + + reserved(def) method(convert_number_column_value)operator(()ident(value)operator(\)) + reserved(case) ident(value) + reserved(when) constant(FalseClass)operator(:) integer(0) + reserved(when) constant(TrueClass)operator(:) integer(1) + reserved(when) string<delimiter(')delimiter(')>operator(:) pre_constant(nil) + reserved(else) ident(value) + reserved(end) + reserved(end) + + reserved(def) method(query_attribute)operator(()ident(attr_name)operator(\)) + ident(attribute) operator(=) instance_variable(@attributes)operator([)ident(attr_name)operator(]) + reserved(if) ident(attribute)operator(.)ident(kind_of?)operator(()constant(Fixnum)operator(\)) operator(&&) ident(attribute) operator(==) integer(0) + pre_constant(false) + reserved(elsif) ident(attribute)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) operator(&&) ident(attribute) operator(==) string<delimiter(")content(0)delimiter(")> + pre_constant(false) + reserved(elsif) ident(attribute)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) operator(&&) ident(attribute)operator(.)ident(empty?) + pre_constant(false) + reserved(elsif) ident(attribute)operator(.)ident(nil?) + pre_constant(false) + reserved(elsif) ident(attribute) operator(==) pre_constant(false) + pre_constant(false) + reserved(elsif) ident(attribute) operator(==) string<delimiter(")content(f)delimiter(")> + pre_constant(false) + reserved(elsif) ident(attribute) operator(==) string<delimiter(")content(false)delimiter(")> + pre_constant(false) + reserved(else) + pre_constant(true) + reserved(end) + reserved(end) + + reserved(def) method(remove_attributes_protected_from_mass_assignment)operator(()ident(attributes)operator(\)) + reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(accessible_attributes)operator(.)ident(nil?) operator(&&) pre_constant(self)operator(.)ident(class)operator(.)ident(protected_attributes)operator(.)ident(nil?) + ident(attributes)operator(.)ident(reject) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) ident(attributes_protected_by_default)operator(.)ident(include?)operator(()ident(key)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\()content(.+)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\))operator(\)) operator(}) + reserved(elsif) pre_constant(self)operator(.)ident(class)operator(.)ident(protected_attributes)operator(.)ident(nil?) + ident(attributes)operator(.)ident(reject) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) operator(!)pre_constant(self)operator(.)ident(class)operator(.)ident(accessible_attributes)operator(.)ident(include?)operator(()ident(key)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\()content(.+)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\))operator(.)ident(intern)operator(\)) operator(||) ident(attributes_protected_by_default)operator(.)ident(include?)operator(()ident(key)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\()content(.+)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\))operator(\)) operator(}) + reserved(elsif) pre_constant(self)operator(.)ident(class)operator(.)ident(accessible_attributes)operator(.)ident(nil?) + ident(attributes)operator(.)ident(reject) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) pre_constant(self)operator(.)ident(class)operator(.)ident(protected_attributes)operator(.)ident(include?)operator(()ident(key)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\()content(.+)delimiter(/)>operator(,)string<delimiter(")delimiter(")>operator(\))operator(.)ident(intern)operator(\)) operator(||) ident(attributes_protected_by_default)operator(.)ident(include?)operator(()ident(key)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\()content(.+)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\))operator(\)) operator(}) + reserved(end) + reserved(end) + + comment(# The primary key and inheritance column can never be set by mass-assignment for security reasons.) + reserved(def) method(attributes_protected_by_default) + ident(default) operator(=) operator([) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(,) pre_constant(self)operator(.)ident(class)operator(.)ident(inheritance_column) operator(]) + ident(default) operator(<<) string<delimiter(')content(id)delimiter(')> reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(.)ident(eql?) string<delimiter(')content(id)delimiter(')> + ident(default) + reserved(end) + + comment(# Returns copy of the attributes hash where all the values have been safely quoted for use in) + comment(# an SQL statement.) + reserved(def) method(attributes_with_quotes)operator(()ident(include_primary_key) operator(=) pre_constant(true)operator(\)) + ident(attributes)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(quoted)operator(,) operator(()ident(name)operator(,) ident(value)operator(\))operator(|) + reserved(if) ident(column) operator(=) ident(column_for_attribute)operator(()ident(name)operator(\)) + ident(quoted)operator([)ident(name)operator(]) operator(=) ident(quote)operator(()ident(value)operator(,) ident(column)operator(\)) reserved(unless) operator(!)ident(include_primary_key) operator(&&) ident(column)operator(.)ident(primary) + reserved(end) + ident(quoted) + reserved(end) + reserved(end) + + comment(# Quote strings appropriately for SQL statements.) + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(connection)operator(.)ident(quote)operator(()ident(value)operator(,) ident(column)operator(\)) + reserved(end) + + comment(# Interpolate custom sql string in instance context.) + comment(# Optional record argument is meant for custom insert_sql.) + reserved(def) method(interpolate_sql)operator(()ident(sql)operator(,) ident(record) operator(=) pre_constant(nil)operator(\)) + ident(instance_eval)operator(()string<delimiter(")content(%@)inline<inline_delimiter(#{)ident(sql)operator(.)ident(gsub)operator(()string<delimiter(')content(@)delimiter(')>operator(,) string<delimiter(')content(\\@)delimiter(')>operator(\))inline_delimiter(})>content(@)delimiter(")>operator(\)) + reserved(end) + + comment(# Initializes the attributes array with keys matching the columns from the linked table and) + comment(# the values matching the corresponding default value of that column, so) + comment(# that a new instance, or one populated from a passed-in Hash, still has all the attributes) + comment(# that instances loaded from the database would.) + reserved(def) method(attributes_from_column_definition) + pre_constant(self)operator(.)ident(class)operator(.)ident(columns)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(attributes)operator(,) ident(column)operator(|) + ident(attributes)operator([)ident(column)operator(.)ident(name)operator(]) operator(=) ident(column)operator(.)ident(default) reserved(unless) ident(column)operator(.)ident(name) operator(==) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key) + ident(attributes) + reserved(end) + reserved(end) + + comment(# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done) + comment(# by calling new on the column type or aggregation type (through composed_of\) object with these parameters.) + comment(# So having the pairs written_on(1\) = "2004", written_on(2\) = "6", written_on(3\) = "24", will instantiate) + comment(# written_on (a date type\) with Date.new("2004", "6", "24"\). You can also specify a typecast character in the) + comment(# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum, f for Float,) + comment(# s for String, and a for Array. If all the values for a given attribute is empty, the attribute will be set to nil.) + reserved(def) method(assign_multiparameter_attributes)operator(()ident(pairs)operator(\)) + ident(execute_callstack_for_multiparameter_attributes)operator(() + ident(extract_callstack_for_multiparameter_attributes)operator(()ident(pairs)operator(\)) + operator(\)) + reserved(end) + + comment(# Includes an ugly hack for Time.local instead of Time.new because the latter is reserved by Time itself.) + reserved(def) method(execute_callstack_for_multiparameter_attributes)operator(()ident(callstack)operator(\)) + ident(errors) operator(=) operator([)operator(]) + ident(callstack)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(values)operator(|) + ident(klass) operator(=) operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(reflect_on_aggregation)operator(()ident(name)operator(.)ident(to_sym)operator(\)) operator(||) ident(column_for_attribute)operator(()ident(name)operator(\))operator(\))operator(.)ident(klass) + reserved(if) ident(values)operator(.)ident(empty?) + ident(send)operator(()ident(name) operator(+) string<delimiter(")content(=)delimiter(")>operator(,) pre_constant(nil)operator(\)) + reserved(else) + reserved(begin) + ident(send)operator(()ident(name) operator(+) string<delimiter(")content(=)delimiter(")>operator(,) constant(Time) operator(==) ident(klass) operator(?) ident(klass)operator(.)ident(local)operator(()operator(*)ident(values)operator(\)) operator(:) ident(klass)operator(.)ident(new)operator(()operator(*)ident(values)operator(\))operator(\)) + reserved(rescue) operator(=)operator(>) ident(ex) + ident(errors) operator(<<) constant(AttributeAssignmentError)operator(.)ident(new)operator(()string<delimiter(")content(error on assignment )inline<inline_delimiter(#{)ident(values)operator(.)ident(inspect)inline_delimiter(})>content( to )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(ex)operator(,) ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(unless) ident(errors)operator(.)ident(empty?) + ident(raise) constant(MultiparameterAssignmentErrors)operator(.)ident(new)operator(()ident(errors)operator(\))operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(errors)operator(.)ident(size)inline_delimiter(})>content( error(s\) on assignment of multiparameter attributes)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(extract_callstack_for_multiparameter_attributes)operator(()ident(pairs)operator(\)) + ident(attributes) operator(=) operator({) operator(}) + + reserved(for) ident(pair) reserved(in) ident(pairs) + ident(multiparameter_name)operator(,) ident(value) operator(=) ident(pair) + ident(attribute_name) operator(=) ident(multiparameter_name)operator(.)ident(split)operator(()string<delimiter(")content(()delimiter(")>operator(\))operator(.)ident(first) + ident(attributes)operator([)ident(attribute_name)operator(]) operator(=) operator([)operator(]) reserved(unless) ident(attributes)operator(.)ident(include?)operator(()ident(attribute_name)operator(\)) + + reserved(unless) ident(value)operator(.)ident(empty?) + ident(attributes)operator([)ident(attribute_name)operator(]) operator(<<) + operator([) ident(find_parameter_position)operator(()ident(multiparameter_name)operator(\))operator(,) ident(type_cast_attribute_value)operator(()ident(multiparameter_name)operator(,) ident(value)operator(\)) operator(]) + reserved(end) + reserved(end) + + ident(attributes)operator(.)ident(each) operator({) operator(|)ident(name)operator(,) ident(values)operator(|) ident(attributes)operator([)ident(name)operator(]) operator(=) ident(values)operator(.)ident(sort_by)operator({) operator(|)ident(v)operator(|) ident(v)operator(.)ident(first) operator(})operator(.)ident(collect) operator({) operator(|)ident(v)operator(|) ident(v)operator(.)ident(last) operator(}) operator(}) + reserved(end) + + reserved(def) method(type_cast_attribute_value)operator(()ident(multiparameter_name)operator(,) ident(value)operator(\)) + ident(multiparameter_name) operator(=)operator(~) regexp<delimiter(/)char(\\()content([0-9]*([a-z]\))char(\\\))delimiter(/)> operator(?) ident(value)operator(.)ident(send)operator(()string<delimiter(")content(to_)delimiter(")> operator(+) global_variable($1)operator(\)) operator(:) ident(value) + reserved(end) + + reserved(def) method(find_parameter_position)operator(()ident(multiparameter_name)operator(\)) + ident(multiparameter_name)operator(.)ident(scan)operator(()regexp<delimiter(/)char(\\()content(([0-9]*\).*)char(\\\))delimiter(/)>operator(\))operator(.)ident(first)operator(.)ident(first) + reserved(end) + + comment(# Returns a comma-separated pair list, like "key1 = val1, key2 = val2".) + reserved(def) method(comma_pair_list)operator(()ident(hash)operator(\)) + ident(hash)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) operator({) operator(|)ident(list)operator(,) ident(pair)operator(|) ident(list) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(pair)operator(.)ident(first)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(pair)operator(.)ident(last)inline_delimiter(})>delimiter(")> operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(quoted_column_names)operator(()ident(attributes) operator(=) ident(attributes_with_quotes)operator(\)) + ident(attributes)operator(.)ident(keys)operator(.)ident(collect) reserved(do) operator(|)ident(column_name)operator(|) + pre_constant(self)operator(.)ident(class)operator(.)ident(connection)operator(.)ident(quote_column_name)operator(()ident(column_name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(quote_columns)operator(()ident(quoter)operator(,) ident(hash)operator(\)) + ident(hash)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(quoted)operator(,) operator(()ident(name)operator(,) ident(value)operator(\))operator(|) + ident(quoted)operator([)ident(quoter)operator(.)ident(quote_column_name)operator(()ident(name)operator(\))operator(]) operator(=) ident(value) + ident(quoted) + reserved(end) + reserved(end) + + reserved(def) method(quoted_comma_pair_list)operator(()ident(quoter)operator(,) ident(hash)operator(\)) + ident(comma_pair_list)operator(()ident(quote_columns)operator(()ident(quoter)operator(,) ident(hash)operator(\))operator(\)) + reserved(end) + + reserved(def) method(object_from_yaml)operator(()ident(string)operator(\)) + reserved(return) ident(string) reserved(unless) ident(string)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + constant(YAML)operator(::)ident(load)operator(()ident(string)operator(\)) reserved(rescue) ident(string) + reserved(end) + + reserved(def) method(clone_attributes)operator(()ident(reader_method) operator(=) symbol(:read_attribute)operator(,) ident(attributes) operator(=) operator({)operator(})operator(\)) + pre_constant(self)operator(.)ident(attribute_names)operator(.)ident(inject)operator(()ident(attributes)operator(\)) reserved(do) operator(|)ident(attributes)operator(,) ident(name)operator(|) + ident(attributes)operator([)ident(name)operator(]) operator(=) ident(clone_attribute_value)operator(()ident(reader_method)operator(,) ident(name)operator(\)) + ident(attributes) + reserved(end) + reserved(end) + + reserved(def) method(clone_attribute_value)operator(()ident(reader_method)operator(,) ident(attribute_name)operator(\)) + ident(value) operator(=) ident(send)operator(()ident(reader_method)operator(,) ident(attribute_name)operator(\)) + ident(value)operator(.)ident(clone) + reserved(rescue) constant(TypeError)operator(,) constant(NoMethodError) + ident(value) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Calculations) comment(#:nodoc:) + constant(CALCULATIONS_OPTIONS) operator(=) operator([)symbol(:conditions)operator(,) symbol(:joins)operator(,) symbol(:order)operator(,) symbol(:select)operator(,) symbol(:group)operator(,) symbol(:having)operator(,) symbol(:distinct)operator(,) symbol(:limit)operator(,) symbol(:offset)operator(]) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Count operates using three different approaches. ) + comment(#) + comment(# * Count all: By not passing any parameters to count, it will return a count of all the rows for the model.) + comment(# * Count by conditions or joins: For backwards compatibility, you can pass in +conditions+ and +joins+ as individual parameters.) + comment(# * Count using options will find the row count matched by the options used.) + comment(#) + comment(# The last approach, count using options, accepts an option hash as the only parameter. The options are:) + comment(#) + comment(# * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.) + comment(# * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed\).) + comment(# The records will be returned read-only since they will have attributes that do not correspond to the table's columns.) + comment(# * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer) + comment(# to already defined associations. When using named associations count returns the number DISTINCT items for the model you're counting.) + comment(# See eager loading under Associations.) + comment(# * <tt>:order</tt>: An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations\).) + comment(# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.) + comment(# * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not) + comment(# include the joined columns.) + comment(# * <tt>:distinct</tt>: Set this to true to make this a distinct calculation, such as SELECT COUNT(DISTINCT posts.id\) ...) + comment(#) + comment(# Examples for counting all:) + comment(# Person.count # returns the total count of all people) + comment(#) + comment(# Examples for count by +conditions+ and +joins+ (for backwards compatibility\):) + comment(# Person.count("age > 26"\) # returns the number of people older than 26) + comment(# Person.find("age > 26 AND job.salary > 60000", "LEFT JOIN jobs on jobs.person_id = person.id"\) # returns the total number of rows matching the conditions and joins fetched by SELECT COUNT(*\).) + comment(#) + comment(# Examples for count with options:) + comment(# Person.count(:conditions => "age > 26"\)) + comment(# Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job\) # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN.) + comment(# Person.count(:conditions => "age > 26 AND job.salary > 60000", :joins => "LEFT JOIN jobs on jobs.person_id = person.id"\) # finds the number of rows matching the conditions and joins. ) + comment(# Person.count('id', :conditions => "age > 26"\) # Performs a COUNT(id\)) + comment(# Person.count(:all, :conditions => "age > 26"\) # Performs a COUNT(*\) (:all is an alias for '*'\)) + comment(#) + comment(# Note: Person.count(:all\) will not work because it will use :all as the condition. Use Person.count instead.) + reserved(def) method(count)operator(()operator(*)ident(args)operator(\)) + ident(options) operator(=) operator({)operator(}) + ident(column_name) operator(=) symbol(:all) + comment(# For backwards compatibility, we need to handle both count(conditions=nil, joins=nil\) or count(options={}\) or count(column_name=:all, options={}\).) + reserved(if) ident(args)operator(.)ident(size) operator(>)operator(=) integer(0) operator(&&) ident(args)operator(.)ident(size) operator(<=) integer(2) + reserved(if) ident(args)operator(.)ident(first)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(options) operator(=) ident(args)operator(.)ident(first) + reserved(elsif) ident(args)operator([)integer(1)operator(])operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + ident(options) operator(=) ident(args)operator([)integer(1)operator(]) + ident(column_name) operator(=) ident(args)operator(.)ident(first) + reserved(else) + comment(# Handle legacy paramter options: def count(conditions=nil, joins=nil\)) + ident(options)operator(.)ident(merge!)operator(()symbol(:conditions) operator(=)operator(>) ident(args)operator([)integer(0)operator(])operator(\)) reserved(if) ident(args)operator(.)ident(length) operator(>) integer(0) + ident(options)operator(.)ident(merge!)operator(()symbol(:joins) operator(=)operator(>) ident(args)operator([)integer(1)operator(])operator(\)) reserved(if) ident(args)operator(.)ident(length) operator(>) integer(1) + reserved(end) + reserved(else) + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")content(Unexpected parameters passed to count(*args\): expected either count(conditions=nil, joins=nil\) or count(options={}\))delimiter(")>operator(\)) + reserved(end) + + reserved(if) ident(options)operator([)symbol(:include)operator(]) operator(||) ident(scope)operator(()symbol(:find)operator(,) symbol(:include)operator(\)) + ident(count_with_associations)operator(()ident(options)operator(\)) + reserved(else) + ident(calculate)operator(()symbol(:count)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + comment(# Calculates average value on a given column. The value is returned as a float. See #calculate for examples with options.) + comment(#) + comment(# Person.average('age'\)) + reserved(def) method(average)operator(()ident(column_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(calculate)operator(()symbol(:avg)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Calculates the minimum value on a given column. The value is returned with the same data type of the column.. See #calculate for examples with options.) + comment(#) + comment(# Person.minimum('age'\)) + reserved(def) method(minimum)operator(()ident(column_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(calculate)operator(()symbol(:min)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Calculates the maximum value on a given column. The value is returned with the same data type of the column.. See #calculate for examples with options.) + comment(#) + comment(# Person.maximum('age'\)) + reserved(def) method(maximum)operator(()ident(column_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(calculate)operator(()symbol(:max)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# Calculates the sum value on a given column. The value is returned with the same data type of the column.. See #calculate for examples with options.) + comment(#) + comment(# Person.sum('age'\)) + reserved(def) method(sum)operator(()ident(column_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(calculate)operator(()symbol(:sum)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + reserved(end) + + comment(# This calculates aggregate values in the given column: Methods for count, sum, average, minimum, and maximum have been added as shortcuts.) + comment(# Options such as :conditions, :order, :group, :having, and :joins can be passed to customize the query. ) + comment(#) + comment(# There are two basic forms of output:) + comment(# * Single aggregate value: The single value is type cast to Fixnum for COUNT, Float for AVG, and the given column's type for everything else.) + comment(# * Grouped values: This returns an ordered hash of the values and groups them by the :group option. It takes either a column name, or the name ) + comment(# of a belongs_to association.) + comment(#) + comment(# values = Person.maximum(:age, :group => 'last_name'\)) + comment(# puts values["Drake"]) + comment(# => 43) + comment(#) + comment(# drake = Family.find_by_last_name('Drake'\)) + comment(# values = Person.maximum(:age, :group => :family\) # Person belongs_to :family) + comment(# puts values[drake]) + comment(# => 43) + comment(#) + comment(# values.each do |family, max_age|) + comment(# ...) + comment(# end) + comment(#) + comment(# Options:) + comment(# * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.) + comment(# * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed\).) + comment(# The records will be returned read-only since they will have attributes that do not correspond to the table's columns.) + comment(# * <tt>:order</tt>: An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations\).) + comment(# * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause.) + comment(# * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not) + comment(# include the joined columns.) + comment(# * <tt>:distinct</tt>: Set this to true to make this a distinct calculation, such as SELECT COUNT(DISTINCT posts.id\) ...) + comment(#) + comment(# Examples:) + comment(# Person.calculate(:count, :all\) # The same as Person.count) + comment(# Person.average(:age\) # SELECT AVG(age\) FROM people...) + comment(# Person.minimum(:age, :conditions => ['last_name != ?', 'Drake']\) # Selects the minimum age for everyone with a last name other than 'Drake') + comment(# Person.minimum(:age, :having => 'min(age\) > 17', :group => :last_name\) # Selects the minimum age for any family without any minors) + reserved(def) method(calculate)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(validate_calculation_options)operator(()ident(operation)operator(,) ident(options)operator(\)) + ident(column_name) operator(=) ident(options)operator([)symbol(:select)operator(]) reserved(if) ident(options)operator([)symbol(:select)operator(]) + ident(column_name) operator(=) string<delimiter(')content(*)delimiter(')> reserved(if) ident(column_name) operator(==) symbol(:all) + ident(column) operator(=) ident(column_for) ident(column_name) + ident(aggregate) operator(=) ident(select_aggregate)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + ident(aggregate_alias) operator(=) ident(column_alias_for)operator(()ident(operation)operator(,) ident(column_name)operator(\)) + reserved(if) ident(options)operator([)symbol(:group)operator(]) + ident(execute_grouped_calculation)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(column)operator(,) ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(\)) + reserved(else) + ident(execute_simple_calculation)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(column)operator(,) ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(construct_calculation_sql)operator(()ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(scope) operator(=) ident(scope)operator(()symbol(:find)operator(\)) + ident(sql) operator(=) string<delimiter(")content(SELECT )inline<inline_delimiter(#{)ident(aggregate)inline_delimiter(})>content( AS )inline<inline_delimiter(#{)ident(aggregate_alias)inline_delimiter(})>delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(, )inline<inline_delimiter(#{)ident(options)operator([)symbol(:group_field)operator(])inline_delimiter(})>content( AS )inline<inline_delimiter(#{)ident(options)operator([)symbol(:group_alias)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:group)operator(]) + ident(sql) operator(<<) string<delimiter(")content( FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )delimiter(")> + ident(add_joins!)operator(()ident(sql)operator(,) ident(options)operator(,) ident(scope)operator(\)) + ident(add_conditions!)operator(()ident(sql)operator(,) ident(options)operator([)symbol(:conditions)operator(])operator(,) ident(scope)operator(\)) + ident(sql) operator(<<) string<delimiter(")content( GROUP BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:group_field)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:group)operator(]) + ident(sql) operator(<<) string<delimiter(")content( HAVING )inline<inline_delimiter(#{)ident(options)operator([)symbol(:having)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:group)operator(]) operator(&&) ident(options)operator([)symbol(:having)operator(]) + ident(sql) operator(<<) string<delimiter(")content( ORDER BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:order)operator(]) + ident(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(\)) + ident(sql) + reserved(end) + + reserved(def) method(execute_simple_calculation)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(column)operator(,) ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(value) operator(=) ident(connection)operator(.)ident(select_value)operator(()ident(construct_calculation_sql)operator(()ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(\))operator(\)) + ident(type_cast_calculated_value)operator(()ident(value)operator(,) ident(column)operator(,) ident(operation)operator(\)) + reserved(end) + + reserved(def) method(execute_grouped_calculation)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(column)operator(,) ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(group_attr) operator(=) ident(options)operator([)symbol(:group)operator(])operator(.)ident(to_s) + ident(association) operator(=) ident(reflect_on_association)operator(()ident(group_attr)operator(.)ident(to_sym)operator(\)) + ident(associated) operator(=) ident(association) operator(&&) ident(association)operator(.)ident(macro) operator(==) symbol(:belongs_to) comment(# only count belongs_to associations) + ident(group_field) operator(=) operator(()ident(associated) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:group)operator(])inline_delimiter(})>content(_id)delimiter(")> operator(:) ident(options)operator([)symbol(:group)operator(])operator(\))operator(.)ident(to_s) + ident(group_alias) operator(=) ident(column_alias_for)operator(()ident(group_field)operator(\)) + ident(group_column) operator(=) ident(column_for) ident(group_field) + ident(sql) operator(=) ident(construct_calculation_sql)operator(()ident(aggregate)operator(,) ident(aggregate_alias)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:group_field) operator(=)operator(>) ident(group_field)operator(,) symbol(:group_alias) operator(=)operator(>) ident(group_alias)operator(\))operator(\)) + ident(calculated_data) operator(=) ident(connection)operator(.)ident(select_all)operator(()ident(sql)operator(\)) + + reserved(if) ident(association) + ident(key_ids) operator(=) ident(calculated_data)operator(.)ident(collect) operator({) operator(|)ident(row)operator(|) ident(row)operator([)ident(group_alias)operator(]) operator(}) + ident(key_records) operator(=) ident(association)operator(.)ident(klass)operator(.)ident(base_class)operator(.)ident(find)operator(()ident(key_ids)operator(\)) + ident(key_records) operator(=) ident(key_records)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(hsh)operator(,) ident(r)operator(|) ident(hsh)operator(.)ident(merge)operator(()ident(r)operator(.)ident(id) operator(=)operator(>) ident(r)operator(\)) operator(}) + reserved(end) + + ident(calculated_data)operator(.)ident(inject)operator(()constant(OrderedHash)operator(.)ident(new)operator(\)) reserved(do) operator(|)ident(all)operator(,) ident(row)operator(|) + ident(key) operator(=) ident(associated) operator(?) ident(key_records)operator([)ident(row)operator([)ident(group_alias)operator(])operator(.)ident(to_i)operator(]) operator(:) ident(type_cast_calculated_value)operator(()ident(row)operator([)ident(group_alias)operator(])operator(,) ident(group_column)operator(\)) + ident(value) operator(=) ident(row)operator([)ident(aggregate_alias)operator(]) + ident(all) operator(<<) operator([)ident(key)operator(,) ident(type_cast_calculated_value)operator(()ident(value)operator(,) ident(column)operator(,) ident(operation)operator(\))operator(]) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(validate_calculation_options)operator(()ident(operation)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(operation)operator(.)ident(to_s) operator(==) string<delimiter(')content(count)delimiter(')> + ident(options)operator(.)ident(assert_valid_keys)operator(()constant(CALCULATIONS_OPTIONS) operator(+) operator([)symbol(:include)operator(])operator(\)) + reserved(else) + ident(options)operator(.)ident(assert_valid_keys)operator(()constant(CALCULATIONS_OPTIONS)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(select_aggregate)operator(()ident(operation)operator(,) ident(column_name)operator(,) ident(options)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(operation)inline_delimiter(})>content(()inline<inline_delimiter(#{)string<delimiter(')content(DISTINCT )delimiter(')> reserved(if) ident(options)operator([)symbol(:distinct)operator(])inline_delimiter(})>inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + comment(# converts a given key to the value that the database adapter returns as) + comment(#) + comment(# users.id #=> users_id) + comment(# sum(id\) #=> sum_id) + comment(# count(distinct users.id\) #=> count_distinct_users_id) + comment(# count(*\) #=> count_all) + reserved(def) method(column_alias_for)operator(()operator(*)ident(keys)operator(\)) + ident(keys)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\))operator(.)ident(downcase)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\*)delimiter(/)>operator(,) string<delimiter(')content(all)delimiter(')>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\W)content(+)delimiter(/)>operator(,) string<delimiter(')content( )delimiter(')>operator(\))operator(.)ident(strip)operator(.)ident(gsub)operator(()regexp<delimiter(/)content( +)delimiter(/)>operator(,) string<delimiter(')content(_)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(column_for)operator(()ident(field)operator(\)) + ident(field_name) operator(=) ident(field)operator(.)ident(to_s)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(.)ident(last) + ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name)operator(.)ident(to_s) operator(==) ident(field_name) operator(}) + reserved(end) + + reserved(def) method(type_cast_calculated_value)operator(()ident(value)operator(,) ident(column)operator(,) ident(operation) operator(=) pre_constant(nil)operator(\)) + ident(operation) operator(=) ident(operation)operator(.)ident(to_s)operator(.)ident(downcase) + reserved(case) ident(operation) + reserved(when) string<delimiter(')content(count)delimiter(')> reserved(then) ident(value)operator(.)ident(to_i) + reserved(when) string<delimiter(')content(avg)delimiter(')> reserved(then) ident(value)operator(.)ident(to_f) + reserved(else) ident(column) operator(?) ident(column)operator(.)ident(type_cast)operator(()ident(value)operator(\)) operator(:) ident(value) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(observer)delimiter(')> + +reserved(module) class(ActiveRecord) + comment(# Callbacks are hooks into the lifecycle of an Active Record object that allows you to trigger logic) + comment(# before or after an alteration of the object state. This can be used to make sure that associated and) + comment(# dependent objects are deleted when destroy is called (by overwriting before_destroy\) or to massage attributes) + comment(# before they're validated (by overwriting before_validation\). As an example of the callbacks initiated, consider) + comment(# the Base#save call:) + comment(#) + comment(# * (-\) save) + comment(# * (-\) valid?) + comment(# * (1\) before_validation) + comment(# * (2\) before_validation_on_create) + comment(# * (-\) validate) + comment(# * (-\) validate_on_create) + comment(# * (3\) after_validation) + comment(# * (4\) after_validation_on_create) + comment(# * (5\) before_save) + comment(# * (6\) before_create) + comment(# * (-\) create) + comment(# * (7\) after_create) + comment(# * (8\) after_save) + comment(#) + comment(# That's a total of eight callbacks, which gives you immense power to react and prepare for each state in the) + comment(# Active Record lifecycle.) + comment(#) + comment(# Examples:) + comment(# class CreditCard < ActiveRecord::Base) + comment(# # Strip everything but digits, so the user can specify "555 234 34" or) + comment(# # "5552-3434" or both will mean "55523434") + comment(# def before_validation_on_create) + comment(# self.number = number.gsub(/[^0-9]/, ""\) if attribute_present?("number"\)) + comment(# end) + comment(# end) + comment(#) + comment(# class Subscription < ActiveRecord::Base) + comment(# before_create :record_signup) + comment(#) + comment(# private) + comment(# def record_signup) + comment(# self.signed_up_on = Date.today) + comment(# end) + comment(# end) + comment(#) + comment(# class Firm < ActiveRecord::Base) + comment(# # Destroys the associated clients and people when the firm is destroyed) + comment(# before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }) + comment(# before_destroy { |record| Client.destroy_all "client_of = #{record.id}" }) + comment(# end) + comment(#) + comment(# == Inheritable callback queues) + comment(#) + comment(# Besides the overwriteable callback methods, it's also possible to register callbacks through the use of the callback macros.) + comment(# Their main advantage is that the macros add behavior into a callback queue that is kept intact down through an inheritance) + comment(# hierarchy. Example:) + comment(#) + comment(# class Topic < ActiveRecord::Base) + comment(# before_destroy :destroy_author) + comment(# end) + comment(#) + comment(# class Reply < Topic) + comment(# before_destroy :destroy_readers) + comment(# end) + comment(#) + comment(# Now, when Topic#destroy is run only +destroy_author+ is called. When Reply#destroy is run both +destroy_author+ and) + comment(# +destroy_readers+ is called. Contrast this to the situation where we've implemented the save behavior through overwriteable) + comment(# methods:) + comment(#) + comment(# class Topic < ActiveRecord::Base) + comment(# def before_destroy(\) destroy_author end) + comment(# end) + comment(#) + comment(# class Reply < Topic) + comment(# def before_destroy(\) destroy_readers end) + comment(# end) + comment(#) + comment(# In that case, Reply#destroy would only run +destroy_readers+ and _not_ +destroy_author+. So use the callback macros when) + comment(# you want to ensure that a certain callback is called for the entire hierarchy and the regular overwriteable methods when you) + comment(# want to leave it up to each descendent to decide whether they want to call +super+ and trigger the inherited callbacks.) + comment(#) + comment(# *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the callbacks before specifying the) + comment(# associations. Otherwise, you might trigger the loading of a child before the parent has registered the callbacks and they won't) + comment(# be inherited.) + comment(#) + comment(# == Types of callbacks) + comment(#) + comment(# There are four types of callbacks accepted by the callback macros: Method references (symbol\), callback objects,) + comment(# inline methods (using a proc\), and inline eval methods (using a string\). Method references and callback objects are the) + comment(# recommended approaches, inline methods using a proc are sometimes appropriate (such as for creating mix-ins\), and inline) + comment(# eval methods are deprecated.) + comment(#) + comment(# The method reference callbacks work by specifying a protected or private method available in the object, like this:) + comment(#) + comment(# class Topic < ActiveRecord::Base) + comment(# before_destroy :delete_parents) + comment(#) + comment(# private) + comment(# def delete_parents) + comment(# self.class.delete_all "parent_id = #{id}") + comment(# end) + comment(# end) + comment(#) + comment(# The callback objects have methods named after the callback called with the record as the only parameter, such as:) + comment(#) + comment(# class BankAccount < ActiveRecord::Base) + comment(# before_save EncryptionWrapper.new("credit_card_number"\)) + comment(# after_save EncryptionWrapper.new("credit_card_number"\)) + comment(# after_initialize EncryptionWrapper.new("credit_card_number"\)) + comment(# end) + comment(#) + comment(# class EncryptionWrapper) + comment(# def initialize(attribute\)) + comment(# @attribute = attribute) + comment(# end) + comment(#) + comment(# def before_save(record\)) + comment(# record.credit_card_number = encrypt(record.credit_card_number\)) + comment(# end) + comment(#) + comment(# def after_save(record\)) + comment(# record.credit_card_number = decrypt(record.credit_card_number\)) + comment(# end) + comment(#) + comment(# alias_method :after_find, :after_save) + comment(#) + comment(# private) + comment(# def encrypt(value\)) + comment(# # Secrecy is committed) + comment(# end) + comment(#) + comment(# def decrypt(value\)) + comment(# # Secrecy is unveiled) + comment(# end) + comment(# end) + comment(#) + comment(# So you specify the object you want messaged on a given callback. When that callback is triggered, the object has) + comment(# a method by the name of the callback messaged.) + comment(#) + comment(# The callback macros usually accept a symbol for the method they're supposed to run, but you can also pass a "method string",) + comment(# which will then be evaluated within the binding of the callback. Example:) + comment(#) + comment(# class Topic < ActiveRecord::Base) + comment(# before_destroy 'self.class.delete_all "parent_id = #{id}"') + comment(# end) + comment(#) + comment(# Notice that single plings ('\) are used so the #{id} part isn't evaluated until the callback is triggered. Also note that these) + comment(# inline callbacks can be stacked just like the regular ones:) + comment(#) + comment(# class Topic < ActiveRecord::Base) + comment(# before_destroy 'self.class.delete_all "parent_id = #{id}"',) + comment(# 'puts "Evaluated after parents are destroyed"') + comment(# end) + comment(#) + comment(# == The after_find and after_initialize exceptions) + comment(#) + comment(# Because after_find and after_initialize are called for each object found and instantiated by a finder, such as Base.find(:all\), we've had) + comment(# to implement a simple performance constraint (50% more speed on a simple test case\). Unlike all the other callbacks, after_find and) + comment(# after_initialize will only be run if an explicit implementation is defined (<tt>def after_find</tt>\). In that case, all of the) + comment(# callback types will be called.) + comment(#) + comment(# == Cancelling callbacks) + comment(#) + comment(# If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns) + comment(# false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks) + comment(# defined as methods on the model, which are called last.) + reserved(module) class(Callbacks) + constant(CALLBACKS) operator(=) string<delimiter(%w()content( + after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation + after_validation before_validation_on_create after_validation_on_create before_validation_on_update + after_validation_on_update before_destroy after_destroy + )delimiter(\))> + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + ident(base)operator(.)ident(class_eval) reserved(do) + reserved(class) operator(<<) class(self) + ident(include) constant(Observable) + ident(alias_method) symbol(:instantiate_without_callbacks)operator(,) symbol(:instantiate) + ident(alias_method) symbol(:instantiate)operator(,) symbol(:instantiate_with_callbacks) + reserved(end) + + ident(alias_method) symbol(:initialize_without_callbacks)operator(,) symbol(:initialize) + ident(alias_method) symbol(:initialize)operator(,) symbol(:initialize_with_callbacks) + + ident(alias_method) symbol(:create_or_update_without_callbacks)operator(,) symbol(:create_or_update) + ident(alias_method) symbol(:create_or_update)operator(,) symbol(:create_or_update_with_callbacks) + + ident(alias_method) symbol(:valid_without_callbacks)operator(,) symbol(:valid?) + ident(alias_method) symbol(:valid?)operator(,) symbol(:valid_with_callbacks) + + ident(alias_method) symbol(:create_without_callbacks)operator(,) symbol(:create) + ident(alias_method) symbol(:create)operator(,) symbol(:create_with_callbacks) + + ident(alias_method) symbol(:update_without_callbacks)operator(,) symbol(:update) + ident(alias_method) symbol(:update)operator(,) symbol(:update_with_callbacks) + + ident(alias_method) symbol(:destroy_without_callbacks)operator(,) symbol(:destroy) + ident(alias_method) symbol(:destroy)operator(,) symbol(:destroy_with_callbacks) + reserved(end) + + constant(CALLBACKS)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(base)operator(.)ident(class_eval) string<delimiter(<<-"end_eval")>string<content( + def self.)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content((*callbacks, &block\) + callbacks << block if block_given? + write_inheritable_array()inline<inline_delimiter(#{)ident(method)operator(.)ident(to_sym)operator(.)ident(inspect)inline_delimiter(})>content(, callbacks\) + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + reserved(def) method(instantiate_with_callbacks)operator(()ident(record)operator(\)) + ident(object) operator(=) ident(instantiate_without_callbacks)operator(()ident(record)operator(\)) + + reserved(if) ident(object)operator(.)ident(respond_to_without_attributes?)operator(()symbol(:after_find)operator(\)) + ident(object)operator(.)ident(send)operator(()symbol(:callback)operator(,) symbol(:after_find)operator(\)) + reserved(end) + + reserved(if) ident(object)operator(.)ident(respond_to_without_attributes?)operator(()symbol(:after_initialize)operator(\)) + ident(object)operator(.)ident(send)operator(()symbol(:callback)operator(,) symbol(:after_initialize)operator(\)) + reserved(end) + + ident(object) + reserved(end) + reserved(end) + + comment(# Is called when the object was instantiated by one of the finders, like Base.find.) + comment(#def after_find(\) end) + + comment(# Is called after the object has been instantiated by a call to Base.new.) + comment(#def after_initialize(\) end) + + reserved(def) method(initialize_with_callbacks)operator(()ident(attributes) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(initialize_without_callbacks)operator(()ident(attributes)operator(\)) + ident(result) operator(=) reserved(yield) pre_constant(self) reserved(if) ident(block_given?) + ident(callback)operator(()symbol(:after_initialize)operator(\)) reserved(if) ident(respond_to_without_attributes?)operator(()symbol(:after_initialize)operator(\)) + ident(result) + reserved(end) + + comment(# Is called _before_ Base.save (regardless of whether it's a create or update save\).) + reserved(def) method(before_save)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Base.save (regardless of whether it's a create or update save\).) + comment(#) + comment(# class Contact < ActiveRecord::Base) + comment(# after_save { logger.info( 'New contact saved!' \) }) + comment(# end) + reserved(def) method(after_save)operator(()operator(\)) reserved(end) + reserved(def) method(create_or_update_with_callbacks) comment(#:nodoc:) + reserved(return) pre_constant(false) reserved(if) ident(callback)operator(()symbol(:before_save)operator(\)) operator(==) pre_constant(false) + ident(result) operator(=) ident(create_or_update_without_callbacks) + ident(callback)operator(()symbol(:after_save)operator(\)) + ident(result) + reserved(end) + + comment(# Is called _before_ Base.save on new objects that haven't been saved yet (no record exists\).) + reserved(def) method(before_create)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Base.save on new objects that haven't been saved yet (no record exists\).) + reserved(def) method(after_create)operator(()operator(\)) reserved(end) + reserved(def) method(create_with_callbacks) comment(#:nodoc:) + reserved(return) pre_constant(false) reserved(if) ident(callback)operator(()symbol(:before_create)operator(\)) operator(==) pre_constant(false) + ident(result) operator(=) ident(create_without_callbacks) + ident(callback)operator(()symbol(:after_create)operator(\)) + ident(result) + reserved(end) + + comment(# Is called _before_ Base.save on existing objects that have a record.) + reserved(def) method(before_update)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Base.save on existing objects that have a record.) + reserved(def) method(after_update)operator(()operator(\)) reserved(end) + + reserved(def) method(update_with_callbacks) comment(#:nodoc:) + reserved(return) pre_constant(false) reserved(if) ident(callback)operator(()symbol(:before_update)operator(\)) operator(==) pre_constant(false) + ident(result) operator(=) ident(update_without_callbacks) + ident(callback)operator(()symbol(:after_update)operator(\)) + ident(result) + reserved(end) + + comment(# Is called _before_ Validations.validate (which is part of the Base.save call\).) + reserved(def) method(before_validation)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Validations.validate (which is part of the Base.save call\).) + reserved(def) method(after_validation)operator(()operator(\)) reserved(end) + + comment(# Is called _before_ Validations.validate (which is part of the Base.save call\) on new objects) + comment(# that haven't been saved yet (no record exists\).) + reserved(def) method(before_validation_on_create)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Validations.validate (which is part of the Base.save call\) on new objects) + comment(# that haven't been saved yet (no record exists\).) + reserved(def) method(after_validation_on_create)operator(()operator(\)) reserved(end) + + comment(# Is called _before_ Validations.validate (which is part of the Base.save call\) on) + comment(# existing objects that have a record.) + reserved(def) method(before_validation_on_update)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Validations.validate (which is part of the Base.save call\) on) + comment(# existing objects that have a record.) + reserved(def) method(after_validation_on_update)operator(()operator(\)) reserved(end) + + reserved(def) method(valid_with_callbacks) comment(#:nodoc:) + reserved(return) pre_constant(false) reserved(if) ident(callback)operator(()symbol(:before_validation)operator(\)) operator(==) pre_constant(false) + reserved(if) ident(new_record?) reserved(then) ident(result) operator(=) ident(callback)operator(()symbol(:before_validation_on_create)operator(\)) reserved(else) ident(result) operator(=) ident(callback)operator(()symbol(:before_validation_on_update)operator(\)) reserved(end) + reserved(return) pre_constant(false) reserved(if) ident(result) operator(==) pre_constant(false) + + ident(result) operator(=) ident(valid_without_callbacks) + + ident(callback)operator(()symbol(:after_validation)operator(\)) + reserved(if) ident(new_record?) reserved(then) ident(callback)operator(()symbol(:after_validation_on_create)operator(\)) reserved(else) ident(callback)operator(()symbol(:after_validation_on_update)operator(\)) reserved(end) + + reserved(return) ident(result) + reserved(end) + + comment(# Is called _before_ Base.destroy.) + comment(#) + comment(# Note: If you need to _destroy_ or _nullify_ associated records first,) + comment(# use the _:dependent_ option on your associations.) + reserved(def) method(before_destroy)operator(()operator(\)) reserved(end) + + comment(# Is called _after_ Base.destroy (and all the attributes have been frozen\).) + comment(#) + comment(# class Contact < ActiveRecord::Base) + comment(# after_destroy { |record| logger.info( "Contact #{record.id} was destroyed." \) }) + comment(# end) + reserved(def) method(after_destroy)operator(()operator(\)) reserved(end) + reserved(def) method(destroy_with_callbacks) comment(#:nodoc:) + reserved(return) pre_constant(false) reserved(if) ident(callback)operator(()symbol(:before_destroy)operator(\)) operator(==) pre_constant(false) + ident(result) operator(=) ident(destroy_without_callbacks) + ident(callback)operator(()symbol(:after_destroy)operator(\)) + ident(result) + reserved(end) + + ident(private) + reserved(def) method(callback)operator(()ident(method)operator(\)) + ident(notify)operator(()ident(method)operator(\)) + + ident(callbacks_for)operator(()ident(method)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(callback)operator(|) + ident(result) operator(=) reserved(case) ident(callback) + reserved(when) constant(Symbol) + pre_constant(self)operator(.)ident(send)operator(()ident(callback)operator(\)) + reserved(when) constant(String) + ident(eval)operator(()ident(callback)operator(,) ident(binding)operator(\)) + reserved(when) constant(Proc)operator(,) constant(Method) + ident(callback)operator(.)ident(call)operator(()pre_constant(self)operator(\)) + reserved(else) + reserved(if) ident(callback)operator(.)ident(respond_to?)operator(()ident(method)operator(\)) + ident(callback)operator(.)ident(send)operator(()ident(method)operator(,) pre_constant(self)operator(\)) + reserved(else) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")content(Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method.)delimiter(")> + reserved(end) + reserved(end) + reserved(return) pre_constant(false) reserved(if) ident(result) operator(==) pre_constant(false) + reserved(end) + + ident(result) operator(=) ident(send)operator(()ident(method)operator(\)) reserved(if) ident(respond_to_without_attributes?)operator(()ident(method)operator(\)) + + reserved(return) ident(result) + reserved(end) + + reserved(def) method(callbacks_for)operator(()ident(method)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(read_inheritable_attribute)operator(()ident(method)operator(.)ident(to_sym)operator(\)) reserved(or) operator([)operator(]) + reserved(end) + + reserved(def) method(invoke_and_notify)operator(()ident(method)operator(\)) + ident(notify)operator(()ident(method)operator(\)) + ident(send)operator(()ident(method)operator(\)) reserved(if) ident(respond_to_without_attributes?)operator(()ident(method)operator(\)) + reserved(end) + + reserved(def) method(notify)operator(()ident(method)operator(\)) comment(#:nodoc:) + pre_constant(self)operator(.)ident(class)operator(.)ident(changed) + pre_constant(self)operator(.)ident(class)operator(.)ident(notify_observers)operator(()ident(method)operator(,) pre_constant(self)operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(set)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + reserved(class) class(ConnectionSpecification) comment(#:nodoc:) + ident(attr_reader) symbol(:config)operator(,) symbol(:adapter_method) + reserved(def) method(initialize) operator(()ident(config)operator(,) ident(adapter_method)operator(\)) + instance_variable(@config)operator(,) instance_variable(@adapter_method) operator(=) ident(config)operator(,) ident(adapter_method) + reserved(end) + reserved(end) + + comment(# Check for activity after at least +verification_timeout+ seconds.) + comment(# Defaults to 0 (always check.\)) + ident(cattr_accessor) symbol(:verification_timeout) + class_variable(@@verification_timeout) operator(=) integer(0) + + comment(# The class -> [adapter_method, config] map) + class_variable(@@defined_connections) operator(=) operator({)operator(}) + + comment(# The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency\)) + class_variable(@@active_connections) operator(=) operator({)operator(}) + + reserved(class) operator(<<) class(self) + comment(# Retrieve the connection cache.) + reserved(def) method(thread_safe_active_connections) comment(#:nodoc:) + class_variable(@@active_connections)operator([)constant(Thread)operator(.)ident(current)operator(.)ident(object_id)operator(]) operator(||=) operator({)operator(}) + reserved(end) + + reserved(def) method(single_threaded_active_connections) comment(#:nodoc:) + class_variable(@@active_connections) + reserved(end) + + comment(# pick up the right active_connection method from @@allow_concurrency) + reserved(if) class_variable(@@allow_concurrency) + ident(alias_method) symbol(:active_connections)operator(,) symbol(:thread_safe_active_connections) + reserved(else) + ident(alias_method) symbol(:active_connections)operator(,) symbol(:single_threaded_active_connections) + reserved(end) + + comment(# set concurrency support flag (not thread safe, like most of the methods in this file\)) + reserved(def) method(allow_concurrency=)operator(()ident(threaded)operator(\)) comment(#:nodoc:) + ident(logger)operator(.)ident(debug) string<delimiter(")content(allow_concurrency=)inline<inline_delimiter(#{)ident(threaded)inline_delimiter(})>delimiter(")> reserved(if) ident(logger) + reserved(return) reserved(if) class_variable(@@allow_concurrency) operator(==) ident(threaded) + ident(clear_all_cached_connections!) + class_variable(@@allow_concurrency) operator(=) ident(threaded) + ident(method_prefix) operator(=) ident(threaded) operator(?) string<delimiter(")content(thread_safe)delimiter(")> operator(:) string<delimiter(")content(single_threaded)delimiter(")> + ident(sing) operator(=) operator(()reserved(class) operator(<<) class(self)operator(;) pre_constant(self)operator(;) reserved(end)operator(\)) + operator([)symbol(:active_connections)operator(,) symbol(:scoped_methods)operator(])operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(sing)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) ident(method)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(method_prefix)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + ident(log_connections) reserved(if) ident(logger) + reserved(end) + + reserved(def) method(active_connection_name) comment(#:nodoc:) + instance_variable(@active_connection_name) operator(||=) + reserved(if) ident(active_connections)operator([)ident(name)operator(]) operator(||) class_variable(@@defined_connections)operator([)ident(name)operator(]) + ident(name) + reserved(elsif) pre_constant(self) operator(==) constant(ActiveRecord)operator(::)constant(Base) + pre_constant(nil) + reserved(else) + ident(superclass)operator(.)ident(active_connection_name) + reserved(end) + reserved(end) + + reserved(def) method(clear_active_connection_name) comment(#:nodoc:) + instance_variable(@active_connection_name) operator(=) pre_constant(nil) + ident(subclasses)operator(.)ident(each) operator({) operator(|)ident(klass)operator(|) ident(klass)operator(.)ident(clear_active_connection_name) operator(}) + reserved(end) + + comment(# Returns the connection currently associated with the class. This can) + comment(# also be used to "borrow" the connection to do database work unrelated) + comment(# to any of the specific Active Records.) + reserved(def) method(connection) + reserved(if) instance_variable(@active_connection_name) operator(&&) operator(()ident(conn) operator(=) ident(active_connections)operator([)instance_variable(@active_connection_name)operator(])operator(\)) + ident(conn) + reserved(else) + comment(# retrieve_connection sets the cache key.) + ident(conn) operator(=) ident(retrieve_connection) + ident(active_connections)operator([)instance_variable(@active_connection_name)operator(]) operator(=) ident(conn) + reserved(end) + reserved(end) + + comment(# Clears the cache which maps classes to connections.) + reserved(def) method(clear_active_connections!) + ident(clear_cache!)operator(()class_variable(@@active_connections)operator(\)) reserved(do) operator(|)ident(name)operator(,) ident(conn)operator(|) + ident(conn)operator(.)ident(disconnect!) + reserved(end) + reserved(end) + + comment(# Verify active connections.) + reserved(def) method(verify_active_connections!) comment(#:nodoc:) + reserved(if) class_variable(@@allow_concurrency) + ident(remove_stale_cached_threads!)operator(()class_variable(@@active_connections)operator(\)) reserved(do) operator(|)ident(name)operator(,) ident(conn)operator(|) + ident(conn)operator(.)ident(disconnect!) + reserved(end) + reserved(end) + + ident(active_connections)operator(.)ident(each_value) reserved(do) operator(|)ident(connection)operator(|) + ident(connection)operator(.)ident(verify!)operator(()class_variable(@@verification_timeout)operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(clear_cache!)operator(()ident(cache)operator(,) ident(thread_id) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + reserved(if) ident(cache) + reserved(if) class_variable(@@allow_concurrency) + ident(thread_id) operator(||=) constant(Thread)operator(.)ident(current)operator(.)ident(object_id) + ident(thread_cache)operator(,) ident(cache) operator(=) ident(cache)operator(,) ident(cache)operator([)ident(thread_id)operator(]) + reserved(return) reserved(unless) ident(cache) + reserved(end) + + ident(cache)operator(.)ident(each)operator(()operator(&)ident(block)operator(\)) reserved(if) ident(block_given?) + ident(cache)operator(.)ident(clear) + reserved(end) + reserved(ensure) + reserved(if) ident(thread_cache) operator(&&) class_variable(@@allow_concurrency) + ident(thread_cache)operator(.)ident(delete)operator(()ident(thread_id)operator(\)) + reserved(end) + reserved(end) + + comment(# Remove stale threads from the cache.) + reserved(def) method(remove_stale_cached_threads!)operator(()ident(cache)operator(,) operator(&)ident(block)operator(\)) + ident(stale) operator(=) constant(Set)operator(.)ident(new)operator(()ident(cache)operator(.)ident(keys)operator(\)) + + constant(Thread)operator(.)ident(list)operator(.)ident(each) reserved(do) operator(|)ident(thread)operator(|) + ident(stale)operator(.)ident(delete)operator(()ident(thread)operator(.)ident(object_id)operator(\)) reserved(if) ident(thread)operator(.)ident(alive?) + reserved(end) + + ident(stale)operator(.)ident(each) reserved(do) operator(|)ident(thread_id)operator(|) + ident(clear_cache!)operator(()ident(cache)operator(,) ident(thread_id)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(clear_all_cached_connections!) + reserved(if) class_variable(@@allow_concurrency) + class_variable(@@active_connections)operator(.)ident(each_value) reserved(do) operator(|)ident(connection_hash_for_thread)operator(|) + ident(connection_hash_for_thread)operator(.)ident(each_value) operator({)operator(|)ident(conn)operator(|) ident(conn)operator(.)ident(disconnect!) operator(}) + ident(connection_hash_for_thread)operator(.)ident(clear) + reserved(end) + reserved(else) + class_variable(@@active_connections)operator(.)ident(each_value) operator({)operator(|)ident(conn)operator(|) ident(conn)operator(.)ident(disconnect!) operator(}) + reserved(end) + class_variable(@@active_connections)operator(.)ident(clear) + reserved(end) + reserved(end) + + comment(# Returns the connection currently associated with the class. This can) + comment(# also be used to "borrow" the connection to do database work that isn't) + comment(# easily done without going straight to SQL.) + reserved(def) method(connection) + pre_constant(self)operator(.)ident(class)operator(.)ident(connection) + reserved(end) + + comment(# Establishes the connection to the database. Accepts a hash as input where) + comment(# the :adapter key must be specified with the name of a database adapter (in lower-case\)) + comment(# example for regular databases (MySQL, Postgresql, etc\):) + comment(#) + comment(# ActiveRecord::Base.establish_connection() + comment(# :adapter => "mysql",) + comment(# :host => "localhost",) + comment(# :username => "myuser",) + comment(# :password => "mypass",) + comment(# :database => "somedatabase") + comment(# \)) + comment(#) + comment(# Example for SQLite database:) + comment(#) + comment(# ActiveRecord::Base.establish_connection() + comment(# :adapter => "sqlite",) + comment(# :database => "path/to/dbfile") + comment(# \)) + comment(#) + comment(# Also accepts keys as strings (for parsing from yaml for example\):) + comment(# ActiveRecord::Base.establish_connection() + comment(# "adapter" => "sqlite",) + comment(# "database" => "path/to/dbfile") + comment(# \)) + comment(#) + comment(# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError) + comment(# may be returned on an error.) + reserved(def) pre_constant(self)operator(.)ident(establish_connection)operator(()ident(spec) operator(=) pre_constant(nil)operator(\)) + reserved(case) ident(spec) + reserved(when) pre_constant(nil) + ident(raise) constant(AdapterNotSpecified) reserved(unless) reserved(defined?) constant(RAILS_ENV) + ident(establish_connection)operator(()constant(RAILS_ENV)operator(\)) + reserved(when) constant(ConnectionSpecification) + ident(clear_active_connection_name) + instance_variable(@active_connection_name) operator(=) ident(name) + class_variable(@@defined_connections)operator([)ident(name)operator(]) operator(=) ident(spec) + reserved(when) constant(Symbol)operator(,) constant(String) + reserved(if) ident(configuration) operator(=) ident(configurations)operator([)ident(spec)operator(.)ident(to_s)operator(]) + ident(establish_connection)operator(()ident(configuration)operator(\)) + reserved(else) + ident(raise) constant(AdapterNotSpecified)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(spec)inline_delimiter(})>content( database is not configured)delimiter(")> + reserved(end) + reserved(else) + ident(spec) operator(=) ident(spec)operator(.)ident(symbolize_keys) + reserved(unless) ident(spec)operator(.)ident(key?)operator(()symbol(:adapter)operator(\)) reserved(then) ident(raise) constant(AdapterNotSpecified)operator(,) string<delimiter(")content(database configuration does not specify adapter)delimiter(")> reserved(end) + ident(adapter_method) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(spec)operator([)symbol(:adapter)operator(])inline_delimiter(})>content(_connection)delimiter(")> + reserved(unless) ident(respond_to?)operator(()ident(adapter_method)operator(\)) reserved(then) ident(raise) constant(AdapterNotFound)operator(,) string<delimiter(")content(database configuration specifies nonexistent )inline<inline_delimiter(#{)ident(spec)operator([)symbol(:adapter)operator(])inline_delimiter(})>content( adapter)delimiter(")> reserved(end) + ident(remove_connection) + ident(establish_connection)operator(()constant(ConnectionSpecification)operator(.)ident(new)operator(()ident(spec)operator(,) ident(adapter_method)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Locate the connection of the nearest super class. This can be an) + comment(# active or defined connections: if it is the latter, it will be) + comment(# opened and set as the active connection for the class it was defined) + comment(# for (not necessarily the current class\).) + reserved(def) pre_constant(self)operator(.)ident(retrieve_connection) comment(#:nodoc:) + comment(# Name is nil if establish_connection hasn't been called for) + comment(# some class along the inheritance chain up to AR::Base yet.) + reserved(if) ident(name) operator(=) ident(active_connection_name) + reserved(if) ident(conn) operator(=) ident(active_connections)operator([)ident(name)operator(]) + comment(# Verify the connection.) + ident(conn)operator(.)ident(verify!)operator(()class_variable(@@verification_timeout)operator(\)) + reserved(elsif) ident(spec) operator(=) class_variable(@@defined_connections)operator([)ident(name)operator(]) + comment(# Activate this connection specification.) + ident(klass) operator(=) ident(name)operator(.)ident(constantize) + ident(klass)operator(.)ident(connection) operator(=) ident(spec) + ident(conn) operator(=) ident(active_connections)operator([)ident(name)operator(]) + reserved(end) + reserved(end) + + ident(conn) reserved(or) ident(raise) constant(ConnectionNotEstablished) + reserved(end) + + comment(# Returns true if a connection that's accessible to this class have already been opened.) + reserved(def) pre_constant(self)operator(.)ident(connected?) + ident(active_connections)operator([)ident(active_connection_name)operator(]) operator(?) pre_constant(true) operator(:) pre_constant(false) + reserved(end) + + comment(# Remove the connection for this class. This will close the active) + comment(# connection and the defined connection (if they exist\). The result) + comment(# can be used as argument for establish_connection, for easy) + comment(# re-establishing of the connection.) + reserved(def) pre_constant(self)operator(.)ident(remove_connection)operator(()ident(klass)operator(=)pre_constant(self)operator(\)) + ident(spec) operator(=) class_variable(@@defined_connections)operator([)ident(klass)operator(.)ident(name)operator(]) + ident(konn) operator(=) ident(active_connections)operator([)ident(klass)operator(.)ident(name)operator(]) + class_variable(@@defined_connections)operator(.)ident(delete_if) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) ident(value) operator(==) ident(spec) operator(}) + ident(active_connections)operator(.)ident(delete_if) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) ident(value) operator(==) ident(konn) operator(}) + ident(konn)operator(.)ident(disconnect!) reserved(if) ident(konn) + ident(spec)operator(.)ident(config) reserved(if) ident(spec) + reserved(end) + + comment(# Set the connection for the class.) + reserved(def) pre_constant(self)operator(.)ident(connection)operator(=)operator(()ident(spec)operator(\)) comment(#:nodoc:) + reserved(if) ident(spec)operator(.)ident(kind_of?)operator(()constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(AbstractAdapter)operator(\)) + ident(active_connections)operator([)ident(name)operator(]) operator(=) ident(spec) + reserved(elsif) ident(spec)operator(.)ident(kind_of?)operator(()constant(ConnectionSpecification)operator(\)) + pre_constant(self)operator(.)ident(connection) operator(=) pre_constant(self)operator(.)ident(send)operator(()ident(spec)operator(.)ident(adapter_method)operator(,) ident(spec)operator(.)ident(config)operator(\)) + reserved(elsif) ident(spec)operator(.)ident(nil?) + ident(raise) constant(ConnectionNotEstablished) + reserved(else) + ident(establish_connection) ident(spec) + reserved(end) + reserved(end) + + comment(# connection state logging) + reserved(def) pre_constant(self)operator(.)ident(log_connections) comment(#:nodoc:) + reserved(if) ident(logger) + ident(logger)operator(.)ident(info) string<delimiter(")content(Defined connections: )inline<inline_delimiter(#{)class_variable(@@defined_connections)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + ident(logger)operator(.)ident(info) string<delimiter(")content(Active connections: )inline<inline_delimiter(#{)ident(active_connections)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + ident(logger)operator(.)ident(info) string<delimiter(")content(Active connection name: )inline<inline_delimiter(#{)instance_variable(@active_connection_name)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(ConnectionAdapters) comment(# :nodoc:) + reserved(module) class(DatabaseStatements) + comment(# Returns an array of record hashes with the column names as keys and) + comment(# column values as values.) + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(end) + + comment(# Returns a record hash with the column names as keys and column values) + comment(# as values.) + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(end) + + comment(# Returns a single value from a record) + reserved(def) method(select_value)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(result) operator(=) ident(select_one)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(result)operator(.)ident(values)operator(.)ident(first) + reserved(end) + + comment(# Returns an array of the values of the first column in a select:) + comment(# select_values("SELECT id FROM companies LIMIT 3"\) => [1,2,3]) + reserved(def) method(select_values)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(result) operator(=) ident(select_all)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(map)operator({) operator(|)ident(v)operator(|) ident(v)operator(.)ident(values)operator(.)ident(first) operator(}) + reserved(end) + + comment(# Executes the SQL statement in the context of this connection.) + comment(# This abstract method raises a NotImplementedError.) + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(raise) constant(NotImplementedError)operator(,) string<delimiter(")content(execute is an abstract method)delimiter(")> + reserved(end) + + comment(# Returns the last auto-generated ID from the affected table.) + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) reserved(end) + + comment(# Executes the update statement and returns the number of rows affected.) + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) reserved(end) + + comment(# Executes the delete statement and returns the number of rows affected.) + reserved(def) method(delete)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) reserved(end) + + comment(# Wrap a block in a transaction. Returns result of block.) + reserved(def) method(transaction)operator(()ident(start_db_transaction) operator(=) pre_constant(true)operator(\)) + ident(transaction_open) operator(=) pre_constant(false) + reserved(begin) + reserved(if) ident(block_given?) + reserved(if) ident(start_db_transaction) + ident(begin_db_transaction) + ident(transaction_open) operator(=) pre_constant(true) + reserved(end) + reserved(yield) + reserved(end) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(database_transaction_rollback) + reserved(if) ident(transaction_open) + ident(transaction_open) operator(=) pre_constant(false) + ident(rollback_db_transaction) + reserved(end) + ident(raise) + reserved(end) + reserved(ensure) + ident(commit_db_transaction) reserved(if) ident(transaction_open) + reserved(end) + + comment(# Begins the transaction (and turns off auto-committing\).) + reserved(def) method(begin_db_transaction)operator(()operator(\)) reserved(end) + + comment(# Commits the transaction (and turns on auto-committing\).) + reserved(def) method(commit_db_transaction)operator(()operator(\)) reserved(end) + + comment(# Rolls back the transaction (and turns on auto-committing\). Must be) + comment(# done if the transaction block raises an exception or returns false.) + reserved(def) method(rollback_db_transaction)operator(()operator(\)) reserved(end) + + comment(# Alias for #add_limit_offset!.) + reserved(def) method(add_limit!)operator(()ident(sql)operator(,) ident(options)operator(\)) + ident(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) reserved(if) ident(options) + reserved(end) + + comment(# Appends +LIMIT+ and +OFFSET+ options to a SQL statement.) + comment(# This method *modifies* the +sql+ parameter.) + comment(# ===== Examples) + comment(# add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50}\)) + comment(# generates) + comment(# SELECT * FROM suppliers LIMIT 10 OFFSET 50) + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) + reserved(if) ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) + ident(sql) operator(<<) string<delimiter(")content( LIMIT )inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>delimiter(")> + reserved(if) ident(offset) operator(=) ident(options)operator([)symbol(:offset)operator(]) + ident(sql) operator(<<) string<delimiter(")content( OFFSET )inline<inline_delimiter(#{)ident(offset)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(default_sequence_name)operator(()ident(table)operator(,) ident(column)operator(\)) + pre_constant(nil) + reserved(end) + + comment(# Set the sequence to the max value of the table's column.) + reserved(def) method(reset_sequence!)operator(()ident(table)operator(,) ident(column)operator(,) ident(sequence) operator(=) pre_constant(nil)operator(\)) + comment(# Do nothing by default. Implement for PostgreSQL, Oracle, ...) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(ConnectionAdapters) comment(# :nodoc:) + reserved(module) class(Quoting) + comment(# Quotes the column value to help prevent) + comment(# {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection].) + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + reserved(case) ident(value) + reserved(when) constant(String) + reserved(if) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) operator(&&) ident(column)operator(.)ident(class)operator(.)ident(respond_to?)operator(()symbol(:string_to_binary)operator(\)) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(column)operator(.)ident(class)operator(.)ident(string_to_binary)operator(()ident(value)operator(\))operator(\))inline_delimiter(})>content(')delimiter(")> comment(# ' (for ruby-mode\)) + reserved(elsif) ident(column) operator(&&) operator([)symbol(:integer)operator(,) symbol(:float)operator(])operator(.)ident(include?)operator(()ident(column)operator(.)ident(type)operator(\)) + ident(value)operator(.)ident(to_s) + reserved(else) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> comment(# ' (for ruby-mode\)) + reserved(end) + reserved(when) constant(NilClass) reserved(then) string<delimiter(")content(NULL)delimiter(")> + reserved(when) constant(TrueClass) reserved(then) operator(()ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:integer) operator(?) string<delimiter(')content(1)delimiter(')> operator(:) ident(quoted_true)operator(\)) + reserved(when) constant(FalseClass) reserved(then) operator(()ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:integer) operator(?) string<delimiter(')content(0)delimiter(')> operator(:) ident(quoted_false)operator(\)) + reserved(when) constant(Float)operator(,) constant(Fixnum)operator(,) constant(Bignum) reserved(then) ident(value)operator(.)ident(to_s) + reserved(when) constant(Date) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(to_s)inline_delimiter(})>content(')delimiter(")> + reserved(when) constant(Time)operator(,) constant(DateTime) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quoted_date)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_yaml)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + + comment(# Quotes a string, escaping any ' (single quote\) and \\ (backslash\)) + comment(# characters.) + reserved(def) method(quote_string)operator(()ident(s)operator(\)) + ident(s)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\\\)delimiter(/)>operator(,) string<delimiter(')content(\\&)content(\\&)delimiter(')>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(")content('')delimiter(")>operator(\)) comment(# ' (for ruby-mode\)) + reserved(end) + + comment(# Returns a quoted form of the column name. This is highly adapter) + comment(# specific.) + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) + ident(name) + reserved(end) + + reserved(def) method(quoted_true) + string<delimiter(")content('t')delimiter(")> + reserved(end) + + reserved(def) method(quoted_false) + string<delimiter(")content('f')delimiter(")> + reserved(end) + + reserved(def) method(quoted_date)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(parsedate)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(module) class(ConnectionAdapters) comment(#:nodoc:) + comment(# An abstract definition of a column in a table.) + reserved(class) class(Column) + ident(attr_reader) symbol(:name)operator(,) symbol(:default)operator(,) symbol(:type)operator(,) symbol(:limit)operator(,) symbol(:null)operator(,) symbol(:sql_type) + ident(attr_accessor) symbol(:primary) + + comment(# Instantiates a new column in the table.) + comment(#) + comment(# +name+ is the column's name, as in <tt><b>supplier_id</b> int(11\)</tt>.) + comment(# +default+ is the type-casted default value, such as <tt>sales_stage varchar(20\) default <b>'new'</b></tt>.) + comment(# +sql_type+ is only used to extract the column's length, if necessary. For example, <tt>company_name varchar(<b>60</b>\)</tt>.) + comment(# +null+ determines if this column allows +NULL+ values.) + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(default)operator(,) ident(sql_type) operator(=) pre_constant(nil)operator(,) ident(null) operator(=) pre_constant(true)operator(\)) + instance_variable(@name)operator(,) instance_variable(@type)operator(,) instance_variable(@null) operator(=) ident(name)operator(,) ident(simplified_type)operator(()ident(sql_type)operator(\))operator(,) ident(null) + instance_variable(@sql_type) operator(=) ident(sql_type) + comment(# have to do this one separately because type_cast depends on #type) + instance_variable(@default) operator(=) ident(type_cast)operator(()ident(default)operator(\)) + instance_variable(@limit) operator(=) ident(extract_limit)operator(()ident(sql_type)operator(\)) reserved(unless) ident(sql_type)operator(.)ident(nil?) + instance_variable(@primary) operator(=) pre_constant(nil) + instance_variable(@text) operator(=) operator([)symbol(:string)operator(,) symbol(:text)operator(])operator(.)ident(include?) instance_variable(@type) + instance_variable(@number) operator(=) operator([)symbol(:float)operator(,) symbol(:integer)operator(])operator(.)ident(include?) instance_variable(@type) + reserved(end) + + reserved(def) method(text?) + instance_variable(@text) + reserved(end) + + reserved(def) method(number?) + instance_variable(@number) + reserved(end) + + comment(# Returns the Ruby class that corresponds to the abstract data type.) + reserved(def) method(klass) + reserved(case) ident(type) + reserved(when) symbol(:integer) reserved(then) constant(Fixnum) + reserved(when) symbol(:float) reserved(then) constant(Float) + reserved(when) symbol(:datetime) reserved(then) constant(Time) + reserved(when) symbol(:date) reserved(then) constant(Date) + reserved(when) symbol(:timestamp) reserved(then) constant(Time) + reserved(when) symbol(:time) reserved(then) constant(Time) + reserved(when) symbol(:text)operator(,) symbol(:string) reserved(then) constant(String) + reserved(when) symbol(:binary) reserved(then) constant(String) + reserved(when) symbol(:boolean) reserved(then) constant(Object) + reserved(end) + reserved(end) + + comment(# Casts value (which is a String\) to an appropriate instance.) + reserved(def) method(type_cast)operator(()ident(value)operator(\)) + reserved(return) pre_constant(nil) reserved(if) ident(value)operator(.)ident(nil?) + reserved(case) ident(type) + reserved(when) symbol(:string) reserved(then) ident(value) + reserved(when) symbol(:text) reserved(then) ident(value) + reserved(when) symbol(:integer) reserved(then) ident(value)operator(.)ident(to_i) reserved(rescue) ident(value) operator(?) integer(1) operator(:) integer(0) + reserved(when) symbol(:float) reserved(then) ident(value)operator(.)ident(to_f) + reserved(when) symbol(:datetime) reserved(then) pre_constant(self)operator(.)ident(class)operator(.)ident(string_to_time)operator(()ident(value)operator(\)) + reserved(when) symbol(:timestamp) reserved(then) pre_constant(self)operator(.)ident(class)operator(.)ident(string_to_time)operator(()ident(value)operator(\)) + reserved(when) symbol(:time) reserved(then) pre_constant(self)operator(.)ident(class)operator(.)ident(string_to_dummy_time)operator(()ident(value)operator(\)) + reserved(when) symbol(:date) reserved(then) pre_constant(self)operator(.)ident(class)operator(.)ident(string_to_date)operator(()ident(value)operator(\)) + reserved(when) symbol(:binary) reserved(then) pre_constant(self)operator(.)ident(class)operator(.)ident(binary_to_string)operator(()ident(value)operator(\)) + reserved(when) symbol(:boolean) reserved(then) pre_constant(self)operator(.)ident(class)operator(.)ident(value_to_boolean)operator(()ident(value)operator(\)) + reserved(else) ident(value) + reserved(end) + reserved(end) + + reserved(def) method(type_cast_code)operator(()ident(var_name)operator(\)) + reserved(case) ident(type) + reserved(when) symbol(:string) reserved(then) pre_constant(nil) + reserved(when) symbol(:text) reserved(then) pre_constant(nil) + reserved(when) symbol(:integer) reserved(then) string<delimiter(")content(()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(.to_i rescue )inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content( ? 1 : 0\))delimiter(")> + reserved(when) symbol(:float) reserved(then) string<delimiter(")inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(.to_f)delimiter(")> + reserved(when) symbol(:datetime) reserved(then) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(.string_to_time()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(\))delimiter(")> + reserved(when) symbol(:timestamp) reserved(then) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(.string_to_time()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(\))delimiter(")> + reserved(when) symbol(:time) reserved(then) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(.string_to_dummy_time()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(\))delimiter(")> + reserved(when) symbol(:date) reserved(then) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(.string_to_date()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(\))delimiter(")> + reserved(when) symbol(:binary) reserved(then) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(.binary_to_string()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(\))delimiter(")> + reserved(when) symbol(:boolean) reserved(then) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(.value_to_boolean()inline<inline_delimiter(#{)ident(var_name)inline_delimiter(})>content(\))delimiter(")> + reserved(else) pre_constant(nil) + reserved(end) + reserved(end) + + comment(# Returns the human name of the column name.) + comment(#) + comment(# ===== Examples) + comment(# Column.new('sales_stage', ...\).human_name #=> 'Sales stage') + reserved(def) method(human_name) + constant(Base)operator(.)ident(human_attribute_name)operator(()instance_variable(@name)operator(\)) + reserved(end) + + comment(# Used to convert from Strings to BLOBs) + reserved(def) pre_constant(self)operator(.)ident(string_to_binary)operator(()ident(value)operator(\)) + ident(value) + reserved(end) + + comment(# Used to convert from BLOBs to Strings) + reserved(def) pre_constant(self)operator(.)ident(binary_to_string)operator(()ident(value)operator(\)) + ident(value) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(string_to_date)operator(()ident(string)operator(\)) + reserved(return) ident(string) reserved(unless) ident(string)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(date_array) operator(=) constant(ParseDate)operator(.)ident(parsedate)operator(()ident(string)operator(\)) + comment(# treat 0000-00-00 as nil) + constant(Date)operator(.)ident(new)operator(()ident(date_array)operator([)integer(0)operator(])operator(,) ident(date_array)operator([)integer(1)operator(])operator(,) ident(date_array)operator([)integer(2)operator(])operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(string_to_time)operator(()ident(string)operator(\)) + reserved(return) ident(string) reserved(unless) ident(string)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(time_array) operator(=) constant(ParseDate)operator(.)ident(parsedate)operator(()ident(string)operator(\))operator([)integer(0)operator(..)integer(5)operator(]) + comment(# treat 0000-00-00 00:00:00 as nil) + constant(Time)operator(.)ident(send)operator(()constant(Base)operator(.)ident(default_timezone)operator(,) operator(*)ident(time_array)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(string_to_dummy_time)operator(()ident(string)operator(\)) + reserved(return) ident(string) reserved(unless) ident(string)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(time_array) operator(=) constant(ParseDate)operator(.)ident(parsedate)operator(()ident(string)operator(\)) + comment(# pad the resulting array with dummy date information) + ident(time_array)operator([)integer(0)operator(]) operator(=) integer(2000)operator(;) ident(time_array)operator([)integer(1)operator(]) operator(=) integer(1)operator(;) ident(time_array)operator([)integer(2)operator(]) operator(=) integer(1)operator(;) + constant(Time)operator(.)ident(send)operator(()constant(Base)operator(.)ident(default_timezone)operator(,) operator(*)ident(time_array)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + comment(# convert something to a boolean) + reserved(def) pre_constant(self)operator(.)ident(value_to_boolean)operator(()ident(value)operator(\)) + reserved(return) ident(value) reserved(if) ident(value)operator(==)pre_constant(true) operator(||) ident(value)operator(==)pre_constant(false) + reserved(case) ident(value)operator(.)ident(to_s)operator(.)ident(downcase) + reserved(when) string<delimiter(")content(true)delimiter(")>operator(,) string<delimiter(")content(t)delimiter(")>operator(,) string<delimiter(")content(1)delimiter(")> reserved(then) pre_constant(true) + reserved(else) pre_constant(false) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(extract_limit)operator(()ident(sql_type)operator(\)) + global_variable($1)operator(.)ident(to_i) reserved(if) ident(sql_type) operator(=)operator(~) regexp<delimiter(/)char(\\()content((.*\))char(\\\))delimiter(/)> + reserved(end) + + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(case) ident(field_type) + reserved(when) regexp<delimiter(/)content(int)delimiter(/)modifier(i)> + symbol(:integer) + reserved(when) regexp<delimiter(/)content(float|double|decimal|numeric)delimiter(/)modifier(i)> + symbol(:float) + reserved(when) regexp<delimiter(/)content(datetime)delimiter(/)modifier(i)> + symbol(:datetime) + reserved(when) regexp<delimiter(/)content(timestamp)delimiter(/)modifier(i)> + symbol(:timestamp) + reserved(when) regexp<delimiter(/)content(time)delimiter(/)modifier(i)> + symbol(:time) + reserved(when) regexp<delimiter(/)content(date)delimiter(/)modifier(i)> + symbol(:date) + reserved(when) regexp<delimiter(/)content(clob)delimiter(/)modifier(i)>operator(,) regexp<delimiter(/)content(text)delimiter(/)modifier(i)> + symbol(:text) + reserved(when) regexp<delimiter(/)content(blob)delimiter(/)modifier(i)>operator(,) regexp<delimiter(/)content(binary)delimiter(/)modifier(i)> + symbol(:binary) + reserved(when) regexp<delimiter(/)content(char)delimiter(/)modifier(i)>operator(,) regexp<delimiter(/)content(string)delimiter(/)modifier(i)> + symbol(:string) + reserved(when) regexp<delimiter(/)content(boolean)delimiter(/)modifier(i)> + symbol(:boolean) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(IndexDefinition) operator(<) constant(Struct)operator(.)ident(new)operator(()symbol(:table)operator(,) symbol(:name)operator(,) symbol(:unique)operator(,) symbol(:columns)operator(\)) comment(#:nodoc:) + reserved(end) + + reserved(class) class(ColumnDefinition) operator(<) constant(Struct)operator(.)ident(new)operator(()symbol(:base)operator(,) symbol(:name)operator(,) symbol(:type)operator(,) symbol(:limit)operator(,) symbol(:default)operator(,) symbol(:null)operator(\)) comment(#:nodoc:) + reserved(def) method(to_sql) + ident(column_sql) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(base)operator(.)ident(quote_column_name)operator(()ident(name)operator(\))inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(.)ident(to_sym)operator(,) ident(limit)operator(\))inline_delimiter(})>delimiter(")> + ident(add_column_options!)operator(()ident(column_sql)operator(,) symbol(:null) operator(=)operator(>) ident(null)operator(,) symbol(:default) operator(=)operator(>) ident(default)operator(\)) + ident(column_sql) + reserved(end) + reserved(alias) method(to_s) symbol(:to_sql) + + ident(private) + reserved(def) method(type_to_sql)operator(()ident(name)operator(,) ident(limit)operator(\)) + ident(base)operator(.)ident(type_to_sql)operator(()ident(name)operator(,) ident(limit)operator(\)) reserved(rescue) ident(name) + reserved(end) + + reserved(def) method(add_column_options!)operator(()ident(sql)operator(,) ident(options)operator(\)) + ident(base)operator(.)ident(add_column_options!)operator(()ident(sql)operator(,) ident(options)operator(.)ident(merge)operator(()symbol(:column) operator(=)operator(>) pre_constant(self)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Represents a SQL table in an abstract way.) + comment(# Columns are stored as ColumnDefinition in the #columns attribute.) + reserved(class) class(TableDefinition) + ident(attr_accessor) symbol(:columns) + + reserved(def) method(initialize)operator(()ident(base)operator(\)) + instance_variable(@columns) operator(=) operator([)operator(]) + instance_variable(@base) operator(=) ident(base) + reserved(end) + + comment(# Appends a primary key definition to the table definition.) + comment(# Can be called multiple times, but this is probably not a good idea.) + reserved(def) method(primary_key)operator(()ident(name)operator(\)) + ident(column)operator(()ident(name)operator(,) ident(native)operator([)symbol(:primary_key)operator(])operator(\)) + reserved(end) + + comment(# Returns a ColumnDefinition for the column with name +name+.) + reserved(def) method([])operator(()ident(name)operator(\)) + instance_variable(@columns)operator(.)ident(find) operator({)operator(|)ident(column)operator(|) ident(column)operator(.)ident(name)operator(.)ident(to_s) operator(==) ident(name)operator(.)ident(to_s)operator(}) + reserved(end) + + comment(# Instantiates a new column for the table.) + comment(# The +type+ parameter must be one of the following values:) + comment(# <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,) + comment(# <tt>:integer</tt>, <tt>:float</tt>, <tt>:datetime</tt>,) + comment(# <tt>:timestamp</tt>, <tt>:time</tt>, <tt>:date</tt>,) + comment(# <tt>:binary</tt>, <tt>:boolean</tt>.) + comment(#) + comment(# Available options are (none of these exists by default\):) + comment(# * <tt>:limit</tt>:) + comment(# Requests a maximum column length (<tt>:string</tt>, <tt>:text</tt>,) + comment(# <tt>:binary</tt> or <tt>:integer</tt> columns only\)) + comment(# * <tt>:default</tt>:) + comment(# The column's default value. You cannot explicitely set the default) + comment(# value to +NULL+. Simply leave off this option if you want a +NULL+) + comment(# default value.) + comment(# * <tt>:null</tt>:) + comment(# Allows or disallows +NULL+ values in the column. This option could) + comment(# have been named <tt>:null_allowed</tt>.) + comment(#) + comment(# This method returns <tt>self</tt>.) + comment(#) + comment(# ===== Examples) + comment(# # Assuming def is an instance of TableDefinition) + comment(# def.column(:granted, :boolean\)) + comment(# #=> granted BOOLEAN) + comment(#) + comment(# def.column(:picture, :binary, :limit => 2.megabytes\)) + comment(# #=> picture BLOB(2097152\)) + comment(#) + comment(# def.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false\)) + comment(# #=> sales_stage VARCHAR(20\) DEFAULT 'new' NOT NULL) + reserved(def) method(column)operator(()ident(name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(column) operator(=) pre_constant(self)operator([)ident(name)operator(]) operator(||) constant(ColumnDefinition)operator(.)ident(new)operator(()instance_variable(@base)operator(,) ident(name)operator(,) ident(type)operator(\)) + ident(column)operator(.)ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) operator(||) ident(native)operator([)ident(type)operator(.)ident(to_sym)operator(])operator([)symbol(:limit)operator(]) reserved(if) ident(options)operator([)symbol(:limit)operator(]) reserved(or) ident(native)operator([)ident(type)operator(.)ident(to_sym)operator(]) + ident(column)operator(.)ident(default) operator(=) ident(options)operator([)symbol(:default)operator(]) + ident(column)operator(.)ident(null) operator(=) ident(options)operator([)symbol(:null)operator(]) + instance_variable(@columns) operator(<<) ident(column) reserved(unless) instance_variable(@columns)operator(.)ident(include?) ident(column) + pre_constant(self) + reserved(end) + + comment(# Returns a String whose contents are the column definitions) + comment(# concatenated together. This string can then be pre and appended to) + comment(# to generate the final SQL to create the table.) + reserved(def) method(to_sql) + instance_variable(@columns) operator(*) string<delimiter(')content(, )delimiter(')> + reserved(end) + + ident(private) + reserved(def) method(native) + instance_variable(@base)operator(.)ident(native_database_types) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(ConnectionAdapters) comment(# :nodoc:) + reserved(module) class(SchemaStatements) + comment(# Returns a Hash of mappings from the abstract data types to the native) + comment(# database types. See TableDefinition#column for details on the recognized) + comment(# abstract data types.) + reserved(def) method(native_database_types) + operator({)operator(}) + reserved(end) + + comment(# This is the maximum length a table alias can be) + reserved(def) method(table_alias_length) + integer(255) + reserved(end) + + comment(# Truncates a table alias according to the limits of the current adapter. ) + reserved(def) method(table_alias_for)operator(()ident(table_name)operator(\)) + ident(table_name)operator([)integer(0)operator(..)ident(table_alias_length)operator(-)integer(1)operator(])operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\.)delimiter(/)>operator(,) string<delimiter(')content(_)delimiter(')>operator(\)) + reserved(end) + + comment(# def tables(name = nil\) end) + + comment(# Returns an array of indexes for the given table.) + comment(# def indexes(table_name, name = nil\) end) + + comment(# Returns an array of Column objects for the table specified by +table_name+.) + comment(# See the concrete implementation for details on the expected parameter values.) + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) reserved(end) + + comment(# Creates a new table) + comment(# There are two ways to work with #create_table. You can use the block) + comment(# form or the regular form, like this:) + comment(#) + comment(# === Block form) + comment(# # create_table(\) yields a TableDefinition instance) + comment(# create_table(:suppliers\) do |t|) + comment(# t.column :name, :string, :limit => 60) + comment(# # Other fields here) + comment(# end) + comment(#) + comment(# === Regular form) + comment(# create_table(:suppliers\)) + comment(# add_column(:suppliers, :name, :string, {:limit => 60}\)) + comment(#) + comment(# The +options+ hash can include the following keys:) + comment(# [<tt>:id</tt>]) + comment(# Set to true or false to add/not add a primary key column) + comment(# automatically. Defaults to true.) + comment(# [<tt>:primary_key</tt>]) + comment(# The name of the primary key, if one is to be added automatically.) + comment(# Defaults to +id+.) + comment(# [<tt>:options</tt>]) + comment(# Any extra options you want appended to the table definition.) + comment(# [<tt>:temporary</tt>]) + comment(# Make a temporary table.) + comment(# [<tt>:force</tt>]) + comment(# Set to true or false to drop the table before creating it.) + comment(# Defaults to false.) + comment(#) + comment(# ===== Examples) + comment(# ====== Add a backend specific option to the generated SQL (MySQL\)) + comment(# create_table(:suppliers, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8'\)) + comment(# generates:) + comment(# CREATE TABLE suppliers () + comment(# id int(11\) DEFAULT NULL auto_increment PRIMARY KEY) + comment(# \) ENGINE=InnoDB DEFAULT CHARSET=utf8) + comment(#) + comment(# ====== Rename the primary key column) + comment(# create_table(:objects, :primary_key => 'guid'\) do |t|) + comment(# t.column :name, :string, :limit => 80) + comment(# end) + comment(# generates:) + comment(# CREATE TABLE objects () + comment(# guid int(11\) DEFAULT NULL auto_increment PRIMARY KEY,) + comment(# name varchar(80\)) + comment(# \)) + comment(#) + comment(# ====== Do not add a primary key column) + comment(# create_table(:categories_suppliers, :id => false\) do |t|) + comment(# t.column :category_id, :integer) + comment(# t.column :supplier_id, :integer) + comment(# end) + comment(# generates:) + comment(# CREATE TABLE categories_suppliers_join () + comment(# category_id int,) + comment(# supplier_id int) + comment(# \)) + comment(#) + comment(# See also TableDefinition#column for details on how to create columns.) + reserved(def) method(create_table)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(table_definition) operator(=) constant(TableDefinition)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + ident(table_definition)operator(.)ident(primary_key)operator(()ident(options)operator([)symbol(:primary_key)operator(]) operator(||) string<delimiter(")content(id)delimiter(")>operator(\)) reserved(unless) ident(options)operator([)symbol(:id)operator(]) operator(==) pre_constant(false) + + reserved(yield) ident(table_definition) + + reserved(if) ident(options)operator([)symbol(:force)operator(]) + ident(drop_table)operator(()ident(name)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + ident(create_sql) operator(=) string<delimiter(")content(CREATE)inline<inline_delimiter(#{)string<delimiter(')content( TEMPORARY)delimiter(')> reserved(if) ident(options)operator([)symbol(:temporary)operator(])inline_delimiter(})>content( TABLE )delimiter(")> + ident(create_sql) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( ()delimiter(")> + ident(create_sql) operator(<<) ident(table_definition)operator(.)ident(to_sql) + ident(create_sql) operator(<<) string<delimiter(")content(\) )inline<inline_delimiter(#{)ident(options)operator([)symbol(:options)operator(])inline_delimiter(})>delimiter(")> + ident(execute) ident(create_sql) + reserved(end) + + comment(# Renames a table.) + comment(# ===== Example) + comment(# rename_table('octopuses', 'octopi'\)) + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + ident(raise) constant(NotImplementedError)operator(,) string<delimiter(")content(rename_table is not implemented)delimiter(")> + reserved(end) + + comment(# Drops a table from the database.) + reserved(def) method(drop_table)operator(()ident(name)operator(\)) + ident(execute) string<delimiter(")content(DROP TABLE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Adds a new column to the named table.) + comment(# See TableDefinition#column for details of the options you can use.) + reserved(def) method(add_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(add_column_sql) operator(=) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ADD )inline<inline_delimiter(#{)ident(quote_column_name)operator(()ident(column_name)operator(\))inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")> + ident(add_column_options!)operator(()ident(add_column_sql)operator(,) ident(options)operator(\)) + ident(execute)operator(()ident(add_column_sql)operator(\)) + reserved(end) + + comment(# Removes the column from the table definition.) + comment(# ===== Examples) + comment(# remove_column(:suppliers, :qualification\)) + reserved(def) method(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP )inline<inline_delimiter(#{)ident(quote_column_name)operator(()ident(column_name)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Changes the column's definition according to the new options.) + comment(# See TableDefinition#column for details of the options you can use.) + comment(# ===== Examples) + comment(# change_column(:suppliers, :name, :string, :limit => 80\)) + comment(# change_column(:accounts, :description, :text\)) + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(raise) constant(NotImplementedError)operator(,) string<delimiter(")content(change_column is not implemented)delimiter(")> + reserved(end) + + comment(# Sets a new default value for a column. If you want to set the default) + comment(# value to +NULL+, you are out of luck. You need to) + comment(# DatabaseStatements#execute the apppropriate SQL statement yourself.) + comment(# ===== Examples) + comment(# change_column_default(:suppliers, :qualification, 'new'\)) + comment(# change_column_default(:accounts, :authorized, 1\)) + reserved(def) method(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(default)operator(\)) + ident(raise) constant(NotImplementedError)operator(,) string<delimiter(")content(change_column_default is not implemented)delimiter(")> + reserved(end) + + comment(# Renames a column.) + comment(# ===== Example) + comment(# rename_column(:suppliers, :description, :name\)) + reserved(def) method(rename_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(new_column_name)operator(\)) + ident(raise) constant(NotImplementedError)operator(,) string<delimiter(")content(rename_column is not implemented)delimiter(")> + reserved(end) + + comment(# Adds a new index to the table. +column_name+ can be a single Symbol, or) + comment(# an Array of Symbols.) + comment(#) + comment(# The index will be named after the table and the first column names,) + comment(# unless you pass +:name+ as an option.) + comment(#) + comment(# When creating an index on multiple columns, the first column is used as a name) + comment(# for the index. For example, when you specify an index on two columns) + comment(# [+:first+, +:last+], the DBMS creates an index for both columns as well as an) + comment(# index for the first colum +:first+. Using just the first name for this index) + comment(# makes sense, because you will never have to create a singular index with this) + comment(# name.) + comment(#) + comment(# ===== Examples) + comment(# ====== Creating a simple index) + comment(# add_index(:suppliers, :name\)) + comment(# generates) + comment(# CREATE INDEX suppliers_name_index ON suppliers(name\)) + comment(# ====== Creating a unique index) + comment(# add_index(:accounts, [:branch_id, :party_id], :unique => true\)) + comment(# generates) + comment(# CREATE UNIQUE INDEX accounts_branch_id_index ON accounts(branch_id, party_id\)) + comment(# ====== Creating a named index) + comment(# add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party'\)) + comment(# generates) + comment(# CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id\)) + reserved(def) method(add_index)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(column_names) operator(=) ident(Array)operator(()ident(column_name)operator(\)) + ident(index_name) operator(=) ident(index_name)operator(()ident(table_name)operator(,) symbol(:column) operator(=)operator(>) ident(column_names)operator(.)ident(first)operator(\)) + + reserved(if) constant(Hash) operator(===) ident(options) comment(# legacy support, since this param was a string) + ident(index_type) operator(=) ident(options)operator([)symbol(:unique)operator(]) operator(?) string<delimiter(")content(UNIQUE)delimiter(")> operator(:) string<delimiter(")delimiter(")> + ident(index_name) operator(=) ident(options)operator([)symbol(:name)operator(]) operator(||) ident(index_name) + reserved(else) + ident(index_type) operator(=) ident(options) + reserved(end) + ident(quoted_column_names) operator(=) ident(column_names)operator(.)ident(map) operator({) operator(|)ident(e)operator(|) ident(quote_column_name)operator(()ident(e)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + ident(execute) string<delimiter(")content(CREATE )inline<inline_delimiter(#{)ident(index_type)inline_delimiter(})>content( INDEX )inline<inline_delimiter(#{)ident(quote_column_name)operator(()ident(index_name)operator(\))inline_delimiter(})>content( ON )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(quoted_column_names)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + comment(# Remove the given index from the table.) + comment(#) + comment(# Remove the suppliers_name_index in the suppliers table (legacy support, use the second or third forms\).) + comment(# remove_index :suppliers, :name) + comment(# Remove the index named accounts_branch_id in the accounts table.) + comment(# remove_index :accounts, :column => :branch_id) + comment(# Remove the index named by_branch_party in the accounts table.) + comment(# remove_index :accounts, :name => :by_branch_party) + comment(#) + comment(# You can remove an index on multiple columns by specifying the first column.) + comment(# add_index :accounts, [:username, :password]) + comment(# remove_index :accounts, :username) + reserved(def) method(remove_index)operator(()ident(table_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(execute) string<delimiter(")content(DROP INDEX )inline<inline_delimiter(#{)ident(quote_column_name)operator(()ident(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\))operator(\))inline_delimiter(})>content( ON )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\)) comment(#:nodoc:) + reserved(if) constant(Hash) operator(===) ident(options) comment(# legacy support) + reserved(if) ident(options)operator([)symbol(:column)operator(]) + string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(options)operator([)symbol(:column)operator(])inline_delimiter(})>content(_index)delimiter(")> + reserved(elsif) ident(options)operator([)symbol(:name)operator(]) + ident(options)operator([)symbol(:name)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(You must specify the index name)delimiter(")> + reserved(end) + reserved(else) + string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(options)inline_delimiter(})>content(_index)delimiter(")> + reserved(end) + reserved(end) + + comment(# Returns a string of <tt>CREATE TABLE</tt> SQL statement(s\) for recreating the) + comment(# entire structure of the database.) + reserved(def) method(structure_dump) + reserved(end) + + comment(# Should not be called normally, but this operation is non-destructive.) + comment(# The migrations module handles this automatically.) + reserved(def) method(initialize_schema_information) + reserved(begin) + ident(execute) string<delimiter(")content(CREATE TABLE )inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(schema_info_table_name)inline_delimiter(})>content( (version )inline<inline_delimiter(#{)ident(type_to_sql)operator(()symbol(:integer)operator(\))inline_delimiter(})>content(\))delimiter(")> + ident(execute) string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(schema_info_table_name)inline_delimiter(})>content( (version\) VALUES(0\))delimiter(")> + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) + comment(# Schema has been intialized) + reserved(end) + reserved(end) + + reserved(def) method(dump_schema_information) comment(#:nodoc:) + reserved(begin) + reserved(if) operator(()ident(current_schema) operator(=) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(current_version)operator(\)) operator(>) integer(0) + reserved(return) string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(schema_info_table_name)inline_delimiter(})>content( (version\) VALUES ()inline<inline_delimiter(#{)ident(current_schema)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) + comment(# No Schema Info) + reserved(end) + reserved(end) + + + reserved(def) method(type_to_sql)operator(()ident(type)operator(,) ident(limit) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(native) operator(=) ident(native_database_types)operator([)ident(type)operator(]) + ident(limit) operator(||=) ident(native)operator([)symbol(:limit)operator(]) + ident(column_type_sql) operator(=) ident(native)operator([)symbol(:name)operator(]) + ident(column_type_sql) operator(<<) string<delimiter(")content(()inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(limit) + ident(column_type_sql) + reserved(end) + + reserved(def) method(add_column_options!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(sql) operator(<<) string<delimiter(")content( DEFAULT )inline<inline_delimiter(#{)ident(quote)operator(()ident(options)operator([)symbol(:default)operator(])operator(,) ident(options)operator([)symbol(:column)operator(])operator(\))inline_delimiter(})>delimiter(")> reserved(unless) ident(options)operator([)symbol(:default)operator(])operator(.)ident(nil?) + ident(sql) operator(<<) string<delimiter(")content( NOT NULL)delimiter(")> reserved(if) ident(options)operator([)symbol(:null)operator(]) operator(==) pre_constant(false) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(benchmark)delimiter(')> +ident(require) string<delimiter(')content(date)delimiter(')> + +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract/schema_definitions)delimiter(')> +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract/schema_statements)delimiter(')> +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract/database_statements)delimiter(')> +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract/quoting)delimiter(')> +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract/connection_specification)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(module) class(ConnectionAdapters) comment(# :nodoc:) + comment(# All the concrete database adapters follow the interface laid down in this class.) + comment(# You can use this interface directly by borrowing the database connection from the Base with) + comment(# Base.connection.) + comment(#) + comment(# Most of the methods in the adapter are useful during migrations. Most) + comment(# notably, SchemaStatements#create_table, SchemaStatements#drop_table,) + comment(# SchemaStatements#add_index, SchemaStatements#remove_index,) + comment(# SchemaStatements#add_column, SchemaStatements#change_column and) + comment(# SchemaStatements#remove_column are very useful.) + reserved(class) class(AbstractAdapter) + ident(include) constant(Quoting)operator(,) constant(DatabaseStatements)operator(,) constant(SchemaStatements) + class_variable(@@row_even) operator(=) pre_constant(true) + + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(logger) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@connection)operator(,) instance_variable(@logger) operator(=) ident(connection)operator(,) ident(logger) + instance_variable(@runtime) operator(=) integer(0) + instance_variable(@last_verification) operator(=) integer(0) + reserved(end) + + comment(# Returns the human-readable name of the adapter. Use mixed case - one) + comment(# can always use downcase if needed.) + reserved(def) method(adapter_name) + string<delimiter(')content(Abstract)delimiter(')> + reserved(end) + + comment(# Does this adapter support migrations? Backend specific, as the) + comment(# abstract adapter always returns +false+.) + reserved(def) method(supports_migrations?) + pre_constant(false) + reserved(end) + + comment(# Does this adapter support using DISTINCT within COUNT? This is +true+) + comment(# for all adapters except sqlite.) + reserved(def) method(supports_count_distinct?) + pre_constant(true) + reserved(end) + + comment(# Should primary key values be selected from their corresponding) + comment(# sequence before the insert statement? If true, next_sequence_value) + comment(# is called before each insert to set the record's primary key.) + comment(# This is false for all adapters but Firebird.) + reserved(def) method(prefetch_primary_key?)operator(()ident(table_name) operator(=) pre_constant(nil)operator(\)) + pre_constant(false) + reserved(end) + + reserved(def) method(reset_runtime) comment(#:nodoc:) + ident(rt)operator(,) instance_variable(@runtime) operator(=) instance_variable(@runtime)operator(,) integer(0) + ident(rt) + reserved(end) + + + comment(# CONNECTION MANAGEMENT ====================================) + + comment(# Is this connection active and ready to perform queries?) + reserved(def) method(active?) + instance_variable(@active) operator(!=) pre_constant(false) + reserved(end) + + comment(# Close this connection and open a new one in its place.) + reserved(def) method(reconnect!) + instance_variable(@active) operator(=) pre_constant(true) + reserved(end) + + comment(# Close this connection) + reserved(def) method(disconnect!) + instance_variable(@active) operator(=) pre_constant(false) + reserved(end) + + comment(# Lazily verify this connection, calling +active?+ only if it hasn't) + comment(# been called for +timeout+ seconds. ) + reserved(def) method(verify!)operator(()ident(timeout)operator(\)) + ident(now) operator(=) constant(Time)operator(.)ident(now)operator(.)ident(to_i) + reserved(if) operator(()ident(now) operator(-) instance_variable(@last_verification)operator(\)) operator(>) ident(timeout) + ident(reconnect!) reserved(unless) ident(active?) + instance_variable(@last_verification) operator(=) ident(now) + reserved(end) + reserved(end) + + comment(# Provides access to the underlying database connection. Useful for) + comment(# when you need to call a proprietary method such as postgresql's lo_*) + comment(# methods) + reserved(def) method(raw_connection) + instance_variable(@connection) + reserved(end) + + ident(protected) + reserved(def) method(log)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(if) ident(block_given?) + reserved(if) instance_variable(@logger) reserved(and) instance_variable(@logger)operator(.)ident(level) operator(<=) constant(Logger)operator(::)constant(INFO) + ident(result) operator(=) pre_constant(nil) + ident(seconds) operator(=) constant(Benchmark)operator(.)ident(realtime) operator({) ident(result) operator(=) reserved(yield) operator(}) + instance_variable(@runtime) operator(+=) ident(seconds) + ident(log_info)operator(()ident(sql)operator(,) ident(name)operator(,) ident(seconds)operator(\)) + ident(result) + reserved(else) + reserved(yield) + reserved(end) + reserved(else) + ident(log_info)operator(()ident(sql)operator(,) ident(name)operator(,) integer(0)operator(\)) + pre_constant(nil) + reserved(end) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + comment(# Log message and raise exception.) + comment(# Set last_verfication to 0, so that connection gets verified) + comment(# upon reentering the request loop) + instance_variable(@last_verification) operator(=) integer(0) + ident(message) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(e)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(sql)inline_delimiter(})>delimiter(")> + ident(log_info)operator(()ident(message)operator(,) ident(name)operator(,) integer(0)operator(\)) + ident(raise) constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(,) ident(message) + reserved(end) + + reserved(def) method(log_info)operator(()ident(sql)operator(,) ident(name)operator(,) ident(runtime)operator(\)) + reserved(return) reserved(unless) instance_variable(@logger) + + instance_variable(@logger)operator(.)ident(debug)operator(() + ident(format_log_entry)operator(() + string<delimiter(")inline<inline_delimiter(#{)ident(name)operator(.)ident(nil?) operator(?) string<delimiter(")content(SQL)delimiter(")> operator(:) ident(name)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(sprintf)operator(()string<delimiter(")content(%f)delimiter(")>operator(,) ident(runtime)operator(\))inline_delimiter(})>content(\))delimiter(")>operator(,) + ident(sql)operator(.)ident(gsub)operator(()regexp<delimiter(/)content( +)delimiter(/)>operator(,) string<delimiter(")content( )delimiter(")>operator(\)) + operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(format_log_entry)operator(()ident(message)operator(,) ident(dump) operator(=) pre_constant(nil)operator(\)) + reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(colorize_logging) + reserved(if) class_variable(@@row_even) + class_variable(@@row_even) operator(=) pre_constant(false) + ident(message_color)operator(,) ident(dump_color) operator(=) string<delimiter(")content(4;36;1)delimiter(")>operator(,) string<delimiter(")content(0;1)delimiter(")> + reserved(else) + class_variable(@@row_even) operator(=) pre_constant(true) + ident(message_color)operator(,) ident(dump_color) operator(=) string<delimiter(")content(4;35;1)delimiter(")>operator(,) string<delimiter(")content(0)delimiter(")> + reserved(end) + + ident(log_entry) operator(=) string<delimiter(")content( )char(\\e)content([)inline<inline_delimiter(#{)ident(message_color)inline_delimiter(})>content(m)inline<inline_delimiter(#{)ident(message)inline_delimiter(})>char(\\e)content([0m )delimiter(")> + ident(log_entry) operator(<<) string<delimiter(")char(\\e)content([)inline<inline_delimiter(#{)ident(dump_color)inline_delimiter(})>content(m%)inline<inline_delimiter(#{)constant(String) operator(===) ident(dump) operator(?) string<delimiter(')content(s)delimiter(')> operator(:) string<delimiter(')content(p)delimiter(')>inline_delimiter(})>char(\\e)content([0m)delimiter(")> operator(%) ident(dump) reserved(if) ident(dump) + ident(log_entry) + reserved(else) + string<delimiter(")content(%s %s)delimiter(")> operator(%) operator([)ident(message)operator(,) ident(dump)operator(]) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(# Author/Maintainer: Maik Schmidt <contact@maik-schmidt.de>) + +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(begin) + ident(require) string<delimiter(')content(db2/db2cli)delimiter(')> reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?)operator(()symbol(:DB2CLI)operator(\)) + ident(require) string<delimiter(')content(active_record/vendor/db2)delimiter(')> + + reserved(module) class(ActiveRecord) + reserved(class) class(Base) + comment(# Establishes a connection to the database that's used by) + comment(# all Active Record objects) + reserved(def) pre_constant(self)operator(.)ident(db2_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + ident(usr) operator(=) ident(config)operator([)symbol(:username)operator(]) + ident(pwd) operator(=) ident(config)operator([)symbol(:password)operator(]) + ident(schema) operator(=) ident(config)operator([)symbol(:schema)operator(]) + + reserved(if) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(database) operator(=) ident(config)operator([)symbol(:database)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(No database specified. Missing argument: database.)delimiter(')> + reserved(end) + + ident(connection) operator(=) constant(DB2)operator(::)constant(Connection)operator(.)ident(new)operator(()constant(DB2)operator(::)constant(Environment)operator(.)ident(new)operator(\)) + ident(connection)operator(.)ident(connect)operator(()ident(database)operator(,) ident(usr)operator(,) ident(pwd)operator(\)) + constant(ConnectionAdapters)operator(::)constant(DB2Adapter)operator(.)ident(new)operator(()ident(connection)operator(,) ident(logger)operator(,) symbol(:schema) operator(=)operator(>) ident(schema)operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(ConnectionAdapters) + comment(# The DB2 adapter works with the C-based CLI driver (http://rubyforge.org/projects/ruby-dbi/\)) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:username</tt> -- Defaults to nothing) + comment(# * <tt>:password</tt> -- Defaults to nothing) + comment(# * <tt>:database</tt> -- The name of the database. No default, must be provided.) + comment(# * <tt>:schema</tt> -- Database schema to be set initially.) + reserved(class) class(DB2Adapter) operator(<) constant(AbstractAdapter) + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(logger)operator(,) ident(connection_options)operator(\)) + reserved(super)operator(()ident(connection)operator(,) ident(logger)operator(\)) + instance_variable(@connection_options) operator(=) ident(connection_options) + reserved(if) ident(schema) operator(=) instance_variable(@connection_options)operator([)symbol(:schema)operator(]) + ident(with_statement) reserved(do) operator(|)ident(stmt)operator(|) + ident(stmt)operator(.)ident(exec_direct)operator(()string<delimiter(")content(SET SCHEMA=)inline<inline_delimiter(#{)ident(schema)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) + ident(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(id_value) operator(||) ident(last_insert_id) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(rows_affected) operator(=) integer(0) + ident(with_statement) reserved(do) operator(|)ident(stmt)operator(|) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + ident(stmt)operator(.)ident(exec_direct)operator(()ident(sql)operator(\)) + ident(rows_affected) operator(=) ident(stmt)operator(.)ident(row_count) + reserved(end) + reserved(end) + ident(rows_affected) + reserved(end) + + ident(alias_method) symbol(:update)operator(,) symbol(:execute) + ident(alias_method) symbol(:delete)operator(,) symbol(:execute) + + reserved(def) method(begin_db_transaction) + instance_variable(@connection)operator(.)ident(set_auto_commit_off) + reserved(end) + + reserved(def) method(commit_db_transaction) + instance_variable(@connection)operator(.)ident(commit) + instance_variable(@connection)operator(.)ident(set_auto_commit_on) + reserved(end) + + reserved(def) method(rollback_db_transaction) + instance_variable(@connection)operator(.)ident(rollback) + instance_variable(@connection)operator(.)ident(set_auto_commit_on) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(column_name)operator(\)) + ident(column_name) + reserved(end) + + reserved(def) method(adapter_name)operator(()operator(\)) + string<delimiter(')content(DB2)delimiter(')> + reserved(end) + + reserved(def) method(quote_string)operator(()ident(string)operator(\)) + ident(string)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(")content('')delimiter(")>operator(\)) comment(# ' (for ruby-mode\)) + reserved(end) + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) + reserved(if) ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) + ident(offset) operator(=) ident(options)operator([)symbol(:offset)operator(]) operator(||) integer(0) + comment(# The following trick was added by andrea+rails@webcom.it.) + ident(sql)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(SELECT)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(SELECT B.* FROM (SELECT A.*, row_number(\) over (\) AS internal$rownum FROM (SELECT)delimiter(')>operator(\)) + ident(sql) operator(<<) string<delimiter(")content(\) A \) B WHERE B.internal$rownum > )inline<inline_delimiter(#{)ident(offset)inline_delimiter(})>content( AND B.internal$rownum <= )inline<inline_delimiter(#{)ident(limit) operator(+) ident(offset)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + ident(result) operator(=) operator([)operator(]) + ident(schema) operator(=) instance_variable(@connection_options)operator([)symbol(:schema)operator(]) operator(||) string<delimiter(')content(%)delimiter(')> + ident(with_statement) reserved(do) operator(|)ident(stmt)operator(|) + ident(stmt)operator(.)ident(tables)operator(()ident(schema)operator(\))operator(.)ident(each) operator({) operator(|)ident(t)operator(|) ident(result) operator(<<) ident(t)operator([)integer(2)operator(])operator(.)ident(downcase) operator(}) + reserved(end) + ident(result) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(tmp) operator(=) operator({)operator(}) + ident(schema) operator(=) instance_variable(@connection_options)operator([)symbol(:schema)operator(]) operator(||) string<delimiter(')delimiter(')> + ident(with_statement) reserved(do) operator(|)ident(stmt)operator(|) + ident(stmt)operator(.)ident(indexes)operator(()ident(table_name)operator(,) ident(schema)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(t)operator(|) + reserved(next) reserved(unless) ident(t)operator([)integer(5)operator(]) + reserved(next) reserved(if) ident(t)operator([)integer(4)operator(]) operator(==) string<delimiter(')content(SYSIBM)delimiter(')> comment(# Skip system indexes.) + ident(idx_name) operator(=) ident(t)operator([)integer(5)operator(])operator(.)ident(downcase) + ident(col_name) operator(=) ident(t)operator([)integer(8)operator(])operator(.)ident(downcase) + reserved(if) ident(tmp)operator(.)ident(has_key?)operator(()ident(idx_name)operator(\)) + ident(tmp)operator([)ident(idx_name)operator(])operator(.)ident(columns) operator(<<) ident(col_name) + reserved(else) + ident(is_unique) operator(=) ident(t)operator([)integer(3)operator(]) operator(==) integer(0) + ident(tmp)operator([)ident(idx_name)operator(]) operator(=) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,) ident(idx_name)operator(,) ident(is_unique)operator(,) operator([)ident(col_name)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + ident(tmp)operator(.)ident(values) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(result) operator(=) operator([)operator(]) + ident(schema) operator(=) instance_variable(@connection_options)operator([)symbol(:schema)operator(]) operator(||) string<delimiter(')content(%)delimiter(')> + ident(with_statement) reserved(do) operator(|)ident(stmt)operator(|) + ident(stmt)operator(.)ident(columns)operator(()ident(table_name)operator(,) ident(schema)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(c)operator(|) + ident(c_name) operator(=) ident(c)operator([)integer(3)operator(])operator(.)ident(downcase) + ident(c_default) operator(=) ident(c)operator([)integer(12)operator(]) operator(==) string<delimiter(')content(NULL)delimiter(')> operator(?) pre_constant(nil) operator(:) ident(c)operator([)integer(12)operator(]) + ident(c_default)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(^'(.*\)'$)delimiter(/)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) reserved(if) operator(!)ident(c_default)operator(.)ident(nil?) + ident(c_type) operator(=) ident(c)operator([)integer(5)operator(])operator(.)ident(downcase) + ident(c_type) operator(+=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(c)operator([)integer(6)operator(])inline_delimiter(})>content(\))delimiter(")> reserved(if) operator(!)ident(c)operator([)integer(6)operator(])operator(.)ident(nil?) operator(&&) ident(c)operator([)integer(6)operator(]) operator(!=) string<delimiter(')delimiter(')> + ident(result) operator(<<) constant(Column)operator(.)ident(new)operator(()ident(c_name)operator(,) ident(c_default)operator(,) ident(c_type)operator(,) ident(c)operator([)integer(17)operator(]) operator(==) string<delimiter(')content(YES)delimiter(')>operator(\)) + reserved(end) + reserved(end) + ident(result) + reserved(end) + + reserved(def) method(native_database_types) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(')content(int generated by default as identity (start with 42\) primary key)delimiter(')>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(varchar)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(clob)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(32768) operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(int)delimiter(')> operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(float)delimiter(')> operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(timestamp)delimiter(')> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(timestamp)delimiter(')> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(time)delimiter(')> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(date)delimiter(')> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(blob)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(32768) operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(')content(decimal)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(1) operator(}) + operator(}) + reserved(end) + + reserved(def) method(quoted_true) + string<delimiter(')content(1)delimiter(')> + reserved(end) + + reserved(def) method(quoted_false) + string<delimiter(')content(0)delimiter(')> + reserved(end) + + reserved(def) method(active?) + instance_variable(@connection)operator(.)ident(select_one) string<delimiter(')content(select 1 from ibm.sysdummy1)delimiter(')> + pre_constant(true) + reserved(rescue) constant(Exception) + pre_constant(false) + reserved(end) + + reserved(def) method(reconnect!) + reserved(end) + + reserved(def) method(table_alias_length) + integer(128) + reserved(end) + + ident(private) + + reserved(def) method(with_statement) + ident(stmt) operator(=) constant(DB2)operator(::)constant(Statement)operator(.)ident(new)operator(()instance_variable(@connection)operator(\)) + reserved(yield) ident(stmt) + ident(stmt)operator(.)ident(free) + reserved(end) + + reserved(def) method(last_insert_id) + ident(row) operator(=) ident(select_one)operator(()string<delimiter(<<-GETID)>operator(.)ident(strip)operator(\))string<content( + with temp(id\) as (values (identity_val_local(\)\)\) select * from temp)delimiter( + GETID)> + ident(row)operator([)string<delimiter(')content(id)delimiter(')>operator(])operator(.)ident(to_i) + reserved(end) + + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(rows) operator(=) operator([)operator(]) + ident(with_statement) reserved(do) operator(|)ident(stmt)operator(|) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + ident(stmt)operator(.)ident(exec_direct)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(sql)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(=)char(\\s)content(*null)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(IS NULL)delimiter(')>operator(\))inline_delimiter(})>content( with ur)delimiter(")>operator(\)) + reserved(end) + + reserved(while) ident(row) operator(=) ident(stmt)operator(.)ident(fetch_as_hash) + ident(row)operator(.)ident(delete)operator(()string<delimiter(')content(internal$rownum)delimiter(')>operator(\)) + ident(rows) operator(<<) ident(row) + reserved(end) + reserved(end) + ident(rows) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(rescue) constant(LoadError) + comment(# DB2 driver is unavailable.) + reserved(module) class(ActiveRecord) comment(# :nodoc:) + reserved(class) class(Base) + reserved(def) pre_constant(self)operator(.)ident(db2_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + comment(# Set up a reasonable error message) + ident(raise) constant(LoadError)operator(,) string<delimiter(")content(DB2 Libraries could not be loaded.)delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(# Author: Ken Kunz <kennethkunz@gmail.com>) + +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(module) class(FireRuby) comment(# :nodoc: all) + reserved(class) class(Database) + reserved(def) pre_constant(self)operator(.)ident(new_from_params)operator(()ident(database)operator(,) ident(host)operator(,) ident(port)operator(,) ident(service)operator(\)) + ident(db_string) operator(=) string<delimiter(")delimiter(")> + reserved(if) ident(host) + ident(db_string) operator(<<) ident(host) + ident(db_string) operator(<<) string<delimiter(")content(/)inline<inline_delimiter(#{)ident(service) operator(||) ident(port)inline_delimiter(})>delimiter(")> reserved(if) ident(service) operator(||) ident(port) + ident(db_string) operator(<<) string<delimiter(")content(:)delimiter(")> + reserved(end) + ident(db_string) operator(<<) ident(database) + ident(new)operator(()ident(db_string)operator(\)) + reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(ActiveRecord) + reserved(class) operator(<<) class(Base) + reserved(def) method(firebird_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(require_library_or_gem) string<delimiter(')content(fireruby)delimiter(')> + reserved(unless) reserved(defined?) constant(FireRuby)operator(::)constant(SQLType) + ident(raise) constant(AdapterNotFound)operator(,) + string<delimiter(')content(The Firebird adapter requires FireRuby version 0.4.0 or greater; you appear )delimiter(')> operator(<<) + string<delimiter(')content(to be running an older version -- please update FireRuby (gem install fireruby\).)delimiter(')> + reserved(end) + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + reserved(unless) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database specified. Missing argument: database.)delimiter(")> + reserved(end) + ident(options) operator(=) ident(config)operator([)symbol(:charset)operator(]) operator(?) operator({) constant(CHARACTER_SET) operator(=)operator(>) ident(config)operator([)symbol(:charset)operator(]) operator(}) operator(:) operator({)operator(}) + ident(connection_params) operator(=) operator([)ident(config)operator([)symbol(:username)operator(])operator(,) ident(config)operator([)symbol(:password)operator(])operator(,) ident(options)operator(]) + ident(db) operator(=) constant(FireRuby)operator(::)constant(Database)operator(.)ident(new_from_params)operator(()operator(*)ident(config)operator(.)ident(values_at)operator(()symbol(:database)operator(,) symbol(:host)operator(,) symbol(:port)operator(,) symbol(:service)operator(\))operator(\)) + ident(connection) operator(=) ident(db)operator(.)ident(connect)operator(()operator(*)ident(connection_params)operator(\)) + constant(ConnectionAdapters)operator(::)constant(FirebirdAdapter)operator(.)ident(new)operator(()ident(connection)operator(,) ident(logger)operator(,) ident(connection_params)operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(ConnectionAdapters) + reserved(class) class(FirebirdColumn) operator(<) constant(Column) comment(# :nodoc:) + constant(VARCHAR_MAX_LENGTH) operator(=) integer(32_765) + constant(BLOB_MAX_LENGTH) operator(=) integer(32_767) + + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(domain)operator(,) ident(type)operator(,) ident(sub_type)operator(,) ident(length)operator(,) ident(precision)operator(,) ident(scale)operator(,) ident(default_source)operator(,) ident(null_flag)operator(\)) + instance_variable(@firebird_type) operator(=) constant(FireRuby)operator(::)constant(SQLType)operator(.)ident(to_base_type)operator(()ident(type)operator(,) ident(sub_type)operator(\))operator(.)ident(to_s) + reserved(super)operator(()ident(name)operator(.)ident(downcase)operator(,) pre_constant(nil)operator(,) instance_variable(@firebird_type)operator(,) operator(!)ident(null_flag)operator(\)) + instance_variable(@default) operator(=) ident(parse_default)operator(()ident(default_source)operator(\)) reserved(if) ident(default_source) + instance_variable(@limit) operator(=) ident(type) operator(==) string<delimiter(')content(BLOB)delimiter(')> operator(?) constant(BLOB_MAX_LENGTH) operator(:) ident(length) + instance_variable(@domain)operator(,) instance_variable(@sub_type)operator(,) instance_variable(@precision)operator(,) instance_variable(@scale) operator(=) ident(domain)operator(,) ident(sub_type)operator(,) ident(precision)operator(,) ident(scale) + reserved(end) + + reserved(def) method(type) + reserved(if) instance_variable(@domain) operator(=)operator(~) regexp<delimiter(/)content(BOOLEAN)delimiter(/)> + symbol(:boolean) + reserved(elsif) instance_variable(@type) operator(==) symbol(:binary) reserved(and) instance_variable(@sub_type) operator(==) integer(1) + symbol(:text) + reserved(else) + instance_variable(@type) + reserved(end) + reserved(end) + + comment(# Submits a _CAST_ query to the database, casting the default value to the specified SQL type.) + comment(# This enables Firebird to provide an actual value when context variables are used as column) + comment(# defaults (such as CURRENT_TIMESTAMP\).) + reserved(def) method(default) + reserved(if) instance_variable(@default) + ident(sql) operator(=) string<delimiter(")content(SELECT CAST()inline<inline_delimiter(#{)instance_variable(@default)inline_delimiter(})>content( AS )inline<inline_delimiter(#{)ident(column_def)inline_delimiter(})>content(\) FROM RDB$DATABASE)delimiter(")> + ident(connection) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(active_connections)operator(.)ident(values)operator(.)ident(detect) operator({) operator(|)ident(conn)operator(|) ident(conn) operator(&&) ident(conn)operator(.)ident(adapter_name) operator(==) string<delimiter(')content(Firebird)delimiter(')> operator(}) + reserved(if) ident(connection) + ident(type_cast) ident(connection)operator(.)ident(execute)operator(()ident(sql)operator(\))operator(.)ident(to_a)operator(.)ident(first)operator([)string<delimiter(')content(CAST)delimiter(')>operator(]) + reserved(else) + ident(raise) constant(ConnectionNotEstablished)operator(,) string<delimiter(")content(No Firebird connections established.)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(type_cast)operator(()ident(value)operator(\)) + reserved(if) ident(type) operator(==) symbol(:boolean) + ident(value) operator(==) pre_constant(true) reserved(or) ident(value) operator(==) constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(FirebirdAdapter)operator(.)ident(boolean_domain)operator([)symbol(:true)operator(]) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(parse_default)operator(()ident(default_source)operator(\)) + ident(default_source) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*DEFAULT)char(\\s)content(+(.*\))char(\\s)content(*$)delimiter(/)modifier(i)> + reserved(return) global_variable($1) reserved(unless) global_variable($1)operator(.)ident(upcase) operator(==) string<delimiter(")content(NULL)delimiter(")> + reserved(end) + + reserved(def) method(column_def) + reserved(case) instance_variable(@firebird_type) + reserved(when) string<delimiter(')content(BLOB)delimiter(')> reserved(then) string<delimiter(")content(VARCHAR()inline<inline_delimiter(#{)constant(VARCHAR_MAX_LENGTH)inline_delimiter(})>content(\))delimiter(")> + reserved(when) string<delimiter(')content(CHAR)delimiter(')>operator(,) string<delimiter(')content(VARCHAR)delimiter(')> reserved(then) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@firebird_type)inline_delimiter(})>content(()inline<inline_delimiter(#{)instance_variable(@limit)inline_delimiter(})>content(\))delimiter(")> + reserved(when) string<delimiter(')content(NUMERIC)delimiter(')>operator(,) string<delimiter(')content(DECIMAL)delimiter(')> reserved(then) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@firebird_type)inline_delimiter(})>content(()inline<inline_delimiter(#{)instance_variable(@precision)inline_delimiter(})>content(,)inline<inline_delimiter(#{)instance_variable(@scale)operator(.)ident(abs)inline_delimiter(})>content(\))delimiter(")> + reserved(when) string<delimiter(')content(DOUBLE)delimiter(')> reserved(then) string<delimiter(")content(DOUBLE PRECISION)delimiter(")> + reserved(else) instance_variable(@firebird_type) + reserved(end) + reserved(end) + + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(if) ident(field_type) operator(==) string<delimiter(')content(TIMESTAMP)delimiter(')> + symbol(:datetime) + reserved(else) + reserved(super) + reserved(end) + reserved(end) + reserved(end) + + comment(# The Firebird adapter relies on the FireRuby[http://rubyforge.org/projects/fireruby/]) + comment(# extension, version 0.4.0 or later (available as a gem or from) + comment(# RubyForge[http://rubyforge.org/projects/fireruby/]\). FireRuby works with) + comment(# Firebird 1.5.x on Linux, OS X and Win32 platforms.) + comment(#) + comment(# == Usage Notes) + comment(#) + comment(# === Sequence (Generator\) Names) + comment(# The Firebird adapter supports the same approach adopted for the Oracle) + comment(# adapter. See ActiveRecord::Base#set_sequence_name for more details.) + comment(#) + comment(# Note that in general there is no need to create a <tt>BEFORE INSERT</tt>) + comment(# trigger corresponding to a Firebird sequence generator when using) + comment(# ActiveRecord. In other words, you don't have to try to make Firebird) + comment(# simulate an <tt>AUTO_INCREMENT</tt> or +IDENTITY+ column. When saving a) + comment(# new record, ActiveRecord pre-fetches the next sequence value for the table) + comment(# and explicitly includes it in the +INSERT+ statement. (Pre-fetching the) + comment(# next primary key value is the only reliable method for the Firebird) + comment(# adapter to report back the +id+ after a successful insert.\)) + comment(#) + comment(# === BOOLEAN Domain) + comment(# Firebird 1.5 does not provide a native +BOOLEAN+ type. But you can easily) + comment(# define a +BOOLEAN+ _domain_ for this purpose, e.g.:) + comment(#) + comment(# CREATE DOMAIN D_BOOLEAN AS SMALLINT CHECK (VALUE IN (0, 1\)\);) + comment(#) + comment(# When the Firebird adapter encounters a column that is based on a domain) + comment(# that includes "BOOLEAN" in the domain name, it will attempt to treat) + comment(# the column as a +BOOLEAN+.) + comment(#) + comment(# By default, the Firebird adapter will assume that the BOOLEAN domain is) + comment(# defined as above. This can be modified if needed. For example, if you) + comment(# have a legacy schema with the following +BOOLEAN+ domain defined:) + comment(#) + comment(# CREATE DOMAIN BOOLEAN AS CHAR(1\) CHECK (VALUE IN ('T', 'F'\)\);) + comment(#) + comment(# ...you can add the following line to your <tt>environment.rb</tt> file:) + comment(#) + comment(# ActiveRecord::ConnectionAdapters::FirebirdAdapter.boolean_domain = { :true => 'T', :false => 'F' }) + comment(#) + comment(# === BLOB Elements) + comment(# The Firebird adapter currently provides only limited support for +BLOB+) + comment(# columns. You cannot currently retrieve or insert a +BLOB+ as an IO stream.) + comment(# When selecting a +BLOB+, the entire element is converted into a String.) + comment(# When inserting or updating a +BLOB+, the entire value is included in-line) + comment(# in the SQL statement, limiting you to values <= 32KB in size.) + comment(#) + comment(# === Column Name Case Semantics) + comment(# Firebird and ActiveRecord have somewhat conflicting case semantics for) + comment(# column names.) + comment(#) + comment(# [*Firebird*]) + comment(# The standard practice is to use unquoted column names, which can be) + comment(# thought of as case-insensitive. (In fact, Firebird converts them to) + comment(# uppercase.\) Quoted column names (not typically used\) are case-sensitive.) + comment(# [*ActiveRecord*]) + comment(# Attribute accessors corresponding to column names are case-sensitive.) + comment(# The defaults for primary key and inheritance columns are lowercase, and) + comment(# in general, people use lowercase attribute names.) + comment(#) + comment(# In order to map between the differing semantics in a way that conforms) + comment(# to common usage for both Firebird and ActiveRecord, uppercase column names) + comment(# in Firebird are converted to lowercase attribute names in ActiveRecord,) + comment(# and vice-versa. Mixed-case column names retain their case in both) + comment(# directions. Lowercase (quoted\) Firebird column names are not supported.) + comment(# This is similar to the solutions adopted by other adapters.) + comment(#) + comment(# In general, the best approach is to use unqouted (case-insensitive\) column) + comment(# names in your Firebird DDL (or if you must quote, use uppercase column) + comment(# names\). These will correspond to lowercase attributes in ActiveRecord.) + comment(#) + comment(# For example, a Firebird table based on the following DDL:) + comment(#) + comment(# CREATE TABLE products () + comment(# id BIGINT NOT NULL PRIMARY KEY,) + comment(# "TYPE" VARCHAR(50\),) + comment(# name VARCHAR(255\) \);) + comment(#) + comment(# ...will correspond to an ActiveRecord model class called +Product+ with) + comment(# the following attributes: +id+, +type+, +name+.) + comment(#) + comment(# ==== Quoting <tt>"TYPE"</tt> and other Firebird reserved words:) + comment(# In ActiveRecord, the default inheritance column name is +type+. The word) + comment(# _type_ is a Firebird reserved word, so it must be quoted in any Firebird) + comment(# SQL statements. Because of the case mapping described above, you should) + comment(# always reference this column using quoted-uppercase syntax) + comment(# (<tt>"TYPE"</tt>\) within Firebird DDL or other SQL statements (as in the) + comment(# example above\). This holds true for any other Firebird reserved words used) + comment(# as column names as well.) + comment(#) + comment(# === Migrations) + comment(# The Firebird adapter does not currently support Migrations. I hope to) + comment(# add this feature in the near future.) + comment(#) + comment(# == Connection Options) + comment(# The following options are supported by the Firebird adapter. None of the) + comment(# options have default values.) + comment(#) + comment(# <tt>:database</tt>::) + comment(# <i>Required option.</i> Specifies one of: (i\) a Firebird database alias;) + comment(# (ii\) the full path of a database file; _or_ (iii\) a full Firebird) + comment(# connection string. <i>Do not specify <tt>:host</tt>, <tt>:service</tt>) + comment(# or <tt>:port</tt> as separate options when using a full connection) + comment(# string.</i>) + comment(# <tt>:host</tt>::) + comment(# Set to <tt>"remote.host.name"</tt> for remote database connections.) + comment(# May be omitted for local connections if a full database path is) + comment(# specified for <tt>:database</tt>. Some platforms require a value of) + comment(# <tt>"localhost"</tt> for local connections when using a Firebird) + comment(# database _alias_.) + comment(# <tt>:service</tt>::) + comment(# Specifies a service name for the connection. Only used if <tt>:host</tt>) + comment(# is provided. Required when connecting to a non-standard service.) + comment(# <tt>:port</tt>::) + comment(# Specifies the connection port. Only used if <tt>:host</tt> is provided) + comment(# and <tt>:service</tt> is not. Required when connecting to a non-standard) + comment(# port and <tt>:service</tt> is not defined.) + comment(# <tt>:username</tt>::) + comment(# Specifies the database user. May be omitted or set to +nil+ (together) + comment(# with <tt>:password</tt>\) to use the underlying operating system user) + comment(# credentials on supported platforms.) + comment(# <tt>:password</tt>::) + comment(# Specifies the database password. Must be provided if <tt>:username</tt>) + comment(# is explicitly specified; should be omitted if OS user credentials are) + comment(# are being used.) + comment(# <tt>:charset</tt>::) + comment(# Specifies the character set to be used by the connection. Refer to) + comment(# Firebird documentation for valid options.) + reserved(class) class(FirebirdAdapter) operator(<) constant(AbstractAdapter) + class_variable(@@boolean_domain) operator(=) operator({) symbol(:true) operator(=)operator(>) integer(1)operator(,) symbol(:false) operator(=)operator(>) integer(0) operator(}) + ident(cattr_accessor) symbol(:boolean_domain) + + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(logger)operator(,) ident(connection_params)operator(=)pre_constant(nil)operator(\)) + reserved(super)operator(()ident(connection)operator(,) ident(logger)operator(\)) + instance_variable(@connection_params) operator(=) ident(connection_params) + reserved(end) + + reserved(def) method(adapter_name) comment(# :nodoc:) + string<delimiter(')content(Firebird)delimiter(')> + reserved(end) + + comment(# Returns true for Firebird adapter (since Firebird requires primary key) + comment(# values to be pre-fetched before insert\). See also #next_sequence_value.) + reserved(def) method(prefetch_primary_key?)operator(()ident(table_name) operator(=) pre_constant(nil)operator(\)) + pre_constant(true) + reserved(end) + + reserved(def) method(default_sequence_name)operator(()ident(table_name)operator(,) ident(primary_key)operator(\)) comment(# :nodoc:) + string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(_seq)delimiter(")> + reserved(end) + + + comment(# QUOTING ==================================================) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + reserved(if) operator([)constant(Time)operator(,) constant(DateTime)operator(])operator(.)ident(include?)operator(()ident(value)operator(.)ident(class)operator(\)) + string<delimiter(")content(CAST(')inline<inline_delimiter(#{)ident(value)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(\))inline_delimiter(})>content(' AS TIMESTAMP\))delimiter(")> + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(def) method(quote_string)operator(()ident(string)operator(\)) comment(# :nodoc:) + ident(string)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(")content('')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(column_name)operator(\)) comment(# :nodoc:) + string<delimiter(%Q()content(")inline<inline_delimiter(#{)ident(ar_to_fb_case)operator(()ident(column_name)operator(\))inline_delimiter(})>content(")delimiter(\))> + reserved(end) + + reserved(def) method(quoted_true) comment(# :nodoc:) + ident(quote)operator(()ident(boolean_domain)operator([)symbol(:true)operator(])operator(\)) + reserved(end) + + reserved(def) method(quoted_false) comment(# :nodoc:) + ident(quote)operator(()ident(boolean_domain)operator([)symbol(:false)operator(])operator(\)) + reserved(end) + + + comment(# CONNECTION MANAGEMENT ====================================) + + reserved(def) method(active?) + reserved(not) instance_variable(@connection)operator(.)ident(closed?) + reserved(end) + + reserved(def) method(reconnect!) + instance_variable(@connection)operator(.)ident(close) + instance_variable(@connection) operator(=) instance_variable(@connection)operator(.)ident(database)operator(.)ident(connect)operator(()operator(*)instance_variable(@connection_params)operator(\)) + reserved(end) + + + comment(# DATABASE STATEMENTS ======================================) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + ident(result) operator(=) ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(result)operator(.)ident(first) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) comment(# :nodoc:) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + reserved(if) instance_variable(@transaction) + instance_variable(@connection)operator(.)ident(execute)operator(()ident(sql)operator(,) instance_variable(@transaction)operator(,) operator(&)ident(block)operator(\)) + reserved(else) + instance_variable(@connection)operator(.)ident(execute_immediate)operator(()ident(sql)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(id_value) + reserved(end) + + ident(alias_method) symbol(:update)operator(,) symbol(:execute) + ident(alias_method) symbol(:delete)operator(,) symbol(:execute) + + reserved(def) method(begin_db_transaction)operator(()operator(\)) comment(# :nodoc:) + instance_variable(@transaction) operator(=) instance_variable(@connection)operator(.)ident(start_transaction) + reserved(end) + + reserved(def) method(commit_db_transaction)operator(()operator(\)) comment(# :nodoc:) + instance_variable(@transaction)operator(.)ident(commit) + reserved(ensure) + instance_variable(@transaction) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(rollback_db_transaction)operator(()operator(\)) comment(# :nodoc:) + instance_variable(@transaction)operator(.)ident(rollback) + reserved(ensure) + instance_variable(@transaction) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(# :nodoc:) + reserved(if) ident(options)operator([)symbol(:limit)operator(]) + ident(limit_string) operator(=) string<delimiter(")content(FIRST )inline<inline_delimiter(#{)ident(options)operator([)symbol(:limit)operator(])inline_delimiter(})>delimiter(")> + ident(limit_string) operator(<<) string<delimiter(")content( SKIP )inline<inline_delimiter(#{)ident(options)operator([)symbol(:offset)operator(])inline_delimiter(})>delimiter(")> reserved(if) ident(options)operator([)symbol(:offset)operator(]) + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)char(\\A)content(()char(\\s)content(*SELECT)char(\\s)content(\))delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\&)delimiter(')> operator(+) ident(limit_string) operator(+) string<delimiter(')content( )delimiter(')>operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the next sequence value from a sequence generator. Not generally) + comment(# called directly; used by ActiveRecord to get the next primary key value) + comment(# when inserting a new database record (see #prefetch_primary_key?\).) + reserved(def) method(next_sequence_value)operator(()ident(sequence_name)operator(\)) + constant(FireRuby)operator(::)constant(Generator)operator(.)ident(new)operator(()ident(sequence_name)operator(,) instance_variable(@connection)operator(\))operator(.)ident(next)operator(()integer(1)operator(\)) + reserved(end) + + + comment(# SCHEMA STATEMENTS ========================================) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + ident(sql) operator(=) string<delimiter(<<-END_SQL)>string<content( + SELECT r.rdb$field_name, r.rdb$field_source, f.rdb$field_type, f.rdb$field_sub_type, + f.rdb$field_length, f.rdb$field_precision, f.rdb$field_scale, + COALESCE(r.rdb$default_source, f.rdb$default_source\) rdb$default_source, + COALESCE(r.rdb$null_flag, f.rdb$null_flag\) rdb$null_flag + FROM rdb$relation_fields r + JOIN rdb$fields f ON r.rdb$field_source = f.rdb$field_name + WHERE r.rdb$relation_name = ')inline<inline_delimiter(#{)ident(table_name)operator(.)ident(to_s)operator(.)ident(upcase)inline_delimiter(})>content(' + ORDER BY r.rdb$field_position)delimiter( + END_SQL)> + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(collect) reserved(do) operator(|)ident(field)operator(|) + ident(field_values) operator(=) ident(field)operator(.)ident(values)operator(.)ident(collect) reserved(do) operator(|)ident(value)operator(|) + reserved(case) ident(value) + reserved(when) constant(String) reserved(then) ident(value)operator(.)ident(rstrip) + reserved(when) constant(FireRuby)operator(::)constant(Blob) reserved(then) ident(value)operator(.)ident(to_s) + reserved(else) ident(value) + reserved(end) + reserved(end) + constant(FirebirdColumn)operator(.)ident(new)operator(()operator(*)ident(field_values)operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(collect) reserved(do) operator(|)ident(row)operator(|) + ident(hashed_row) operator(=) operator({)operator(}) + ident(row)operator(.)ident(each) reserved(do) operator(|)ident(column)operator(,) ident(value)operator(|) + ident(value) operator(=) ident(value)operator(.)ident(to_s) reserved(if) constant(FireRuby)operator(::)constant(Blob) operator(===) ident(value) + ident(hashed_row)operator([)ident(fb_to_ar_case)operator(()ident(column)operator(\))operator(]) operator(=) ident(value) + reserved(end) + ident(hashed_row) + reserved(end) + reserved(end) + + comment(# Maps uppercase Firebird column names to lowercase for ActiveRecord;) + comment(# mixed-case columns retain their original case.) + reserved(def) method(fb_to_ar_case)operator(()ident(column_name)operator(\)) + ident(column_name) operator(=)operator(~) regexp<delimiter(/)content([[:lower:]])delimiter(/)> operator(?) ident(column_name) operator(:) ident(column_name)operator(.)ident(downcase) + reserved(end) + + comment(# Maps lowercase ActiveRecord column names to uppercase for Fierbird;) + comment(# mixed-case columns retain their original case.) + reserved(def) method(ar_to_fb_case)operator(()ident(column_name)operator(\)) + ident(column_name) operator(=)operator(~) regexp<delimiter(/)content([[:upper:]])delimiter(/)> operator(?) ident(column_name) operator(:) ident(column_name)operator(.)ident(upcase) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + comment(# Establishes a connection to the database that's used by all Active Record objects.) + reserved(def) pre_constant(self)operator(.)ident(mysql_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + comment(# Only include the MySQL driver if one hasn't already been loaded) + reserved(unless) reserved(defined?) constant(Mysql) + reserved(begin) + ident(require_library_or_gem) string<delimiter(')content(mysql)delimiter(')> + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(cannot_require_mysql) + comment(# Only use the supplied backup Ruby/MySQL driver if no driver is already in place) + reserved(begin) + ident(require) string<delimiter(')content(active_record/vendor/mysql)delimiter(')> + reserved(rescue) constant(LoadError) + ident(raise) ident(cannot_require_mysql) + reserved(end) + reserved(end) + reserved(end) + + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + ident(host) operator(=) ident(config)operator([)symbol(:host)operator(]) + ident(port) operator(=) ident(config)operator([)symbol(:port)operator(]) + ident(socket) operator(=) ident(config)operator([)symbol(:socket)operator(]) + ident(username) operator(=) ident(config)operator([)symbol(:username)operator(]) operator(?) ident(config)operator([)symbol(:username)operator(])operator(.)ident(to_s) operator(:) string<delimiter(')content(root)delimiter(')> + ident(password) operator(=) ident(config)operator([)symbol(:password)operator(])operator(.)ident(to_s) + + reserved(if) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(database) operator(=) ident(config)operator([)symbol(:database)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database specified. Missing argument: database.)delimiter(")> + reserved(end) + + ident(mysql) operator(=) constant(Mysql)operator(.)ident(init) + ident(mysql)operator(.)ident(ssl_set)operator(()ident(config)operator([)symbol(:sslkey)operator(])operator(,) ident(config)operator([)symbol(:sslcert)operator(])operator(,) ident(config)operator([)symbol(:sslca)operator(])operator(,) ident(config)operator([)symbol(:sslcapath)operator(])operator(,) ident(config)operator([)symbol(:sslcipher)operator(])operator(\)) reserved(if) ident(config)operator([)symbol(:sslkey)operator(]) + constant(ConnectionAdapters)operator(::)constant(MysqlAdapter)operator(.)ident(new)operator(()ident(mysql)operator(,) ident(logger)operator(,) operator([)ident(host)operator(,) ident(username)operator(,) ident(password)operator(,) ident(database)operator(,) ident(port)operator(,) ident(socket)operator(])operator(,) ident(config)operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(ConnectionAdapters) + reserved(class) class(MysqlColumn) operator(<) constant(Column) comment(#:nodoc:) + ident(private) + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(return) symbol(:boolean) reserved(if) constant(MysqlAdapter)operator(.)ident(emulate_booleans) operator(&&) ident(field_type)operator(.)ident(downcase)operator(.)ident(index)operator(()string<delimiter(")content(tinyint(1\))delimiter(")>operator(\)) + reserved(return) symbol(:string) reserved(if) ident(field_type) operator(=)operator(~) regexp<delimiter(/)content(enum)delimiter(/)modifier(i)> + reserved(super) + reserved(end) + reserved(end) + + comment(# The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with) + comment(# the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/\).) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:host</tt> -- Defaults to localhost) + comment(# * <tt>:port</tt> -- Defaults to 3306) + comment(# * <tt>:socket</tt> -- Defaults to /tmp/mysql.sock) + comment(# * <tt>:username</tt> -- Defaults to root) + comment(# * <tt>:password</tt> -- Defaults to nothing) + comment(# * <tt>:database</tt> -- The name of the database. No default, must be provided.) + comment(# * <tt>:sslkey</tt> -- Necessary to use MySQL with an SSL connection) + comment(# * <tt>:sslcert</tt> -- Necessary to use MySQL with an SSL connection) + comment(# * <tt>:sslcapath</tt> -- Necessary to use MySQL with an SSL connection) + comment(# * <tt>:sslcipher</tt> -- Necessary to use MySQL with an SSL connection) + comment(#) + comment(# By default, the MysqlAdapter will consider all columns of type tinyint(1\)) + comment(# as boolean. If you wish to disable this emulation (which was the default) + comment(# behavior in versions 0.13.1 and earlier\) you can add the following line) + comment(# to your environment.rb file:) + comment(#) + comment(# ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false) + reserved(class) class(MysqlAdapter) operator(<) constant(AbstractAdapter) + class_variable(@@emulate_booleans) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:emulate_booleans) + + constant(LOST_CONNECTION_ERROR_MESSAGES) operator(=) operator([) + string<delimiter(")content(Server shutdown in progress)delimiter(")>operator(,) + string<delimiter(")content(Broken pipe)delimiter(")>operator(,) + string<delimiter(")content(Lost connection to MySQL server during query)delimiter(")>operator(,) + string<delimiter(")content(MySQL server has gone away)delimiter(")> + operator(]) + + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(logger)operator(,) ident(connection_options)operator(,) ident(config)operator(\)) + reserved(super)operator(()ident(connection)operator(,) ident(logger)operator(\)) + instance_variable(@connection_options)operator(,) instance_variable(@config) operator(=) ident(connection_options)operator(,) ident(config) + instance_variable(@null_values_in_each_hash) operator(=) constant(Mysql)operator(.)ident(const_defined?)operator(()symbol(:VERSION)operator(\)) + ident(connect) + reserved(end) + + reserved(def) method(adapter_name) comment(#:nodoc:) + string<delimiter(')content(MySQL)delimiter(')> + reserved(end) + + reserved(def) method(supports_migrations?) comment(#:nodoc:) + pre_constant(true) + reserved(end) + + reserved(def) method(native_database_types) comment(#:nodoc) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(int(11\) DEFAULT NULL auto_increment PRIMARY KEY)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(varchar)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(text)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(int)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(11) operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(float)delimiter(")> operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(time)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(date)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(blob)delimiter(")> operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(tinyint)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(1) operator(}) + operator(}) + reserved(end) + + + comment(# QUOTING ==================================================) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) operator(&&) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) operator(&&) ident(column)operator(.)ident(class)operator(.)ident(respond_to?)operator(()symbol(:string_to_binary)operator(\)) + ident(s) operator(=) ident(column)operator(.)ident(class)operator(.)ident(string_to_binary)operator(()ident(value)operator(\))operator(.)ident(unpack)operator(()string<delimiter(")content(H*)delimiter(")>operator(\))operator([)integer(0)operator(]) + string<delimiter(")content(x')inline<inline_delimiter(#{)ident(s)inline_delimiter(})>content(')delimiter(")> + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) comment(#:nodoc:) + string<delimiter(")content(`)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(`)delimiter(")> + reserved(end) + + reserved(def) method(quote_string)operator(()ident(string)operator(\)) comment(#:nodoc:) + instance_variable(@connection)operator(.)ident(quote)operator(()ident(string)operator(\)) + reserved(end) + + reserved(def) method(quoted_true) + string<delimiter(")content(1)delimiter(")> + reserved(end) + + reserved(def) method(quoted_false) + string<delimiter(")content(0)delimiter(")> + reserved(end) + + + comment(# CONNECTION MANAGEMENT ====================================) + + reserved(def) method(active?) + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:stat)operator(\)) + instance_variable(@connection)operator(.)ident(stat) + reserved(else) + instance_variable(@connection)operator(.)ident(query) string<delimiter(')content(select 1)delimiter(')> + reserved(end) + + comment(# mysql-ruby doesn't raise an exception when stat fails.) + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:errno)operator(\)) + instance_variable(@connection)operator(.)ident(errno)operator(.)ident(zero?) + reserved(else) + pre_constant(true) + reserved(end) + reserved(rescue) constant(Mysql)operator(::)constant(Error) + pre_constant(false) + reserved(end) + + reserved(def) method(reconnect!) + ident(disconnect!) + ident(connect) + reserved(end) + + reserved(def) method(disconnect!) + instance_variable(@connection)operator(.)ident(close) reserved(rescue) pre_constant(nil) + reserved(end) + + + comment(# DATABASE STATEMENTS ======================================) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(result) operator(=) ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(result)operator(.)ident(first) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(retries) operator(=) integer(2)operator(\)) comment(#:nodoc:) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(query)operator(()ident(sql)operator(\)) operator(}) + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) operator(=)operator(>) ident(exception) + reserved(if) ident(exception)operator(.)ident(message)operator(.)ident(split)operator(()string<delimiter(")content(:)delimiter(")>operator(\))operator(.)ident(first) operator(=)operator(~) regexp<delimiter(/)content(Packets out of order)delimiter(/)> + ident(raise) constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(,) string<delimiter(")content('Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql\) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings.)delimiter(")> + reserved(else) + ident(raise) + reserved(end) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(id_value) operator(||) instance_variable(@connection)operator(.)ident(insert_id) + reserved(end) + + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + instance_variable(@connection)operator(.)ident(affected_rows) + reserved(end) + + ident(alias_method) symbol(:delete)operator(,) symbol(:update) comment(#:nodoc:) + + + reserved(def) method(begin_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(BEGIN)delimiter(")> + reserved(rescue) constant(Exception) + comment(# Transactions aren't supported) + reserved(end) + + reserved(def) method(commit_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(COMMIT)delimiter(")> + reserved(rescue) constant(Exception) + comment(# Transactions aren't supported) + reserved(end) + + reserved(def) method(rollback_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ROLLBACK)delimiter(")> + reserved(rescue) constant(Exception) + comment(# Transactions aren't supported) + reserved(end) + + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(#:nodoc) + reserved(if) ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) + reserved(unless) ident(offset) operator(=) ident(options)operator([)symbol(:offset)operator(]) + ident(sql) operator(<<) string<delimiter(")content( LIMIT )inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>delimiter(")> + reserved(else) + ident(sql) operator(<<) string<delimiter(")content( LIMIT )inline<inline_delimiter(#{)ident(offset)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + + comment(# SCHEMA STATEMENTS ========================================) + + reserved(def) method(structure_dump) comment(#:nodoc:) + reserved(if) ident(supports_views?) + ident(sql) operator(=) string<delimiter(")content(SHOW FULL TABLES WHERE Table_type = 'BASE TABLE')delimiter(")> + reserved(else) + ident(sql) operator(=) string<delimiter(")content(SHOW TABLES)delimiter(")> + reserved(end) + + ident(select_all)operator(()ident(sql)operator(\))operator(.)ident(inject)operator(()string<delimiter(")delimiter(")>operator(\)) reserved(do) operator(|)ident(structure)operator(,) ident(table)operator(|) + ident(table)operator(.)ident(delete)operator(()string<delimiter(')content(Table_type)delimiter(')>operator(\)) + ident(structure) operator(+=) ident(select_one)operator(()string<delimiter(")content(SHOW CREATE TABLE )inline<inline_delimiter(#{)ident(table)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last)inline_delimiter(})>delimiter(")>operator(\))operator([)string<delimiter(")content(Create Table)delimiter(")>operator(]) operator(+) string<delimiter(")content(;)char(\\n)char(\\n)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(recreate_database)operator(()ident(name)operator(\)) comment(#:nodoc:) + ident(drop_database)operator(()ident(name)operator(\)) + ident(create_database)operator(()ident(name)operator(\)) + reserved(end) + + reserved(def) method(create_database)operator(()ident(name)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(CREATE DATABASE `)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(`)delimiter(")> + reserved(end) + + reserved(def) method(drop_database)operator(()ident(name)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(DROP DATABASE IF EXISTS `)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(`)delimiter(")> + reserved(end) + + reserved(def) method(current_database) + ident(select_one)operator(()string<delimiter(")content(SELECT DATABASE(\) as db)delimiter(")>operator(\))operator([)string<delimiter(")content(db)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(tables) operator(=) operator([)operator(]) + ident(execute)operator(()string<delimiter(")content(SHOW TABLES)delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(each) operator({) operator(|)ident(field)operator(|) ident(tables) operator(<<) ident(field)operator([)integer(0)operator(]) operator(}) + ident(tables) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\))comment(#:nodoc:) + ident(indexes) operator(=) operator([)operator(]) + ident(current_index) operator(=) pre_constant(nil) + ident(execute)operator(()string<delimiter(")content(SHOW KEYS FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + reserved(if) ident(current_index) operator(!=) ident(row)operator([)integer(2)operator(]) + reserved(next) reserved(if) ident(row)operator([)integer(2)operator(]) operator(==) string<delimiter(")content(PRIMARY)delimiter(")> comment(# skip the primary key) + ident(current_index) operator(=) ident(row)operator([)integer(2)operator(]) + ident(indexes) operator(<<) constant(IndexDefinition)operator(.)ident(new)operator(()ident(row)operator([)integer(0)operator(])operator(,) ident(row)operator([)integer(2)operator(])operator(,) ident(row)operator([)integer(1)operator(]) operator(==) string<delimiter(")content(0)delimiter(")>operator(,) operator([)operator(])operator(\)) + reserved(end) + + ident(indexes)operator(.)ident(last)operator(.)ident(columns) operator(<<) ident(row)operator([)integer(4)operator(]) + reserved(end) + ident(indexes) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\))comment(#:nodoc:) + ident(sql) operator(=) string<delimiter(")content(SHOW FIELDS FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")> + ident(columns) operator(=) operator([)operator(]) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(each) operator({) operator(|)ident(field)operator(|) ident(columns) operator(<<) constant(MysqlColumn)operator(.)ident(new)operator(()ident(field)operator([)integer(0)operator(])operator(,) ident(field)operator([)integer(4)operator(])operator(,) ident(field)operator([)integer(1)operator(])operator(,) ident(field)operator([)integer(2)operator(]) operator(==) string<delimiter(")content(YES)delimiter(")>operator(\)) operator(}) + ident(columns) + reserved(end) + + reserved(def) method(create_table)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + reserved(super)operator(()ident(name)operator(,) operator({)symbol(:options) operator(=)operator(>) string<delimiter(")content(ENGINE=InnoDB)delimiter(")>operator(})operator(.)ident(merge)operator(()ident(options)operator(\))operator(\)) + reserved(end) + + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + ident(execute) string<delimiter(")content(RENAME TABLE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( TO )inline<inline_delimiter(#{)ident(new_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(default)operator(\)) comment(#:nodoc:) + ident(current_type) operator(=) ident(select_one)operator(()string<delimiter(")content(SHOW COLUMNS FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( LIKE ')inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(')delimiter(")>operator(\))operator([)string<delimiter(")content(Type)delimiter(")>operator(]) + + ident(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(current_type)operator(,) operator({) symbol(:default) operator(=)operator(>) ident(default) operator(})operator(\)) + reserved(end) + + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(options)operator([)symbol(:default)operator(]) operator(||=) ident(select_one)operator(()string<delimiter(")content(SHOW COLUMNS FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( LIKE ')inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(')delimiter(")>operator(\))operator([)string<delimiter(")content(Default)delimiter(")>operator(]) + + ident(change_column_sql) operator(=) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( CHANGE )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")> + ident(add_column_options!)operator(()ident(change_column_sql)operator(,) ident(options)operator(\)) + ident(execute)operator(()ident(change_column_sql)operator(\)) + reserved(end) + + reserved(def) method(rename_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(new_column_name)operator(\)) comment(#:nodoc:) + ident(current_type) operator(=) ident(select_one)operator(()string<delimiter(")content(SHOW COLUMNS FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( LIKE ')inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(')delimiter(")>operator(\))operator([)string<delimiter(")content(Type)delimiter(")>operator(]) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( CHANGE )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(new_column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(current_type)inline_delimiter(})>delimiter(")> + reserved(end) + + + ident(private) + reserved(def) method(connect) + ident(encoding) operator(=) instance_variable(@config)operator([)symbol(:encoding)operator(]) + reserved(if) ident(encoding) + instance_variable(@connection)operator(.)ident(options)operator(()constant(Mysql)operator(::)constant(SET_CHARSET_NAME)operator(,) ident(encoding)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + instance_variable(@connection)operator(.)ident(real_connect)operator(()operator(*)instance_variable(@connection_options)operator(\)) + ident(execute)operator(()string<delimiter(")content(SET NAMES ')inline<inline_delimiter(#{)ident(encoding)inline_delimiter(})>content(')delimiter(")>operator(\)) reserved(if) ident(encoding) + reserved(end) + + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + instance_variable(@connection)operator(.)ident(query_with_result) operator(=) pre_constant(true) + ident(result) operator(=) ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(rows) operator(=) operator([)operator(]) + reserved(if) instance_variable(@null_values_in_each_hash) + ident(result)operator(.)ident(each_hash) operator({) operator(|)ident(row)operator(|) ident(rows) operator(<<) ident(row) operator(}) + reserved(else) + ident(all_fields) operator(=) ident(result)operator(.)ident(fetch_fields)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) operator({) operator(|)ident(fields)operator(,) ident(f)operator(|) ident(fields)operator([)ident(f)operator(.)ident(name)operator(]) operator(=) pre_constant(nil)operator(;) ident(fields) operator(}) + ident(result)operator(.)ident(each_hash) operator({) operator(|)ident(row)operator(|) ident(rows) operator(<<) ident(all_fields)operator(.)ident(dup)operator(.)ident(update)operator(()ident(row)operator(\)) operator(}) + reserved(end) + ident(result)operator(.)ident(free) + ident(rows) + reserved(end) + + reserved(def) method(supports_views?) + ident(version)operator([)integer(0)operator(]) operator(>)operator(=) integer(5) + reserved(end) + + reserved(def) method(version) + instance_variable(@version) operator(||=) instance_variable(@connection)operator(.)ident(server_info)operator(.)ident(scan)operator(()regexp<delimiter(/)content(^()char(\\d)content(+\))char(\\.)content(()char(\\d)content(+\))char(\\.)content(()char(\\d)content(+\))delimiter(/)>operator(\))operator(.)ident(flatten)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) ident(v)operator(.)ident(to_i) operator(}) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + comment(# Establishes a connection to the database that's used by all Active Record objects) + reserved(def) pre_constant(self)operator(.)ident(openbase_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(require_library_or_gem) string<delimiter(')content(openbase)delimiter(')> reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?)operator(()symbol(:OpenBase)operator(\)) + + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + ident(host) operator(=) ident(config)operator([)symbol(:host)operator(]) + ident(username) operator(=) ident(config)operator([)symbol(:username)operator(])operator(.)ident(to_s) + ident(password) operator(=) ident(config)operator([)symbol(:password)operator(])operator(.)ident(to_s) + + + reserved(if) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(database) operator(=) ident(config)operator([)symbol(:database)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database specified. Missing argument: database.)delimiter(")> + reserved(end) + + ident(oba) operator(=) constant(ConnectionAdapters)operator(::)constant(OpenBaseAdapter)operator(.)ident(new)operator(() + constant(OpenBase)operator(.)ident(new)operator(()ident(database)operator(,) ident(host)operator(,) ident(username)operator(,) ident(password)operator(\))operator(,) ident(logger) + operator(\)) + + ident(oba) + reserved(end) + + reserved(end) + + reserved(module) class(ConnectionAdapters) + reserved(class) class(OpenBaseColumn) operator(<) constant(Column) comment(#:nodoc:) + ident(private) + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(return) symbol(:integer) reserved(if) ident(field_type)operator(.)ident(downcase) operator(=)operator(~) regexp<delimiter(/)content(long)delimiter(/)> + reserved(return) symbol(:float) reserved(if) ident(field_type)operator(.)ident(downcase) operator(==) string<delimiter(")content(money)delimiter(")> + reserved(return) symbol(:binary) reserved(if) ident(field_type)operator(.)ident(downcase) operator(==) string<delimiter(")content(object)delimiter(")> + reserved(super) + reserved(end) + reserved(end) + comment(# The OpenBase adapter works with the Ruby/Openbase driver by Tetsuya Suzuki.) + comment(# http://www.spice-of-life.net/ruby-openbase/ (needs version 0.7.3+\)) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:host</tt> -- Defaults to localhost) + comment(# * <tt>:username</tt> -- Defaults to nothing) + comment(# * <tt>:password</tt> -- Defaults to nothing) + comment(# * <tt>:database</tt> -- The name of the database. No default, must be provided.) + comment(#) + comment(# The OpenBase adapter will make use of OpenBase's ability to generate unique ids) + comment(# for any column with an unique index applied. Thus, if the value of a primary) + comment(# key is not specified at the time an INSERT is performed, the adapter will prefetch) + comment(# a unique id for the primary key. This prefetching is also necessary in order ) + comment(# to return the id after an insert.) + comment(#) + comment(# Caveat: Operations involving LIMIT and OFFSET do not yet work!) + comment(#) + comment(# Maintainer: derrickspell@cdmplus.com) + reserved(class) class(OpenBaseAdapter) operator(<) constant(AbstractAdapter) + reserved(def) method(adapter_name) + string<delimiter(')content(OpenBase)delimiter(')> + reserved(end) + + reserved(def) method(native_database_types) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(integer UNIQUE INDEX DEFAULT _rowid)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(char)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(4096) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(text)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(integer)delimiter(")> operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(float)delimiter(")> operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(timestamp)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(time)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(date)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(object)delimiter(")> operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(boolean)delimiter(")> operator(}) + operator(}) + reserved(end) + + reserved(def) method(supports_migrations?) + pre_constant(false) + reserved(end) + + reserved(def) method(prefetch_primary_key?)operator(()ident(table_name) operator(=) pre_constant(nil)operator(\)) + pre_constant(true) + reserved(end) + + reserved(def) method(default_sequence_name)operator(()ident(table_name)operator(,) ident(primary_key)operator(\)) comment(# :nodoc:) + string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(primary_key)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(next_sequence_value)operator(()ident(sequence_name)operator(\)) + ident(ary) operator(=) ident(sequence_name)operator(.)ident(split)operator(()string<delimiter(')content( )delimiter(')>operator(\)) + reserved(if) operator(()operator(!)ident(ary)operator([)integer(1)operator(])operator(\)) reserved(then) + ident(ary)operator([)integer(0)operator(]) operator(=)operator(~) regexp<delimiter(/)content(()char(\\w)content(+\)_nonstd_seq)delimiter(/)> + ident(ary)operator([)integer(0)operator(]) operator(=) global_variable($1) + reserved(end) + instance_variable(@connection)operator(.)ident(unique_row_id)operator(()ident(ary)operator([)integer(0)operator(])operator(,) ident(ary)operator([)integer(1)operator(])operator(\)) + reserved(end) + + + comment(# QUOTING ==================================================) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) operator(&&) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) + string<delimiter(")content(')inline<inline_delimiter(#{)instance_variable(@connection)operator(.)ident(insert_binary)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(def) method(quoted_true) + string<delimiter(")content(1)delimiter(")> + reserved(end) + + reserved(def) method(quoted_false) + string<delimiter(")content(0)delimiter(")> + reserved(end) + + + + comment(# DATABASE STATEMENTS ======================================) + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(#:nodoc) + reserved(if) ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) + reserved(unless) ident(offset) operator(=) ident(options)operator([)symbol(:offset)operator(]) + ident(sql) operator(<<) string<delimiter(")content( RETURN RESULTS )inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>delimiter(")> + reserved(else) + ident(limit) operator(=) ident(limit) operator(+) ident(offset) + ident(sql) operator(<<) string<delimiter(")content( RETURN RESULTS )inline<inline_delimiter(#{)ident(offset)inline_delimiter(})>content( TO )inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(add_limit_offset!)operator(()ident(sql)operator(,)operator({)symbol(:limit) operator(=)operator(>) integer(1)operator(})operator(\)) + ident(results) operator(=) ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(results)operator(.)ident(first) reserved(if) ident(results) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(update_nulls_after_insert)operator(()ident(sql)operator(,) ident(name)operator(,) ident(pk)operator(,) ident(id_value)operator(,) ident(sequence_name)operator(\)) + ident(id_value) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) operator(}) + reserved(end) + + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(rows_affected) + reserved(end) + + ident(alias_method) symbol(:delete)operator(,) symbol(:update) comment(#:nodoc:) +comment(#=begin) + reserved(def) method(begin_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(START TRANSACTION)delimiter(")> + reserved(rescue) constant(Exception) + comment(# Transactions aren't supported) + reserved(end) + + reserved(def) method(commit_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(COMMIT)delimiter(")> + reserved(rescue) constant(Exception) + comment(# Transactions aren't supported) + reserved(end) + + reserved(def) method(rollback_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ROLLBACK)delimiter(")> + reserved(rescue) constant(Exception) + comment(# Transactions aren't supported) + reserved(end) +comment(#=end ) + + comment(# SCHEMA STATEMENTS ========================================) + + comment(# Return the list of all tables in the schema search path.) + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(tables) operator(=) instance_variable(@connection)operator(.)ident(tables) + ident(tables)operator(.)ident(reject!) operator({) operator(|)ident(t)operator(|) regexp<delimiter(/)char(\\A)content(_SYS_)delimiter(/)> operator(===) ident(t) operator(}) + ident(tables) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(sql) operator(=) string<delimiter(")content(SELECT * FROM _sys_tables )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(WHERE tablename=')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' AND INDEXOF(fieldname,'_'\)<>0 )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(ORDER BY columnNumber)delimiter(")> + ident(columns) operator(=) operator([)operator(]) + ident(select_all)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(columns) operator(<<) constant(OpenBaseColumn)operator(.)ident(new)operator(()ident(row)operator([)string<delimiter(")content(fieldname)delimiter(")>operator(])operator(,) + ident(default_value)operator(()ident(row)operator([)string<delimiter(")content(defaultvalue)delimiter(")>operator(])operator(\))operator(,) + ident(sql_type_name)operator(()ident(row)operator([)string<delimiter(")content(typename)delimiter(")>operator(])operator(,)ident(row)operator([)string<delimiter(")content(length)delimiter(")>operator(])operator(\))operator(,) + ident(row)operator([)string<delimiter(")content(notnull)delimiter(")>operator(]) + operator(\)) + comment(# breakpoint(\) if row["fieldname"] == "content") + reserved(end) + ident(columns) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\))comment(#:nodoc:) + ident(sql) operator(=) string<delimiter(")content(SELECT fieldname, notnull, searchindex, uniqueindex, clusteredindex FROM _sys_tables )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(WHERE tablename=')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' AND INDEXOF(fieldname,'_'\)<>0 )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(AND primarykey=0 )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(AND (searchindex=1 OR uniqueindex=1 OR clusteredindex=1\) )delimiter(")> + ident(sql) operator(<<) string<delimiter(")content(ORDER BY columnNumber)delimiter(")> + ident(indexes) operator(=) operator([)operator(]) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(indexes) operator(<<) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,)ident(index_name)operator(()ident(row)operator(\))operator(,)ident(row)operator([)integer(3)operator(])operator(==)integer(1)operator(,)operator([)ident(row)operator([)integer(0)operator(])operator(])operator(\)) + reserved(end) + ident(indexes) + reserved(end) + + + ident(private) + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(sql) operator(=) ident(translate_sql)operator(()ident(sql)operator(\)) + ident(results) operator(=) ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + + ident(date_cols) operator(=) operator([)operator(]) + ident(col_names) operator(=) operator([)operator(]) + ident(results)operator(.)ident(column_infos)operator(.)ident(each) reserved(do) operator(|)ident(info)operator(|) + ident(col_names) operator(<<) ident(info)operator(.)ident(name) + ident(date_cols) operator(<<) ident(info)operator(.)ident(name) reserved(if) ident(info)operator(.)ident(type) operator(==) string<delimiter(")content(date)delimiter(")> + reserved(end) + + ident(rows) operator(=) operator([)operator(]) + reserved(if) operator(() ident(results)operator(.)ident(rows_affected) operator(\)) + ident(results)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) comment(# loop through result rows) + ident(hashed_row) operator(=) operator({)operator(}) + ident(row)operator(.)ident(each_index) reserved(do) operator(|)ident(index)operator(|) + ident(hashed_row)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(col_names)operator([)ident(index)operator(])inline_delimiter(})>delimiter(")>operator(]) operator(=) ident(row)operator([)ident(index)operator(]) reserved(unless) ident(col_names)operator([)ident(index)operator(]) operator(==) string<delimiter(")content(_rowid)delimiter(")> + reserved(end) + ident(date_cols)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + reserved(unless) ident(hashed_row)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(])operator(.)ident(nil?) reserved(or) ident(hashed_row)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(])operator(.)ident(empty?) + ident(hashed_row)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(]) operator(=) constant(Date)operator(.)ident(parse)operator(()ident(hashed_row)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(])operator(,)pre_constant(false)operator(\))operator(.)ident(to_s) + reserved(end) + reserved(end) + ident(rows) operator(<<) ident(hashed_row) + reserved(end) + reserved(end) + ident(rows) + reserved(end) + + reserved(def) method(default_value)operator(()ident(value)operator(\)) + comment(# Boolean type values) + reserved(return) pre_constant(true) reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(true)delimiter(/)> + reserved(return) pre_constant(false) reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(false)delimiter(/)> + + comment(# Date / Time magic values) + reserved(return) constant(Time)operator(.)ident(now)operator(.)ident(to_s) reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^now)char(\\()char(\\\))delimiter(/)modifier(i)> + + comment(# Empty strings should be set to null) + reserved(return) pre_constant(nil) reserved(if) ident(value)operator(.)ident(empty?) + + comment(# Otherwise return what we got from OpenBase) + comment(# and hope for the best...) + reserved(return) ident(value) + reserved(end) + + reserved(def) method(sql_type_name)operator(()ident(type_name)operator(,) ident(length)operator(\)) + reserved(return) string<delimiter(")inline<inline_delimiter(#{)ident(type_name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(length)inline_delimiter(})>content(\))delimiter(")> reserved(if) operator(() ident(type_name) operator(=)operator(~) regexp<delimiter(/)content(char)delimiter(/)> operator(\)) + ident(type_name) + reserved(end) + + reserved(def) method(index_name)operator(()ident(row) operator(=) operator([)operator(])operator(\)) + ident(name) operator(=) string<delimiter(")delimiter(")> + ident(name) operator(<<) string<delimiter(")content(UNIQUE )delimiter(")> reserved(if) ident(row)operator([)integer(3)operator(]) + ident(name) operator(<<) string<delimiter(")content(CLUSTERED )delimiter(")> reserved(if) ident(row)operator([)integer(4)operator(]) + ident(name) operator(<<) string<delimiter(")content(INDEX)delimiter(")> + ident(name) + reserved(end) + + reserved(def) method(translate_sql)operator(()ident(sql)operator(\)) + + comment(# Change table.* to list of columns in table) + reserved(while) operator(()ident(sql) operator(=)operator(~) regexp<delimiter(/)content(SELECT.*)char(\\s)content(()char(\\w)content(+\))char(\\.)char(\\*)delimiter(/)>operator(\)) + ident(table) operator(=) global_variable($1) + ident(cols) operator(=) ident(columns)operator(()ident(table)operator(\)) + reserved(if) operator(() ident(cols)operator(.)ident(size) operator(==) integer(0) operator(\)) reserved(then) + comment(# Maybe this is a table alias) + ident(sql) operator(=)operator(~) regexp<delimiter(/)content(FROM(.+?\)(?:LEFT|OUTER|JOIN|WHERE|GROUP|HAVING|ORDER|RETURN|$\))delimiter(/)> + global_variable($1) operator(=)operator(~) regexp<delimiter(/)content([)char(\\s)content(|,]()char(\\w)content(+\))char(\\s)content(+)inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content([)char(\\s)content(|,])delimiter(/)> comment(# get the tablename for this alias) + ident(cols) operator(=) ident(columns)operator(()global_variable($1)operator(\)) + reserved(end) + ident(select_columns) operator(=) operator([)operator(]) + ident(cols)operator(.)ident(each) reserved(do) operator(|)ident(col)operator(|) + ident(select_columns) operator(<<) ident(table) operator(+) string<delimiter(')content(.)delimiter(')> operator(+) ident(col)operator(.)ident(name) + reserved(end) + ident(sql)operator(.)ident(gsub!)operator(()ident(table) operator(+) string<delimiter(')content(.*)delimiter(')>operator(,)ident(select_columns)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))operator(\)) reserved(if) ident(select_columns) + reserved(end) + + comment(# Change JOIN clause to table list and WHERE condition) + reserved(while) operator(()ident(sql) operator(=)operator(~) regexp<delimiter(/)content(JOIN)delimiter(/)>operator(\)) + ident(sql) operator(=)operator(~) regexp<delimiter(/)content(((LEFT \)?(OUTER \)?JOIN ()char(\\w)content(+\) ON \)(.+?\)(?:LEFT|OUTER|JOIN|WHERE|GROUP|HAVING|ORDER|RETURN|$\))delimiter(/)> + ident(join_clause) operator(=) global_variable($1) operator(+) global_variable($5) + ident(is_outer_join) operator(=) global_variable($3) + ident(join_table) operator(=) global_variable($4) + ident(join_condition) operator(=) global_variable($5) + ident(join_condition)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(=)delimiter(/)>operator(,)string<delimiter(")content(*)delimiter(")>operator(\)) reserved(if) ident(is_outer_join) + reserved(if) operator(()ident(sql) operator(=)operator(~) regexp<delimiter(/)content(WHERE)delimiter(/)>operator(\)) + ident(sql)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(WHERE)delimiter(/)>operator(,)string<delimiter(")content(WHERE ()inline<inline_delimiter(#{)ident(join_condition)inline_delimiter(})>content(\) AND)delimiter(")>operator(\)) + reserved(else) + ident(sql)operator(.)ident(gsub!)operator(()ident(join_clause)operator(,)string<delimiter(")inline<inline_delimiter(#{)ident(join_clause)inline_delimiter(})>content( WHERE )inline<inline_delimiter(#{)ident(join_condition)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + ident(sql) operator(=)operator(~) regexp<delimiter(/)content((FROM .+?\)(?:LEFT|OUTER|JOIN|WHERE|$\))delimiter(/)> + ident(from_clause) operator(=) global_variable($1) + ident(sql)operator(.)ident(gsub!)operator(()ident(from_clause)operator(,)string<delimiter(")inline<inline_delimiter(#{)ident(from_clause)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(join_table)inline_delimiter(})>content( )delimiter(")>operator(\)) + ident(sql)operator(.)ident(gsub!)operator(()ident(join_clause)operator(,)string<delimiter(")delimiter(")>operator(\)) + reserved(end) + + comment(# ORDER BY _rowid if no explicit ORDER BY) + comment(# This will ensure that find(:first\) returns the first inserted row) + reserved(if) operator(()ident(sql) operator(!)operator(~) regexp<delimiter(/)content((ORDER BY\)|(GROUP BY\))delimiter(/)>operator(\)) + reserved(if) operator(()ident(sql) operator(=)operator(~) regexp<delimiter(/)content(RETURN RESULTS)delimiter(/)>operator(\)) + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(RETURN RESULTS)delimiter(/)>operator(,)string<delimiter(")content(ORDER BY _rowid RETURN RESULTS)delimiter(")>operator(\)) + reserved(else) + ident(sql) operator(<<) string<delimiter(")content( ORDER BY _rowid)delimiter(")> + reserved(end) + reserved(end) + + ident(sql) + reserved(end) + + reserved(def) method(update_nulls_after_insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) + ident(sql) operator(=)operator(~) regexp<delimiter(/)content(INSERT INTO ()char(\\w)content(+\) )char(\\()content((.*\))char(\\\))content( VALUES)char(\\s)content(*)char(\\()content((.*\))char(\\\))delimiter(/)modifier(m)> + ident(table) operator(=) global_variable($1) + ident(cols) operator(=) global_variable($2) + ident(values) operator(=) global_variable($3) + ident(cols) operator(=) ident(cols)operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + ident(values)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content('[^']*')delimiter(/)>operator(,)string<delimiter(")content('')delimiter(")>operator(\)) + ident(values)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content("[^"]*")delimiter(/)>operator(,)string<delimiter(")char(\\")char(\\")delimiter(")>operator(\)) + ident(values) operator(=) ident(values)operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + ident(update_cols) operator(=) operator([)operator(]) + ident(values)operator(.)ident(each_index) operator({) operator(|)ident(index)operator(|) ident(update_cols) operator(<<) ident(cols)operator([)ident(index)operator(]) reserved(if) ident(values)operator([)ident(index)operator(]) operator(=)operator(~) regexp<delimiter(/)char(\\s)content(*NULL)char(\\s)content(*)delimiter(/)> operator(}) + ident(update_sql) operator(=) string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content( SET)delimiter(")> + ident(update_cols)operator(.)ident(each) operator({) operator(|)ident(col)operator(|) ident(update_sql) operator(<<) string<delimiter(")content( )inline<inline_delimiter(#{)ident(col)inline_delimiter(})>content(=NULL,)delimiter(")> reserved(unless) ident(col)operator(.)ident(empty?) operator(}) + ident(update_sql)operator(.)ident(chop!)operator(()operator(\)) + ident(update_sql) operator(<<) string<delimiter(")content( WHERE )inline<inline_delimiter(#{)ident(pk)inline_delimiter(})>content(=)inline<inline_delimiter(#{)ident(quote)operator(()ident(id_value)operator(\))inline_delimiter(})>delimiter(")> + ident(execute)operator(()ident(update_sql)operator(,) ident(name) operator(+) string<delimiter(")content( NULL Correction)delimiter(")>operator(\)) reserved(if) ident(update_cols)operator(.)ident(size) operator(>) integer(0) + reserved(end) + + reserved(end) + reserved(end) +reserved(end) +comment(# oracle_adapter.rb -- ActiveRecord adapter for Oracle 8i, 9i, 10g) +comment(#) +comment(# Original author: Graham Jenkins) +comment(#) +comment(# Current maintainer: Michael Schoen <schoenm@earthlink.net>) +comment(#) +comment(#########################################################################) +comment(#) +comment(# Implementation notes:) +comment(# 1. Redefines (safely\) a method in ActiveRecord to make it possible to) +comment(# implement an autonumbering solution for Oracle.) +comment(# 2. The OCI8 driver is patched to properly handle values for LONG and) +comment(# TIMESTAMP columns. The driver-author has indicated that a future) +comment(# release of the driver will obviate this patch.) +comment(# 3. LOB support is implemented through an after_save callback.) +comment(# 4. Oracle does not offer native LIMIT and OFFSET options; this) +comment(# functionality is mimiced through the use of nested selects.) +comment(# See http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:127412348064) +comment(#) +comment(# Do what you want with this code, at your own peril, but if any) +comment(# significant portion of my code remains then please acknowledge my) +comment(# contribution.) +comment(# portions Copyright 2005 Graham Jenkins) + +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> +ident(require) string<delimiter(')content(delegate)delimiter(')> + +reserved(begin) + ident(require_library_or_gem) string<delimiter(')content(oci8)delimiter(')> reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?) symbol(:OCI8) + + reserved(module) class(ActiveRecord) + reserved(class) class(Base) + reserved(def) pre_constant(self)operator(.)ident(oracle_connection)operator(()ident(config)operator(\)) comment(#:nodoc:) + comment(# Use OCI8AutoRecover instead of normal OCI8 driver.) + constant(ConnectionAdapters)operator(::)constant(OracleAdapter)operator(.)ident(new) constant(OCI8AutoRecover)operator(.)ident(new)operator(()ident(config)operator(\))operator(,) ident(logger) + reserved(end) + + comment(# for backwards-compatibility) + reserved(def) pre_constant(self)operator(.)ident(oci_connection)operator(()ident(config)operator(\)) comment(#:nodoc:) + ident(config)operator([)symbol(:database)operator(]) operator(=) ident(config)operator([)symbol(:host)operator(]) + pre_constant(self)operator(.)ident(oracle_connection)operator(()ident(config)operator(\)) + reserved(end) + + comment(# Enable the id column to be bound into the sql later, by the adapter's insert method.) + comment(# This is preferable to inserting the hard-coded value here, because the insert method) + comment(# needs to know the id value explicitly.) + reserved(alias) symbol(:attributes_with_quotes_pre_oracle) symbol(:attributes_with_quotes) + reserved(def) method(attributes_with_quotes)operator(()ident(include_primary_key) operator(=) pre_constant(true)operator(\)) comment(#:nodoc:) + ident(aq) operator(=) ident(attributes_with_quotes_pre_oracle)operator(()ident(include_primary_key)operator(\)) + reserved(if) ident(connection)operator(.)ident(class) operator(==) constant(ConnectionAdapters)operator(::)constant(OracleAdapter) + ident(aq)operator([)pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(]) operator(=) string<delimiter(")content(:id)delimiter(")> reserved(if) ident(include_primary_key) operator(&&) ident(aq)operator([)pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)operator(])operator(.)ident(nil?) + reserved(end) + ident(aq) + reserved(end) + + comment(# After setting large objects to empty, select the OCI8::LOB) + comment(# and write back the data.) + ident(after_save) symbol(:write_lobs) + reserved(def) method(write_lobs)operator(()operator(\)) comment(#:nodoc:) + reserved(if) ident(connection)operator(.)ident(is_a?)operator(()constant(ConnectionAdapters)operator(::)constant(OracleAdapter)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(columns)operator(.)ident(select) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(type) operator(==) symbol(:binary) operator(})operator(.)ident(each) operator({) operator(|)ident(c)operator(|) + ident(value) operator(=) pre_constant(self)operator([)ident(c)operator(.)ident(name)operator(]) + reserved(next) reserved(if) ident(value)operator(.)ident(nil?) operator(||) operator(()ident(value) operator(==) string<delimiter(')delimiter(')>operator(\)) + ident(lob) operator(=) ident(connection)operator(.)ident(select_one)operator(() + string<delimiter(")content(SELECT )inline<inline_delimiter(#{) ident(c)operator(.)ident(name)inline_delimiter(})>content( FROM )inline<inline_delimiter(#{) pre_constant(self)operator(.)ident(class)operator(.)ident(table_name) inline_delimiter(})>content( WHERE )inline<inline_delimiter(#{) pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quote)operator(()ident(id)operator(\))inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(')content(Writable Large Object)delimiter(')>operator(\))operator([)ident(c)operator(.)ident(name)operator(]) + ident(lob)operator(.)ident(write) ident(value) + operator(}) + reserved(end) + reserved(end) + + ident(private) symbol(:write_lobs) + reserved(end) + + + reserved(module) class(ConnectionAdapters) comment(#:nodoc:) + reserved(class) class(OracleColumn) operator(<) constant(Column) comment(#:nodoc:) + ident(attr_reader) symbol(:sql_type) + + comment(# overridden to add the concept of scale, required to differentiate) + comment(# between integer and float fields) + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(default)operator(,) ident(sql_type)operator(,) ident(limit)operator(,) ident(scale)operator(,) ident(null)operator(\)) + instance_variable(@name)operator(,) instance_variable(@limit)operator(,) instance_variable(@sql_type)operator(,) instance_variable(@scale)operator(,) instance_variable(@null) operator(=) ident(name)operator(,) ident(limit)operator(,) ident(sql_type)operator(,) ident(scale)operator(,) ident(null) + + instance_variable(@type) operator(=) ident(simplified_type)operator(()ident(sql_type)operator(\)) + instance_variable(@default) operator(=) ident(type_cast)operator(()ident(default)operator(\)) + + instance_variable(@primary) operator(=) pre_constant(nil) + instance_variable(@text) operator(=) operator([)symbol(:string)operator(,) symbol(:text)operator(])operator(.)ident(include?) instance_variable(@type) + instance_variable(@number) operator(=) operator([)symbol(:float)operator(,) symbol(:integer)operator(])operator(.)ident(include?) instance_variable(@type) + reserved(end) + + reserved(def) method(type_cast)operator(()ident(value)operator(\)) + reserved(return) pre_constant(nil) reserved(if) ident(value)operator(.)ident(nil?) operator(||) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*null)char(\\s)content(*$)delimiter(/)modifier(i)> + reserved(case) ident(type) + reserved(when) symbol(:string) reserved(then) ident(value) + reserved(when) symbol(:integer) reserved(then) reserved(defined?)operator(()ident(value)operator(.)ident(to_i)operator(\)) operator(?) ident(value)operator(.)ident(to_i) operator(:) operator(()ident(value) operator(?) integer(1) operator(:) integer(0)operator(\)) + reserved(when) symbol(:float) reserved(then) ident(value)operator(.)ident(to_f) + reserved(when) symbol(:datetime) reserved(then) ident(cast_to_date_or_time)operator(()ident(value)operator(\)) + reserved(when) symbol(:time) reserved(then) ident(cast_to_time)operator(()ident(value)operator(\)) + reserved(else) ident(value) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(case) ident(field_type) + reserved(when) regexp<delimiter(/)content(char)delimiter(/)modifier(i)> operator(:) symbol(:string) + reserved(when) regexp<delimiter(/)content(num|float|double|dec|real|int)delimiter(/)modifier(i)> operator(:) instance_variable(@scale) operator(==) integer(0) operator(?) symbol(:integer) operator(:) symbol(:float) + reserved(when) regexp<delimiter(/)content(date|time)delimiter(/)modifier(i)> operator(:) instance_variable(@name) operator(=)operator(~) regexp<delimiter(/)content(_at$)delimiter(/)> operator(?) symbol(:time) operator(:) symbol(:datetime) + reserved(when) regexp<delimiter(/)content(clob)delimiter(/)modifier(i)> operator(:) symbol(:text) + reserved(when) regexp<delimiter(/)content(blob)delimiter(/)modifier(i)> operator(:) symbol(:binary) + reserved(end) + reserved(end) + + reserved(def) method(cast_to_date_or_time)operator(()ident(value)operator(\)) + reserved(return) ident(value) reserved(if) ident(value)operator(.)ident(is_a?) constant(Date) + reserved(return) pre_constant(nil) reserved(if) ident(value)operator(.)ident(blank?) + ident(guess_date_or_time) operator(()ident(value)operator(.)ident(is_a?) constant(Time)operator(\)) operator(?) ident(value) operator(:) ident(cast_to_time)operator(()ident(value)operator(\)) + reserved(end) + + reserved(def) method(cast_to_time)operator(()ident(value)operator(\)) + reserved(return) ident(value) reserved(if) ident(value)operator(.)ident(is_a?) constant(Time) + ident(time_array) operator(=) constant(ParseDate)operator(.)ident(parsedate) ident(value) + ident(time_array)operator([)integer(0)operator(]) operator(||=) integer(2000)operator(;) ident(time_array)operator([)integer(1)operator(]) operator(||=) integer(1)operator(;) ident(time_array)operator([)integer(2)operator(]) operator(||=) integer(1)operator(;) + constant(Time)operator(.)ident(send)operator(()constant(Base)operator(.)ident(default_timezone)operator(,) operator(*)ident(time_array)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(guess_date_or_time)operator(()ident(value)operator(\)) + operator(()ident(value)operator(.)ident(hour) operator(==) integer(0) reserved(and) ident(value)operator(.)ident(min) operator(==) integer(0) reserved(and) ident(value)operator(.)ident(sec) operator(==) integer(0)operator(\)) operator(?) + constant(Date)operator(.)ident(new)operator(()ident(value)operator(.)ident(year)operator(,) ident(value)operator(.)ident(month)operator(,) ident(value)operator(.)ident(day)operator(\)) operator(:) ident(value) + reserved(end) + reserved(end) + + + comment(# This is an Oracle/OCI adapter for the ActiveRecord persistence) + comment(# framework. It relies upon the OCI8 driver, which works with Oracle 8i) + comment(# and above. Most recent development has been on Debian Linux against) + comment(# a 10g database, ActiveRecord 1.12.1 and OCI8 0.1.13.) + comment(# See: http://rubyforge.org/projects/ruby-oci8/) + comment(#) + comment(# Usage notes:) + comment(# * Key generation assumes a "${table_name}_seq" sequence is available) + comment(# for all tables; the sequence name can be changed using) + comment(# ActiveRecord::Base.set_sequence_name. When using Migrations, these) + comment(# sequences are created automatically.) + comment(# * Oracle uses DATE or TIMESTAMP datatypes for both dates and times.) + comment(# Consequently some hacks are employed to map data back to Date or Time) + comment(# in Ruby. If the column_name ends in _time it's created as a Ruby Time.) + comment(# Else if the hours/minutes/seconds are 0, I make it a Ruby Date. Else) + comment(# it's a Ruby Time. This is a bit nasty - but if you use Duck Typing) + comment(# you'll probably not care very much. In 9i and up it's tempting to) + comment(# map DATE to Date and TIMESTAMP to Time, but too many databases use) + comment(# DATE for both. Timezones and sub-second precision on timestamps are) + comment(# not supported.) + comment(# * Default values that are functions (such as "SYSDATE"\) are not) + comment(# supported. This is a restriction of the way ActiveRecord supports) + comment(# default values.) + comment(# * Support for Oracle8 is limited by Rails' use of ANSI join syntax, which) + comment(# is supported in Oracle9i and later. You will need to use #finder_sql for) + comment(# has_and_belongs_to_many associations to run against Oracle8.) + comment(#) + comment(# Required parameters:) + comment(#) + comment(# * <tt>:username</tt>) + comment(# * <tt>:password</tt>) + comment(# * <tt>:database</tt>) + reserved(class) class(OracleAdapter) operator(<) constant(AbstractAdapter) + + reserved(def) method(adapter_name) comment(#:nodoc:) + string<delimiter(')content(Oracle)delimiter(')> + reserved(end) + + reserved(def) method(supports_migrations?) comment(#:nodoc:) + pre_constant(true) + reserved(end) + + reserved(def) method(native_database_types) comment(#:nodoc) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(NUMBER(38\) NOT NULL PRIMARY KEY)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(VARCHAR2)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(CLOB)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(NUMBER)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(38) operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(NUMBER)delimiter(")> operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(DATE)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(DATE)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(DATE)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(DATE)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(BLOB)delimiter(")> operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(NUMBER)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(1) operator(}) + operator(}) + reserved(end) + + reserved(def) method(table_alias_length) + integer(30) + reserved(end) + + comment(# QUOTING ==================================================) + comment(#) + comment(# see: abstract/quoting.rb) + + comment(# camelCase column names need to be quoted; not that anyone using Oracle) + comment(# would really do this, but handling this case means we pass the test...) + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) comment(#:nodoc:) + ident(name) operator(=)operator(~) regexp<delimiter(/)content([A-Z])delimiter(/)> operator(?) string<delimiter(")char(\\")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>char(\\")delimiter(")> operator(:) ident(name) + reserved(end) + + reserved(def) method(quote_string)operator(()ident(string)operator(\)) comment(#:nodoc:) + ident(string)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(")content('')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + reserved(if) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) + string<delimiter(%Q{)content(empty_)inline<inline_delimiter(#{) ident(column)operator(.)ident(sql_type) reserved(rescue) string<delimiter(')content(blob)delimiter(')> inline_delimiter(})>content((\))delimiter(})> + reserved(else) + reserved(case) ident(value) + reserved(when) constant(String) operator(:) string<delimiter(%Q{)content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(})> + reserved(when) constant(NilClass) operator(:) string<delimiter(')content(null)delimiter(')> + reserved(when) constant(TrueClass) operator(:) string<delimiter(')content(1)delimiter(')> + reserved(when) constant(FalseClass) operator(:) string<delimiter(')content(0)delimiter(')> + reserved(when) constant(Numeric) operator(:) ident(value)operator(.)ident(to_s) + reserved(when) constant(Date)operator(,) constant(Time) operator(:) string<delimiter(%Q{)content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(\))inline_delimiter(})>content(')delimiter(})> + reserved(else) string<delimiter(%Q{)content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_yaml)operator(\))inline_delimiter(})>content(')delimiter(})> + reserved(end) + reserved(end) + reserved(end) + + + comment(# CONNECTION MANAGEMENT ====================================) + comment(#) + + comment(# Returns true if the connection is active.) + reserved(def) method(active?) + comment(# Pings the connection to check if it's still good. Note that an) + comment(# #active? method is also available, but that simply returns the ) + comment(# last known state, which isn't good enough if the connection has) + comment(# gone stale since the last use.) + instance_variable(@connection)operator(.)ident(ping) + reserved(rescue) constant(OCIException) + pre_constant(false) + reserved(end) + + comment(# Reconnects to the database.) + reserved(def) method(reconnect!) + instance_variable(@connection)operator(.)ident(reset!) + reserved(rescue) constant(OCIException) operator(=)operator(>) ident(e) + instance_variable(@logger)operator(.)ident(warn) string<delimiter(")inline<inline_delimiter(#{)ident(adapter_name)inline_delimiter(})>content( automatic reconnection failed: )inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>delimiter(")> + reserved(end) + + comment(# Disconnects from the database.) + reserved(def) method(disconnect!) + instance_variable(@connection)operator(.)ident(logoff) reserved(rescue) pre_constant(nil) + instance_variable(@connection)operator(.)ident(active) operator(=) pre_constant(false) + reserved(end) + + + comment(# DATABASE STATEMENTS ======================================) + comment(#) + comment(# see: abstract/database_statements.rb) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(result) operator(=) ident(select_all)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(size) operator(>) integer(0) operator(?) ident(result)operator(.)ident(first) operator(:) pre_constant(nil) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(exec) ident(sql) operator(}) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + reserved(if) ident(pk)operator(.)ident(nil?) comment(# Who called us? What does the sql look like? No idea!) + ident(execute) ident(sql)operator(,) ident(name) + reserved(elsif) ident(id_value) comment(# Pre-assigned id) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(exec) ident(sql) operator(}) + reserved(else) comment(# Assume the sql contains a bind-variable for the id) + ident(id_value) operator(=) ident(select_one)operator(()string<delimiter(")content(select )inline<inline_delimiter(#{)ident(sequence_name)inline_delimiter(})>content(.nextval id from dual)delimiter(")>operator(\))operator([)string<delimiter(')content(id)delimiter(')>operator(]) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(exec) ident(sql)operator(,) ident(id_value) operator(}) + reserved(end) + + ident(id_value) + reserved(end) + + reserved(alias) symbol(:update) symbol(:execute) comment(#:nodoc:) + reserved(alias) symbol(:delete) symbol(:execute) comment(#:nodoc:) + + reserved(def) method(begin_db_transaction) comment(#:nodoc:) + instance_variable(@connection)operator(.)ident(autocommit) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(commit_db_transaction) comment(#:nodoc:) + instance_variable(@connection)operator(.)ident(commit) + reserved(ensure) + instance_variable(@connection)operator(.)ident(autocommit) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(rollback_db_transaction) comment(#:nodoc:) + instance_variable(@connection)operator(.)ident(rollback) + reserved(ensure) + instance_variable(@connection)operator(.)ident(autocommit) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(offset) operator(=) ident(options)operator([)symbol(:offset)operator(]) operator(||) integer(0) + + reserved(if) ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) + ident(sql)operator(.)ident(replace) string<delimiter(")content(select * from (select raw_sql_.*, rownum raw_rnum_ from ()inline<inline_delimiter(#{)ident(sql)inline_delimiter(})>content(\) raw_sql_ where rownum <= )inline<inline_delimiter(#{)ident(offset)operator(+)ident(limit)inline_delimiter(})>content(\) where raw_rnum_ > )inline<inline_delimiter(#{)ident(offset)inline_delimiter(})>delimiter(")> + reserved(elsif) ident(offset) operator(>) integer(0) + ident(sql)operator(.)ident(replace) string<delimiter(")content(select * from (select raw_sql_.*, rownum raw_rnum_ from ()inline<inline_delimiter(#{)ident(sql)inline_delimiter(})>content(\) raw_sql_\) where raw_rnum_ > )inline<inline_delimiter(#{)ident(offset)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(default_sequence_name)operator(()ident(table)operator(,) ident(column)operator(\)) comment(#:nodoc:) + string<delimiter(")inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content(_seq)delimiter(")> + reserved(end) + + + comment(# SCHEMA STATEMENTS ========================================) + comment(#) + comment(# see: abstract/schema_statements.rb) + + reserved(def) method(current_database) comment(#:nodoc:) + ident(select_one)operator(()string<delimiter(")content(select sys_context('userenv','db_name'\) db from dual)delimiter(")>operator(\))operator([)string<delimiter(")content(db)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(select_all)operator(()string<delimiter(")content(select lower(table_name\) from user_tables)delimiter(")>operator(\))operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|) ident(tabs)operator(,) ident(t) operator(|) + ident(tabs) operator(<<) ident(t)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last) + reserved(end) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(result) operator(=) ident(select_all)operator(()string<delimiter(<<-SQL)>operator(,) ident(name)operator(\))string<content( + SELECT lower(i.index_name\) as index_name, i.uniqueness, lower(c.column_name\) as column_name + FROM user_indexes i, user_ind_columns c + WHERE i.table_name = ')inline<inline_delimiter(#{)ident(table_name)operator(.)ident(to_s)operator(.)ident(upcase)inline_delimiter(})>content(' + AND c.index_name = i.index_name + AND i.index_name NOT IN (SELECT index_name FROM user_constraints WHERE constraint_type = 'P'\) + ORDER BY i.index_name, c.column_position)delimiter( + SQL)> + + ident(current_index) operator(=) pre_constant(nil) + ident(indexes) operator(=) operator([)operator(]) + + ident(result)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + reserved(if) ident(current_index) operator(!=) ident(row)operator([)string<delimiter(')content(index_name)delimiter(')>operator(]) + ident(indexes) operator(<<) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,) ident(row)operator([)string<delimiter(')content(index_name)delimiter(')>operator(])operator(,) ident(row)operator([)string<delimiter(')content(uniqueness)delimiter(')>operator(]) operator(==) string<delimiter(")content(UNIQUE)delimiter(")>operator(,) operator([)operator(])operator(\)) + ident(current_index) operator(=) ident(row)operator([)string<delimiter(')content(index_name)delimiter(')>operator(]) + reserved(end) + + ident(indexes)operator(.)ident(last)operator(.)ident(columns) operator(<<) ident(row)operator([)string<delimiter(')content(column_name)delimiter(')>operator(]) + reserved(end) + + ident(indexes) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + operator(()ident(owner)operator(,) ident(table_name)operator(\)) operator(=) instance_variable(@connection)operator(.)ident(describe)operator(()ident(table_name)operator(\)) + + ident(table_cols) operator(=) string<delimiter(%Q{)content( + select column_name, data_type, data_default, nullable, + decode(data_type, 'NUMBER', data_precision, + 'VARCHAR2', data_length, + null\) as length, + decode(data_type, 'NUMBER', data_scale, null\) as scale + from all_tab_columns + where owner = ')inline<inline_delimiter(#{)ident(owner)inline_delimiter(})>content(' + and table_name = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' + order by column_id + )delimiter(})> + + ident(select_all)operator(()ident(table_cols)operator(,) ident(name)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(row)operator(|) + reserved(if) ident(row)operator([)string<delimiter(')content(data_default)delimiter(')>operator(]) + ident(row)operator([)string<delimiter(')content(data_default)delimiter(')>operator(])operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^(.*?\))char(\\s)content(*$)delimiter(/)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(row)operator([)string<delimiter(')content(data_default)delimiter(')>operator(])operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^'(.*\)'$)delimiter(/)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + reserved(end) + constant(OracleColumn)operator(.)ident(new)operator(() + ident(oracle_downcase)operator(()ident(row)operator([)string<delimiter(')content(column_name)delimiter(')>operator(])operator(\))operator(,) + ident(row)operator([)string<delimiter(')content(data_default)delimiter(')>operator(])operator(,) + ident(row)operator([)string<delimiter(')content(data_type)delimiter(')>operator(])operator(,) + operator(()ident(l) operator(=) ident(row)operator([)string<delimiter(')content(length)delimiter(')>operator(])operator(\))operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(l)operator(.)ident(to_i)operator(,) + operator(()ident(s) operator(=) ident(row)operator([)string<delimiter(')content(scale)delimiter(')>operator(])operator(\))operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(s)operator(.)ident(to_i)operator(,) + ident(row)operator([)string<delimiter(')content(nullable)delimiter(')>operator(]) operator(==) string<delimiter(')content(Y)delimiter(')> + operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(create_table)operator(()ident(name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + reserved(super)operator(()ident(name)operator(,) ident(options)operator(\)) + ident(execute) string<delimiter(")content(CREATE SEQUENCE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(_seq START WITH 10000)delimiter(")> reserved(unless) ident(options)operator([)symbol(:id)operator(]) operator(==) pre_constant(false) + reserved(end) + + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(RENAME )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( TO )inline<inline_delimiter(#{)ident(new_name)inline_delimiter(})>delimiter(")> + ident(execute) string<delimiter(")content(RENAME )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(_seq TO )inline<inline_delimiter(#{)ident(new_name)inline_delimiter(})>content(_seq)delimiter(")> reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(drop_table)operator(()ident(name)operator(\)) comment(#:nodoc:) + reserved(super)operator(()ident(name)operator(\)) + ident(execute) string<delimiter(")content(DROP SEQUENCE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(_seq)delimiter(")> reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(remove_index)operator(()ident(table_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(DROP INDEX )inline<inline_delimiter(#{)ident(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(default)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( MODIFY )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( DEFAULT )inline<inline_delimiter(#{)ident(quote)operator(()ident(default)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(change_column_sql) operator(=) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( MODIFY )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")> + ident(add_column_options!)operator(()ident(change_column_sql)operator(,) ident(options)operator(\)) + ident(execute)operator(()ident(change_column_sql)operator(\)) + reserved(end) + + reserved(def) method(rename_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(new_column_name)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( RENAME COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( to )inline<inline_delimiter(#{)ident(new_column_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(structure_dump) comment(#:nodoc:) + ident(s) operator(=) ident(select_all)operator(()string<delimiter(")content(select sequence_name from user_sequences)delimiter(")>operator(\))operator(.)ident(inject)operator(()string<delimiter(")delimiter(")>operator(\)) reserved(do) operator(|)ident(structure)operator(,) ident(seq)operator(|) + ident(structure) operator(<<) string<delimiter(")content(create sequence )inline<inline_delimiter(#{)ident(seq)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last)inline_delimiter(})>content(;)char(\\n)char(\\n)delimiter(")> + reserved(end) + + ident(select_all)operator(()string<delimiter(")content(select table_name from user_tables)delimiter(")>operator(\))operator(.)ident(inject)operator(()ident(s)operator(\)) reserved(do) operator(|)ident(structure)operator(,) ident(table)operator(|) + ident(ddl) operator(=) string<delimiter(")content(create table )inline<inline_delimiter(#{)ident(table)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last)inline_delimiter(})>content( ()char(\\n)content( )delimiter(")> + ident(cols) operator(=) ident(select_all)operator(()string<delimiter(%Q{)content( + select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable + from user_tab_columns + where table_name = ')inline<inline_delimiter(#{)ident(table)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last)inline_delimiter(})>content(' + order by column_id + )delimiter(})>operator(\))operator(.)ident(map) reserved(do) operator(|)ident(row)operator(|) + ident(col) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(row)operator([)string<delimiter(')content(column_name)delimiter(')>operator(])operator(.)ident(downcase)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(row)operator([)string<delimiter(')content(data_type)delimiter(')>operator(])operator(.)ident(downcase)inline_delimiter(})>delimiter(")> + reserved(if) ident(row)operator([)string<delimiter(')content(data_type)delimiter(')>operator(]) operator(==)string<delimiter(')content(NUMBER)delimiter(')> reserved(and) operator(!)ident(row)operator([)string<delimiter(')content(data_precision)delimiter(')>operator(])operator(.)ident(nil?) + ident(col) operator(<<) string<delimiter(")content(()inline<inline_delimiter(#{)ident(row)operator([)string<delimiter(')content(data_precision)delimiter(')>operator(])operator(.)ident(to_i)inline_delimiter(})>delimiter(")> + ident(col) operator(<<) string<delimiter(")content(,)inline<inline_delimiter(#{)ident(row)operator([)string<delimiter(')content(data_scale)delimiter(')>operator(])operator(.)ident(to_i)inline_delimiter(})>delimiter(")> reserved(if) operator(!)ident(row)operator([)string<delimiter(')content(data_scale)delimiter(')>operator(])operator(.)ident(nil?) + ident(col) operator(<<) string<delimiter(')content(\))delimiter(')> + reserved(elsif) ident(row)operator([)string<delimiter(')content(data_type)delimiter(')>operator(])operator(.)ident(include?)operator(()string<delimiter(')content(CHAR)delimiter(')>operator(\)) + ident(col) operator(<<) string<delimiter(")content(()inline<inline_delimiter(#{)ident(row)operator([)string<delimiter(')content(data_length)delimiter(')>operator(])operator(.)ident(to_i)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + ident(col) operator(<<) string<delimiter(")content( default )inline<inline_delimiter(#{)ident(row)operator([)string<delimiter(')content(data_default)delimiter(')>operator(])inline_delimiter(})>delimiter(")> reserved(if) operator(!)ident(row)operator([)string<delimiter(')content(data_default)delimiter(')>operator(])operator(.)ident(nil?) + ident(col) operator(<<) string<delimiter(')content( not null)delimiter(')> reserved(if) ident(row)operator([)string<delimiter(')content(nullable)delimiter(')>operator(]) operator(==) string<delimiter(')content(N)delimiter(')> + ident(col) + reserved(end) + ident(ddl) operator(<<) ident(cols)operator(.)ident(join)operator(()string<delimiter(")content(,)char(\\n)content( )delimiter(")>operator(\)) + ident(ddl) operator(<<) string<delimiter(")content(\);)char(\\n)char(\\n)delimiter(")> + ident(structure) operator(<<) ident(ddl) + reserved(end) + reserved(end) + + reserved(def) method(structure_drop) comment(#:nodoc:) + ident(s) operator(=) ident(select_all)operator(()string<delimiter(")content(select sequence_name from user_sequences)delimiter(")>operator(\))operator(.)ident(inject)operator(()string<delimiter(")delimiter(")>operator(\)) reserved(do) operator(|)ident(drop)operator(,) ident(seq)operator(|) + ident(drop) operator(<<) string<delimiter(")content(drop sequence )inline<inline_delimiter(#{)ident(seq)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last)inline_delimiter(})>content(;)char(\\n)char(\\n)delimiter(")> + reserved(end) + + ident(select_all)operator(()string<delimiter(")content(select table_name from user_tables)delimiter(")>operator(\))operator(.)ident(inject)operator(()ident(s)operator(\)) reserved(do) operator(|)ident(drop)operator(,) ident(table)operator(|) + ident(drop) operator(<<) string<delimiter(")content(drop table )inline<inline_delimiter(#{)ident(table)operator(.)ident(to_a)operator(.)ident(first)operator(.)ident(last)inline_delimiter(})>content( cascade constraints;)char(\\n)char(\\n)delimiter(")> + reserved(end) + reserved(end) + + + ident(private) + + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(cursor) operator(=) ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(cols) operator(=) ident(cursor)operator(.)ident(get_col_names)operator(.)ident(map) operator({) operator(|)ident(x)operator(|) ident(oracle_downcase)operator(()ident(x)operator(\)) operator(}) + ident(rows) operator(=) operator([)operator(]) + + reserved(while) ident(row) operator(=) ident(cursor)operator(.)ident(fetch) + ident(hash) operator(=) constant(Hash)operator(.)ident(new) + + ident(cols)operator(.)ident(each_with_index) reserved(do) operator(|)ident(col)operator(,) ident(i)operator(|) + ident(hash)operator([)ident(col)operator(]) operator(=) + reserved(case) ident(row)operator([)ident(i)operator(]) + reserved(when) constant(OCI8)operator(::)constant(LOB) + ident(name) operator(==) string<delimiter(')content(Writable Large Object)delimiter(')> operator(?) ident(row)operator([)ident(i)operator(])operator(:) ident(row)operator([)ident(i)operator(])operator(.)ident(read) + reserved(when) constant(OraDate) + operator(()ident(row)operator([)ident(i)operator(])operator(.)ident(hour) operator(==) integer(0) reserved(and) ident(row)operator([)ident(i)operator(])operator(.)ident(minute) operator(==) integer(0) reserved(and) ident(row)operator([)ident(i)operator(])operator(.)ident(second) operator(==) integer(0)operator(\)) operator(?) + ident(row)operator([)ident(i)operator(])operator(.)ident(to_date) operator(:) ident(row)operator([)ident(i)operator(])operator(.)ident(to_time) + reserved(else) ident(row)operator([)ident(i)operator(]) + reserved(end) reserved(unless) ident(col) operator(==) string<delimiter(')content(raw_rnum_)delimiter(')> + reserved(end) + + ident(rows) operator(<<) ident(hash) + reserved(end) + + ident(rows) + reserved(ensure) + ident(cursor)operator(.)ident(close) reserved(if) ident(cursor) + reserved(end) + + comment(# Oracle column names by default are case-insensitive, but treated as upcase;) + comment(# for neatness, we'll downcase within Rails. EXCEPT that folks CAN quote) + comment(# their column names when creating Oracle tables, which makes then case-sensitive.) + comment(# I don't know anybody who does this, but we'll handle the theoretical case of a) + comment(# camelCase column name. I imagine other dbs handle this different, since there's a) + comment(# unit test that's currently failing test_oci.) + reserved(def) method(oracle_downcase)operator(()ident(column_name)operator(\)) + ident(column_name) operator(=)operator(~) regexp<delimiter(/)content([a-z])delimiter(/)> operator(?) ident(column_name) operator(:) ident(column_name)operator(.)ident(downcase) + reserved(end) + + reserved(end) + reserved(end) + reserved(end) + + + reserved(class) class(OCI8) comment(#:nodoc:) + + comment(# This OCI8 patch may not longer be required with the upcoming) + comment(# release of version 0.2.) + reserved(class) class(Cursor) comment(#:nodoc:) + reserved(alias) symbol(:define_a_column_pre_ar) symbol(:define_a_column) + reserved(def) method(define_a_column)operator(()ident(i)operator(\)) + reserved(case) ident(do_ocicall)operator(()instance_variable(@ctx)operator(\)) operator({) instance_variable(@parms)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(attrGet)operator(()constant(OCI_ATTR_DATA_TYPE)operator(\)) operator(}) + reserved(when) integer(8) operator(:) instance_variable(@stmt)operator(.)ident(defineByPos)operator(()ident(i)operator(,) constant(String)operator(,) integer(65535)operator(\)) comment(# Read LONG values) + reserved(when) integer(187) operator(:) instance_variable(@stmt)operator(.)ident(defineByPos)operator(()ident(i)operator(,) constant(OraDate)operator(\)) comment(# Read TIMESTAMP values) + reserved(when) integer(108) + reserved(if) instance_variable(@parms)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(attrGet)operator(()constant(OCI_ATTR_TYPE_NAME)operator(\)) operator(==) string<delimiter(')content(XMLTYPE)delimiter(')> + instance_variable(@stmt)operator(.)ident(defineByPos)operator(()ident(i)operator(,) constant(String)operator(,) integer(65535)operator(\)) + reserved(else) + ident(raise) string<delimiter(')content(unsupported datatype)delimiter(')> + reserved(end) + reserved(else) ident(define_a_column_pre_ar) ident(i) + reserved(end) + reserved(end) + reserved(end) + + comment(# missing constant from oci8 < 0.1.14) + constant(OCI_PTYPE_UNK) operator(=) integer(0) reserved(unless) reserved(defined?)operator(()constant(OCI_PTYPE_UNK)operator(\)) + + comment(# Uses the describeAny OCI call to find the target owner and table_name) + comment(# indicated by +name+, parsing through synonynms as necessary. Returns) + comment(# an array of [owner, table_name].) + reserved(def) method(describe)operator(()ident(name)operator(\)) + instance_variable(@desc) operator(||=) class_variable(@@env)operator(.)ident(alloc)operator(()constant(OCIDescribe)operator(\)) + instance_variable(@desc)operator(.)ident(attrSet)operator(()constant(OCI_ATTR_DESC_PUBLIC)operator(,) integer(-1)operator(\)) reserved(if) constant(VERSION) operator(>)operator(=) string<delimiter(')content(0.1.14)delimiter(')> + instance_variable(@desc)operator(.)ident(describeAny)operator(()instance_variable(@svc)operator(,) ident(name)operator(.)ident(to_s)operator(,) constant(OCI_PTYPE_UNK)operator(\)) + ident(info) operator(=) instance_variable(@desc)operator(.)ident(attrGet)operator(()constant(OCI_ATTR_PARAM)operator(\)) + + reserved(case) ident(info)operator(.)ident(attrGet)operator(()constant(OCI_ATTR_PTYPE)operator(\)) + reserved(when) constant(OCI_PTYPE_TABLE)operator(,) constant(OCI_PTYPE_VIEW) + ident(owner) operator(=) ident(info)operator(.)ident(attrGet)operator(()constant(OCI_ATTR_OBJ_SCHEMA)operator(\)) + ident(table_name) operator(=) ident(info)operator(.)ident(attrGet)operator(()constant(OCI_ATTR_OBJ_NAME)operator(\)) + operator([)ident(owner)operator(,) ident(table_name)operator(]) + reserved(when) constant(OCI_PTYPE_SYN) + ident(schema) operator(=) ident(info)operator(.)ident(attrGet)operator(()constant(OCI_ATTR_SCHEMA_NAME)operator(\)) + ident(name) operator(=) ident(info)operator(.)ident(attrGet)operator(()constant(OCI_ATTR_NAME)operator(\)) + ident(describe)operator(()ident(schema) operator(+) string<delimiter(')content(.)delimiter(')> operator(+) ident(name)operator(\)) + reserved(end) + reserved(end) + + reserved(end) + + + comment(# The OracleConnectionFactory factors out the code necessary to connect and) + comment(# configure an Oracle/OCI connection.) + reserved(class) class(OracleConnectionFactory) comment(#:nodoc:) + reserved(def) method(new_connection)operator(()ident(username)operator(,) ident(password)operator(,) ident(database)operator(\)) + ident(conn) operator(=) constant(OCI8)operator(.)ident(new) ident(username)operator(,) ident(password)operator(,) ident(database) + ident(conn)operator(.)ident(exec) string<delimiter(%q{)content(alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS')delimiter(})> + ident(conn)operator(.)ident(exec) string<delimiter(%q{)content(alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS')delimiter(})> reserved(rescue) pre_constant(nil) + ident(conn)operator(.)ident(autocommit) operator(=) pre_constant(true) + ident(conn) + reserved(end) + reserved(end) + + + comment(# The OCI8AutoRecover class enhances the OCI8 driver with auto-recover and) + comment(# reset functionality. If a call to #exec fails, and autocommit is turned on) + comment(# (ie., we're not in the middle of a longer transaction\), it will ) + comment(# automatically reconnect and try again. If autocommit is turned off,) + comment(# this would be dangerous (as the earlier part of the implied transaction) + comment(# may have failed silently if the connection died\) -- so instead the ) + comment(# connection is marked as dead, to be reconnected on it's next use.) + reserved(class) class(OCI8AutoRecover) operator(<) ident(DelegateClass)operator(()constant(OCI8)operator(\)) comment(#:nodoc:) + ident(attr_accessor) symbol(:active) + reserved(alias) symbol(:active?) symbol(:active) + + ident(cattr_accessor) symbol(:auto_retry) + reserved(class) operator(<<) class(self) + reserved(alias) symbol(:auto_retry?) symbol(:auto_retry) + reserved(end) + class_variable(@@auto_retry) operator(=) pre_constant(false) + + reserved(def) method(initialize)operator(()ident(config)operator(,) ident(factory) operator(=) constant(OracleConnectionFactory)operator(.)ident(new)operator(\)) + instance_variable(@active) operator(=) pre_constant(true) + instance_variable(@username)operator(,) instance_variable(@password)operator(,) instance_variable(@database) operator(=) ident(config)operator([)symbol(:username)operator(])operator(,) ident(config)operator([)symbol(:password)operator(])operator(,) ident(config)operator([)symbol(:database)operator(]) + instance_variable(@factory) operator(=) ident(factory) + instance_variable(@connection) operator(=) instance_variable(@factory)operator(.)ident(new_connection) instance_variable(@username)operator(,) instance_variable(@password)operator(,) instance_variable(@database) + reserved(super) instance_variable(@connection) + reserved(end) + + comment(# Checks connection, returns true if active. Note that ping actively) + comment(# checks the connection, while #active? simply returns the last) + comment(# known state.) + reserved(def) method(ping) + instance_variable(@connection)operator(.)ident(exec)operator(()string<delimiter(")content(select 1 from dual)delimiter(")>operator(\)) operator({) operator(|)ident(r)operator(|) pre_constant(nil) operator(}) + instance_variable(@active) operator(=) pre_constant(true) + reserved(rescue) + instance_variable(@active) operator(=) pre_constant(false) + ident(raise) + reserved(end) + + comment(# Resets connection, by logging off and creating a new connection.) + reserved(def) method(reset!) + ident(logoff) reserved(rescue) pre_constant(nil) + reserved(begin) + instance_variable(@connection) operator(=) instance_variable(@factory)operator(.)ident(new_connection) instance_variable(@username)operator(,) instance_variable(@password)operator(,) instance_variable(@database) + ident(__setobj__) instance_variable(@connection) + instance_variable(@active) operator(=) pre_constant(true) + reserved(rescue) + instance_variable(@active) operator(=) pre_constant(false) + ident(raise) + reserved(end) + reserved(end) + + comment(# ORA-00028: your session has been killed) + comment(# ORA-01012: not logged on ) + comment(# ORA-03113: end-of-file on communication channel) + comment(# ORA-03114: not connected to ORACLE) + constant(LOST_CONNECTION_ERROR_CODES) operator(=) operator([) integer(28)operator(,) integer(1012)operator(,) integer(3113)operator(,) integer(3114) operator(]) + + comment(# Adds auto-recovery functionality.) + comment(#) + comment(# See: http://www.jiubao.org/ruby-oci8/api.en.html#label-11) + reserved(def) method(exec)operator(()ident(sql)operator(,) operator(*)ident(bindvars)operator(\)) + ident(should_retry) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(auto_retry?) operator(&&) ident(autocommit?) + + reserved(begin) + instance_variable(@connection)operator(.)ident(exec)operator(()ident(sql)operator(,) operator(*)ident(bindvars)operator(\)) + reserved(rescue) constant(OCIException) operator(=)operator(>) ident(e) + ident(raise) reserved(unless) constant(LOST_CONNECTION_ERROR_CODES)operator(.)ident(include?)operator(()ident(e)operator(.)ident(code)operator(\)) + instance_variable(@active) operator(=) pre_constant(false) + ident(raise) reserved(unless) ident(should_retry) + ident(should_retry) operator(=) pre_constant(false) + ident(reset!) reserved(rescue) pre_constant(nil) + reserved(retry) + reserved(end) + reserved(end) + + reserved(end) + +reserved(rescue) constant(LoadError) + comment(# OCI8 driver is unavailable.) + reserved(module) class(ActiveRecord) comment(# :nodoc:) + reserved(class) class(Base) + reserved(def) pre_constant(self)operator(.)ident(oracle_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + comment(# Set up a reasonable error message) + ident(raise) constant(LoadError)operator(,) string<delimiter(")content(Oracle/OCI libraries could not be loaded.)delimiter(")> + reserved(end) + reserved(def) pre_constant(self)operator(.)ident(oci_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + comment(# Set up a reasonable error message) + ident(raise) constant(LoadError)operator(,) string<delimiter(")content(Oracle/OCI libraries could not be loaded.)delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + comment(# Establishes a connection to the database that's used by all Active Record objects) + reserved(def) pre_constant(self)operator(.)ident(postgresql_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(require_library_or_gem) string<delimiter(')content(postgres)delimiter(')> reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?)operator(()symbol(:PGconn)operator(\)) + + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + ident(host) operator(=) ident(config)operator([)symbol(:host)operator(]) + ident(port) operator(=) ident(config)operator([)symbol(:port)operator(]) operator(||) integer(5432) reserved(unless) ident(host)operator(.)ident(nil?) + ident(username) operator(=) ident(config)operator([)symbol(:username)operator(])operator(.)ident(to_s) + ident(password) operator(=) ident(config)operator([)symbol(:password)operator(])operator(.)ident(to_s) + + ident(min_messages) operator(=) ident(config)operator([)symbol(:min_messages)operator(]) + + reserved(if) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(database) operator(=) ident(config)operator([)symbol(:database)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database specified. Missing argument: database.)delimiter(")> + reserved(end) + + ident(pga) operator(=) constant(ConnectionAdapters)operator(::)constant(PostgreSQLAdapter)operator(.)ident(new)operator(() + constant(PGconn)operator(.)ident(connect)operator(()ident(host)operator(,) ident(port)operator(,) string<delimiter(")delimiter(")>operator(,) string<delimiter(")delimiter(")>operator(,) ident(database)operator(,) ident(username)operator(,) ident(password)operator(\))operator(,) ident(logger)operator(,) ident(config) + operator(\)) + + constant(PGconn)operator(.)ident(translate_results) operator(=) pre_constant(false) reserved(if) constant(PGconn)operator(.)ident(respond_to?) symbol(:translate_results=) + + ident(pga)operator(.)ident(schema_search_path) operator(=) ident(config)operator([)symbol(:schema_search_path)operator(]) operator(||) ident(config)operator([)symbol(:schema_order)operator(]) + + ident(pga) + reserved(end) + reserved(end) + + reserved(module) class(ConnectionAdapters) + comment(# The PostgreSQL adapter works both with the C-based (http://www.postgresql.jp/interfaces/ruby/\) and the Ruby-base) + comment(# (available both as gem and from http://rubyforge.org/frs/?group_id=234&release_id=1145\) drivers.) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:host</tt> -- Defaults to localhost) + comment(# * <tt>:port</tt> -- Defaults to 5432) + comment(# * <tt>:username</tt> -- Defaults to nothing) + comment(# * <tt>:password</tt> -- Defaults to nothing) + comment(# * <tt>:database</tt> -- The name of the database. No default, must be provided.) + comment(# * <tt>:schema_search_path</tt> -- An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the :schema_order option.) + comment(# * <tt>:encoding</tt> -- An optional client encoding that is using in a SET client_encoding TO <encoding> call on connection.) + comment(# * <tt>:min_messages</tt> -- An optional client min messages that is using in a SET client_min_messages TO <min_messages> call on connection.) + reserved(class) class(PostgreSQLAdapter) operator(<) constant(AbstractAdapter) + reserved(def) method(adapter_name) + string<delimiter(')content(PostgreSQL)delimiter(')> + reserved(end) + + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(logger)operator(,) ident(config) operator(=) operator({)operator(})operator(\)) + reserved(super)operator(()ident(connection)operator(,) ident(logger)operator(\)) + instance_variable(@config) operator(=) ident(config) + ident(configure_connection) + reserved(end) + + comment(# Is this connection alive and ready for queries?) + reserved(def) method(active?) + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:status)operator(\)) + instance_variable(@connection)operator(.)ident(status) operator(==) constant(PGconn)operator(::)constant(CONNECTION_OK) + reserved(else) + instance_variable(@connection)operator(.)ident(query) string<delimiter(')content(SELECT 1)delimiter(')> + pre_constant(true) + reserved(end) + comment(# postgres-pr raises a NoMethodError when querying if no conn is available) + reserved(rescue) constant(PGError)operator(,) constant(NoMethodError) + pre_constant(false) + reserved(end) + + comment(# Close then reopen the connection.) + reserved(def) method(reconnect!) + comment(# TODO: postgres-pr doesn't have PGconn#reset.) + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:reset)operator(\)) + instance_variable(@connection)operator(.)ident(reset) + ident(configure_connection) + reserved(end) + reserved(end) + + reserved(def) method(disconnect!) + comment(# Both postgres and postgres-pr respond to :close) + instance_variable(@connection)operator(.)ident(close) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(native_database_types) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(serial primary key)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(character varying)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(text)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(integer)delimiter(")> operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(float)delimiter(")> operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(timestamp)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(timestamp)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(time)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(date)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(bytea)delimiter(")> operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(boolean)delimiter(")> operator(}) + operator(}) + reserved(end) + + reserved(def) method(supports_migrations?) + pre_constant(true) + reserved(end) + + reserved(def) method(table_alias_length) + integer(63) + reserved(end) + + comment(# QUOTING ==================================================) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) operator(&&) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(escape_bytea)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) + reserved(super) + reserved(end) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) + string<delimiter(%()content(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(")delimiter(\))> + reserved(end) + + + comment(# DATABASE STATEMENTS ======================================) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(result) operator(=) ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(first) reserved(if) ident(result) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(table) operator(=) ident(sql)operator(.)ident(split)operator(()string<delimiter(")content( )delimiter(")>operator(,) integer(4)operator(\))operator([)integer(2)operator(]) + ident(id_value) operator(||) ident(last_insert_id)operator(()ident(table)operator(,) ident(sequence_name) operator(||) ident(default_sequence_name)operator(()ident(table)operator(,) ident(pk)operator(\))operator(\)) + reserved(end) + + reserved(def) method(query)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(query)operator(()ident(sql)operator(\)) operator(}) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(exec)operator(()ident(sql)operator(\)) operator(}) + reserved(end) + + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(cmdtuples) + reserved(end) + + ident(alias_method) symbol(:delete)operator(,) symbol(:update) comment(#:nodoc:) + + + reserved(def) method(begin_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(BEGIN)delimiter(")> + reserved(end) + + reserved(def) method(commit_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(COMMIT)delimiter(")> + reserved(end) + + reserved(def) method(rollback_db_transaction) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ROLLBACK)delimiter(")> + reserved(end) + + + comment(# SCHEMA STATEMENTS ========================================) + + comment(# Return the list of all tables in the schema search path.) + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(schemas) operator(=) ident(schema_search_path)operator(.)ident(split)operator(()regexp<delimiter(/)content(,)delimiter(/)>operator(\))operator(.)ident(map) operator({) operator(|)ident(p)operator(|) ident(quote)operator(()ident(p)operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\)) + ident(query)operator(()string<delimiter(<<-SQL)>operator(,) ident(name)operator(\))operator(.)ident(map) operator({) operator(|)ident(row)operator(|) ident(row)operator([)integer(0)operator(]) operator(})string<content( + SELECT tablename + FROM pg_tables + WHERE schemaname IN ()inline<inline_delimiter(#{)ident(schemas)inline_delimiter(})>content(\))delimiter( + SQL)> + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(result) operator(=) ident(query)operator(()string<delimiter(<<-SQL)>operator(,) ident(name)operator(\))string<content( + SELECT i.relname, d.indisunique, a.attname + FROM pg_class t, pg_class i, pg_index d, pg_attribute a + WHERE i.relkind = 'i' + AND d.indexrelid = i.oid + AND d.indisprimary = 'f' + AND t.oid = d.indrelid + AND t.relname = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' + AND a.attrelid = t.oid + AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum + OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum + OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum + OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum + OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum \) + ORDER BY i.relname)delimiter( + SQL)> + + ident(current_index) operator(=) pre_constant(nil) + ident(indexes) operator(=) operator([)operator(]) + + ident(result)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + reserved(if) ident(current_index) operator(!=) ident(row)operator([)integer(0)operator(]) + ident(indexes) operator(<<) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,) ident(row)operator([)integer(0)operator(])operator(,) ident(row)operator([)integer(1)operator(]) operator(==) string<delimiter(")content(t)delimiter(")>operator(,) operator([)operator(])operator(\)) + ident(current_index) operator(=) ident(row)operator([)integer(0)operator(]) + reserved(end) + + ident(indexes)operator(.)ident(last)operator(.)ident(columns) operator(<<) ident(row)operator([)integer(2)operator(]) + reserved(end) + + ident(indexes) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(column_definitions)operator(()ident(table_name)operator(\))operator(.)ident(collect) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(,) ident(default)operator(,) ident(notnull)operator(|) + constant(Column)operator(.)ident(new)operator(()ident(name)operator(,) ident(default_value)operator(()ident(default)operator(\))operator(,) ident(translate_field_type)operator(()ident(type)operator(\))operator(,) + ident(notnull) operator(==) string<delimiter(")content(f)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + comment(# Set the schema search path to a string of comma-separated schema names.) + comment(# Names beginning with $ are quoted (e.g. $user => '$user'\)) + comment(# See http://www.postgresql.org/docs/8.0/interactive/ddl-schemas.html) + reserved(def) method(schema_search_path=)operator(()ident(schema_csv)operator(\)) comment(#:nodoc:) + reserved(if) ident(schema_csv) + ident(execute) string<delimiter(")content(SET search_path TO )inline<inline_delimiter(#{)ident(schema_csv)inline_delimiter(})>delimiter(")> + instance_variable(@schema_search_path) operator(=) pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(schema_search_path) comment(#:nodoc:) + instance_variable(@schema_search_path) operator(||=) ident(query)operator(()string<delimiter(')content(SHOW search_path)delimiter(')>operator(\))operator([)integer(0)operator(])operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(default_sequence_name)operator(()ident(table_name)operator(,) ident(pk) operator(=) pre_constant(nil)operator(\)) + ident(default_pk)operator(,) ident(default_seq) operator(=) ident(pk_and_sequence_for)operator(()ident(table_name)operator(\)) + ident(default_seq) operator(||) string<delimiter(")inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(pk) operator(||) ident(default_pk) operator(||) string<delimiter(')content(id)delimiter(')>inline_delimiter(})>content(_seq)delimiter(")> + reserved(end) + + comment(# Resets sequence to the max value of the table's pk if present.) + reserved(def) method(reset_pk_sequence!)operator(()ident(table)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(sequence) operator(=) pre_constant(nil)operator(\)) + reserved(unless) ident(pk) reserved(and) ident(sequence) + ident(default_pk)operator(,) ident(default_sequence) operator(=) ident(pk_and_sequence_for)operator(()ident(table)operator(\)) + ident(pk) operator(||=) ident(default_pk) + ident(sequence) operator(||=) ident(default_sequence) + reserved(end) + reserved(if) ident(pk) + reserved(if) ident(sequence) + ident(select_value) string<delimiter(<<-end_sql)>operator(,) string<delimiter(')content(Reset sequence)delimiter(')>string<content( + SELECT setval(')inline<inline_delimiter(#{)ident(sequence)inline_delimiter(})>content(', (SELECT COALESCE(MAX()inline<inline_delimiter(#{)ident(pk)inline_delimiter(})>content(\)+(SELECT increment_by FROM )inline<inline_delimiter(#{)ident(sequence)inline_delimiter(})>content(\), (SELECT min_value FROM )inline<inline_delimiter(#{)ident(sequence)inline_delimiter(})>content(\)\) FROM )inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content(\), false\))delimiter( + end_sql)> + reserved(else) + instance_variable(@logger)operator(.)ident(warn) string<delimiter(")inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content( has primary key )inline<inline_delimiter(#{)ident(pk)inline_delimiter(})>content( with no default sequence)delimiter(")> reserved(if) instance_variable(@logger) + reserved(end) + reserved(end) + reserved(end) + + comment(# Find a table's primary key and sequence.) + reserved(def) method(pk_and_sequence_for)operator(()ident(table)operator(\)) + comment(# First try looking for a sequence with a dependency on the) + comment(# given table's primary key.) + ident(result) operator(=) ident(execute)operator(()string<delimiter(<<-end_sql)>operator(,) string<delimiter(')content(PK and serial sequence)delimiter(')>operator(\))operator([)integer(0)operator(])string<content( + SELECT attr.attname, name.nspname, seq.relname + FROM pg_class seq, + pg_attribute attr, + pg_depend dep, + pg_namespace name, + pg_constraint cons + WHERE seq.oid = dep.objid + AND seq.relnamespace = name.oid + AND seq.relkind = 'S' + AND attr.attrelid = dep.refobjid + AND attr.attnum = dep.refobjsubid + AND attr.attrelid = cons.conrelid + AND attr.attnum = cons.conkey[1] + AND cons.contype = 'p' + AND dep.refobjid = ')inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content('::regclass)delimiter( + end_sql)> + + reserved(if) ident(result)operator(.)ident(nil?) reserved(or) ident(result)operator(.)ident(empty?) + comment(# If that fails, try parsing the primary key's default value.) + comment(# Support the 7.x and 8.0 nextval('foo'::text\) as well as) + comment(# the 8.1+ nextval('foo'::regclass\).) + comment(# TODO: assumes sequence is in same schema as table.) + ident(result) operator(=) ident(execute)operator(()string<delimiter(<<-end_sql)>operator(,) string<delimiter(')content(PK and custom sequence)delimiter(')>operator(\))operator([)integer(0)operator(])string<content( + SELECT attr.attname, name.nspname, split_part(def.adsrc, ')char(\\\\)char(\\')content(', 2\) + FROM pg_class t + JOIN pg_namespace name ON (t.relnamespace = name.oid\) + JOIN pg_attribute attr ON (t.oid = attrelid\) + JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum\) + JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1]\) + WHERE t.oid = ')inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content('::regclass + AND cons.contype = 'p' + AND def.adsrc ~* 'nextval')delimiter( + end_sql)> + reserved(end) + comment(# check for existence of . in sequence name as in public.foo_sequence. if it does not exist, join the current namespace) + ident(result)operator(.)ident(last)operator([)string<delimiter(')content(.)delimiter(')>operator(]) operator(?) operator([)ident(result)operator(.)ident(first)operator(,) ident(result)operator(.)ident(last)operator(]) operator(:) operator([)ident(result)operator(.)ident(first)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(result)operator([)integer(1)operator(])inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(result)operator([)integer(2)operator(])inline_delimiter(})>delimiter(")>operator(]) + reserved(rescue) + pre_constant(nil) + reserved(end) + + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( RENAME TO )inline<inline_delimiter(#{)ident(new_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(add_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(execute)operator(()string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ADD )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")>operator(\)) + ident(execute)operator(()string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ALTER )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( SET NOT NULL)delimiter(")>operator(\)) reserved(if) ident(options)operator([)symbol(:null)operator(]) operator(==) pre_constant(false) + ident(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(options)operator([)symbol(:default)operator(])operator(\)) reserved(unless) ident(options)operator([)symbol(:default)operator(])operator(.)ident(nil?) + reserved(end) + + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + reserved(begin) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ALTER )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( TYPE )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")> + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) + comment(# This is PG7, so we use a more arcane way of doing it.) + ident(begin_db_transaction) + ident(add_column)operator(()ident(table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(_ar_tmp)delimiter(")>operator(,) ident(type)operator(,) ident(options)operator(\)) + ident(execute) string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( SET )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(_ar_tmp = CAST()inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( AS )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>content(\))delimiter(")> + ident(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(rename_column)operator(()ident(table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(_ar_tmp)delimiter(")>operator(,) ident(column_name)operator(\)) + ident(commit_db_transaction) + reserved(end) + ident(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(options)operator([)symbol(:default)operator(])operator(\)) reserved(unless) ident(options)operator([)symbol(:default)operator(])operator(.)ident(nil?) + reserved(end) + + reserved(def) method(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(default)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ALTER COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( SET DEFAULT ')inline<inline_delimiter(#{)ident(default)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(def) method(rename_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(new_column_name)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( RENAME COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( TO )inline<inline_delimiter(#{)ident(new_column_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(remove_index)operator(()ident(table_name)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(DROP INDEX )inline<inline_delimiter(#{)ident(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + ident(private) + constant(BYTEA_COLUMN_TYPE_OID) operator(=) integer(17) + constant(TIMESTAMPOID) operator(=) integer(1114) + constant(TIMESTAMPTZOID) operator(=) integer(1184) + + reserved(def) method(configure_connection) + reserved(if) instance_variable(@config)operator([)symbol(:encoding)operator(]) + ident(execute)operator(()string<delimiter(")content(SET client_encoding TO ')inline<inline_delimiter(#{)instance_variable(@config)operator([)symbol(:encoding)operator(])inline_delimiter(})>content(')delimiter(")>operator(\)) + reserved(end) + reserved(if) instance_variable(@config)operator([)symbol(:min_messages)operator(]) + ident(execute)operator(()string<delimiter(")content(SET client_min_messages TO ')inline<inline_delimiter(#{)instance_variable(@config)operator([)symbol(:min_messages)operator(])inline_delimiter(})>content(')delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(last_insert_id)operator(()ident(table)operator(,) ident(sequence_name)operator(\)) + ident(Integer)operator(()ident(select_value)operator(()string<delimiter(")content(SELECT currval(')inline<inline_delimiter(#{)ident(sequence_name)inline_delimiter(})>content('\))delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(res) operator(=) ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(results) operator(=) ident(res)operator(.)ident(result) + ident(rows) operator(=) operator([)operator(]) + reserved(if) ident(results)operator(.)ident(length) operator(>) integer(0) + ident(fields) operator(=) ident(res)operator(.)ident(fields) + ident(results)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(hashed_row) operator(=) operator({)operator(}) + ident(row)operator(.)ident(each_index) reserved(do) operator(|)ident(cel_index)operator(|) + ident(column) operator(=) ident(row)operator([)ident(cel_index)operator(]) + + reserved(case) ident(res)operator(.)ident(type)operator(()ident(cel_index)operator(\)) + reserved(when) constant(BYTEA_COLUMN_TYPE_OID) + ident(column) operator(=) ident(unescape_bytea)operator(()ident(column)operator(\)) + reserved(when) constant(TIMESTAMPTZOID)operator(,) constant(TIMESTAMPOID) + ident(column) operator(=) ident(cast_to_time)operator(()ident(column)operator(\)) + reserved(end) + + ident(hashed_row)operator([)ident(fields)operator([)ident(cel_index)operator(])operator(]) operator(=) ident(column) + reserved(end) + ident(rows) operator(<<) ident(hashed_row) + reserved(end) + reserved(end) + reserved(return) ident(rows) + reserved(end) + + reserved(def) method(escape_bytea)operator(()ident(s)operator(\)) + reserved(if) constant(PGconn)operator(.)ident(respond_to?) symbol(:escape_bytea) + pre_constant(self)operator(.)ident(class)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:escape_bytea)operator(\)) reserved(do) operator(|)ident(s)operator(|) + constant(PGconn)operator(.)ident(escape_bytea)operator(()ident(s)operator(\)) reserved(if) ident(s) + reserved(end) + reserved(else) + pre_constant(self)operator(.)ident(class)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:escape_bytea)operator(\)) reserved(do) operator(|)ident(s)operator(|) + reserved(if) ident(s) + ident(result) operator(=) string<delimiter(')delimiter(')> + ident(s)operator(.)ident(each_byte) operator({) operator(|)ident(c)operator(|) ident(result) operator(<<) ident(sprintf)operator(()string<delimiter(')char(\\\\)char(\\\\)content(%03o)delimiter(')>operator(,) ident(c)operator(\)) operator(}) + ident(result) + reserved(end) + reserved(end) + reserved(end) + ident(escape_bytea)operator(()ident(s)operator(\)) + reserved(end) + + reserved(def) method(unescape_bytea)operator(()ident(s)operator(\)) + reserved(if) constant(PGconn)operator(.)ident(respond_to?) symbol(:unescape_bytea) + pre_constant(self)operator(.)ident(class)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:unescape_bytea)operator(\)) reserved(do) operator(|)ident(s)operator(|) + constant(PGconn)operator(.)ident(unescape_bytea)operator(()ident(s)operator(\)) reserved(if) ident(s) + reserved(end) + reserved(else) + pre_constant(self)operator(.)ident(class)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:unescape_bytea)operator(\)) reserved(do) operator(|)ident(s)operator(|) + reserved(if) ident(s) + ident(result) operator(=) string<delimiter(')delimiter(')> + ident(i)operator(,) ident(max) operator(=) integer(0)operator(,) ident(s)operator(.)ident(size) + reserved(while) ident(i) operator(<) ident(max) + ident(char) operator(=) ident(s)operator([)ident(i)operator(]) + reserved(if) ident(char) operator(==) integer(?\\\\) + reserved(if) ident(s)operator([)ident(i)operator(+)integer(1)operator(]) operator(==) integer(?\\\\) + ident(char) operator(=) integer(?\\\\) + ident(i) operator(+=) integer(1) + reserved(else) + ident(char) operator(=) ident(s)operator([)ident(i)operator(+)integer(1)operator(..)ident(i)operator(+)integer(3)operator(])operator(.)ident(oct) + ident(i) operator(+=) integer(3) + reserved(end) + reserved(end) + ident(result) operator(<<) ident(char) + ident(i) operator(+=) integer(1) + reserved(end) + ident(result) + reserved(end) + reserved(end) + reserved(end) + ident(unescape_bytea)operator(()ident(s)operator(\)) + reserved(end) + + comment(# Query a table's column names, default values, and types.) + comment(#) + comment(# The underlying query is roughly:) + comment(# SELECT column.name, column.type, default.value) + comment(# FROM column LEFT JOIN default) + comment(# ON column.table_id = default.table_id) + comment(# AND column.num = default.column_num) + comment(# WHERE column.table_id = get_table_id('table_name'\)) + comment(# AND column.num > 0) + comment(# AND NOT column.is_dropped) + comment(# ORDER BY column.num) + comment(#) + comment(# If the table name is not prefixed with a schema, the database will) + comment(# take the first match from the schema search path.) + comment(#) + comment(# Query implementation notes:) + comment(# - format_type includes the column size constraint, e.g. varchar(50\)) + comment(# - ::regclass is a function that gives the id for a table name) + reserved(def) method(column_definitions)operator(()ident(table_name)operator(\)) + ident(query) string<delimiter(<<-end_sql)>string<content( + SELECT a.attname, format_type(a.atttypid, a.atttypmod\), d.adsrc, a.attnotnull + FROM pg_attribute a LEFT JOIN pg_attrdef d + ON a.attrelid = d.adrelid AND a.attnum = d.adnum + WHERE a.attrelid = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content('::regclass + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum)delimiter( + end_sql)> + reserved(end) + + comment(# Translate PostgreSQL-specific types into simplified SQL types.) + comment(# These are special cases; standard types are handled by) + comment(# ConnectionAdapters::Column#simplified_type.) + reserved(def) method(translate_field_type)operator(()ident(field_type)operator(\)) + comment(# Match the beginning of field_type since it may have a size constraint on the end.) + reserved(case) ident(field_type) + reserved(when) regexp<delimiter(/)content(^timestamp)delimiter(/)modifier(i)> reserved(then) string<delimiter(')content(datetime)delimiter(')> + reserved(when) regexp<delimiter(/)content(^real|^money)delimiter(/)modifier(i)> reserved(then) string<delimiter(')content(float)delimiter(')> + reserved(when) regexp<delimiter(/)content(^interval)delimiter(/)modifier(i)> reserved(then) string<delimiter(')content(string)delimiter(')> + comment(# geometric types (the line type is currently not implemented in postgresql\)) + reserved(when) regexp<delimiter(/)content(^(?:point|lseg|box|"?path"?|polygon|circle\))delimiter(/)modifier(i)> reserved(then) string<delimiter(')content(string)delimiter(')> + reserved(when) regexp<delimiter(/)content(^bytea)delimiter(/)modifier(i)> reserved(then) string<delimiter(')content(binary)delimiter(')> + reserved(else) ident(field_type) comment(# Pass through standard types.) + reserved(end) + reserved(end) + + reserved(def) method(default_value)operator(()ident(value)operator(\)) + comment(# Boolean types) + reserved(return) string<delimiter(")content(t)delimiter(")> reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(true)delimiter(/)modifier(i)> + reserved(return) string<delimiter(")content(f)delimiter(")> reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(false)delimiter(/)modifier(i)> + + comment(# Char/String/Bytea type values) + reserved(return) global_variable($1) reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^'(.*\)'::(bpchar|text|character varying|bytea\)$)delimiter(/)> + + comment(# Numeric values) + reserved(return) ident(value) reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^-?[0-9]+()char(\\.)content([0-9]*\)?)delimiter(/)> + + comment(# Fixed dates / times) + reserved(return) global_variable($1) reserved(if) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^'(.+\)'::(date|timestamp\))delimiter(/)> + + comment(# Anything else is blank, some user type, or some function) + comment(# and we can't know the value of that, so return nil.) + reserved(return) pre_constant(nil) + reserved(end) + + comment(# Only needed for DateTime instances) + reserved(def) method(cast_to_time)operator(()ident(value)operator(\)) + reserved(return) ident(value) reserved(unless) ident(value)operator(.)ident(class) operator(==) constant(DateTime) + ident(v) operator(=) ident(value) + ident(time_array) operator(=) operator([)ident(v)operator(.)ident(year)operator(,) ident(v)operator(.)ident(month)operator(,) ident(v)operator(.)ident(day)operator(,) ident(v)operator(.)ident(hour)operator(,) ident(v)operator(.)ident(min)operator(,) ident(v)operator(.)ident(sec)operator(]) + constant(Time)operator(.)ident(send)operator(()constant(Base)operator(.)ident(default_timezone)operator(,) operator(*)ident(time_array)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(# Author: Luke Holden <lholden@cablelan.net>) +comment(# Updated for SQLite3: Jamis Buck <jamis@37signals.com>) + +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + reserved(class) operator(<<) class(self) + comment(# sqlite3 adapter reuses sqlite_connection.) + reserved(def) method(sqlite3_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(parse_config!)operator(()ident(config)operator(\)) + + reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?)operator(()symbol(:SQLite3)operator(\)) + ident(require_library_or_gem)operator(()ident(config)operator([)symbol(:adapter)operator(])operator(\)) + reserved(end) + + ident(db) operator(=) constant(SQLite3)operator(::)constant(Database)operator(.)ident(new)operator(() + ident(config)operator([)symbol(:database)operator(])operator(,) + symbol(:results_as_hash) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:type_translation) operator(=)operator(>) pre_constant(false) + operator(\)) + constant(ConnectionAdapters)operator(::)constant(SQLiteAdapter)operator(.)ident(new)operator(()ident(db)operator(,) ident(logger)operator(\)) + reserved(end) + + comment(# Establishes a connection to the database that's used by all Active Record objects) + reserved(def) method(sqlite_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(parse_config!)operator(()ident(config)operator(\)) + + reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?)operator(()symbol(:SQLite)operator(\)) + ident(require_library_or_gem)operator(()ident(config)operator([)symbol(:adapter)operator(])operator(\)) + + ident(db) operator(=) constant(SQLite)operator(::)constant(Database)operator(.)ident(new)operator(()ident(config)operator([)symbol(:database)operator(])operator(,) integer(0)operator(\)) + ident(db)operator(.)ident(show_datatypes) operator(=) string<delimiter(")content(ON)delimiter(")> reserved(if) operator(!)reserved(defined?) constant(SQLite)operator(::)constant(Version) + ident(db)operator(.)ident(results_as_hash) operator(=) pre_constant(true) reserved(if) reserved(defined?) constant(SQLite)operator(::)constant(Version) + ident(db)operator(.)ident(type_translation) operator(=) pre_constant(false) + + comment(# "Downgrade" deprecated sqlite API) + reserved(if) constant(SQLite)operator(.)ident(const_defined?)operator(()symbol(:Version)operator(\)) + constant(ConnectionAdapters)operator(::)constant(SQLite2Adapter)operator(.)ident(new)operator(()ident(db)operator(,) ident(logger)operator(\)) + reserved(else) + constant(ConnectionAdapters)operator(::)constant(DeprecatedSQLiteAdapter)operator(.)ident(new)operator(()ident(db)operator(,) ident(logger)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(parse_config!)operator(()ident(config)operator(\)) + ident(config)operator([)symbol(:database)operator(]) operator(||=) ident(config)operator([)symbol(:dbfile)operator(]) + comment(# Require database.) + reserved(unless) ident(config)operator([)symbol(:database)operator(]) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database file specified. Missing argument: database)delimiter(")> + reserved(end) + + comment(# Allow database path relative to RAILS_ROOT, but only if) + comment(# the database path is not the special path that tells) + comment(# Sqlite build a database only in memory.) + reserved(if) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:RAILS_ROOT)operator(\)) operator(&&) string<delimiter(')content(:memory:)delimiter(')> operator(!=) ident(config)operator([)symbol(:database)operator(]) + ident(config)operator([)symbol(:database)operator(]) operator(=) constant(File)operator(.)ident(expand_path)operator(()ident(config)operator([)symbol(:database)operator(])operator(,) constant(RAILS_ROOT)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(ConnectionAdapters) comment(#:nodoc:) + reserved(class) class(SQLiteColumn) operator(<) constant(Column) comment(#:nodoc:) + reserved(class) operator(<<) class(self) + reserved(def) method(string_to_binary)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\0)content(|)char(\\%)delimiter(/)>operator(\)) reserved(do) operator(|)ident(b)operator(|) + reserved(case) ident(b) + reserved(when) string<delimiter(")char(\\0)delimiter(")> reserved(then) string<delimiter(")content(%00)delimiter(")> + reserved(when) string<delimiter(")content(%)delimiter(")> reserved(then) string<delimiter(")content(%25)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(binary_to_string)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(%00|%25)delimiter(/)>operator(\)) reserved(do) operator(|)ident(b)operator(|) + reserved(case) ident(b) + reserved(when) string<delimiter(")content(%00)delimiter(")> reserved(then) string<delimiter(")char(\\0)delimiter(")> + reserved(when) string<delimiter(")content(%25)delimiter(")> reserved(then) string<delimiter(")content(%)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby drivers (available both as gems and) + comment(# from http://rubyforge.org/projects/sqlite-ruby/\).) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:database</tt> -- Path to the database file.) + reserved(class) class(SQLiteAdapter) operator(<) constant(AbstractAdapter) + reserved(def) method(adapter_name) comment(#:nodoc:) + string<delimiter(')content(SQLite)delimiter(')> + reserved(end) + + reserved(def) method(supports_migrations?) comment(#:nodoc:) + pre_constant(true) + reserved(end) + + reserved(def) method(supports_count_distinct?) comment(#:nodoc:) + pre_constant(false) + reserved(end) + + reserved(def) method(native_database_types) comment(#:nodoc:) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(INTEGER PRIMARY KEY NOT NULL)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(varchar)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(text)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(integer)delimiter(")> operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(float)delimiter(")> operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(date)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(blob)delimiter(")> operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(boolean)delimiter(")> operator(}) + operator(}) + reserved(end) + + + comment(# QUOTING ==================================================) + + reserved(def) method(quote_string)operator(()ident(s)operator(\)) comment(#:nodoc:) + instance_variable(@connection)operator(.)ident(class)operator(.)ident(quote)operator(()ident(s)operator(\)) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) comment(#:nodoc:) + string<delimiter(%Q()content(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(")delimiter(\))> + reserved(end) + + + comment(# DATABASE STATEMENTS ======================================) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(catch_schema_changes) operator({) ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) operator(}) operator(}) + reserved(end) + + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + instance_variable(@connection)operator(.)ident(changes) + reserved(end) + + reserved(def) method(delete)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(sql) operator(+=) string<delimiter(")content( WHERE 1=1)delimiter(")> reserved(unless) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(WHERE)delimiter(/)modifier(i)> + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + instance_variable(@connection)operator(.)ident(changes) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(id_value) operator(||) instance_variable(@connection)operator(.)ident(last_insert_row_id) + reserved(end) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(row)operator(|) + ident(record) operator(=) operator({)operator(}) + ident(row)operator(.)ident(each_key) reserved(do) operator(|)ident(key)operator(|) + reserved(if) ident(key)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(record)operator([)ident(key)operator(.)ident(sub)operator(()regexp<delimiter(/)content(^)char(\\w)content(+)char(\\.)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\))operator(]) operator(=) ident(row)operator([)ident(key)operator(]) + reserved(end) + reserved(end) + ident(record) + reserved(end) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(result) operator(=) ident(select_all)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(result)operator(.)ident(first) + reserved(end) + + + reserved(def) method(begin_db_transaction) comment(#:nodoc:) + ident(catch_schema_changes) operator({) instance_variable(@connection)operator(.)ident(transaction) operator(}) + reserved(end) + + reserved(def) method(commit_db_transaction) comment(#:nodoc:) + ident(catch_schema_changes) operator({) instance_variable(@connection)operator(.)ident(commit) operator(}) + reserved(end) + + reserved(def) method(rollback_db_transaction) comment(#:nodoc:) + ident(catch_schema_changes) operator({) instance_variable(@connection)operator(.)ident(rollback) operator(}) + reserved(end) + + + comment(# SCHEMA STATEMENTS ========================================) + + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()string<delimiter(")content(SELECT name FROM sqlite_master WHERE type = 'table')delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(row)operator(|) + ident(row)operator([)integer(0)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(table_structure)operator(()ident(table_name)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(field)operator(|) + constant(SQLiteColumn)operator(.)ident(new)operator(()ident(field)operator([)string<delimiter(')content(name)delimiter(')>operator(])operator(,) ident(field)operator([)string<delimiter(')content(dflt_value)delimiter(')>operator(])operator(,) ident(field)operator([)string<delimiter(')content(type)delimiter(')>operator(])operator(,) ident(field)operator([)string<delimiter(')content(notnull)delimiter(')>operator(]) operator(==) string<delimiter(")content(0)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(execute)operator(()string<delimiter(")content(PRAGMA index_list()inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(\))delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(row)operator(|) + ident(index) operator(=) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,) ident(row)operator([)string<delimiter(')content(name)delimiter(')>operator(])operator(\)) + ident(index)operator(.)ident(unique) operator(=) ident(row)operator([)string<delimiter(')content(unique)delimiter(')>operator(]) operator(!=) string<delimiter(')content(0)delimiter(')> + ident(index)operator(.)ident(columns) operator(=) ident(execute)operator(()string<delimiter(")content(PRAGMA index_info(')inline<inline_delimiter(#{)ident(index)operator(.)ident(name)inline_delimiter(})>content('\))delimiter(")>operator(\))operator(.)ident(map) operator({) operator(|)ident(col)operator(|) ident(col)operator([)string<delimiter(')content(name)delimiter(')>operator(]) operator(}) + ident(index) + reserved(end) + reserved(end) + + reserved(def) method(primary_key)operator(()ident(table_name)operator(\)) comment(#:nodoc:) + ident(column) operator(=) ident(table_structure)operator(()ident(table_name)operator(\))operator(.)ident(find) operator({)operator(|)ident(field)operator(|) ident(field)operator([)string<delimiter(')content(pk)delimiter(')>operator(])operator(.)ident(to_i) operator(==) integer(1)operator(}) + ident(column) operator(?) ident(column)operator([)string<delimiter(')content(name)delimiter(')>operator(]) operator(:) pre_constant(nil) + reserved(end) + + reserved(def) method(remove_index)operator(()ident(table_name)operator(,) ident(options)operator(=)operator({)operator(})operator(\)) comment(#:nodoc:) + ident(execute) string<delimiter(")content(DROP INDEX )inline<inline_delimiter(#{)ident(quote_column_name)operator(()ident(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\))operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + ident(move_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + reserved(end) + + reserved(def) method(add_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(alter_table)operator(()ident(table_name)operator(\)) reserved(do) operator(|)ident(definition)operator(|) + ident(definition)operator(.)ident(column)operator(()ident(column_name)operator(,) ident(type)operator(,) ident(options)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) comment(#:nodoc:) + ident(alter_table)operator(()ident(table_name)operator(\)) reserved(do) operator(|)ident(definition)operator(|) + ident(definition)operator(.)ident(columns)operator(.)ident(delete)operator(()ident(definition)operator([)ident(column_name)operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(change_column_default)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(default)operator(\)) comment(#:nodoc:) + ident(alter_table)operator(()ident(table_name)operator(\)) reserved(do) operator(|)ident(definition)operator(|) + ident(definition)operator([)ident(column_name)operator(])operator(.)ident(default) operator(=) ident(default) + reserved(end) + reserved(end) + + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(alter_table)operator(()ident(table_name)operator(\)) reserved(do) operator(|)ident(definition)operator(|) + ident(definition)operator([)ident(column_name)operator(])operator(.)ident(instance_eval) reserved(do) + pre_constant(self)operator(.)ident(type) operator(=) ident(type) + pre_constant(self)operator(.)ident(limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) reserved(if) ident(options)operator([)symbol(:limit)operator(]) + pre_constant(self)operator(.)ident(default) operator(=) ident(options)operator([)symbol(:default)operator(]) reserved(if) ident(options)operator([)symbol(:default)operator(]) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(rename_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(new_column_name)operator(\)) comment(#:nodoc:) + ident(alter_table)operator(()ident(table_name)operator(,) symbol(:rename) operator(=)operator(>) operator({)ident(column_name) operator(=)operator(>) ident(new_column_name)operator(})operator(\)) + reserved(end) + + + ident(protected) + reserved(def) method(table_structure)operator(()ident(table_name)operator(\)) + ident(returning) ident(structure) operator(=) ident(execute)operator(()string<delimiter(")content(PRAGMA table_info()inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(\))delimiter(")>operator(\)) reserved(do) + ident(raise) constant(ActiveRecord)operator(::)constant(StatementInvalid) reserved(if) ident(structure)operator(.)ident(empty?) + reserved(end) + reserved(end) + + reserved(def) method(alter_table)operator(()ident(table_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(altered_table_name) operator(=) string<delimiter(")content(altered_)inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")> + ident(caller) operator(=) ident(lambda) operator({)operator(|)ident(definition)operator(|) reserved(yield) ident(definition) reserved(if) ident(block_given?)operator(}) + + ident(transaction) reserved(do) + ident(move_table)operator(()ident(table_name)operator(,) ident(altered_table_name)operator(,) + ident(options)operator(.)ident(merge)operator(()symbol(:temporary) operator(=)operator(>) pre_constant(true)operator(\))operator(\)) + ident(move_table)operator(()ident(altered_table_name)operator(,) ident(table_name)operator(,) operator(&)ident(caller)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(move_table)operator(()ident(from)operator(,) ident(to)operator(,) ident(options) operator(=) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) comment(#:nodoc:) + ident(copy_table)operator(()ident(from)operator(,) ident(to)operator(,) ident(options)operator(,) operator(&)ident(block)operator(\)) + ident(drop_table)operator(()ident(from)operator(\)) + reserved(end) + + reserved(def) method(copy_table)operator(()ident(from)operator(,) ident(to)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(create_table)operator(()ident(to)operator(,) ident(options)operator(\)) reserved(do) operator(|)instance_variable(@definition)operator(|) + ident(columns)operator(()ident(from)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(column)operator(|) + ident(column_name) operator(=) ident(options)operator([)symbol(:rename)operator(]) operator(?) + operator(()ident(options)operator([)symbol(:rename)operator(])operator([)ident(column)operator(.)ident(name)operator(]) operator(||) + ident(options)operator([)symbol(:rename)operator(])operator([)ident(column)operator(.)ident(name)operator(.)ident(to_sym)operator(]) operator(||) + ident(column)operator(.)ident(name)operator(\)) operator(:) ident(column)operator(.)ident(name) + + instance_variable(@definition)operator(.)ident(column)operator(()ident(column_name)operator(,) ident(column)operator(.)ident(type)operator(,) + symbol(:limit) operator(=)operator(>) ident(column)operator(.)ident(limit)operator(,) symbol(:default) operator(=)operator(>) ident(column)operator(.)ident(default)operator(,) + symbol(:null) operator(=)operator(>) ident(column)operator(.)ident(null)operator(\)) + reserved(end) + instance_variable(@definition)operator(.)ident(primary_key)operator(()ident(primary_key)operator(()ident(from)operator(\))operator(\)) + reserved(yield) instance_variable(@definition) reserved(if) ident(block_given?) + reserved(end) + + ident(copy_table_indexes)operator(()ident(from)operator(,) ident(to)operator(\)) + ident(copy_table_contents)operator(()ident(from)operator(,) ident(to)operator(,) + instance_variable(@definition)operator(.)ident(columns)operator(.)ident(map) operator({)operator(|)ident(column)operator(|) ident(column)operator(.)ident(name)operator(})operator(,) + ident(options)operator([)symbol(:rename)operator(]) operator(||) operator({)operator(})operator(\)) + reserved(end) + + reserved(def) method(copy_table_indexes)operator(()ident(from)operator(,) ident(to)operator(\)) comment(#:nodoc:) + ident(indexes)operator(()ident(from)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(index)operator(|) + ident(name) operator(=) ident(index)operator(.)ident(name) + reserved(if) ident(to) operator(==) string<delimiter(")content(altered_)inline<inline_delimiter(#{)ident(from)inline_delimiter(})>delimiter(")> + ident(name) operator(=) string<delimiter(")content(temp_)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + reserved(elsif) ident(from) operator(==) string<delimiter(")content(altered_)inline<inline_delimiter(#{)ident(to)inline_delimiter(})>delimiter(")> + ident(name) operator(=) ident(name)operator([)integer(5)operator(..)integer(-1)operator(]) + reserved(end) + + ident(opts) operator(=) operator({) symbol(:name) operator(=)operator(>) ident(name) operator(}) + ident(opts)operator([)symbol(:unique)operator(]) operator(=) pre_constant(true) reserved(if) ident(index)operator(.)ident(unique) + ident(add_index)operator(()ident(to)operator(,) ident(index)operator(.)ident(columns)operator(,) ident(opts)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(copy_table_contents)operator(()ident(from)operator(,) ident(to)operator(,) ident(columns)operator(,) ident(rename) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(column_mappings) operator(=) constant(Hash)operator([)operator(*)ident(columns)operator(.)ident(map) operator({)operator(|)ident(name)operator(|) operator([)ident(name)operator(,) ident(name)operator(])operator(})operator(.)ident(flatten)operator(]) + ident(rename)operator(.)ident(inject)operator(()ident(column_mappings)operator(\)) operator({)operator(|)ident(map)operator(,) ident(a)operator(|) ident(map)operator([)ident(a)operator(.)ident(last)operator(]) operator(=) ident(a)operator(.)ident(first)operator(;) ident(map)operator(}) + + instance_variable(@connection)operator(.)ident(execute) string<delimiter(")content(SELECT * FROM )inline<inline_delimiter(#{)ident(from)inline_delimiter(})>delimiter(")> reserved(do) operator(|)ident(row)operator(|) + ident(sql) operator(=) string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)ident(to)inline_delimiter(})>content( VALUES ()delimiter(")> + ident(sql) operator(<<) ident(columns)operator(.)ident(map) operator({)operator(|)ident(col)operator(|) ident(quote) ident(row)operator([)ident(column_mappings)operator([)ident(col)operator(])operator(])operator(}) operator(*) string<delimiter(')content(, )delimiter(')> + ident(sql) operator(<<) string<delimiter(')content(\))delimiter(')> + instance_variable(@connection)operator(.)ident(execute) ident(sql) + reserved(end) + reserved(end) + + reserved(def) method(catch_schema_changes) + reserved(return) reserved(yield) + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) operator(=)operator(>) ident(exception) + reserved(if) ident(exception)operator(.)ident(message) operator(=)operator(~) regexp<delimiter(/)content(database schema has changed)delimiter(/)> + ident(reconnect!) + reserved(retry) + reserved(else) + ident(raise) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(SQLite2Adapter) operator(<) constant(SQLiteAdapter) comment(# :nodoc:) + comment(# SQLite 2 does not support COUNT(DISTINCT\) queries:) + comment(#) + comment(# select COUNT(DISTINCT ArtistID\) from CDs; ) + comment(#) + comment(# In order to get the number of artists we execute the following statement) + comment(# ) + comment(# SELECT COUNT(ArtistID\) FROM (SELECT DISTINCT ArtistID FROM CDs\);) + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + reserved(super)operator(()ident(rewrite_count_distinct_queries)operator(()ident(sql)operator(\))operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(rewrite_count_distinct_queries)operator(()ident(sql)operator(\)) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(count)char(\\()content(distinct ([^)char(\\\))content(]+\))char(\\\))content(( AS )char(\\w)content(+\)? (.*\))delimiter(/)modifier(i)> + ident(distinct_column) operator(=) global_variable($1) + ident(distinct_query) operator(=) global_variable($3) + ident(column_name) operator(=) ident(distinct_column)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator(.)ident(last) + string<delimiter(")content(SELECT COUNT()inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(\) FROM (SELECT DISTINCT )inline<inline_delimiter(#{)ident(distinct_column)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(distinct_query)inline_delimiter(})>content(\))delimiter(")> + reserved(else) + ident(sql) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(DeprecatedSQLiteAdapter) operator(<) constant(SQLite2Adapter) comment(# :nodoc:) + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(\)) + ident(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(id_value) operator(||) instance_variable(@connection)operator(.)ident(last_insert_rowid) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +comment(# sqlserver_adapter.rb -- ActiveRecord adapter for Microsoft SQL Server) +comment(#) +comment(# Author: Joey Gibson <joey@joeygibson.com>) +comment(# Date: 10/14/2004) +comment(#) +comment(# Modifications: DeLynn Berry <delynnb@megastarfinancial.com>) +comment(# Date: 3/22/2005) +comment(#) +comment(# Modifications (ODBC\): Mark Imbriaco <mark.imbriaco@pobox.com>) +comment(# Date: 6/26/2005) +comment(#) +comment(# Current maintainer: Ryan Tomayko <rtomayko@gmail.com>) +comment(#) +comment(# Modifications (Migrations\): Tom Ward <tom@popdog.net>) +comment(# Date: 27/10/2005) +comment(#) + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + reserved(def) pre_constant(self)operator(.)ident(sqlserver_connection)operator(()ident(config)operator(\)) comment(#:nodoc:) + ident(require_library_or_gem) string<delimiter(')content(dbi)delimiter(')> reserved(unless) pre_constant(self)operator(.)ident(class)operator(.)ident(const_defined?)operator(()symbol(:DBI)operator(\)) + + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + + ident(mode) operator(=) ident(config)operator([)symbol(:mode)operator(]) operator(?) ident(config)operator([)symbol(:mode)operator(])operator(.)ident(to_s)operator(.)ident(upcase) operator(:) string<delimiter(')content(ADO)delimiter(')> + ident(username) operator(=) ident(config)operator([)symbol(:username)operator(]) operator(?) ident(config)operator([)symbol(:username)operator(])operator(.)ident(to_s) operator(:) string<delimiter(')content(sa)delimiter(')> + ident(password) operator(=) ident(config)operator([)symbol(:password)operator(]) operator(?) ident(config)operator([)symbol(:password)operator(])operator(.)ident(to_s) operator(:) string<delimiter(')delimiter(')> + ident(autocommit) operator(=) ident(config)operator(.)ident(key?)operator(()symbol(:autocommit)operator(\)) operator(?) ident(config)operator([)symbol(:autocommit)operator(]) operator(:) pre_constant(true) + reserved(if) ident(mode) operator(==) string<delimiter(")content(ODBC)delimiter(")> + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Missing DSN. Argument ':dsn' must be set in order for this adapter to work.)delimiter(")> reserved(unless) ident(config)operator(.)ident(has_key?)operator(()symbol(:dsn)operator(\)) + ident(dsn) operator(=) ident(config)operator([)symbol(:dsn)operator(]) + ident(driver_url) operator(=) string<delimiter(")content(DBI:ODBC:)inline<inline_delimiter(#{)ident(dsn)inline_delimiter(})>delimiter(")> + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Missing Database. Argument ':database' must be set in order for this adapter to work.)delimiter(")> reserved(unless) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(database) operator(=) ident(config)operator([)symbol(:database)operator(]) + ident(host) operator(=) ident(config)operator([)symbol(:host)operator(]) operator(?) ident(config)operator([)symbol(:host)operator(])operator(.)ident(to_s) operator(:) string<delimiter(')content(localhost)delimiter(')> + ident(driver_url) operator(=) string<delimiter(")content(DBI:ADO:Provider=SQLOLEDB;Data Source=)inline<inline_delimiter(#{)ident(host)inline_delimiter(})>content(;Initial Catalog=)inline<inline_delimiter(#{)ident(database)inline_delimiter(})>content(;User Id=)inline<inline_delimiter(#{)ident(username)inline_delimiter(})>content(;Password=)inline<inline_delimiter(#{)ident(password)inline_delimiter(})>content(;)delimiter(")> + reserved(end) + ident(conn) operator(=) constant(DBI)operator(.)ident(connect)operator(()ident(driver_url)operator(,) ident(username)operator(,) ident(password)operator(\)) + ident(conn)operator([)string<delimiter(")content(AutoCommit)delimiter(")>operator(]) operator(=) ident(autocommit) + constant(ConnectionAdapters)operator(::)constant(SQLServerAdapter)operator(.)ident(new)operator(()ident(conn)operator(,) ident(logger)operator(,) operator([)ident(driver_url)operator(,) ident(username)operator(,) ident(password)operator(])operator(\)) + reserved(end) + reserved(end) comment(# class Base) + + reserved(module) class(ConnectionAdapters) + reserved(class) class(ColumnWithIdentity) operator(<) constant(Column)comment(# :nodoc:) + ident(attr_reader) symbol(:identity)operator(,) symbol(:is_special)operator(,) symbol(:scale) + + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(default)operator(,) ident(sql_type) operator(=) pre_constant(nil)operator(,) ident(is_identity) operator(=) pre_constant(false)operator(,) ident(null) operator(=) pre_constant(true)operator(,) ident(scale_value) operator(=) integer(0)operator(\)) + reserved(super)operator(()ident(name)operator(,) ident(default)operator(,) ident(sql_type)operator(,) ident(null)operator(\)) + instance_variable(@identity) operator(=) ident(is_identity) + instance_variable(@is_special) operator(=) ident(sql_type) operator(=)operator(~) regexp<delimiter(/)content(text|ntext|image)delimiter(/)modifier(i)> operator(?) pre_constant(true) operator(:) pre_constant(false) + instance_variable(@scale) operator(=) ident(scale_value) + comment(# SQL Server only supports limits on *char and float types) + instance_variable(@limit) operator(=) pre_constant(nil) reserved(unless) instance_variable(@type) operator(==) symbol(:float) reserved(or) instance_variable(@type) operator(==) symbol(:string) + reserved(end) + + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(case) ident(field_type) + reserved(when) regexp<delimiter(/)content(int|bigint|smallint|tinyint)delimiter(/)modifier(i)> reserved(then) symbol(:integer) + reserved(when) regexp<delimiter(/)content(float|double|decimal|money|numeric|real|smallmoney)delimiter(/)modifier(i)> reserved(then) instance_variable(@scale) operator(==) integer(0) operator(?) symbol(:integer) operator(:) symbol(:float) + reserved(when) regexp<delimiter(/)content(datetime|smalldatetime)delimiter(/)modifier(i)> reserved(then) symbol(:datetime) + reserved(when) regexp<delimiter(/)content(timestamp)delimiter(/)modifier(i)> reserved(then) symbol(:timestamp) + reserved(when) regexp<delimiter(/)content(time)delimiter(/)modifier(i)> reserved(then) symbol(:time) + reserved(when) regexp<delimiter(/)content(text|ntext)delimiter(/)modifier(i)> reserved(then) symbol(:text) + reserved(when) regexp<delimiter(/)content(binary|image|varbinary)delimiter(/)modifier(i)> reserved(then) symbol(:binary) + reserved(when) regexp<delimiter(/)content(char|nchar|nvarchar|string|varchar)delimiter(/)modifier(i)> reserved(then) symbol(:string) + reserved(when) regexp<delimiter(/)content(bit)delimiter(/)modifier(i)> reserved(then) symbol(:boolean) + reserved(when) regexp<delimiter(/)content(uniqueidentifier)delimiter(/)modifier(i)> reserved(then) symbol(:string) + reserved(end) + reserved(end) + + reserved(def) method(type_cast)operator(()ident(value)operator(\)) + reserved(return) pre_constant(nil) reserved(if) ident(value)operator(.)ident(nil?) operator(||) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*null)char(\\s)content(*$)delimiter(/)modifier(i)> + reserved(case) ident(type) + reserved(when) symbol(:string) reserved(then) ident(value) + reserved(when) symbol(:integer) reserved(then) ident(value) operator(==) pre_constant(true) operator(||) ident(value) operator(==) pre_constant(false) operator(?) ident(value) operator(==) pre_constant(true) operator(?) integer(1) operator(:) integer(0) operator(:) ident(value)operator(.)ident(to_i) + reserved(when) symbol(:float) reserved(then) ident(value)operator(.)ident(to_f) + reserved(when) symbol(:datetime) reserved(then) ident(cast_to_datetime)operator(()ident(value)operator(\)) + reserved(when) symbol(:timestamp) reserved(then) ident(cast_to_time)operator(()ident(value)operator(\)) + reserved(when) symbol(:time) reserved(then) ident(cast_to_time)operator(()ident(value)operator(\)) + reserved(when) symbol(:date) reserved(then) ident(cast_to_datetime)operator(()ident(value)operator(\)) + reserved(when) symbol(:boolean) reserved(then) ident(value) operator(==) pre_constant(true) reserved(or) operator(()ident(value) operator(=)operator(~) regexp<delimiter(/)content(^t(rue\)?$)delimiter(/)modifier(i)>operator(\)) operator(==) integer(0) reserved(or) ident(value)operator(.)ident(to_s) operator(==) string<delimiter(')content(1)delimiter(')> + reserved(else) ident(value) + reserved(end) + reserved(end) + + reserved(def) method(cast_to_time)operator(()ident(value)operator(\)) + reserved(return) ident(value) reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(Time)operator(\)) + ident(time_array) operator(=) constant(ParseDate)operator(.)ident(parsedate)operator(()ident(value)operator(\)) + ident(time_array)operator([)integer(0)operator(]) operator(||=) integer(2000) + ident(time_array)operator([)integer(1)operator(]) operator(||=) integer(1) + ident(time_array)operator([)integer(2)operator(]) operator(||=) integer(1) + constant(Time)operator(.)ident(send)operator(()constant(Base)operator(.)ident(default_timezone)operator(,) operator(*)ident(time_array)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(cast_to_datetime)operator(()ident(value)operator(\)) + reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(Time)operator(\)) + reserved(if) ident(value)operator(.)ident(year) operator(!=) integer(0) reserved(and) ident(value)operator(.)ident(month) operator(!=) integer(0) reserved(and) ident(value)operator(.)ident(day) operator(!=) integer(0) + reserved(return) ident(value) + reserved(else) + reserved(return) constant(Time)operator(.)ident(mktime)operator(()integer(2000)operator(,) integer(1)operator(,) integer(1)operator(,) ident(value)operator(.)ident(hour)operator(,) ident(value)operator(.)ident(min)operator(,) ident(value)operator(.)ident(sec)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + reserved(return) ident(cast_to_time)operator(()ident(value)operator(\)) reserved(if) ident(value)operator(.)ident(is_a?)operator(()constant(Date)operator(\)) reserved(or) ident(value)operator(.)ident(is_a?)operator(()constant(String)operator(\)) reserved(rescue) pre_constant(nil) + ident(value) + reserved(end) + + comment(# These methods will only allow the adapter to insert binary data with a length of 7K or less) + comment(# because of a SQL Server statement length policy.) + reserved(def) pre_constant(self)operator(.)ident(string_to_binary)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(()char(\\r)content(|)char(\\n)content(|)char(\\0)content(|)char(\\x1a)content(\))delimiter(/)>operator(\)) reserved(do) + reserved(case) global_variable($1) + reserved(when) string<delimiter(")char(\\r)delimiter(")> reserved(then) string<delimiter(")content(%00)delimiter(")> + reserved(when) string<delimiter(")char(\\n)delimiter(")> reserved(then) string<delimiter(")content(%01)delimiter(")> + reserved(when) string<delimiter(")char(\\0)delimiter(")> reserved(then) string<delimiter(")content(%02)delimiter(")> + reserved(when) string<delimiter(")char(\\x1a)delimiter(")> reserved(then) string<delimiter(")content(%03)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(binary_to_string)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(gsub)operator(()regexp<delimiter(/)content((%00|%01|%02|%03\))delimiter(/)>operator(\)) reserved(do) + reserved(case) global_variable($1) + reserved(when) string<delimiter(")content(%00)delimiter(")> reserved(then) string<delimiter(")char(\\r)delimiter(")> + reserved(when) string<delimiter(")content(%01)delimiter(")> reserved(then) string<delimiter(")char(\\n)delimiter(")> + reserved(when) string<delimiter(")content(%02)char(\\0)delimiter(")> reserved(then) string<delimiter(")char(\\0)delimiter(")> + reserved(when) string<delimiter(")content(%03)delimiter(")> reserved(then) string<delimiter(")char(\\x1a)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# In ADO mode, this adapter will ONLY work on Windows systems, ) + comment(# since it relies on Win32OLE, which, to my knowledge, is only ) + comment(# available on Windows.) + comment(#) + comment(# This mode also relies on the ADO support in the DBI module. If you are using the) + comment(# one-click installer of Ruby, then you already have DBI installed, but) + comment(# the ADO module is *NOT* installed. You will need to get the latest) + comment(# source distribution of Ruby-DBI from http://ruby-dbi.sourceforge.net/) + comment(# unzip it, and copy the file ) + comment(# <tt>src/lib/dbd_ado/ADO.rb</tt> ) + comment(# to) + comment(# <tt>X:/Ruby/lib/ruby/site_ruby/1.8/DBD/ADO/ADO.rb</tt> ) + comment(# (you will more than likely need to create the ADO directory\).) + comment(# Once you've installed that file, you are ready to go.) + comment(#) + comment(# In ODBC mode, the adapter requires the ODBC support in the DBI module which requires) + comment(# the Ruby ODBC module. Ruby ODBC 0.996 was used in development and testing,) + comment(# and it is available at http://www.ch-werner.de/rubyodbc/) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:mode</tt> -- ADO or ODBC. Defaults to ADO.) + comment(# * <tt>:username</tt> -- Defaults to sa.) + comment(# * <tt>:password</tt> -- Defaults to empty string.) + comment(#) + comment(# ADO specific options:) + comment(#) + comment(# * <tt>:host</tt> -- Defaults to localhost.) + comment(# * <tt>:database</tt> -- The name of the database. No default, must be provided.) + comment(#) + comment(# ODBC specific options: ) + comment(#) + comment(# * <tt>:dsn</tt> -- Defaults to nothing.) + comment(#) + comment(# ADO code tested on Windows 2000 and higher systems,) + comment(# running ruby 1.8.2 (2004-07-29\) [i386-mswin32], and SQL Server 2000 SP3.) + comment(#) + comment(# ODBC code tested on a Fedora Core 4 system, running FreeTDS 0.63, ) + comment(# unixODBC 2.2.11, Ruby ODBC 0.996, Ruby DBI 0.0.23 and Ruby 1.8.2.) + comment(# [Linux strongmad 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 i686 i386 GNU/Linux]) + reserved(class) class(SQLServerAdapter) operator(<) constant(AbstractAdapter) + + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(logger)operator(,) ident(connection_options)operator(=)pre_constant(nil)operator(\)) + reserved(super)operator(()ident(connection)operator(,) ident(logger)operator(\)) + instance_variable(@connection_options) operator(=) ident(connection_options) + reserved(end) + + reserved(def) method(native_database_types) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(int NOT NULL IDENTITY(1, 1\) PRIMARY KEY)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(varchar)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(text)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(int)delimiter(")> operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(float)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(8) operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(image)delimiter(")>operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(bit)delimiter(")>operator(}) + operator(}) + reserved(end) + + reserved(def) method(adapter_name) + string<delimiter(')content(SQLServer)delimiter(')> + reserved(end) + + reserved(def) method(supports_migrations?) comment(#:nodoc:) + pre_constant(true) + reserved(end) + + comment(# CONNECTION MANAGEMENT ====================================#) + + comment(# Returns true if the connection is active.) + reserved(def) method(active?) + instance_variable(@connection)operator(.)ident(execute)operator(()string<delimiter(")content(SELECT 1)delimiter(")>operator(\)) operator({) operator(}) + pre_constant(true) + reserved(rescue) constant(DBI)operator(::)constant(DatabaseError)operator(,) constant(DBI)operator(::)constant(InterfaceError) + pre_constant(false) + reserved(end) + + comment(# Reconnects to the database, returns false if no connection could be made.) + reserved(def) method(reconnect!) + ident(disconnect!) + instance_variable(@connection) operator(=) constant(DBI)operator(.)ident(connect)operator(()operator(*)instance_variable(@connection_options)operator(\)) + reserved(rescue) constant(DBI)operator(::)constant(DatabaseError) operator(=)operator(>) ident(e) + instance_variable(@logger)operator(.)ident(warn) string<delimiter(")inline<inline_delimiter(#{)ident(adapter_name)inline_delimiter(})>content( reconnection failed: )inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>delimiter(")> reserved(if) instance_variable(@logger) + pre_constant(false) + reserved(end) + + comment(# Disconnects from the database) + + reserved(def) method(disconnect!) + instance_variable(@connection)operator(.)ident(disconnect) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(add_limit!)operator(()ident(sql)operator(,) symbol(:limit) operator(=)operator(>) integer(1)operator(\)) + ident(result) operator(=) ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(result)operator(.)ident(first) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(return) operator([)operator(]) reserved(if) ident(table_name)operator(.)ident(blank?) + ident(table_name) operator(=) ident(table_name)operator(.)ident(to_s) reserved(if) ident(table_name)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + ident(table_name) operator(=) ident(table_name)operator(.)ident(split)operator(()string<delimiter(')content(.)delimiter(')>operator(\))operator([)integer(-1)operator(]) reserved(unless) ident(table_name)operator(.)ident(nil?) + ident(sql) operator(=) string<delimiter(")content(SELECT COLUMN_NAME as ColName, COLUMN_DEFAULT as DefaultValue, DATA_TYPE as ColType, IS_NULLABLE As IsNullable, COL_LENGTH(')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(', COLUMN_NAME\) as Length, COLUMNPROPERTY(OBJECT_ID(')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content('\), COLUMN_NAME, 'IsIdentity'\) as IsIdentity, NUMERIC_SCALE as Scale FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(')delimiter(")> + comment(# Comment out if you want to have the Columns select statment logged.) + comment(# Personally, I think it adds unnecessary bloat to the log. ) + comment(# If you do comment it out, make sure to un-comment the "result" line that follows) + ident(result) operator(=) ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(select_all)operator(()ident(sql)operator(\)) operator(}) + comment(#result = @connection.select_all(sql\)) + ident(columns) operator(=) operator([)operator(]) + ident(result)operator(.)ident(each) reserved(do) operator(|)ident(field)operator(|) + ident(default) operator(=) ident(field)operator([)symbol(:DefaultValue)operator(])operator(.)ident(to_s)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content([(\))char(\\')content(])delimiter(/)>operator(,)string<delimiter(")delimiter(")>operator(\)) operator(=)operator(~) regexp<delimiter(/)content(null)delimiter(/)> operator(?) pre_constant(nil) operator(:) ident(field)operator([)symbol(:DefaultValue)operator(]) + ident(type) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(field)operator([)symbol(:ColType)operator(])inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(field)operator([)symbol(:Length)operator(])inline_delimiter(})>content(\))delimiter(")> + ident(is_identity) operator(=) ident(field)operator([)symbol(:IsIdentity)operator(]) operator(==) integer(1) + ident(is_nullable) operator(=) ident(field)operator([)symbol(:IsNullable)operator(]) operator(==) string<delimiter(')content(YES)delimiter(')> + ident(columns) operator(<<) constant(ColumnWithIdentity)operator(.)ident(new)operator(()ident(field)operator([)symbol(:ColName)operator(])operator(,) ident(default)operator(,) ident(type)operator(,) ident(is_identity)operator(,) ident(is_nullable)operator(,) ident(field)operator([)symbol(:Scale)operator(])operator(\)) + reserved(end) + ident(columns) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) + reserved(begin) + ident(table_name) operator(=) ident(get_table_name)operator(()ident(sql)operator(\)) + ident(col) operator(=) ident(get_identity_column)operator(()ident(table_name)operator(\)) + ident(ii_enabled) operator(=) pre_constant(false) + + reserved(if) ident(col) operator(!=) pre_constant(nil) + reserved(if) ident(query_contains_identity_column)operator(()ident(sql)operator(,) ident(col)operator(\)) + reserved(begin) + ident(execute) ident(enable_identity_insert)operator(()ident(table_name)operator(,) pre_constant(true)operator(\)) + ident(ii_enabled) operator(=) pre_constant(true) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")content(IDENTITY_INSERT could not be turned ON)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + instance_variable(@connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) + ident(id_value) operator(||) ident(select_one)operator(()string<delimiter(")content(SELECT @@IDENTITY AS Ident)delimiter(")>operator(\))operator([)string<delimiter(")content(Ident)delimiter(")>operator(]) + reserved(end) + reserved(ensure) + reserved(if) ident(ii_enabled) + reserved(begin) + ident(execute) ident(enable_identity_insert)operator(()ident(table_name)operator(,) pre_constant(false)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")content(IDENTITY_INSERT could not be turned OFF)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*INSERT)delimiter(/)modifier(i)> + ident(insert)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(elsif) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*UPDATE|^)char(\\s)content(*DELETE)delimiter(/)modifier(i)> + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + instance_variable(@connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) + ident(retVal) operator(=) ident(select_one)operator(()string<delimiter(")content(SELECT @@ROWCOUNT AS AffectedRows)delimiter(")>operator(\))operator([)string<delimiter(")content(AffectedRows)delimiter(")>operator(]) + reserved(end) + reserved(else) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) operator({) instance_variable(@connection)operator(.)ident(execute)operator(()ident(sql)operator(\)) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + ident(alias_method) symbol(:delete)operator(,) symbol(:update) + + reserved(def) method(begin_db_transaction) + instance_variable(@connection)operator([)string<delimiter(")content(AutoCommit)delimiter(")>operator(]) operator(=) pre_constant(false) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + instance_variable(@connection)operator([)string<delimiter(")content(AutoCommit)delimiter(")>operator(]) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(commit_db_transaction) + instance_variable(@connection)operator(.)ident(commit) + reserved(ensure) + instance_variable(@connection)operator([)string<delimiter(")content(AutoCommit)delimiter(")>operator(]) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(rollback_db_transaction) + instance_variable(@connection)operator(.)ident(rollback) + reserved(ensure) + instance_variable(@connection)operator([)string<delimiter(")content(AutoCommit)delimiter(")>operator(]) operator(=) pre_constant(true) + reserved(end) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + reserved(case) ident(value) + reserved(when) constant(String) + reserved(if) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) operator(&&) ident(column)operator(.)ident(class)operator(.)ident(respond_to?)operator(()symbol(:string_to_binary)operator(\)) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(column)operator(.)ident(class)operator(.)ident(string_to_binary)operator(()ident(value)operator(\))operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(when) constant(NilClass) reserved(then) string<delimiter(")content(NULL)delimiter(")> + reserved(when) constant(TrueClass) reserved(then) string<delimiter(')content(1)delimiter(')> + reserved(when) constant(FalseClass) reserved(then) string<delimiter(')content(0)delimiter(')> + reserved(when) constant(Float)operator(,) constant(Fixnum)operator(,) constant(Bignum) reserved(then) ident(value)operator(.)ident(to_s) + reserved(when) constant(Date) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(to_s)inline_delimiter(})>content(')delimiter(")> + reserved(when) constant(Time)operator(,) constant(DateTime) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_yaml)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(quote_string)operator(()ident(string)operator(\)) + ident(string)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\')delimiter(/)>operator(,) string<delimiter(")content('')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(quoted_true) + string<delimiter(")content(1)delimiter(")> + reserved(end) + + reserved(def) method(quoted_false) + string<delimiter(")content(0)delimiter(")> + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) + string<delimiter(")content([)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(])delimiter(")> + reserved(end) + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) + reserved(if) ident(options)operator([)symbol(:limit)operator(]) reserved(and) ident(options)operator([)symbol(:offset)operator(]) + ident(total_rows) operator(=) instance_variable(@connection)operator(.)ident(select_all)operator(()string<delimiter(")content(SELECT count(*\) as TotalRows from ()inline<inline_delimiter(#{)ident(sql)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\b)content(SELECT)char(\\b)delimiter(/)modifier(i)>operator(,) string<delimiter(")content(SELECT TOP 1000000000)delimiter(")>operator(\))inline_delimiter(})>content(\) tally)delimiter(")>operator(\))operator([)integer(0)operator(])operator([)symbol(:TotalRows)operator(])operator(.)ident(to_i) + reserved(if) operator(()ident(options)operator([)symbol(:limit)operator(]) operator(+) ident(options)operator([)symbol(:offset)operator(])operator(\)) operator(>)operator(=) ident(total_rows) + ident(options)operator([)symbol(:limit)operator(]) operator(=) operator(()ident(total_rows) operator(-) ident(options)operator([)symbol(:offset)operator(]) operator(>)operator(=) integer(0)operator(\)) operator(?) operator(()ident(total_rows) operator(-) ident(options)operator([)symbol(:offset)operator(])operator(\)) operator(:) integer(0) + reserved(end) + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^)char(\\s)content(*SELECT)delimiter(/)modifier(i)>operator(,) string<delimiter(")content(SELECT * FROM (SELECT TOP )inline<inline_delimiter(#{)ident(options)operator([)symbol(:limit)operator(])inline_delimiter(})>content( * FROM (SELECT TOP )inline<inline_delimiter(#{)ident(options)operator([)symbol(:limit)operator(]) operator(+) ident(options)operator([)symbol(:offset)operator(])inline_delimiter(})>content( )delimiter(")>operator(\)) + ident(sql) operator(<<) string<delimiter(")content(\) AS tmp1)delimiter(")> + reserved(if) ident(options)operator([)symbol(:order)operator(]) + ident(options)operator([)symbol(:order)operator(]) operator(=) ident(options)operator([)symbol(:order)operator(])operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\))operator(.)ident(map) reserved(do) operator(|)ident(field)operator(|) + ident(parts) operator(=) ident(field)operator(.)ident(split)operator(()string<delimiter(")content( )delimiter(")>operator(\)) + ident(tc) operator(=) ident(parts)operator([)integer(0)operator(]) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)char(\\.)char(\\[)delimiter(/)> reserved(and) ident(tc) operator(=)operator(~) regexp<delimiter(/)char(\\.)delimiter(/)> comment(# if column quoting used in query) + ident(tc)operator(.)ident(gsub!)operator(()regexp<delimiter(/)char(\\.)delimiter(/)>operator(,) string<delimiter(')char(\\\\)content(.)char(\\\\)content([)delimiter(')>operator(\)) + ident(tc) operator(<<) string<delimiter(')char(\\\\)content(])delimiter(')> + reserved(end) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)inline<inline_delimiter(#{)ident(tc)inline_delimiter(})>content( AS (t)char(\\d)content(_r)char(\\d)char(\\d)content(?\))delimiter(/)> + ident(parts)operator([)integer(0)operator(]) operator(=) global_variable($1) + reserved(end) + ident(parts)operator(.)ident(join)operator(()string<delimiter(')content( )delimiter(')>operator(\)) + reserved(end)operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\)) + ident(sql) operator(<<) string<delimiter(")content( ORDER BY )inline<inline_delimiter(#{)ident(change_order_direction)operator(()ident(options)operator([)symbol(:order)operator(])operator(\))inline_delimiter(})>content(\) AS tmp2 ORDER BY )inline<inline_delimiter(#{)ident(options)operator([)symbol(:order)operator(])inline_delimiter(})>delimiter(")> + reserved(else) + ident(sql) operator(<<) string<delimiter(")content( \) AS tmp2)delimiter(")> + reserved(end) + reserved(elsif) ident(sql) operator(!)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*SELECT (@@|COUNT)char(\\()content(\))delimiter(/)modifier(i)> + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(^)char(\\s)content(*SELECT([)char(\\s)content(]*distinct\)?)delimiter(/)modifier(i)>operator(\)) reserved(do) + string<delimiter(")content(SELECT)inline<inline_delimiter(#{)global_variable($1)inline_delimiter(})>content( TOP )inline<inline_delimiter(#{)ident(options)operator([)symbol(:limit)operator(])inline_delimiter(})>delimiter(")> + reserved(end) reserved(unless) ident(options)operator([)symbol(:limit)operator(])operator(.)ident(nil?) + reserved(end) + reserved(end) + + reserved(def) method(recreate_database)operator(()ident(name)operator(\)) + ident(drop_database)operator(()ident(name)operator(\)) + ident(create_database)operator(()ident(name)operator(\)) + reserved(end) + + reserved(def) method(drop_database)operator(()ident(name)operator(\)) + ident(execute) string<delimiter(")content(DROP DATABASE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(create_database)operator(()ident(name)operator(\)) + ident(execute) string<delimiter(")content(CREATE DATABASE )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(current_database) + instance_variable(@connection)operator(.)ident(select_one)operator(()string<delimiter(")content(select DB_NAME(\))delimiter(")>operator(\))operator([)integer(0)operator(]) + reserved(end) + + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + ident(execute)operator(()string<delimiter(")content(SELECT table_name from information_schema.tables WHERE table_type = 'BASE TABLE')delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(tables)operator(,) ident(field)operator(|) + ident(table_name) operator(=) ident(field)operator([)integer(0)operator(]) + ident(tables) operator(<<) ident(table_name) reserved(unless) ident(table_name) operator(==) string<delimiter(')content(dtproperties)delimiter(')> + ident(tables) + reserved(end) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(indexes) operator(=) operator([)operator(]) + ident(execute)operator(()string<delimiter(")content(EXEC sp_helpindex )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(index)operator(|) + ident(unique) operator(=) ident(index)operator([)integer(1)operator(]) operator(=)operator(~) regexp<delimiter(/)content(unique)delimiter(/)> + ident(primary) operator(=) ident(index)operator([)integer(1)operator(]) operator(=)operator(~) regexp<delimiter(/)content(primary key)delimiter(/)> + reserved(if) operator(!)ident(primary) + ident(indexes) operator(<<) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,) ident(index)operator([)integer(0)operator(])operator(,) ident(unique)operator(,) ident(index)operator([)integer(2)operator(])operator(.)ident(split)operator(()string<delimiter(")content(, )delimiter(")>operator(\))operator(\)) + reserved(end) + reserved(end) + ident(indexes) + reserved(end) + + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + ident(execute) string<delimiter(")content(EXEC sp_rename ')inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(', ')inline<inline_delimiter(#{)ident(new_name)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(def) method(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(rename_column)operator(()ident(table)operator(,) ident(column)operator(,) ident(new_column_name)operator(\)) + ident(execute) string<delimiter(")content(EXEC sp_rename ')inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(column)inline_delimiter(})>content(', ')inline<inline_delimiter(#{)ident(new_column_name)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(sql_commands) operator(=) operator([)string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ALTER COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")>operator(]) + reserved(if) ident(options)operator([)symbol(:default)operator(]) + ident(remove_default_constraint)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(sql_commands) operator(<<) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ADD CONSTRAINT DF_)inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( DEFAULT )inline<inline_delimiter(#{)ident(options)operator([)symbol(:default)operator(])inline_delimiter(})>content( FOR )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>delimiter(")> + reserved(end) + ident(sql_commands)operator(.)ident(each) operator({)operator(|)ident(c)operator(|) + ident(execute)operator(()ident(c)operator(\)) + operator(}) + reserved(end) + + reserved(def) method(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(remove_default_constraint)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP COLUMN )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(remove_default_constraint)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(defaults) operator(=) ident(select) string<delimiter(")content(select def.name from sysobjects def, syscolumns col, sysobjects tab where col.cdefault = def.id and col.name = ')inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(' and tab.name = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' and col.id = tab.id)delimiter(")> + ident(defaults)operator(.)ident(each) operator({)operator(|)ident(constraint)operator(|) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP CONSTRAINT )inline<inline_delimiter(#{)ident(constraint)operator([)string<delimiter(")content(name)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + operator(}) + reserved(end) + + reserved(def) method(remove_index)operator(()ident(table_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(execute) string<delimiter(")content(DROP INDEX )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(type_to_sql)operator(()ident(type)operator(,) ident(limit) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + ident(native) operator(=) ident(native_database_types)operator([)ident(type)operator(]) + comment(# if there's no :limit in the default type definition, assume that type doesn't support limits) + ident(limit) operator(=) ident(limit) operator(||) ident(native)operator([)symbol(:limit)operator(]) + ident(column_type_sql) operator(=) ident(native)operator([)symbol(:name)operator(]) + ident(column_type_sql) operator(<<) string<delimiter(")content(()inline<inline_delimiter(#{)ident(limit)inline_delimiter(})>content(\))delimiter(")> reserved(if) ident(limit) + ident(column_type_sql) + reserved(end) + + ident(private) + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(rows) operator(=) operator([)operator(]) + ident(repair_special_columns)operator(()ident(sql)operator(\)) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + instance_variable(@connection)operator(.)ident(select_all)operator(()ident(sql)operator(\)) reserved(do) operator(|)ident(row)operator(|) + ident(record) operator(=) operator({)operator(}) + ident(row)operator(.)ident(column_names)operator(.)ident(each) reserved(do) operator(|)ident(col)operator(|) + ident(record)operator([)ident(col)operator(]) operator(=) ident(row)operator([)ident(col)operator(]) + ident(record)operator([)ident(col)operator(]) operator(=) ident(record)operator([)ident(col)operator(])operator(.)ident(to_time) reserved(if) ident(record)operator([)ident(col)operator(])operator(.)ident(is_a?) constant(DBI)operator(::)constant(Timestamp) + reserved(end) + ident(rows) operator(<<) ident(record) + reserved(end) + reserved(end) + ident(rows) + reserved(end) + + reserved(def) method(enable_identity_insert)operator(()ident(table_name)operator(,) ident(enable) operator(=) pre_constant(true)operator(\)) + reserved(if) ident(has_identity_column)operator(()ident(table_name)operator(\)) + string<delimiter(")content(SET IDENTITY_INSERT )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(enable) operator(?) string<delimiter(')content(ON)delimiter(')> operator(:) string<delimiter(')content(OFF)delimiter(')>inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(get_table_name)operator(()ident(sql)operator(\)) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*insert)char(\\s)content(+into)char(\\s)content(+([^)char(\\()char(\\s)content(]+\))char(\\s)content(*|^)char(\\s)content(*update)char(\\s)content(+([^)char(\\()char(\\s)content(]+\))char(\\s)content(*)delimiter(/)modifier(i)> + global_variable($1) + reserved(elsif) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(from)char(\\s)content(+([^)char(\\()char(\\s)content(]+\))char(\\s)content(*)delimiter(/)modifier(i)> + global_variable($1) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(has_identity_column)operator(()ident(table_name)operator(\)) + operator(!)ident(get_identity_column)operator(()ident(table_name)operator(\))operator(.)ident(nil?) + reserved(end) + + reserved(def) method(get_identity_column)operator(()ident(table_name)operator(\)) + instance_variable(@table_columns) operator(=) operator({)operator(}) reserved(unless) instance_variable(@table_columns) + instance_variable(@table_columns)operator([)ident(table_name)operator(]) operator(=) ident(columns)operator(()ident(table_name)operator(\)) reserved(if) instance_variable(@table_columns)operator([)ident(table_name)operator(]) operator(==) pre_constant(nil) + instance_variable(@table_columns)operator([)ident(table_name)operator(])operator(.)ident(each) reserved(do) operator(|)ident(col)operator(|) + reserved(return) ident(col)operator(.)ident(name) reserved(if) ident(col)operator(.)ident(identity) + reserved(end) + + reserved(return) pre_constant(nil) + reserved(end) + + reserved(def) method(query_contains_identity_column)operator(()ident(sql)operator(,) ident(col)operator(\)) + ident(sql) operator(=)operator(~) regexp<delimiter(/)char(\\[)inline<inline_delimiter(#{)ident(col)inline_delimiter(})>char(\\])delimiter(/)> + reserved(end) + + reserved(def) method(change_order_direction)operator(()ident(order)operator(\)) + ident(order)operator(.)ident(split)operator(()string<delimiter(")content(,)delimiter(")>operator(\))operator(.)ident(collect) operator({)operator(|)ident(fragment)operator(|) + reserved(case) ident(fragment) + reserved(when) regexp<delimiter(/)char(\\b)content(DESC)char(\\b)delimiter(/)modifier(i)> reserved(then) ident(fragment)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\b)content(DESC)char(\\b)delimiter(/)modifier(i)>operator(,) string<delimiter(")content(ASC)delimiter(")>operator(\)) + reserved(when) regexp<delimiter(/)char(\\b)content(ASC)char(\\b)delimiter(/)modifier(i)> reserved(then) ident(fragment)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\b)content(ASC)char(\\b)delimiter(/)modifier(i)>operator(,) string<delimiter(")content(DESC)delimiter(")>operator(\)) + reserved(else) constant(String)operator(.)ident(new)operator(()ident(fragment)operator(\))operator(.)ident(split)operator(()string<delimiter(')content(,)delimiter(')>operator(\))operator(.)ident(join)operator(()string<delimiter(')content( DESC,)delimiter(')>operator(\)) operator(+) string<delimiter(')content( DESC)delimiter(')> + reserved(end) + operator(})operator(.)ident(join)operator(()string<delimiter(")content(,)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(get_special_columns)operator(()ident(table_name)operator(\)) + ident(special) operator(=) operator([)operator(]) + instance_variable(@table_columns) operator(||=) operator({)operator(}) + instance_variable(@table_columns)operator([)ident(table_name)operator(]) operator(||=) ident(columns)operator(()ident(table_name)operator(\)) + instance_variable(@table_columns)operator([)ident(table_name)operator(])operator(.)ident(each) reserved(do) operator(|)ident(col)operator(|) + ident(special) operator(<<) ident(col)operator(.)ident(name) reserved(if) ident(col)operator(.)ident(is_special) + reserved(end) + ident(special) + reserved(end) + + reserved(def) method(repair_special_columns)operator(()ident(sql)operator(\)) + ident(special_cols) operator(=) ident(get_special_columns)operator(()ident(get_table_name)operator(()ident(sql)operator(\))operator(\)) + reserved(for) ident(col) reserved(in) ident(special_cols)operator(.)ident(to_a) + ident(sql)operator(.)ident(gsub!)operator(()constant(Regexp)operator(.)ident(new)operator(()string<delimiter(")content( )inline<inline_delimiter(#{)ident(col)operator(.)ident(to_s)inline_delimiter(})>content( = )delimiter(")>operator(\))operator(,) string<delimiter(")content( )inline<inline_delimiter(#{)ident(col)operator(.)ident(to_s)inline_delimiter(})>content( LIKE )delimiter(")>operator(\)) + ident(sql)operator(.)ident(gsub!)operator(()regexp<delimiter(/)content(ORDER BY )inline<inline_delimiter(#{)ident(col)operator(.)ident(to_s)inline_delimiter(})>delimiter(/)modifier(i)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + ident(sql) + reserved(end) + + reserved(end) comment(#class SQLServerAdapter < AbstractAdapter) + reserved(end) comment(#module ConnectionAdapters) +reserved(end) comment(#module ActiveRecord) +comment(# sybase_adaptor.rb) +comment(# Author: John Sheets <dev@metacasa.net>) +comment(# Date: 01 Mar 2006) +comment(#) +comment(# Based on code from Will Sobel (http://dev.rubyonrails.org/ticket/2030\)) +comment(#) +comment(# 17 Mar 2006: Added support for migrations; fixed issues with :boolean columns.) +comment(#) + +ident(require) string<delimiter(')content(active_record/connection_adapters/abstract_adapter)delimiter(')> + +reserved(begin) +ident(require) string<delimiter(')content(sybsql)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + comment(# Establishes a connection to the database that's used by all Active Record objects) + reserved(def) pre_constant(self)operator(.)ident(sybase_connection)operator(()ident(config)operator(\)) comment(# :nodoc:) + ident(config) operator(=) ident(config)operator(.)ident(symbolize_keys) + + ident(username) operator(=) ident(config)operator([)symbol(:username)operator(]) operator(?) ident(config)operator([)symbol(:username)operator(])operator(.)ident(to_s) operator(:) string<delimiter(')content(sa)delimiter(')> + ident(password) operator(=) ident(config)operator([)symbol(:password)operator(]) operator(?) ident(config)operator([)symbol(:password)operator(])operator(.)ident(to_s) operator(:) string<delimiter(')delimiter(')> + + reserved(if) ident(config)operator(.)ident(has_key?)operator(()symbol(:host)operator(\)) + ident(host) operator(=) ident(config)operator([)symbol(:host)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database server name specified. Missing argument: host.)delimiter(")> + reserved(end) + + reserved(if) ident(config)operator(.)ident(has_key?)operator(()symbol(:database)operator(\)) + ident(database) operator(=) ident(config)operator([)symbol(:database)operator(]) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(No database specified. Missing argument: database.)delimiter(")> + reserved(end) + + constant(ConnectionAdapters)operator(::)constant(SybaseAdapter)operator(.)ident(new)operator(() + constant(SybSQL)operator(.)ident(new)operator(()operator({)string<delimiter(')content(S)delimiter(')> operator(=)operator(>) ident(host)operator(,) string<delimiter(')content(U)delimiter(')> operator(=)operator(>) ident(username)operator(,) string<delimiter(')content(P)delimiter(')> operator(=)operator(>) ident(password)operator(})operator(,) + constant(ConnectionAdapters)operator(::)constant(SybaseAdapterContext)operator(\))operator(,) ident(database)operator(,) ident(logger)operator(\)) + reserved(end) + reserved(end) comment(# class Base) + + reserved(module) class(ConnectionAdapters) + + comment(# ActiveRecord connection adapter for Sybase Open Client bindings) + comment(# (see http://raa.ruby-lang.org/project/sybase-ctlib\).) + comment(#) + comment(# Options:) + comment(#) + comment(# * <tt>:host</tt> -- The name of the database server. No default, must be provided.) + comment(# * <tt>:database</tt> -- The name of the database. No default, must be provided.) + comment(# * <tt>:username</tt> -- Defaults to sa.) + comment(# * <tt>:password</tt> -- Defaults to empty string.) + comment(#) + comment(# Usage Notes:) + comment(#) + comment(# * The sybase-ctlib bindings do not support the DATE SQL column type; use DATETIME instead.) + comment(# * Table and column names are limited to 30 chars in Sybase 12.5) + comment(# * :binary columns not yet supported) + comment(# * :boolean columns use the BIT SQL type, which does not allow nulls or ) + comment(# indexes. If a DEFAULT is not specified for ALTER TABLE commands, the) + comment(# column will be declared with DEFAULT 0 (false\).) + comment(#) + comment(# Migrations:) + comment(#) + comment(# The Sybase adapter supports migrations, but for ALTER TABLE commands to) + comment(# work, the database must have the database option 'select into' set to) + comment(# 'true' with sp_dboption (see below\). The sp_helpdb command lists the current) + comment(# options for all databases.) + comment(#) + comment(# 1> use mydb) + comment(# 2> go) + comment(# 1> master..sp_dboption mydb, "select into", true) + comment(# 2> go) + comment(# 1> checkpoint) + comment(# 2> go) + reserved(class) class(SybaseAdapter) operator(<) constant(AbstractAdapter) comment(# :nodoc:) + reserved(class) class(ColumnWithIdentity) operator(<) constant(Column) + ident(attr_reader) symbol(:identity)operator(,) symbol(:primary) + + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(default)operator(,) ident(sql_type) operator(=) pre_constant(nil)operator(,) ident(nullable) operator(=) pre_constant(nil)operator(,) ident(identity) operator(=) pre_constant(nil)operator(,) ident(primary) operator(=) pre_constant(nil)operator(\)) + reserved(super)operator(()ident(name)operator(,) ident(default)operator(,) ident(sql_type)operator(,) ident(nullable)operator(\)) + instance_variable(@default)operator(,) instance_variable(@identity)operator(,) instance_variable(@primary) operator(=) ident(type_cast)operator(()ident(default)operator(\))operator(,) ident(identity)operator(,) ident(primary) + reserved(end) + + reserved(def) method(simplified_type)operator(()ident(field_type)operator(\)) + reserved(case) ident(field_type) + reserved(when) regexp<delimiter(/)content(int|bigint|smallint|tinyint)delimiter(/)modifier(i)> reserved(then) symbol(:integer) + reserved(when) regexp<delimiter(/)content(float|double|decimal|money|numeric|real|smallmoney)delimiter(/)modifier(i)> reserved(then) symbol(:float) + reserved(when) regexp<delimiter(/)content(text|ntext)delimiter(/)modifier(i)> reserved(then) symbol(:text) + reserved(when) regexp<delimiter(/)content(binary|image|varbinary)delimiter(/)modifier(i)> reserved(then) symbol(:binary) + reserved(when) regexp<delimiter(/)content(char|nchar|nvarchar|string|varchar)delimiter(/)modifier(i)> reserved(then) symbol(:string) + reserved(when) regexp<delimiter(/)content(bit)delimiter(/)modifier(i)> reserved(then) symbol(:boolean) + reserved(when) regexp<delimiter(/)content(datetime|smalldatetime)delimiter(/)modifier(i)> reserved(then) symbol(:datetime) + reserved(else) reserved(super) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(string_to_binary)operator(()ident(value)operator(\)) + string<delimiter(")content(0x)inline<inline_delimiter(#{)ident(value)operator(.)ident(unpack)operator(()string<delimiter(")content(H*)delimiter(")>operator(\))operator([)integer(0)operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(binary_to_string)operator(()ident(value)operator(\)) + comment(# FIXME: sybase-ctlib uses separate sql method for binary columns.) + ident(value) + reserved(end) + reserved(end) comment(# class ColumnWithIdentity) + + comment(# Sybase adapter) + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(database)operator(,) ident(logger) operator(=) pre_constant(nil)operator(\)) + reserved(super)operator(()ident(connection)operator(,) ident(logger)operator(\)) + ident(context) operator(=) ident(connection)operator(.)ident(context) + ident(context)operator(.)ident(init)operator(()ident(logger)operator(\)) + instance_variable(@limit) operator(=) instance_variable(@offset) operator(=) integer(0) + reserved(unless) ident(connection)operator(.)ident(sql_norow)operator(()string<delimiter(")content(USE )inline<inline_delimiter(#{)ident(database)inline_delimiter(})>delimiter(")>operator(\)) + ident(raise) string<delimiter(")content(Cannot USE )inline<inline_delimiter(#{)ident(database)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(native_database_types) + operator({) + symbol(:primary_key) operator(=)operator(>) string<delimiter(")content(numeric(9,0\) IDENTITY PRIMARY KEY)delimiter(")>operator(,) + symbol(:string) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(varchar)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(255) operator(})operator(,) + symbol(:text) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(text)delimiter(")> operator(})operator(,) + symbol(:integer) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(int)delimiter(")> operator(})operator(,) + symbol(:float) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(float)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(8) operator(})operator(,) + symbol(:datetime) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:timestamp) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(timestamp)delimiter(")> operator(})operator(,) + symbol(:time) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(time)delimiter(")> operator(})operator(,) + symbol(:date) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")> operator(})operator(,) + symbol(:binary) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(image)delimiter(")>operator(})operator(,) + symbol(:boolean) operator(=)operator(>) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(bit)delimiter(")> operator(}) + operator(}) + reserved(end) + + reserved(def) method(adapter_name) + string<delimiter(')content(Sybase)delimiter(')> + reserved(end) + + reserved(def) method(active?) + operator(!)operator(()instance_variable(@connection)operator(.)ident(connection)operator(.)ident(nil?) operator(||) instance_variable(@connection)operator(.)ident(connection_dead?)operator(\)) + reserved(end) + + reserved(def) method(disconnect!) + instance_variable(@connection)operator(.)ident(close) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(reconnect!) + ident(raise) string<delimiter(")content(Sybase Connection Adapter does not yet support reconnect!)delimiter(")> + comment(# disconnect!) + comment(# connect! # Not yet implemented) + reserved(end) + + reserved(def) method(table_alias_length) + integer(30) + reserved(end) + + comment(# Check for a limit statement and parse out the limit and) + comment(# offset if specified. Remove the limit from the sql statement) + comment(# and call select.) + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + comment(# Remove limit clause from statement. This will almost always) + comment(# contain LIMIT 1 from the caller. set the rowcount to 1 before) + comment(# calling select.) + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(result) operator(=) ident(select)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(result)operator(.)ident(nil?) operator(?) pre_constant(nil) operator(:) ident(result)operator(.)ident(first) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(table_structure)operator(()ident(table_name)operator(\))operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(columns)operator(,) ident(column)operator(|) + ident(name)operator(,) ident(default)operator(,) ident(type)operator(,) ident(nullable)operator(,) ident(identity)operator(,) ident(primary) operator(=) ident(column) + ident(columns) operator(<<) constant(ColumnWithIdentity)operator(.)ident(new)operator(()ident(name)operator(,) ident(default)operator(,) ident(type)operator(,) ident(nullable)operator(,) ident(identity)operator(,) ident(primary)operator(\)) + ident(columns) + reserved(end) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(,) ident(sequence_name) operator(=) pre_constant(nil)operator(\)) + reserved(begin) + ident(table_name) operator(=) ident(get_table_name)operator(()ident(sql)operator(\)) + ident(col) operator(=) ident(get_identity_column)operator(()ident(table_name)operator(\)) + ident(ii_enabled) operator(=) pre_constant(false) + + reserved(if) ident(col) operator(!=) pre_constant(nil) + reserved(if) ident(query_contains_identity_column)operator(()ident(sql)operator(,) ident(col)operator(\)) + reserved(begin) + ident(execute) ident(enable_identity_insert)operator(()ident(table_name)operator(,) pre_constant(true)operator(\)) + ident(ii_enabled) operator(=) pre_constant(true) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")content(IDENTITY_INSERT could not be turned ON)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + ident(execute)operator(()ident(sql)operator(,) ident(name)operator(\)) + ident(ident) operator(=) ident(select_one)operator(()string<delimiter(")content(SELECT @@IDENTITY AS last_id)delimiter(")>operator(\))operator([)string<delimiter(")content(last_id)delimiter(")>operator(]) + ident(id_value) operator(||) ident(ident) + reserved(end) + reserved(ensure) + reserved(if) ident(ii_enabled) + reserved(begin) + ident(execute) ident(enable_identity_insert)operator(()ident(table_name)operator(,) pre_constant(false)operator(\)) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(raise) constant(ActiveRecordError)operator(,) string<delimiter(")content(IDENTITY_INSERT could not be turned OFF)delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + instance_variable(@connection)operator(.)ident(context)operator(.)ident(reset) + instance_variable(@connection)operator(.)ident(set_rowcount)operator(()instance_variable(@limit) operator(||) integer(0)operator(\)) + instance_variable(@limit) operator(=) instance_variable(@offset) operator(=) pre_constant(nil) + instance_variable(@connection)operator(.)ident(sql_norow)operator(()ident(sql)operator(\)) + reserved(if) instance_variable(@connection)operator(.)ident(cmd_fail?) reserved(or) instance_variable(@connection)operator(.)ident(context)operator(.)ident(failed?) + ident(raise) string<delimiter(")content(SQL Command Failed for )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(sql)inline_delimiter(})>char(\\n)content(Message: )inline<inline_delimiter(#{)instance_variable(@connection)operator(.)ident(context)operator(.)ident(message)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + comment(# Return rows affected) + instance_variable(@connection)operator(.)ident(results)operator([)integer(0)operator(])operator(.)ident(row_count) + reserved(end) + + ident(alias_method) symbol(:update)operator(,) symbol(:execute) + ident(alias_method) symbol(:delete)operator(,) symbol(:execute) + + reserved(def) method(begin_db_transaction)operator(()operator(\)) ident(execute) string<delimiter(")content(BEGIN TRAN)delimiter(")> reserved(end) + reserved(def) method(commit_db_transaction)operator(()operator(\)) ident(execute) string<delimiter(")content(COMMIT TRAN)delimiter(")> reserved(end) + reserved(def) method(rollback_db_transaction)operator(()operator(\)) ident(execute) string<delimiter(")content(ROLLBACK TRAN)delimiter(")> reserved(end) + + reserved(def) method(tables)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + ident(tables) operator(=) operator([)operator(]) + ident(select)operator(()string<delimiter(")content(select name from sysobjects where type='U')delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(tables) operator(<<) ident(row)operator([)string<delimiter(')content(name)delimiter(')>operator(]) + reserved(end) + ident(tables) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(indexes) operator(=) operator([)operator(]) + ident(select)operator(()string<delimiter(")content(exec sp_helpindex )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")>operator(,) ident(name)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(index)operator(|) + ident(unique) operator(=) ident(index)operator([)string<delimiter(")content(index_description)delimiter(")>operator(]) operator(=)operator(~) regexp<delimiter(/)content(unique)delimiter(/)> + ident(primary) operator(=) ident(index)operator([)string<delimiter(")content(index_description)delimiter(")>operator(]) operator(=)operator(~) regexp<delimiter(/)content(^clustered)delimiter(/)> + reserved(if) operator(!)ident(primary) + ident(cols) operator(=) ident(index)operator([)string<delimiter(")content(index_keys)delimiter(")>operator(])operator(.)ident(split)operator(()string<delimiter(")content(, )delimiter(")>operator(\))operator(.)ident(each) operator({) operator(|)ident(col)operator(|) ident(col)operator(.)ident(strip!) operator(}) + ident(indexes) operator(<<) constant(IndexDefinition)operator(.)ident(new)operator(()ident(table_name)operator(,) ident(index)operator([)string<delimiter(")content(index_name)delimiter(")>operator(])operator(,) ident(unique)operator(,) ident(cols)operator(\)) + reserved(end) + reserved(end) + ident(indexes) + reserved(end) + + reserved(def) method(quoted_true) + string<delimiter(")content(1)delimiter(")> + reserved(end) + + reserved(def) method(quoted_false) + string<delimiter(")content(0)delimiter(")> + reserved(end) + + reserved(def) method(quote)operator(()ident(value)operator(,) ident(column) operator(=) pre_constant(nil)operator(\)) + reserved(case) ident(value) + reserved(when) constant(String) + reserved(if) ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:binary) operator(&&) ident(column)operator(.)ident(class)operator(.)ident(respond_to?)operator(()symbol(:string_to_binary)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(quote_string)operator(()ident(column)operator(.)ident(class)operator(.)ident(string_to_binary)operator(()ident(value)operator(\))operator(\))inline_delimiter(})>delimiter(")> + reserved(elsif) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^[+-]?[0-9]+$)delimiter(/)modifier(o)> + ident(value) + reserved(else) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(when) constant(NilClass) reserved(then) operator(()ident(column) operator(&&) ident(column)operator(.)ident(type) operator(==) symbol(:boolean)operator(\)) operator(?) string<delimiter(')content(0)delimiter(')> operator(:) string<delimiter(")content(NULL)delimiter(")> + reserved(when) constant(TrueClass) reserved(then) string<delimiter(')content(1)delimiter(')> + reserved(when) constant(FalseClass) reserved(then) string<delimiter(')content(0)delimiter(')> + reserved(when) constant(Float)operator(,) constant(Fixnum)operator(,) constant(Bignum) reserved(then) ident(value)operator(.)ident(to_s) + reserved(when) constant(Date) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(to_s)inline_delimiter(})>content(')delimiter(")> + reserved(when) constant(Time)operator(,) constant(DateTime) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_yaml)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(quote_column)operator(()ident(type)operator(,) ident(value)operator(\)) + reserved(case) ident(type) + reserved(when) symbol(:boolean) + reserved(case) ident(value) + reserved(when) constant(String) reserved(then) ident(value) operator(=)operator(~) regexp<delimiter(/)content(^[ty])delimiter(/)modifier(o)> operator(?) integer(1) operator(:) integer(0) + reserved(when) pre_constant(true) reserved(then) integer(1) + reserved(when) pre_constant(false) reserved(then) integer(0) + reserved(else) ident(value)operator(.)ident(to_i) + reserved(end) + reserved(when) symbol(:integer) reserved(then) ident(value)operator(.)ident(to_i) + reserved(when) symbol(:float) reserved(then) ident(value)operator(.)ident(to_f) + reserved(when) symbol(:text)operator(,) symbol(:string)operator(,) symbol(:enum) + reserved(case) ident(value) + reserved(when) constant(String)operator(,) constant(Symbol)operator(,) constant(Fixnum)operator(,) constant(Float)operator(,) constant(Bignum)operator(,) constant(TrueClass)operator(,) constant(FalseClass) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_s)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(else) + string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_yaml)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(when) symbol(:date)operator(,) symbol(:datetime)operator(,) symbol(:time) + reserved(case) ident(value) + reserved(when) constant(Time)operator(,) constant(DateTime) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(when) constant(Date) reserved(then) string<delimiter(")content(')inline<inline_delimiter(#{)ident(value)operator(.)ident(to_s)inline_delimiter(})>content(')delimiter(")> + reserved(else) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(else) string<delimiter(")content(')inline<inline_delimiter(#{)ident(quote_string)operator(()ident(value)operator(.)ident(to_yaml)operator(\))inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(quote_string)operator(()ident(s)operator(\)) + ident(s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(')delimiter(/)>operator(,) string<delimiter(")content('')delimiter(")>operator(\)) comment(# ' (for ruby-mode\)) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) + string<delimiter(")content([)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(])delimiter(")> + reserved(end) + + reserved(def) method(add_limit_offset!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(# :nodoc:) + instance_variable(@limit) operator(=) ident(options)operator([)symbol(:limit)operator(]) + instance_variable(@offset) operator(=) ident(options)operator([)symbol(:offset)operator(]) + reserved(if) operator(!)ident(normal_select?) + comment(# Use temp table to hack offset with Sybase) + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)content( FROM )delimiter(/)modifier(i)>operator(,) string<delimiter(')content( INTO #artemp FROM )delimiter(')>operator(\)) + reserved(elsif) ident(zero_limit?) + comment(# "SET ROWCOUNT 0" turns off limits, so we have) + comment(# to use a cheap trick.) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(WHERE)delimiter(/)modifier(i)> + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(WHERE)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(WHERE 1 = 2 AND )delimiter(')>operator(\)) + reserved(elsif) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(ORDER)char(\\s)content(+BY)delimiter(/)modifier(i)> + ident(sql)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(ORDER)char(\\s)content(+BY)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(WHERE 1 = 2 ORDER BY)delimiter(')>operator(\)) + reserved(else) + ident(sql) operator(<<) string<delimiter(')content(WHERE 1 = 2)delimiter(')> + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(supports_migrations?) comment(#:nodoc:) + pre_constant(true) + reserved(end) + + reserved(def) method(rename_table)operator(()ident(name)operator(,) ident(new_name)operator(\)) + ident(execute) string<delimiter(")content(EXEC sp_rename ')inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(', ')inline<inline_delimiter(#{)ident(new_name)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(def) method(rename_column)operator(()ident(table)operator(,) ident(column)operator(,) ident(new_column_name)operator(\)) + ident(execute) string<delimiter(")content(EXEC sp_rename ')inline<inline_delimiter(#{)ident(table)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(column)inline_delimiter(})>content(', ')inline<inline_delimiter(#{)ident(new_column_name)inline_delimiter(})>content(')delimiter(")> + reserved(end) + + reserved(def) method(change_column)operator(()ident(table_name)operator(,) ident(column_name)operator(,) ident(type)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) comment(#:nodoc:) + ident(sql_commands) operator(=) operator([)string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( MODIFY )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type_to_sql)operator(()ident(type)operator(,) ident(options)operator([)symbol(:limit)operator(])operator(\))inline_delimiter(})>delimiter(")>operator(]) + reserved(if) ident(options)operator([)symbol(:default)operator(]) + ident(remove_default_constraint)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(sql_commands) operator(<<) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( ADD CONSTRAINT DF_)inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content( DEFAULT )inline<inline_delimiter(#{)ident(options)operator([)symbol(:default)operator(])inline_delimiter(})>content( FOR )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>delimiter(")> + reserved(end) + ident(sql_commands)operator(.)ident(each) operator({) operator(|)ident(c)operator(|) ident(execute)operator(()ident(c)operator(\)) operator(}) + reserved(end) + + reserved(def) method(remove_column)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(remove_default_constraint)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP )inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(remove_default_constraint)operator(()ident(table_name)operator(,) ident(column_name)operator(\)) + ident(defaults) operator(=) ident(select) string<delimiter(")content(select def.name from sysobjects def, syscolumns col, sysobjects tab where col.cdefault = def.id and col.name = ')inline<inline_delimiter(#{)ident(column_name)inline_delimiter(})>content(' and tab.name = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' and col.id = tab.id)delimiter(")> + ident(defaults)operator(.)ident(each) operator({)operator(|)ident(constraint)operator(|) + ident(execute) string<delimiter(")content(ALTER TABLE )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( DROP CONSTRAINT )inline<inline_delimiter(#{)ident(constraint)operator([)string<delimiter(")content(name)delimiter(")>operator(])inline_delimiter(})>delimiter(")> + operator(}) + reserved(end) + + reserved(def) method(remove_index)operator(()ident(table_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(execute) string<delimiter(")content(DROP INDEX )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(index_name)operator(()ident(table_name)operator(,) ident(options)operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(add_column_options!)operator(()ident(sql)operator(,) ident(options)operator(\)) comment(#:nodoc:) + ident(sql) operator(<<) string<delimiter(")content( DEFAULT )inline<inline_delimiter(#{)ident(quote)operator(()ident(options)operator([)symbol(:default)operator(])operator(,) ident(options)operator([)symbol(:column)operator(])operator(\))inline_delimiter(})>delimiter(")> reserved(unless) ident(options)operator([)symbol(:default)operator(])operator(.)ident(nil?) + + reserved(if) ident(check_null_for_column?)operator(()ident(options)operator([)symbol(:column)operator(])operator(,) ident(sql)operator(\)) + ident(sql) operator(<<) operator(()ident(options)operator([)symbol(:null)operator(]) operator(==) pre_constant(false) operator(?) string<delimiter(")content( NOT NULL)delimiter(")> operator(:) string<delimiter(")content( NULL)delimiter(")>operator(\)) + reserved(end) + ident(sql) + reserved(end) + + ident(private) + reserved(def) method(check_null_for_column?)operator(()ident(col)operator(,) ident(sql)operator(\)) + comment(# Sybase columns are NOT NULL by default, so explicitly set NULL) + comment(# if :null option is omitted. Disallow NULLs for boolean.) + ident(type) operator(=) ident(col)operator(.)ident(nil?) operator(?) string<delimiter(")delimiter(")> operator(:) ident(col)operator([)symbol(:type)operator(]) + + comment(# Ignore :null if a primary key) + reserved(return) pre_constant(false) reserved(if) ident(type) operator(=)operator(~) regexp<delimiter(/)content(PRIMARY KEY)delimiter(/)modifier(i)> + + comment(# Ignore :null if a :boolean or BIT column) + reserved(if) operator(()ident(sql) operator(=)operator(~) regexp<delimiter(/)char(\\s)content(+bit()char(\\s)content(+DEFAULT\)?)delimiter(/)modifier(i)>operator(\)) operator(||) ident(type) operator(==) symbol(:boolean) + comment(# If no default clause found on a boolean column, add one.) + ident(sql) operator(<<) string<delimiter(")content( DEFAULT 0)delimiter(")> reserved(if) global_variable($1)operator(.)ident(nil?) + reserved(return) pre_constant(false) + reserved(end) + pre_constant(true) + reserved(end) + + comment(# Return the last value of the identity global value.) + reserved(def) method(last_insert_id) + instance_variable(@connection)operator(.)ident(sql)operator(()string<delimiter(")content(SELECT @@IDENTITY)delimiter(")>operator(\)) + reserved(unless) instance_variable(@connection)operator(.)ident(cmd_fail?) + ident(id) operator(=) instance_variable(@connection)operator(.)ident(top_row_result)operator(.)ident(rows)operator(.)ident(first)operator(.)ident(first) + reserved(if) ident(id) + ident(id) operator(=) ident(id)operator(.)ident(to_i) + ident(id) operator(=) pre_constant(nil) reserved(if) ident(id) operator(==) integer(0) + reserved(end) + reserved(else) + ident(id) operator(=) pre_constant(nil) + reserved(end) + ident(id) + reserved(end) + + reserved(def) method(affected_rows)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + instance_variable(@connection)operator(.)ident(sql)operator(()string<delimiter(")content(SELECT @@ROWCOUNT)delimiter(")>operator(\)) + reserved(unless) instance_variable(@connection)operator(.)ident(cmd_fail?) + ident(count) operator(=) instance_variable(@connection)operator(.)ident(top_row_result)operator(.)ident(rows)operator(.)ident(first)operator(.)ident(first) + ident(count) operator(=) ident(count)operator(.)ident(to_i) reserved(if) ident(count) + reserved(else) + integer(0) + reserved(end) + reserved(end) + + reserved(def) method(normal_select?) + comment(# If limit is not set at all, we can ignore offset;) + comment(# If limit *is* set but offset is zero, use normal select) + comment(# with simple SET ROWCOUNT. Thus, only use the temp table) + comment(# if limit is set and offset > 0.) + ident(has_limit) operator(=) operator(!)instance_variable(@limit)operator(.)ident(nil?) + ident(has_offset) operator(=) operator(!)instance_variable(@offset)operator(.)ident(nil?) operator(&&) instance_variable(@offset) operator(>) integer(0) + operator(!)ident(has_limit) operator(||) operator(!)ident(has_offset) + reserved(end) + + reserved(def) method(zero_limit?) + operator(!)instance_variable(@limit)operator(.)ident(nil?) operator(&&) instance_variable(@limit) operator(==) integer(0) + reserved(end) + + comment(# Select limit number of rows starting at optional offset.) + reserved(def) method(select)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + instance_variable(@connection)operator(.)ident(context)operator(.)ident(reset) + ident(log)operator(()ident(sql)operator(,) ident(name)operator(\)) reserved(do) + reserved(if) ident(normal_select?) + comment(# If limit is not explicitly set, return all results.) + instance_variable(@logger)operator(.)ident(debug) string<delimiter(")content(Setting row count to ()inline<inline_delimiter(#{)instance_variable(@limit) operator(||) string<delimiter(')content(off)delimiter(')>inline_delimiter(})>content(\))delimiter(")> reserved(if) instance_variable(@logger) + + comment(# Run a normal select) + instance_variable(@connection)operator(.)ident(set_rowcount)operator(()instance_variable(@limit) operator(||) integer(0)operator(\)) + instance_variable(@connection)operator(.)ident(sql)operator(()ident(sql)operator(\)) + reserved(else) + comment(# Select into a temp table and prune results) + instance_variable(@logger)operator(.)ident(debug) string<delimiter(")content(Selecting )inline<inline_delimiter(#{)instance_variable(@limit) operator(+) operator(()instance_variable(@offset) operator(||) integer(0)operator(\))inline_delimiter(})>content( or fewer rows into #artemp)delimiter(")> reserved(if) instance_variable(@logger) + instance_variable(@connection)operator(.)ident(set_rowcount)operator(()instance_variable(@limit) operator(+) operator(()instance_variable(@offset) operator(||) integer(0)operator(\))operator(\)) + instance_variable(@connection)operator(.)ident(sql_norow)operator(()ident(sql)operator(\)) comment(# Select into temp table) + instance_variable(@logger)operator(.)ident(debug) string<delimiter(")content(Deleting )inline<inline_delimiter(#{)instance_variable(@offset) operator(||) integer(0)inline_delimiter(})>content( or fewer rows from #artemp)delimiter(")> reserved(if) instance_variable(@logger) + instance_variable(@connection)operator(.)ident(set_rowcount)operator(()instance_variable(@offset) operator(||) integer(0)operator(\)) + instance_variable(@connection)operator(.)ident(sql_norow)operator(()string<delimiter(")content(delete from #artemp)delimiter(")>operator(\)) comment(# Delete leading rows) + instance_variable(@connection)operator(.)ident(set_rowcount)operator(()integer(0)operator(\)) + instance_variable(@connection)operator(.)ident(sql)operator(()string<delimiter(")content(select * from #artemp)delimiter(")>operator(\)) comment(# Return the rest) + reserved(end) + reserved(end) + + ident(rows) operator(=) operator([)operator(]) + reserved(if) instance_variable(@connection)operator(.)ident(context)operator(.)ident(failed?) reserved(or) instance_variable(@connection)operator(.)ident(cmd_fail?) + ident(raise) constant(StatementInvalid)operator(,) string<delimiter(")content(SQL Command Failed for )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(sql)inline_delimiter(})>char(\\n)content(Message: )inline<inline_delimiter(#{)instance_variable(@connection)operator(.)ident(context)operator(.)ident(message)inline_delimiter(})>delimiter(")> + reserved(else) + ident(results) operator(=) instance_variable(@connection)operator(.)ident(top_row_result) + reserved(if) ident(results) operator(&&) ident(results)operator(.)ident(rows)operator(.)ident(length) operator(>) integer(0) + ident(fields) operator(=) ident(fixup_column_names)operator(()ident(results)operator(.)ident(columns)operator(\)) + ident(results)operator(.)ident(rows)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(hashed_row) operator(=) operator({)operator(}) + ident(row)operator(.)ident(zip)operator(()ident(fields)operator(\)) operator({) operator(|)ident(cell)operator(,) ident(column)operator(|) ident(hashed_row)operator([)ident(column)operator(]) operator(=) ident(cell) operator(}) + ident(rows) operator(<<) ident(hashed_row) + reserved(end) + reserved(end) + reserved(end) + instance_variable(@connection)operator(.)ident(sql_norow)operator(()string<delimiter(")content(drop table #artemp)delimiter(")>operator(\)) reserved(if) operator(!)ident(normal_select?) + instance_variable(@limit) operator(=) instance_variable(@offset) operator(=) pre_constant(nil) + reserved(return) ident(rows) + reserved(end) + + reserved(def) method(enable_identity_insert)operator(()ident(table_name)operator(,) ident(enable) operator(=) pre_constant(true)operator(\)) + reserved(if) ident(has_identity_column)operator(()ident(table_name)operator(\)) + string<delimiter(")content(SET IDENTITY_INSERT )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(enable) operator(?) string<delimiter(')content(ON)delimiter(')> operator(:) string<delimiter(')content(OFF)delimiter(')>inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(get_table_name)operator(()ident(sql)operator(\)) + reserved(if) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*insert)char(\\s)content(+into)char(\\s)content(+([^)char(\\()char(\\s)content(]+\))char(\\s)content(*|^)char(\\s)content(*update)char(\\s)content(+([^)char(\\()char(\\s)content(]+\))char(\\s)content(*)delimiter(/)modifier(i)> + global_variable($1) + reserved(elsif) ident(sql) operator(=)operator(~) regexp<delimiter(/)content(from)char(\\s)content(+([^)char(\\()char(\\s)content(]+\))char(\\s)content(*)delimiter(/)modifier(i)> + global_variable($1) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(has_identity_column)operator(()ident(table_name)operator(\)) + operator(!)ident(get_identity_column)operator(()ident(table_name)operator(\))operator(.)ident(nil?) + reserved(end) + + reserved(def) method(get_identity_column)operator(()ident(table_name)operator(\)) + instance_variable(@table_columns) operator(=) operator({)operator(}) reserved(unless) instance_variable(@table_columns) + instance_variable(@table_columns)operator([)ident(table_name)operator(]) operator(=) ident(columns)operator(()ident(table_name)operator(\)) reserved(if) instance_variable(@table_columns)operator([)ident(table_name)operator(]) operator(==) pre_constant(nil) + instance_variable(@table_columns)operator([)ident(table_name)operator(])operator(.)ident(each) reserved(do) operator(|)ident(col)operator(|) + reserved(return) ident(col)operator(.)ident(name) reserved(if) ident(col)operator(.)ident(identity) + reserved(end) + + reserved(return) pre_constant(nil) + reserved(end) + + reserved(def) method(query_contains_identity_column)operator(()ident(sql)operator(,) ident(col)operator(\)) + ident(sql) operator(=)operator(~) regexp<delimiter(/)char(\\[)inline<inline_delimiter(#{)ident(col)inline_delimiter(})>char(\\])delimiter(/)> + reserved(end) + + comment(# Remove trailing _ from names.) + reserved(def) method(fixup_column_names)operator(()ident(columns)operator(\)) + ident(columns)operator(.)ident(map) operator({) operator(|)ident(column)operator(|) ident(column)operator(.)ident(sub)operator(()regexp<delimiter(/)content(_$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) operator(}) + reserved(end) + + reserved(def) method(table_structure)operator(()ident(table_name)operator(\)) + ident(sql) operator(=) string<delimiter(<<SQLTEXT)>string<content( +SELECT col.name AS name, type.name AS type, col.prec, col.scale, col.length, + col.status, obj.sysstat2, def.text + FROM sysobjects obj, syscolumns col, systypes type, syscomments def + WHERE obj.id = col.id AND col.usertype = type.usertype AND col.cdefault *= def.id + AND obj.type = 'U' AND obj.name = ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(' ORDER BY col.colid)delimiter( +SQLTEXT)> + ident(log)operator(()ident(sql)operator(,) string<delimiter(")content(Get Column Info )delimiter(")>operator(\)) reserved(do) + instance_variable(@connection)operator(.)ident(set_rowcount)operator(()integer(0)operator(\)) + instance_variable(@connection)operator(.)ident(sql)operator(()ident(sql)operator(\)) + reserved(end) + reserved(if) instance_variable(@connection)operator(.)ident(context)operator(.)ident(failed?) + ident(raise) string<delimiter(")content(SQL Command for table_structure for )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( failed)char(\\n)content(Message: )inline<inline_delimiter(#{)instance_variable(@connection)operator(.)ident(context)operator(.)ident(message)inline_delimiter(})>delimiter(")> + reserved(elsif) operator(!)instance_variable(@connection)operator(.)ident(cmd_fail?) + ident(columns) operator(=) operator([)operator(]) + ident(results) operator(=) instance_variable(@connection)operator(.)ident(top_row_result) + ident(results)operator(.)ident(rows)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(name)operator(,) ident(type)operator(,) ident(prec)operator(,) ident(scale)operator(,) ident(length)operator(,) ident(status)operator(,) ident(sysstat2)operator(,) ident(default) operator(=) ident(row) + ident(type) operator(=) ident(normalize_type)operator(()ident(type)operator(,) ident(prec)operator(,) ident(scale)operator(,) ident(length)operator(\)) + ident(default_value) operator(=) pre_constant(nil) + ident(name)operator(.)ident(sub!)operator(()regexp<delimiter(/)content(_$)delimiter(/)modifier(o)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(if) ident(default) operator(=)operator(~) regexp<delimiter(/)content(DEFAULT)char(\\s)content(+(.+\))delimiter(/)modifier(o)> + ident(default_value) operator(=) global_variable($1)operator(.)ident(strip) + ident(default_value) operator(=) ident(default_value)operator([)integer(1)operator(...)integer(-1)operator(]) reserved(if) ident(default_value) operator(=)operator(~) regexp<delimiter(/)content(^['"])delimiter(/)modifier(o)> + reserved(end) + ident(nullable) operator(=) operator(()ident(status) operator(&) integer(8)operator(\)) operator(==) integer(8) + ident(identity) operator(=) ident(status) operator(>)operator(=) integer(128) + ident(primary) operator(=) operator(()ident(sysstat2) operator(&) integer(8)operator(\)) operator(==) integer(8) + + ident(columns) operator(<<) operator([)ident(name)operator(,) ident(default_value)operator(,) ident(type)operator(,) ident(nullable)operator(,) ident(identity)operator(,) ident(primary)operator(]) + reserved(end) + ident(columns) + reserved(else) + pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(normalize_type)operator(()ident(field_type)operator(,) ident(prec)operator(,) ident(scale)operator(,) ident(length)operator(\)) + reserved(if) ident(field_type) operator(=)operator(~) regexp<delimiter(/)content(numeric)delimiter(/)modifier(i)> reserved(and) operator(()ident(scale)operator(.)ident(nil?) reserved(or) ident(scale) operator(==) integer(0)operator(\)) + ident(type) operator(=) string<delimiter(')content(int)delimiter(')> + reserved(elsif) ident(field_type) operator(=)operator(~) regexp<delimiter(/)content(money)delimiter(/)modifier(i)> + ident(type) operator(=) string<delimiter(')content(numeric)delimiter(')> + reserved(else) + ident(type) operator(=) ident(field_type) + reserved(end) + ident(size) operator(=) string<delimiter(')delimiter(')> + reserved(if) ident(prec) + ident(size) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(prec)inline_delimiter(})>content(\))delimiter(")> + reserved(elsif) ident(length) + ident(size) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(length)inline_delimiter(})>content(\))delimiter(")> + reserved(end) + reserved(return) ident(type) operator(+) ident(size) + reserved(end) + + reserved(def) method(default_value)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) comment(# class SybaseAdapter) + + reserved(class) class(SybaseAdapterContext) operator(<) constant(SybSQLContext) + constant(DEADLOCK) operator(=) integer(1205) + ident(attr_reader) symbol(:message) + + reserved(def) method(init)operator(()ident(logger) operator(=) pre_constant(nil)operator(\)) + instance_variable(@deadlocked) operator(=) pre_constant(false) + instance_variable(@failed) operator(=) pre_constant(false) + instance_variable(@logger) operator(=) ident(logger) + instance_variable(@message) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(srvmsgCB)operator(()ident(con)operator(,) ident(msg)operator(\)) + comment(# Do not log change of context messages.) + reserved(if) ident(msg)operator([)string<delimiter(')content(severity)delimiter(')>operator(]) operator(==) integer(10) reserved(or) ident(msg)operator([)string<delimiter(')content(severity)delimiter(')>operator(]) operator(==) integer(0) + reserved(return) pre_constant(true) + reserved(end) + + reserved(if) ident(msg)operator([)string<delimiter(')content(msgnumber)delimiter(')>operator(]) operator(==) constant(DEADLOCK) + instance_variable(@deadlocked) operator(=) pre_constant(true) + reserved(else) + instance_variable(@logger)operator(.)ident(info) string<delimiter(")content(SQL Command failed!)delimiter(")> reserved(if) instance_variable(@logger) + instance_variable(@failed) operator(=) pre_constant(true) + reserved(end) + + reserved(if) instance_variable(@logger) + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content(** SybSQLContext Server Message: **)delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( Message number )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(msgnumber)delimiter(')>operator(])inline_delimiter(})>content( Severity )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(severity)delimiter(')>operator(])inline_delimiter(})>content( State )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(state)delimiter(')>operator(])inline_delimiter(})>content( Line )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(line)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( Server )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(srvname)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( Procedure )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(proc)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( Message String: )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(text)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + reserved(end) + + instance_variable(@message) operator(=) ident(msg)operator([)string<delimiter(')content(text)delimiter(')>operator(]) + + pre_constant(true) + reserved(end) + + reserved(def) method(deadlocked?) + instance_variable(@deadlocked) + reserved(end) + + reserved(def) method(failed?) + instance_variable(@failed) + reserved(end) + + reserved(def) method(reset) + instance_variable(@deadlocked) operator(=) pre_constant(false) + instance_variable(@failed) operator(=) pre_constant(false) + instance_variable(@message) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(cltmsgCB)operator(()ident(con)operator(,) ident(msg)operator(\)) + reserved(return) pre_constant(true) reserved(unless) operator(() ident(msg)operator(.)ident(kind_of?)operator(()constant(Hash)operator(\)) operator(\)) + reserved(unless) operator(() ident(msg)operator([) string<delimiter(")content(severity)delimiter(")> operator(]) operator(\)) reserved(then) + reserved(return) pre_constant(true) + reserved(end) + + reserved(if) instance_variable(@logger) + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content(** SybSQLContext Client-Message: **)delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( Message number: LAYER=)inline<inline_delimiter(#{)ident(msg)operator([) string<delimiter(')content(layer)delimiter(')> operator(])inline_delimiter(})>content( ORIGIN=)inline<inline_delimiter(#{)ident(msg)operator([) string<delimiter(')content(origin)delimiter(')> operator(])inline_delimiter(})>content( SEVERITY=)inline<inline_delimiter(#{)ident(msg)operator([) string<delimiter(')content(severity)delimiter(')> operator(])inline_delimiter(})>content( NUMBER=)inline<inline_delimiter(#{)ident(msg)operator([) string<delimiter(')content(number)delimiter(')> operator(])inline_delimiter(})>delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( Message String: )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(msgstring)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + instance_variable(@logger)operator(.)ident(error) string<delimiter(")content( OS Error: )inline<inline_delimiter(#{)ident(msg)operator([)string<delimiter(')content(osstring)delimiter(')>operator(])inline_delimiter(})>delimiter(")> + + instance_variable(@message) operator(=) ident(msg)operator([)string<delimiter(')content(msgstring)delimiter(')>operator(]) + reserved(end) + + instance_variable(@failed) operator(=) pre_constant(true) + + comment(# Not retry , CS_CV_RETRY_FAIL( probability TimeOut \) ) + reserved(if)operator(() ident(msg)operator([) string<delimiter(')content(severity)delimiter(')> operator(]) operator(==) string<delimiter(")content(RETRY_FAIL)delimiter(")> operator(\)) reserved(then) + instance_variable(@timeout_p) operator(=) pre_constant(true) + reserved(return) pre_constant(false) + reserved(end) + + reserved(return) pre_constant(true) + reserved(end) + reserved(end) comment(# class SybaseAdapterContext) + + reserved(end) comment(# module ConnectionAdapters) +reserved(end) comment(# module ActiveRecord) + + +comment(# Allow identity inserts for fixtures.) +ident(require) string<delimiter(")content(active_record/fixtures)delimiter(")> +reserved(class) class(Fixtures) + reserved(alias) symbol(:original_insert_fixtures) symbol(:insert_fixtures) + + reserved(def) method(insert_fixtures) + ident(values)operator(.)ident(each) reserved(do) operator(|)ident(fixture)operator(|) + ident(allow_identity_inserts) ident(table_name)operator(,) pre_constant(true) + instance_variable(@connection)operator(.)ident(execute) string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)instance_variable(@table_name)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(fixture)operator(.)ident(key_list)inline_delimiter(})>content(\) VALUES ()inline<inline_delimiter(#{)ident(fixture)operator(.)ident(value_list)inline_delimiter(})>content(\))delimiter(")>operator(,) string<delimiter(')content(Fixture Insert)delimiter(')> + ident(allow_identity_inserts) ident(table_name)operator(,) pre_constant(false) + reserved(end) + reserved(end) + + reserved(def) method(allow_identity_inserts)operator(()ident(table_name)operator(,) ident(enable)operator(\)) + instance_variable(@connection)operator(.)ident(execute) string<delimiter(")content(SET IDENTITY_INSERT )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(enable) operator(?) string<delimiter(')content(ON)delimiter(')> operator(:) string<delimiter(')content(OFF)delimiter(')>inline_delimiter(})>delimiter(")> reserved(rescue) pre_constant(nil) + reserved(end) +reserved(end) + +reserved(rescue) constant(LoadError) operator(=)operator(>) ident(cannot_require_sybase) + comment(# Couldn't load sybase adapter) +ident(endmodule) constant(ActiveRecord) + reserved(module) class(Associations) comment(# :nodoc:) + reserved(module) class(ClassMethods) + reserved(def) method(deprecated_collection_count_method)operator(()ident(collection_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(_count(force_reload = false\) + )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(.reload if force_reload + )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(.size + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_add_association_relation)operator(()ident(association_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def add_)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content((*items\) + )inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content(.concat(items\) + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_remove_association_relation)operator(()ident(association_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def remove_)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content((*items\) + )inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content(.delete(items\) + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_has_collection_method)operator(()ident(collection_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def has_)inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(?(force_reload = false\) + !)inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content((force_reload\).empty? + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_find_in_collection_method)operator(()ident(collection_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def find_in_)inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content((association_id\) + )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(.find(association_id\) + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_find_all_in_collection_method)operator(()ident(collection_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def find_all_in_)inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content((runtime_conditions = nil, orderings = nil, limit = nil, joins = nil\) + )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(.find_all(runtime_conditions, orderings, limit, joins\) + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_collection_create_method)operator(()ident(collection_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def create_in_)inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content((attributes = {}\) + )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(.create(attributes\) + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_collection_build_method)operator(()ident(collection_name)operator(\))comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def build_to_)inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content((attributes = {}\) + )inline<inline_delimiter(#{)ident(collection_name)inline_delimiter(})>content(.build(attributes\) + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_association_comparison_method)operator(()ident(association_name)operator(,) ident(association_class_name)operator(\)) comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def )inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content(?(comparison_object, force_reload = false\) + if comparison_object.kind_of?()inline<inline_delimiter(#{)ident(association_class_name)inline_delimiter(})>content(\) + )inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content((force_reload\) == comparison_object + else + raise "Comparison object is a )inline<inline_delimiter(#{)ident(association_class_name)inline_delimiter(})>content(, should have been )char(\\#)content({comparison_object.class.name}" + end + end)delimiter( + end_eval)> + reserved(end) + + reserved(def) method(deprecated_has_association_method)operator(()ident(association_name)operator(\)) comment(# :nodoc:) + ident(module_eval) string<delimiter(<<-"end_eval")>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)string<content( + def has_)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content(?(force_reload = false\) + !)inline<inline_delimiter(#{)ident(association_name)inline_delimiter(})>content((force_reload\).nil? + end)delimiter( + end_eval)> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(class) class(Base) + reserved(class) operator(<<) class(self) + comment(# This method is deprecated in favor of find with the :conditions option.) + comment(#) + comment(# Works like find, but the record matching +id+ must also meet the +conditions+.) + comment(# +RecordNotFound+ is raised if no record can be found matching the +id+ or meeting the condition.) + comment(# Example:) + comment(# Person.find_on_conditions 5, "first_name LIKE '%dav%' AND last_name = 'heinemeier'") + reserved(def) method(find_on_conditions)operator(()ident(ids)operator(,) ident(conditions)operator(\)) comment(# :nodoc:) + ident(find)operator(()ident(ids)operator(,) symbol(:conditions) operator(=)operator(>) ident(conditions)operator(\)) + reserved(end) + + comment(# This method is deprecated in favor of find(:first, options\).) + comment(#) + comment(# Returns the object for the first record responding to the conditions in +conditions+, ) + comment(# such as "group = 'master'". If more than one record is returned from the query, it's the first that'll) + comment(# be used to create the object. In such cases, it might be beneficial to also specify ) + comment(# +orderings+, like "income DESC, name", to control exactly which record is to be used. Example: ) + comment(# Employee.find_first "income > 50000", "income DESC, name") + reserved(def) method(find_first)operator(()ident(conditions) operator(=) pre_constant(nil)operator(,) ident(orderings) operator(=) pre_constant(nil)operator(,) ident(joins) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) ident(conditions)operator(,) symbol(:order) operator(=)operator(>) ident(orderings)operator(,) symbol(:joins) operator(=)operator(>) ident(joins)operator(\)) + reserved(end) + + comment(# This method is deprecated in favor of find(:all, options\).) + comment(#) + comment(# Returns an array of all the objects that could be instantiated from the associated) + comment(# table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part\),) + comment(# such as by "color = 'red'", and arrangement of the selection can be done through +orderings+ (ORDER BY-part\),) + comment(# such as by "last_name, first_name DESC". A maximum of returned objects and their offset can be specified in ) + comment(# +limit+ with either just a single integer as the limit or as an array with the first element as the limit, ) + comment(# the second as the offset. Examples:) + comment(# Project.find_all "category = 'accounts'", "last_accessed DESC", 15) + comment(# Project.find_all ["category = ?", category_name], "created ASC", [15, 20]) + reserved(def) method(find_all)operator(()ident(conditions) operator(=) pre_constant(nil)operator(,) ident(orderings) operator(=) pre_constant(nil)operator(,) ident(limit) operator(=) pre_constant(nil)operator(,) ident(joins) operator(=) pre_constant(nil)operator(\)) comment(# :nodoc:) + ident(limit)operator(,) ident(offset) operator(=) ident(limit)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(?) ident(limit) operator(:) operator([) ident(limit)operator(,) pre_constant(nil) operator(]) + ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) ident(conditions)operator(,) symbol(:order) operator(=)operator(>) ident(orderings)operator(,) symbol(:joins) operator(=)operator(>) ident(joins)operator(,) symbol(:limit) operator(=)operator(>) ident(limit)operator(,) symbol(:offset) operator(=)operator(>) ident(offset)operator(\)) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) string<delimiter(')content(erb)delimiter(')> +ident(require) string<delimiter(')content(yaml)delimiter(')> +ident(require) string<delimiter(')content(csv)delimiter(')> + +reserved(module) class(YAML) comment(#:nodoc:) + reserved(class) class(Omap) comment(#:nodoc:) + reserved(def) method(keys)operator(;) ident(map) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(k) operator(}) reserved(end) + reserved(def) method(values)operator(;) ident(map) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(v) operator(}) reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(FixtureClassNotFound) operator(<) constant(ActiveRecord)operator(::)constant(ActiveRecordError) comment(#:nodoc:) +reserved(end) + +comment(# Fixtures are a way of organizing data that you want to test against; in short, sample data. They come in 3 flavours:) +comment(#) +comment(# 1. YAML fixtures) +comment(# 2. CSV fixtures) +comment(# 3. Single-file fixtures) +comment(#) +comment(# = YAML fixtures) +comment(#) +comment(# This type of fixture is in YAML format and the preferred default. YAML is a file format which describes data structures) +comment(# in a non-verbose, humanly-readable format. It ships with Ruby 1.8.1+.) +comment(#) +comment(# Unlike single-file fixtures, YAML fixtures are stored in a single file per model, which are placed in the directory appointed) +comment(# by <tt>Test::Unit::TestCase.fixture_path=(path\)</tt> (this is automatically configured for Rails, so you can just) +comment(# put your files in <your-rails-app>/test/fixtures/\). The fixture file ends with the .yml file extension (Rails example:) +comment(# "<your-rails-app>/test/fixtures/web_sites.yml"\). The format of a YAML fixture file looks like this:) +comment(#) +comment(# rubyonrails:) +comment(# id: 1) +comment(# name: Ruby on Rails) +comment(# url: http://www.rubyonrails.org) +comment(#) +comment(# google:) +comment(# id: 2) +comment(# name: Google) +comment(# url: http://www.google.com) +comment(#) +comment(# This YAML fixture file includes two fixtures. Each YAML fixture (ie. record\) is given a name and is followed by an) +comment(# indented list of key/value pairs in the "key: value" format. Records are separated by a blank line for your viewing) +comment(# pleasure.) +comment(#) +comment(# Note that YAML fixtures are unordered. If you want ordered fixtures, use the omap YAML type. See http://yaml.org/type/omap.html) +comment(# for the specification. You will need ordered fixtures when you have foreign key constraints on keys in the same table.) +comment(# This is commonly needed for tree structures. Example:) +comment(#) +comment(# --- !omap) +comment(# - parent:) +comment(# id: 1) +comment(# parent_id: NULL) +comment(# title: Parent) +comment(# - child:) +comment(# id: 2) +comment(# parent_id: 1) +comment(# title: Child) +comment(#) +comment(# = CSV fixtures) +comment(#) +comment(# Fixtures can also be kept in the Comma Separated Value format. Akin to YAML fixtures, CSV fixtures are stored) +comment(# in a single file, but instead end with the .csv file extension (Rails example: "<your-rails-app>/test/fixtures/web_sites.csv"\)) +comment(#) +comment(# The format of this type of fixture file is much more compact than the others, but also a little harder to read by us) +comment(# humans. The first line of the CSV file is a comma-separated list of field names. The rest of the file is then comprised) +comment(# of the actual data (1 per line\). Here's an example:) +comment(#) +comment(# id, name, url) +comment(# 1, Ruby On Rails, http://www.rubyonrails.org) +comment(# 2, Google, http://www.google.com) +comment(#) +comment(# Should you have a piece of data with a comma character in it, you can place double quotes around that value. If you) +comment(# need to use a double quote character, you must escape it with another double quote.) +comment(#) +comment(# Another unique attribute of the CSV fixture is that it has *no* fixture name like the other two formats. Instead, the) +comment(# fixture names are automatically generated by deriving the class name of the fixture file and adding an incrementing) +comment(# number to the end. In our example, the 1st fixture would be called "web_site_1" and the 2nd one would be called) +comment(# "web_site_2".) +comment(#) +comment(# Most databases and spreadsheets support exporting to CSV format, so this is a great format for you to choose if you) +comment(# have existing data somewhere already.) +comment(#) +comment(# = Single-file fixtures) +comment(#) +comment(# This type of fixtures was the original format for Active Record that has since been deprecated in favor of the YAML and CSV formats.) +comment(# Fixtures for this format are created by placing text files in a sub-directory (with the name of the model\) to the directory) +comment(# appointed by <tt>Test::Unit::TestCase.fixture_path=(path\)</tt> (this is automatically configured for Rails, so you can just) +comment(# put your files in <your-rails-app>/test/fixtures/<your-model-name>/ -- like <your-rails-app>/test/fixtures/web_sites/ for the WebSite) +comment(# model\).) +comment(#) +comment(# Each text file placed in this directory represents a "record". Usually these types of fixtures are named without) +comment(# extensions, but if you are on a Windows machine, you might consider adding .txt as the extension. Here's what the) +comment(# above example might look like:) +comment(#) +comment(# web_sites/google) +comment(# web_sites/yahoo.txt) +comment(# web_sites/ruby-on-rails) +comment(#) +comment(# The file format of a standard fixture is simple. Each line is a property (or column in db speak\) and has the syntax) +comment(# of "name => value". Here's an example of the ruby-on-rails fixture above:) +comment(#) +comment(# id => 1) +comment(# name => Ruby on Rails) +comment(# url => http://www.rubyonrails.org) +comment(#) +comment(# = Using Fixtures) +comment(#) +comment(# Since fixtures are a testing construct, we use them in our unit and functional tests. There are two ways to use the) +comment(# fixtures, but first let's take a look at a sample unit test found:) +comment(#) +comment(# require 'web_site') +comment(#) +comment(# class WebSiteTest < Test::Unit::TestCase) +comment(# def test_web_site_count) +comment(# assert_equal 2, WebSite.count) +comment(# end) +comment(# end) +comment(#) +comment(# As it stands, unless we pre-load the web_site table in our database with two records, this test will fail. Here's the) +comment(# easiest way to add fixtures to the database:) +comment(#) +comment(# ...) +comment(# class WebSiteTest < Test::Unit::TestCase) +comment(# fixtures :web_sites # add more by separating the symbols with commas) +comment(# ...) +comment(#) +comment(# By adding a "fixtures" method to the test case and passing it a list of symbols (only one is shown here tho\), we trigger) +comment(# the testing environment to automatically load the appropriate fixtures into the database before each test. ) +comment(# To ensure consistent data, the environment deletes the fixtures before running the load.) +comment(#) +comment(# In addition to being available in the database, the fixtures are also loaded into a hash stored in an instance variable) +comment(# of the test case. It is named after the symbol... so, in our example, there would be a hash available called) +comment(# @web_sites. This is where the "fixture name" comes into play.) +comment(#) +comment(# On top of that, each record is automatically "found" (using Model.find(id\)\) and placed in the instance variable of its name.) +comment(# So for the YAML fixtures, we'd get @rubyonrails and @google, which could be interrogated using regular Active Record semantics:) +comment(#) +comment(# # test if the object created from the fixture data has the same attributes as the data itself) +comment(# def test_find) +comment(# assert_equal @web_sites["rubyonrails"]["name"], @rubyonrails.name) +comment(# end) +comment(#) +comment(# As seen above, the data hash created from the YAML fixtures would have @web_sites["rubyonrails"]["url"] return) +comment(# "http://www.rubyonrails.org" and @web_sites["google"]["name"] would return "Google". The same fixtures, but loaded) +comment(# from a CSV fixture file, would be accessible via @web_sites["web_site_1"]["name"] == "Ruby on Rails" and have the individual) +comment(# fixtures available as instance variables @web_site_1 and @web_site_2.) +comment(#) +comment(# If you do not wish to use instantiated fixtures (usually for performance reasons\) there are two options.) +comment(#) +comment(# - to completely disable instantiated fixtures:) +comment(# self.use_instantiated_fixtures = false) +comment(#) +comment(# - to keep the fixture instance (@web_sites\) available, but do not automatically 'find' each instance:) +comment(# self.use_instantiated_fixtures = :no_instances ) +comment(#) +comment(# Even if auto-instantiated fixtures are disabled, you can still access them) +comment(# by name via special dynamic methods. Each method has the same name as the) +comment(# model, and accepts the name of the fixture to instantiate:) +comment(#) +comment(# fixtures :web_sites) +comment(#) +comment(# def test_find) +comment(# assert_equal "Ruby on Rails", web_sites(:rubyonrails\).name) +comment(# end) +comment(#) +comment(# = Dynamic fixtures with ERb) +comment(#) +comment(# Some times you don't care about the content of the fixtures as much as you care about the volume. In these cases, you can) +comment(# mix ERb in with your YAML or CSV fixtures to create a bunch of fixtures for load testing, like:) +comment(#) +comment(# <% for i in 1..1000 %>) +comment(# fix_<%= i %>:) +comment(# id: <%= i %>) +comment(# name: guy_<%= 1 %>) +comment(# <% end %>) +comment(#) +comment(# This will create 1000 very simple YAML fixtures.) +comment(#) +comment(# Using ERb, you can also inject dynamic values into your fixtures with inserts like <%= Date.today.strftime("%Y-%m-%d"\) %>.) +comment(# This is however a feature to be used with some caution. The point of fixtures are that they're stable units of predictable) +comment(# sample data. If you feel that you need to inject dynamic values, then perhaps you should reexamine whether your application) +comment(# is properly testable. Hence, dynamic values in fixtures are to be considered a code smell.) +comment(#) +comment(# = Transactional fixtures) +comment(#) +comment(# TestCases can use begin+rollback to isolate their changes to the database instead of having to delete+insert for every test case. ) +comment(# They can also turn off auto-instantiation of fixture data since the feature is costly and often unused.) +comment(#) +comment(# class FooTest < Test::Unit::TestCase) +comment(# self.use_transactional_fixtures = true) +comment(# self.use_instantiated_fixtures = false) +comment(# ) +comment(# fixtures :foos) +comment(# ) +comment(# def test_godzilla) +comment(# assert !Foo.find(:all\).empty?) +comment(# Foo.destroy_all) +comment(# assert Foo.find(:all\).empty?) +comment(# end) +comment(# ) +comment(# def test_godzilla_aftermath) +comment(# assert !Foo.find(:all\).empty?) +comment(# end) +comment(# end) +comment(# ) +comment(# If you preload your test database with all fixture data (probably in the Rakefile task\) and use transactional fixtures, ) +comment(# then you may omit all fixtures declarations in your test cases since all the data's already there and every case rolls back its changes.) +comment(#) +comment(# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to true. This will provide ) +comment(# access to fixture data for every table that has been loaded through fixtures (depending on the value of +use_instantiated_fixtures+\)) +comment(#) +comment(# When *not* to use transactional fixtures: ) +comment(# 1. You're testing whether a transaction works correctly. Nested transactions don't commit until all parent transactions commit, ) +comment(# particularly, the fixtures transaction which is begun in setup and rolled back in teardown. Thus, you won't be able to verify ) +comment(# the results of your transaction until Active Record supports nested transactions or savepoints (in progress.\) ) +comment(# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM. ) +comment(# Use InnoDB, MaxDB, or NDB instead.) +reserved(class) class(Fixtures) operator(<) constant(YAML)operator(::)constant(Omap) + constant(DEFAULT_FILTER_RE) operator(=) regexp<delimiter(/)char(\\.)content(ya?ml$)delimiter(/)> + + reserved(def) pre_constant(self)operator(.)ident(instantiate_fixtures)operator(()ident(object)operator(,) ident(table_name)operator(,) ident(fixtures)operator(,) ident(load_instances)operator(=)pre_constant(true)operator(\)) + ident(object)operator(.)ident(instance_variable_set) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(table_name)operator(.)ident(to_s)operator(.)ident(gsub)operator(()string<delimiter(')content(.)delimiter(')>operator(,)string<delimiter(')content(_)delimiter(')>operator(\))inline_delimiter(})>delimiter(")>operator(,) ident(fixtures) + reserved(if) ident(load_instances) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(silence) reserved(do) + ident(fixtures)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(fixture)operator(|) + reserved(begin) + ident(object)operator(.)ident(instance_variable_set) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")>operator(,) ident(fixture)operator(.)ident(find) + reserved(rescue) constant(FixtureClassNotFound) + pre_constant(nil) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(instantiate_all_loaded_fixtures)operator(()ident(object)operator(,) ident(load_instances)operator(=)pre_constant(true)operator(\)) + ident(all_loaded_fixtures)operator(.)ident(each) reserved(do) operator(|)ident(table_name)operator(,) ident(fixtures)operator(|) + constant(Fixtures)operator(.)ident(instantiate_fixtures)operator(()ident(object)operator(,) ident(table_name)operator(,) ident(fixtures)operator(,) ident(load_instances)operator(\)) + reserved(end) + reserved(end) + + ident(cattr_accessor) symbol(:all_loaded_fixtures) + pre_constant(self)operator(.)ident(all_loaded_fixtures) operator(=) operator({)operator(}) + + reserved(def) pre_constant(self)operator(.)ident(create_fixtures)operator(()ident(fixtures_directory)operator(,) ident(table_names)operator(,) ident(class_names) operator(=) operator({)operator(})operator(\)) + ident(table_names) operator(=) operator([)ident(table_names)operator(])operator(.)ident(flatten)operator(.)ident(map) operator({) operator(|)ident(n)operator(|) ident(n)operator(.)ident(to_s) operator(}) + ident(connection) operator(=) ident(block_given?) operator(?) reserved(yield) operator(:) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(silence) reserved(do) + ident(fixtures_map) operator(=) operator({)operator(}) + ident(fixtures) operator(=) ident(table_names)operator(.)ident(map) reserved(do) operator(|)ident(table_name)operator(|) + ident(fixtures_map)operator([)ident(table_name)operator(]) operator(=) constant(Fixtures)operator(.)ident(new)operator(()ident(connection)operator(,) constant(File)operator(.)ident(split)operator(()ident(table_name)operator(.)ident(to_s)operator(\))operator(.)ident(last)operator(,) ident(class_names)operator([)ident(table_name)operator(.)ident(to_sym)operator(])operator(,) constant(File)operator(.)ident(join)operator(()ident(fixtures_directory)operator(,) ident(table_name)operator(.)ident(to_s)operator(\))operator(\)) + reserved(end) + ident(all_loaded_fixtures)operator(.)ident(merge!) ident(fixtures_map) + + ident(connection)operator(.)ident(transaction) reserved(do) + ident(fixtures)operator(.)ident(reverse)operator(.)ident(each) operator({) operator(|)ident(fixture)operator(|) ident(fixture)operator(.)ident(delete_existing_fixtures) operator(}) + ident(fixtures)operator(.)ident(each) operator({) operator(|)ident(fixture)operator(|) ident(fixture)operator(.)ident(insert_fixtures) operator(}) + + comment(# Cap primary key sequences to max(pk\).) + reserved(if) ident(connection)operator(.)ident(respond_to?)operator(()symbol(:reset_pk_sequence!)operator(\)) + ident(table_names)operator(.)ident(each) reserved(do) operator(|)ident(table_name)operator(|) + ident(connection)operator(.)ident(reset_pk_sequence!)operator(()ident(table_name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(return) ident(fixtures)operator(.)ident(size) operator(>) integer(1) operator(?) ident(fixtures) operator(:) ident(fixtures)operator(.)ident(first) + reserved(end) + reserved(end) + + + ident(attr_reader) symbol(:table_name) + + reserved(def) method(initialize)operator(()ident(connection)operator(,) ident(table_name)operator(,) ident(class_name)operator(,) ident(fixture_path)operator(,) ident(file_filter) operator(=) constant(DEFAULT_FILTER_RE)operator(\)) + instance_variable(@connection)operator(,) instance_variable(@table_name)operator(,) instance_variable(@fixture_path)operator(,) instance_variable(@file_filter) operator(=) ident(connection)operator(,) ident(table_name)operator(,) ident(fixture_path)operator(,) ident(file_filter) + instance_variable(@class_name) operator(=) ident(class_name) operator(||) + operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(?) instance_variable(@table_name)operator(.)ident(singularize)operator(.)ident(camelize) operator(:) instance_variable(@table_name)operator(.)ident(camelize)operator(\)) + instance_variable(@table_name) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(+) instance_variable(@table_name) operator(+) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) + ident(read_fixture_files) + reserved(end) + + reserved(def) method(delete_existing_fixtures) + instance_variable(@connection)operator(.)ident(delete) string<delimiter(")content(DELETE FROM )inline<inline_delimiter(#{)instance_variable(@table_name)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(')content(Fixture Delete)delimiter(')> + reserved(end) + + reserved(def) method(insert_fixtures) + ident(values)operator(.)ident(each) reserved(do) operator(|)ident(fixture)operator(|) + instance_variable(@connection)operator(.)ident(execute) string<delimiter(")content(INSERT INTO )inline<inline_delimiter(#{)instance_variable(@table_name)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(fixture)operator(.)ident(key_list)inline_delimiter(})>content(\) VALUES ()inline<inline_delimiter(#{)ident(fixture)operator(.)ident(value_list)inline_delimiter(})>content(\))delimiter(")>operator(,) string<delimiter(')content(Fixture Insert)delimiter(')> + reserved(end) + reserved(end) + + ident(private) + + reserved(def) method(read_fixture_files) + reserved(if) constant(File)operator(.)ident(file?)operator(()ident(yaml_file_path)operator(\)) + comment(# YAML fixtures) + reserved(begin) + ident(yaml_string) operator(=) string<delimiter(")delimiter(")> + constant(Dir)operator([)string<delimiter(")inline<inline_delimiter(#{)instance_variable(@fixture_path)inline_delimiter(})>content(/**/*.yml)delimiter(")>operator(])operator(.)ident(select) operator({)operator(|)ident(f)operator(|) ident(test)operator(()integer(?f)operator(,)ident(f)operator(\)) operator(})operator(.)ident(each) reserved(do) operator(|)ident(subfixture_path)operator(|) + ident(yaml_string) operator(<<) constant(IO)operator(.)ident(read)operator(()ident(subfixture_path)operator(\)) + reserved(end) + ident(yaml_string) operator(<<) constant(IO)operator(.)ident(read)operator(()ident(yaml_file_path)operator(\)) + + reserved(if) ident(yaml) operator(=) constant(YAML)operator(::)ident(load)operator(()ident(erb_render)operator(()ident(yaml_string)operator(\))operator(\)) + ident(yaml) operator(=) ident(yaml)operator(.)ident(value) reserved(if) ident(yaml)operator(.)ident(respond_to?)operator(()symbol(:type_id)operator(\)) reserved(and) ident(yaml)operator(.)ident(respond_to?)operator(()symbol(:value)operator(\)) + ident(yaml)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(data)operator(|) + pre_constant(self)operator([)ident(name)operator(]) operator(=) constant(Fixture)operator(.)ident(new)operator(()ident(data)operator(,) instance_variable(@class_name)operator(\)) + reserved(end) + reserved(end) + reserved(rescue) constant(Exception)operator(=)operator(>)ident(boom) + ident(raise) constant(Fixture)operator(::)constant(FormatError)operator(,) string<delimiter(")content(a YAML error occured parsing )inline<inline_delimiter(#{)ident(yaml_file_path)inline_delimiter(})>content(. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html)char(\\n)content(The exact error was:)char(\\n)content( )inline<inline_delimiter(#{)ident(boom)operator(.)ident(class)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(boom)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(elsif) constant(File)operator(.)ident(file?)operator(()ident(csv_file_path)operator(\)) + comment(# CSV fixtures) + ident(reader) operator(=) constant(CSV)operator(::)constant(Reader)operator(.)ident(create)operator(()ident(erb_render)operator(()constant(IO)operator(.)ident(read)operator(()ident(csv_file_path)operator(\))operator(\))operator(\)) + ident(header) operator(=) ident(reader)operator(.)ident(shift) + ident(i) operator(=) integer(0) + ident(reader)operator(.)ident(each) reserved(do) operator(|)ident(row)operator(|) + ident(data) operator(=) operator({)operator(}) + ident(row)operator(.)ident(each_with_index) operator({) operator(|)ident(cell)operator(,) ident(j)operator(|) ident(data)operator([)ident(header)operator([)ident(j)operator(])operator(.)ident(to_s)operator(.)ident(strip)operator(]) operator(=) ident(cell)operator(.)ident(to_s)operator(.)ident(strip) operator(}) + pre_constant(self)operator([)string<delimiter(")inline<inline_delimiter(#{)constant(Inflector)operator(::)ident(underscore)operator(()instance_variable(@class_name)operator(\))inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(i)operator(+=)integer(1)inline_delimiter(})>delimiter(")>operator(])operator(=) constant(Fixture)operator(.)ident(new)operator(()ident(data)operator(,) instance_variable(@class_name)operator(\)) + reserved(end) + reserved(elsif) constant(File)operator(.)ident(file?)operator(()ident(deprecated_yaml_file_path)operator(\)) + ident(raise) constant(Fixture)operator(::)constant(FormatError)operator(,) string<delimiter(")content(.yml extension required: rename )inline<inline_delimiter(#{)ident(deprecated_yaml_file_path)inline_delimiter(})>content( to )inline<inline_delimiter(#{)ident(yaml_file_path)inline_delimiter(})>delimiter(")> + reserved(else) + comment(# Standard fixtures) + constant(Dir)operator(.)ident(entries)operator(()instance_variable(@fixture_path)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(file)operator(|) + ident(path) operator(=) constant(File)operator(.)ident(join)operator(()instance_variable(@fixture_path)operator(,) ident(file)operator(\)) + reserved(if) constant(File)operator(.)ident(file?)operator(()ident(path)operator(\)) reserved(and) ident(file) operator(!)operator(~) instance_variable(@file_filter) + pre_constant(self)operator([)ident(file)operator(]) operator(=) constant(Fixture)operator(.)ident(new)operator(()ident(path)operator(,) instance_variable(@class_name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(yaml_file_path) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@fixture_path)inline_delimiter(})>content(.yml)delimiter(")> + reserved(end) + + reserved(def) method(deprecated_yaml_file_path) + string<delimiter(")inline<inline_delimiter(#{)instance_variable(@fixture_path)inline_delimiter(})>content(.yaml)delimiter(")> + reserved(end) + + reserved(def) method(csv_file_path) + instance_variable(@fixture_path) operator(+) string<delimiter(")content(.csv)delimiter(")> + reserved(end) + + reserved(def) method(yaml_fixtures_key)operator(()ident(path)operator(\)) + constant(File)operator(.)ident(basename)operator(()instance_variable(@fixture_path)operator(\))operator(.)ident(split)operator(()string<delimiter(")content(.)delimiter(")>operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(erb_render)operator(()ident(fixture_content)operator(\)) + constant(ERB)operator(.)ident(new)operator(()ident(fixture_content)operator(\))operator(.)ident(result) + reserved(end) +reserved(end) + +reserved(class) class(Fixture) comment(#:nodoc:) + ident(include) constant(Enumerable) + reserved(class) class(FixtureError) operator(<) constant(StandardError)comment(#:nodoc:) + reserved(end) + reserved(class) class(FormatError) operator(<) constant(FixtureError)comment(#:nodoc:) + reserved(end) + + reserved(def) method(initialize)operator(()ident(fixture)operator(,) ident(class_name)operator(\)) + reserved(case) ident(fixture) + reserved(when) constant(Hash)operator(,) constant(YAML)operator(::)constant(Omap) + instance_variable(@fixture) operator(=) ident(fixture) + reserved(when) constant(String) + instance_variable(@fixture) operator(=) ident(read_fixture_file)operator(()ident(fixture)operator(\)) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Bad fixture argument )inline<inline_delimiter(#{)ident(fixture)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + + instance_variable(@class_name) operator(=) ident(class_name) + reserved(end) + + reserved(def) method(each) + instance_variable(@fixture)operator(.)ident(each) operator({) operator(|)ident(item)operator(|) reserved(yield) ident(item) operator(}) + reserved(end) + + reserved(def) method([])operator(()ident(key)operator(\)) + instance_variable(@fixture)operator([)ident(key)operator(]) + reserved(end) + + reserved(def) method(to_hash) + instance_variable(@fixture) + reserved(end) + + reserved(def) method(key_list) + ident(columns) operator(=) instance_variable(@fixture)operator(.)ident(keys)operator(.)ident(collect)operator({) operator(|)ident(column_name)operator(|) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(quote_column_name)operator(()ident(column_name)operator(\)) operator(}) + ident(columns)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(value_list) + instance_variable(@fixture)operator(.)ident(values)operator(.)ident(map) operator({) operator(|)ident(v)operator(|) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(quote)operator(()ident(v)operator(\))operator(.)ident(gsub)operator(()string<delimiter(')char(\\\\)content(n)delimiter(')>operator(,) string<delimiter(")char(\\n)delimiter(")>operator(\))operator(.)ident(gsub)operator(()string<delimiter(')char(\\\\)content(r)delimiter(')>operator(,) string<delimiter(")char(\\r)delimiter(")>operator(\)) operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(find) + ident(klass) operator(=) instance_variable(@class_name)operator(.)ident(is_a?)operator(()constant(Class)operator(\)) operator(?) instance_variable(@class_name) operator(:) constant(Object)operator(.)ident(const_get)operator(()instance_variable(@class_name)operator(\)) reserved(rescue) pre_constant(nil) + reserved(if) ident(klass) + ident(klass)operator(.)ident(find)operator(()pre_constant(self)operator([)ident(klass)operator(.)ident(primary_key)operator(])operator(\)) + reserved(else) + ident(raise) constant(FixtureClassNotFound)operator(,) string<delimiter(")content(The class )inline<inline_delimiter(#{)instance_variable(@class_name)operator(.)ident(inspect)inline_delimiter(})>content( was not found.)delimiter(")> + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(read_fixture_file)operator(()ident(fixture_file_path)operator(\)) + constant(IO)operator(.)ident(readlines)operator(()ident(fixture_file_path)operator(\))operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(fixture)operator(,) ident(line)operator(|) + comment(# Mercifully skip empty lines.) + reserved(next) reserved(if) ident(line) operator(=)operator(~) regexp<delimiter(/)content(^)char(\\s)content(*$)delimiter(/)> + + comment(# Use the same regular expression for attributes as Active Record.) + reserved(unless) ident(md) operator(=) regexp<delimiter(/)content(^)char(\\s)content(*([a-zA-Z][-_)char(\\w)content(]*\))char(\\s)content(*=>)char(\\s)content(*(.+\))char(\\s)content(*$)delimiter(/)>operator(.)ident(match)operator(()ident(line)operator(\)) + ident(raise) constant(FormatError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(fixture_file_path)inline_delimiter(})>content(: fixture format error at ')inline<inline_delimiter(#{)ident(line)inline_delimiter(})>content('. Expecting 'key => value'.)delimiter(")> + reserved(end) + ident(key)operator(,) ident(value) operator(=) ident(md)operator(.)ident(captures) + + comment(# Disallow duplicate keys to catch typos.) + ident(raise) constant(FormatError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(fixture_file_path)inline_delimiter(})>content(: duplicate ')inline<inline_delimiter(#{)ident(key)inline_delimiter(})>content(' in fixture.)delimiter(")> reserved(if) ident(fixture)operator([)ident(key)operator(]) + ident(fixture)operator([)ident(key)operator(]) operator(=) ident(value)operator(.)ident(strip) + ident(fixture) + reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(Test) comment(#:nodoc:) + reserved(module) class(Unit) comment(#:nodoc:) + reserved(class) class(TestCase) comment(#:nodoc:) + ident(cattr_accessor) symbol(:fixture_path) + ident(class_inheritable_accessor) symbol(:fixture_table_names) + ident(class_inheritable_accessor) symbol(:fixture_class_names) + ident(class_inheritable_accessor) symbol(:use_transactional_fixtures) + ident(class_inheritable_accessor) symbol(:use_instantiated_fixtures) comment(# true, false, or :no_instances) + ident(class_inheritable_accessor) symbol(:pre_loaded_fixtures) + + pre_constant(self)operator(.)ident(fixture_table_names) operator(=) operator([)operator(]) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) pre_constant(true) + pre_constant(self)operator(.)ident(pre_loaded_fixtures) operator(=) pre_constant(false) + + pre_constant(self)operator(.)ident(fixture_class_names) operator(=) operator({)operator(}) + + class_variable(@@already_loaded_fixtures) operator(=) operator({)operator(}) + pre_constant(self)operator(.)ident(fixture_class_names) operator(=) operator({)operator(}) + + reserved(def) pre_constant(self)operator(.)ident(set_fixture_class)operator(()ident(class_names) operator(=) operator({)operator(})operator(\)) + pre_constant(self)operator(.)ident(fixture_class_names) operator(=) pre_constant(self)operator(.)ident(fixture_class_names)operator(.)ident(merge)operator(()ident(class_names)operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(fixtures)operator(()operator(*)ident(table_names)operator(\)) + ident(table_names) operator(=) ident(table_names)operator(.)ident(flatten)operator(.)ident(map) operator({) operator(|)ident(n)operator(|) ident(n)operator(.)ident(to_s) operator(}) + pre_constant(self)operator(.)ident(fixture_table_names) operator(|=) ident(table_names) + ident(require_fixture_classes)operator(()ident(table_names)operator(\)) + ident(setup_fixture_accessors)operator(()ident(table_names)operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(require_fixture_classes)operator(()ident(table_names)operator(=)pre_constant(nil)operator(\)) + operator(()ident(table_names) operator(||) ident(fixture_table_names)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(table_name)operator(|) + ident(file_name) operator(=) ident(table_name)operator(.)ident(to_s) + ident(file_name) operator(=) ident(file_name)operator(.)ident(singularize) reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) + reserved(begin) + ident(require) ident(file_name) + reserved(rescue) constant(LoadError) + comment(# Let's hope the developer has included it himself) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(setup_fixture_accessors)operator(()ident(table_names)operator(=)pre_constant(nil)operator(\)) + operator(()ident(table_names) operator(||) ident(fixture_table_names)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(table_name)operator(|) + ident(table_name) operator(=) ident(table_name)operator(.)ident(to_s)operator(.)ident(tr)operator(()string<delimiter(')content(.)delimiter(')>operator(,)string<delimiter(')content(_)delimiter(')>operator(\)) + ident(define_method)operator(()ident(table_name)operator(\)) reserved(do) operator(|)ident(fixture)operator(,) operator(*)ident(optionals)operator(|) + ident(force_reload) operator(=) ident(optionals)operator(.)ident(shift) + instance_variable(@fixture_cache)operator([)ident(table_name)operator(]) operator(||=) constant(Hash)operator(.)ident(new) + instance_variable(@fixture_cache)operator([)ident(table_name)operator(])operator([)ident(fixture)operator(]) operator(=) pre_constant(nil) reserved(if) ident(force_reload) + reserved(if) instance_variable(@loaded_fixtures)operator([)ident(table_name)operator(])operator([)ident(fixture)operator(.)ident(to_s)operator(]) + instance_variable(@fixture_cache)operator([)ident(table_name)operator(])operator([)ident(fixture)operator(]) operator(||=) instance_variable(@loaded_fixtures)operator([)ident(table_name)operator(])operator([)ident(fixture)operator(.)ident(to_s)operator(])operator(.)ident(find) + reserved(else) + ident(raise) constant(StandardError)operator(,) string<delimiter(")content(No fixture with name ')inline<inline_delimiter(#{)ident(fixture)inline_delimiter(})>content(' found for table ')inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>content(')delimiter(")> + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(uses_transaction)operator(()operator(*)ident(methods)operator(\)) + instance_variable(@uses_transaction) operator(||=) operator([)operator(]) + instance_variable(@uses_transaction)operator(.)ident(concat) ident(methods)operator(.)ident(map) operator({) operator(|)ident(m)operator(|) ident(m)operator(.)ident(to_s) operator(}) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(uses_transaction?)operator(()ident(method)operator(\)) + instance_variable(@uses_transaction) operator(&&) instance_variable(@uses_transaction)operator(.)ident(include?)operator(()ident(method)operator(.)ident(to_s)operator(\)) + reserved(end) + + reserved(def) method(use_transactional_fixtures?) + ident(use_transactional_fixtures) operator(&&) + operator(!)pre_constant(self)operator(.)ident(class)operator(.)ident(uses_transaction?)operator(()ident(method_name)operator(\)) + reserved(end) + + reserved(def) method(setup_with_fixtures) + reserved(if) ident(pre_loaded_fixtures) operator(&&) operator(!)ident(use_transactional_fixtures) + ident(raise) constant(RuntimeError)operator(,) string<delimiter(')content(pre_loaded_fixtures requires use_transactional_fixtures)delimiter(')> + reserved(end) + + instance_variable(@fixture_cache) operator(=) constant(Hash)operator(.)ident(new) + + comment(# Load fixtures once and begin transaction.) + reserved(if) ident(use_transactional_fixtures?) + reserved(if) class_variable(@@already_loaded_fixtures)operator([)pre_constant(self)operator(.)ident(class)operator(]) + instance_variable(@loaded_fixtures) operator(=) class_variable(@@already_loaded_fixtures)operator([)pre_constant(self)operator(.)ident(class)operator(]) + reserved(else) + ident(load_fixtures) + class_variable(@@already_loaded_fixtures)operator([)pre_constant(self)operator(.)ident(class)operator(]) operator(=) instance_variable(@loaded_fixtures) + reserved(end) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(lock_mutex) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(begin_db_transaction) + + comment(# Load fixtures for every test.) + reserved(else) + class_variable(@@already_loaded_fixtures)operator([)pre_constant(self)operator(.)ident(class)operator(]) operator(=) pre_constant(nil) + ident(load_fixtures) + reserved(end) + + comment(# Instantiate fixtures for every test if requested.) + ident(instantiate_fixtures) reserved(if) ident(use_instantiated_fixtures) + reserved(end) + + ident(alias_method) symbol(:setup)operator(,) symbol(:setup_with_fixtures) + + reserved(def) method(teardown_with_fixtures) + comment(# Rollback changes.) + reserved(if) ident(use_transactional_fixtures?) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(rollback_db_transaction) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(unlock_mutex) + reserved(end) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(verify_active_connections!) + reserved(end) + + ident(alias_method) symbol(:teardown)operator(,) symbol(:teardown_with_fixtures) + + reserved(def) pre_constant(self)operator(.)ident(method_added)operator(()ident(method)operator(\)) + reserved(case) ident(method)operator(.)ident(to_s) + reserved(when) string<delimiter(')content(setup)delimiter(')> + reserved(unless) ident(method_defined?)operator(()symbol(:setup_without_fixtures)operator(\)) + ident(alias_method) symbol(:setup_without_fixtures)operator(,) symbol(:setup) + ident(define_method)operator(()symbol(:setup)operator(\)) reserved(do) + ident(setup_with_fixtures) + ident(setup_without_fixtures) + reserved(end) + reserved(end) + reserved(when) string<delimiter(')content(teardown)delimiter(')> + reserved(unless) ident(method_defined?)operator(()symbol(:teardown_without_fixtures)operator(\)) + ident(alias_method) symbol(:teardown_without_fixtures)operator(,) symbol(:teardown) + ident(define_method)operator(()symbol(:teardown)operator(\)) reserved(do) + ident(teardown_without_fixtures) + ident(teardown_with_fixtures) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(load_fixtures) + instance_variable(@loaded_fixtures) operator(=) operator({)operator(}) + ident(fixtures) operator(=) constant(Fixtures)operator(.)ident(create_fixtures)operator(()ident(fixture_path)operator(,) ident(fixture_table_names)operator(,) ident(fixture_class_names)operator(\)) + reserved(unless) ident(fixtures)operator(.)ident(nil?) + reserved(if) ident(fixtures)operator(.)ident(instance_of?)operator(()constant(Fixtures)operator(\)) + instance_variable(@loaded_fixtures)operator([)ident(fixtures)operator(.)ident(table_name)operator(]) operator(=) ident(fixtures) + reserved(else) + ident(fixtures)operator(.)ident(each) operator({) operator(|)ident(f)operator(|) instance_variable(@loaded_fixtures)operator([)ident(f)operator(.)ident(table_name)operator(]) operator(=) ident(f) operator(}) + reserved(end) + reserved(end) + reserved(end) + + comment(# for pre_loaded_fixtures, only require the classes once. huge speed improvement) + class_variable(@@required_fixture_classes) operator(=) pre_constant(false) + + reserved(def) method(instantiate_fixtures) + reserved(if) ident(pre_loaded_fixtures) + ident(raise) constant(RuntimeError)operator(,) string<delimiter(')content(Load fixtures before instantiating them.)delimiter(')> reserved(if) constant(Fixtures)operator(.)ident(all_loaded_fixtures)operator(.)ident(empty?) + reserved(unless) class_variable(@@required_fixture_classes) + pre_constant(self)operator(.)ident(class)operator(.)ident(require_fixture_classes) constant(Fixtures)operator(.)ident(all_loaded_fixtures)operator(.)ident(keys) + class_variable(@@required_fixture_classes) operator(=) pre_constant(true) + reserved(end) + constant(Fixtures)operator(.)ident(instantiate_all_loaded_fixtures)operator(()pre_constant(self)operator(,) ident(load_instances?)operator(\)) + reserved(else) + ident(raise) constant(RuntimeError)operator(,) string<delimiter(')content(Load fixtures before instantiating them.)delimiter(')> reserved(if) instance_variable(@loaded_fixtures)operator(.)ident(nil?) + instance_variable(@loaded_fixtures)operator(.)ident(each) reserved(do) operator(|)ident(table_name)operator(,) ident(fixtures)operator(|) + constant(Fixtures)operator(.)ident(instantiate_fixtures)operator(()pre_constant(self)operator(,) ident(table_name)operator(,) ident(fixtures)operator(,) ident(load_instances?)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(load_instances?) + ident(use_instantiated_fixtures) operator(!=) symbol(:no_instances) + reserved(end) + reserved(end) + + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + comment(# Active Records support optimistic locking if the field <tt>lock_version</tt> is present. Each update to the) + comment(# record increments the lock_version column and the locking facilities ensure that records instantiated twice) + comment(# will let the last one saved raise a StaleObjectError if the first was also updated. Example:) + comment(#) + comment(# p1 = Person.find(1\)) + comment(# p2 = Person.find(1\)) + comment(# ) + comment(# p1.first_name = "Michael") + comment(# p1.save) + comment(# ) + comment(# p2.first_name = "should fail") + comment(# p2.save # Raises a ActiveRecord::StaleObjectError) + comment(#) + comment(# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,) + comment(# or otherwise apply the business logic needed to resolve the conflict.) + comment(#) + comment(# You must ensure that your database schema defaults the lock_version column to 0.) + comment(#) + comment(# This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>.) + comment(# To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method.) + comment(# This method uses the same syntax as <tt>set_table_name</tt>) + reserved(module) class(Locking) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:update_without_lock)operator(,) symbol(:update) + ident(alias_method) symbol(:update)operator(,) symbol(:update_with_lock) + reserved(end) + reserved(end) + + reserved(def) method(update_with_lock) comment(#:nodoc:) + reserved(return) ident(update_without_lock) reserved(unless) ident(locking_enabled?) + + ident(lock_col) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(locking_column) + ident(previous_value) operator(=) ident(send)operator(()ident(lock_col)operator(\)) + ident(send)operator(()ident(lock_col) operator(+) string<delimiter(')content(=)delimiter(')>operator(,) ident(previous_value) operator(+) integer(1)operator(\)) + + ident(affected_rows) operator(=) ident(connection)operator(.)ident(update)operator(()string<delimiter(<<-end_sql)>operator(,) string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(name)inline_delimiter(})>content( Update with optimistic locking)delimiter(")>operator(\))string<content( + UPDATE )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content( + SET )inline<inline_delimiter(#{)ident(quoted_comma_pair_list)operator(()ident(connection)operator(,) ident(attributes_with_quotes)operator(()pre_constant(false)operator(\))operator(\))inline_delimiter(})>content( + WHERE )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(primary_key)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quote)operator(()ident(id)operator(\))inline_delimiter(})>content( + AND )inline<inline_delimiter(#{)ident(lock_col)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(quote)operator(()ident(previous_value)operator(\))inline_delimiter(})>delimiter( + end_sql)> + + reserved(unless) ident(affected_rows) operator(==) integer(1) + ident(raise) constant(ActiveRecord)operator(::)constant(StaleObjectError)operator(,) string<delimiter(")content(Attempted to update a stale object)delimiter(")> + reserved(end) + + reserved(return) pre_constant(true) + reserved(end) + reserved(end) + + reserved(class) class(Base) + class_variable(@@lock_optimistically) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:lock_optimistically) + + reserved(def) method(locking_enabled?) comment(#:nodoc:) + ident(lock_optimistically) operator(&&) ident(respond_to?)operator(()pre_constant(self)operator(.)ident(class)operator(.)ident(locking_column)operator(\)) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(def) method(set_locking_column)operator(()ident(value) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(define_attr_method) symbol(:locking_column)operator(,) ident(value)operator(,) operator(&)ident(block) + reserved(end) + + reserved(def) method(locking_column) comment(#:nodoc:) + ident(reset_locking_column) + reserved(end) + + reserved(def) method(reset_locking_column) comment(#:nodoc:) + ident(default) operator(=) string<delimiter(')content(lock_version)delimiter(')> + ident(set_locking_column)operator(()ident(default)operator(\)) + ident(default) + reserved(end) + reserved(end) + + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(class) class(IrreversibleMigration) operator(<) constant(ActiveRecordError)comment(#:nodoc:) + reserved(end) + + reserved(class) class(DuplicateMigrationVersionError) operator(<) constant(ActiveRecordError)comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(version)operator(\)) + reserved(super)operator(()string<delimiter(")content(Multiple migrations have the version number )inline<inline_delimiter(#{)ident(version)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + + comment(# Migrations can manage the evolution of a schema used by several physical databases. It's a solution) + comment(# to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to) + comment(# push that change to other developers and to the production server. With migrations, you can describe the transformations) + comment(# in self-contained classes that can be checked into version control systems and executed against another database that) + comment(# might be one, two, or five versions behind.) + comment(#) + comment(# Example of a simple migration:) + comment(#) + comment(# class AddSsl < ActiveRecord::Migration) + comment(# def self.up) + comment(# add_column :accounts, :ssl_enabled, :boolean, :default => 1) + comment(# end) + comment(#) + comment(# def self.down) + comment(# remove_column :accounts, :ssl_enabled) + comment(# end) + comment(# end) + comment(#) + comment(# This migration will add a boolean flag to the accounts table and remove it again, if you're backing out of the migration.) + comment(# It shows how all migrations have two class methods +up+ and +down+ that describes the transformations required to implement) + comment(# or remove the migration. These methods can consist of both the migration specific methods, like add_column and remove_column,) + comment(# but may also contain regular Ruby code for generating data needed for the transformations.) + comment(#) + comment(# Example of a more complex migration that also needs to initialize data:) + comment(#) + comment(# class AddSystemSettings < ActiveRecord::Migration) + comment(# def self.up) + comment(# create_table :system_settings do |t|) + comment(# t.column :name, :string) + comment(# t.column :label, :string) + comment(# t.column :value, :text) + comment(# t.column :type, :string) + comment(# t.column :position, :integer) + comment(# end) + comment(#) + comment(# SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1) + comment(# end) + comment(#) + comment(# def self.down) + comment(# drop_table :system_settings) + comment(# end) + comment(# end) + comment(#) + comment(# This migration first adds the system_settings table, then creates the very first row in it using the Active Record model) + comment(# that relies on the table. It also uses the more advanced create_table syntax where you can specify a complete table schema) + comment(# in one block call.) + comment(#) + comment(# == Available transformations) + comment(#) + comment(# * <tt>create_table(name, options\)</tt> Creates a table called +name+ and makes the table object available to a block) + comment(# that can then add columns to it, following the same format as add_column. See example above. The options hash is for) + comment(# fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create table definition.) + comment(# * <tt>drop_table(name\)</tt>: Drops the table called +name+.) + comment(# * <tt>rename_table(old_name, new_name\)</tt>: Renames the table called +old_name+ to +new_name+.) + comment(# * <tt>add_column(table_name, column_name, type, options\)</tt>: Adds a new column to the table called +table_name+) + comment(# named +column_name+ specified to be one of the following types:) + comment(# :string, :text, :integer, :float, :datetime, :timestamp, :time, :date, :binary, :boolean. A default value can be specified) + comment(# by passing an +options+ hash like { :default => 11 }.) + comment(# * <tt>rename_column(table_name, column_name, new_column_name\)</tt>: Renames a column but keeps the type and content.) + comment(# * <tt>change_column(table_name, column_name, type, options\)</tt>: Changes the column to a different type using the same) + comment(# parameters as add_column.) + comment(# * <tt>remove_column(table_name, column_name\)</tt>: Removes the column named +column_name+ from the table called +table_name+.) + comment(# * <tt>add_index(table_name, column_names, index_type, index_name\)</tt>: Add a new index with the name of the column, or +index_name+ (if specified\) on the column(s\). Specify an optional +index_type+ (e.g. UNIQUE\).) + comment(# * <tt>remove_index(table_name, index_name\)</tt>: Remove the index specified by +index_name+.) + comment(#) + comment(# == Irreversible transformations) + comment(#) + comment(# Some transformations are destructive in a manner that cannot be reversed. Migrations of that kind should raise) + comment(# an <tt>IrreversibleMigration</tt> exception in their +down+ method.) + comment(#) + comment(# == Running migrations from within Rails) + comment(#) + comment(# The Rails package has several tools to help create and apply migrations.) + comment(#) + comment(# To generate a new migration, use <tt>script/generate migration MyNewMigration</tt>) + comment(# where MyNewMigration is the name of your migration. The generator will) + comment(# create a file <tt>nnn_my_new_migration.rb</tt> in the <tt>db/migrate/</tt>) + comment(# directory, where <tt>nnn</tt> is the next largest migration number.) + comment(# You may then edit the <tt>self.up</tt> and <tt>self.down</tt> methods of) + comment(# n MyNewMigration.) + comment(#) + comment(# To run migrations against the currently configured database, use) + comment(# <tt>rake migrate</tt>. This will update the database by running all of the) + comment(# pending migrations, creating the <tt>schema_info</tt> table if missing.) + comment(#) + comment(# To roll the database back to a previous migration version, use) + comment(# <tt>rake migrate VERSION=X</tt> where <tt>X</tt> is the version to which) + comment(# you wish to downgrade. If any of the migrations throw an) + comment(# <tt>IrreversibleMigration</tt> exception, that step will fail and you'll) + comment(# have some manual work to do.) + comment(#) + comment(# == Database support) + comment(#) + comment(# Migrations are currently supported in MySQL, PostgreSQL, SQLite,) + comment(# SQL Server, Sybase, and Oracle (all supported databases except DB2\).) + comment(#) + comment(# == More examples) + comment(#) + comment(# Not all migrations change the schema. Some just fix the data:) + comment(#) + comment(# class RemoveEmptyTags < ActiveRecord::Migration) + comment(# def self.up) + comment(# Tag.find(:all\).each { |tag| tag.destroy if tag.pages.empty? }) + comment(# end) + comment(#) + comment(# def self.down) + comment(# # not much we can do to restore deleted data) + comment(# raise IrreversibleMigration) + comment(# end) + comment(# end) + comment(#) + comment(# Others remove columns when they migrate up instead of down:) + comment(#) + comment(# class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration) + comment(# def self.up) + comment(# remove_column :items, :incomplete_items_count) + comment(# remove_column :items, :completed_items_count) + comment(# end) + comment(#) + comment(# def self.down) + comment(# add_column :items, :incomplete_items_count) + comment(# add_column :items, :completed_items_count) + comment(# end) + comment(# end) + comment(#) + comment(# And sometimes you need to do something in SQL not abstracted directly by migrations:) + comment(#) + comment(# class MakeJoinUnique < ActiveRecord::Migration) + comment(# def self.up) + comment(# execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`\)") + comment(# end) + comment(#) + comment(# def self.down) + comment(# execute "ALTER TABLE `pages_linked_pages` DROP INDEX `page_id_linked_page_id`") + comment(# end) + comment(# end) + comment(#) + comment(# == Using a model after changing its table) + comment(#) + comment(# Sometimes you'll want to add a column in a migration and populate it immediately after. In that case, you'll need) + comment(# to make a call to Base#reset_column_information in order to ensure that the model has the latest column data from) + comment(# after the new column was added. Example:) + comment(#) + comment(# class AddPeopleSalary < ActiveRecord::Migration) + comment(# def self.up) + comment(# add_column :people, :salary, :integer) + comment(# Person.reset_column_information) + comment(# Person.find(:all\).each do |p|) + comment(# p.salary = SalaryCalculator.compute(p\)) + comment(# end) + comment(# end) + comment(# end) + comment(#) + comment(# == Controlling verbosity) + comment(#) + comment(# By default, migrations will describe the actions they are taking, writing) + comment(# them to the console as they happen, along with benchmarks describing how) + comment(# long each step took.) + comment(#) + comment(# You can quiet them down by setting ActiveRecord::Migration.verbose = false.) + comment(#) + comment(# You can also insert your own messages and benchmarks by using the #say_with_time) + comment(# method:) + comment(#) + comment(# def self.up) + comment(# ...) + comment(# say_with_time "Updating salaries..." do) + comment(# Person.find(:all\).each do |p|) + comment(# p.salary = SalaryCalculator.compute(p\)) + comment(# end) + comment(# end) + comment(# ...) + comment(# end) + comment(#) + comment(# The phrase "Updating salaries..." would then be printed, along with the) + comment(# benchmark for the block when the block completes.) + reserved(class) class(Migration) + class_variable(@@verbose) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:verbose) + + reserved(class) operator(<<) class(self) + reserved(def) method(up_using_benchmarks) comment(#:nodoc:) + ident(migrate)operator(()symbol(:up)operator(\)) + reserved(end) + + reserved(def) method(down_using_benchmarks) comment(#:nodoc:) + ident(migrate)operator(()symbol(:down)operator(\)) + reserved(end) + + comment(# Execute this migration in the named direction) + reserved(def) method(migrate)operator(()ident(direction)operator(\)) + reserved(return) reserved(unless) ident(respond_to?)operator(()ident(direction)operator(\)) + + reserved(case) ident(direction) + reserved(when) symbol(:up) reserved(then) ident(announce) string<delimiter(")content(migrating)delimiter(")> + reserved(when) symbol(:down) reserved(then) ident(announce) string<delimiter(")content(reverting)delimiter(")> + reserved(end) + + ident(result) operator(=) pre_constant(nil) + ident(time) operator(=) constant(Benchmark)operator(.)ident(measure) operator({) ident(result) operator(=) ident(send)operator(()string<delimiter(")content(real_)inline<inline_delimiter(#{)ident(direction)inline_delimiter(})>delimiter(")>operator(\)) operator(}) + + reserved(case) ident(direction) + reserved(when) symbol(:up) reserved(then) ident(announce) string<delimiter(")content(migrated (%.4fs\))delimiter(")> operator(%) ident(time)operator(.)ident(real)operator(;) ident(write) + reserved(when) symbol(:down) reserved(then) ident(announce) string<delimiter(")content(reverted (%.4fs\))delimiter(")> operator(%) ident(time)operator(.)ident(real)operator(;) ident(write) + reserved(end) + + ident(result) + reserved(end) + + comment(# Because the method added may do an alias_method, it can be invoked) + comment(# recursively. We use @ignore_new_methods as a guard to indicate whether) + comment(# it is safe for the call to proceed.) + reserved(def) method(singleton_method_added)operator(()ident(sym)operator(\)) comment(#:nodoc:) + reserved(return) reserved(if) instance_variable(@ignore_new_methods) + + reserved(begin) + instance_variable(@ignore_new_methods) operator(=) pre_constant(true) + + reserved(case) ident(sym) + reserved(when) symbol(:up)operator(,) symbol(:down) + ident(klass) operator(=) operator(()reserved(class) operator(<<) class(self)operator(;) pre_constant(self)operator(;) reserved(end)operator(\)) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) string<delimiter(")content(real_)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>delimiter(")>operator(,) ident(sym)operator(\)) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) ident(sym)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(_using_benchmarks)delimiter(")>operator(\)) + reserved(end) + reserved(ensure) + instance_variable(@ignore_new_methods) operator(=) pre_constant(false) + reserved(end) + reserved(end) + + reserved(def) method(write)operator(()ident(text)operator(=)string<delimiter(")delimiter(")>operator(\)) + ident(puts)operator(()ident(text)operator(\)) reserved(if) ident(verbose) + reserved(end) + + reserved(def) method(announce)operator(()ident(message)operator(\)) + ident(text) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(: )inline<inline_delimiter(#{)ident(message)inline_delimiter(})>delimiter(")> + ident(length) operator(=) operator([)integer(0)operator(,) integer(75) operator(-) ident(text)operator(.)ident(length)operator(])operator(.)ident(max) + ident(write) string<delimiter(")content(== %s %s)delimiter(")> operator(%) operator([)ident(text)operator(,) string<delimiter(")content(=)delimiter(")> operator(*) ident(length)operator(]) + reserved(end) + + reserved(def) method(say)operator(()ident(message)operator(,) ident(subitem)operator(=)pre_constant(false)operator(\)) + ident(write) string<delimiter(")inline<inline_delimiter(#{)ident(subitem) operator(?) string<delimiter(")content( ->)delimiter(")> operator(:) string<delimiter(")content(--)delimiter(")>inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(message)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(say_with_time)operator(()ident(message)operator(\)) + ident(say)operator(()ident(message)operator(\)) + ident(result) operator(=) pre_constant(nil) + ident(time) operator(=) constant(Benchmark)operator(.)ident(measure) operator({) ident(result) operator(=) reserved(yield) operator(}) + ident(say) string<delimiter(")content(%.4fs)delimiter(")> operator(%) ident(time)operator(.)ident(real)operator(,) symbol(:subitem) + ident(result) + reserved(end) + + reserved(def) method(suppress_messages) + ident(save) operator(=) ident(verbose) + pre_constant(self)operator(.)ident(verbose) operator(=) pre_constant(false) + reserved(yield) + reserved(ensure) + pre_constant(self)operator(.)ident(verbose) operator(=) ident(save) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + ident(say_with_time) string<delimiter(")inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(arguments)operator(.)ident(map) operator({) operator(|)ident(a)operator(|) ident(a)operator(.)ident(inspect) operator(})operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))inline_delimiter(})>content(\))delimiter(")> reserved(do) + ident(arguments)operator([)integer(0)operator(]) operator(=) constant(Migrator)operator(.)ident(proper_table_name)operator(()ident(arguments)operator(.)ident(first)operator(\)) reserved(unless) ident(arguments)operator(.)ident(empty?) operator(||) ident(method) operator(==) symbol(:execute) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Migrator)comment(#:nodoc:) + reserved(class) operator(<<) class(self) + reserved(def) method(migrate)operator(()ident(migrations_path)operator(,) ident(target_version) operator(=) pre_constant(nil)operator(\)) + constant(Base)operator(.)ident(connection)operator(.)ident(initialize_schema_information) + + reserved(case) + reserved(when) ident(target_version)operator(.)ident(nil?)operator(,) ident(current_version) operator(<) ident(target_version) + ident(up)operator(()ident(migrations_path)operator(,) ident(target_version)operator(\)) + reserved(when) ident(current_version) operator(>) ident(target_version) + ident(down)operator(()ident(migrations_path)operator(,) ident(target_version)operator(\)) + reserved(when) ident(current_version) operator(==) ident(target_version) + reserved(return) comment(# You're on the right version) + reserved(end) + reserved(end) + + reserved(def) method(up)operator(()ident(migrations_path)operator(,) ident(target_version) operator(=) pre_constant(nil)operator(\)) + pre_constant(self)operator(.)ident(new)operator(()symbol(:up)operator(,) ident(migrations_path)operator(,) ident(target_version)operator(\))operator(.)ident(migrate) + reserved(end) + + reserved(def) method(down)operator(()ident(migrations_path)operator(,) ident(target_version) operator(=) pre_constant(nil)operator(\)) + pre_constant(self)operator(.)ident(new)operator(()symbol(:down)operator(,) ident(migrations_path)operator(,) ident(target_version)operator(\))operator(.)ident(migrate) + reserved(end) + + reserved(def) method(schema_info_table_name) + constant(Base)operator(.)ident(table_name_prefix) operator(+) string<delimiter(")content(schema_info)delimiter(")> operator(+) constant(Base)operator(.)ident(table_name_suffix) + reserved(end) + + reserved(def) method(current_version) + operator(()constant(Base)operator(.)ident(connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT version FROM )inline<inline_delimiter(#{)ident(schema_info_table_name)inline_delimiter(})>delimiter(")>operator(\)) operator(||) operator({)string<delimiter(")content(version)delimiter(")> operator(=)operator(>) integer(0)operator(})operator(\))operator([)string<delimiter(")content(version)delimiter(")>operator(])operator(.)ident(to_i) + reserved(end) + + reserved(def) method(proper_table_name)operator(()ident(name)operator(\)) + comment(# Use the ActiveRecord objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string) + ident(name)operator(.)ident(table_name) reserved(rescue) string<delimiter(")inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix)inline_delimiter(})>inline<inline_delimiter(#{)ident(name)inline_delimiter(})>inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(end) + + reserved(def) method(initialize)operator(()ident(direction)operator(,) ident(migrations_path)operator(,) ident(target_version) operator(=) pre_constant(nil)operator(\)) + ident(raise) constant(StandardError)operator(.)ident(new)operator(()string<delimiter(")content(This database does not yet support migrations)delimiter(")>operator(\)) reserved(unless) constant(Base)operator(.)ident(connection)operator(.)ident(supports_migrations?) + instance_variable(@direction)operator(,) instance_variable(@migrations_path)operator(,) instance_variable(@target_version) operator(=) ident(direction)operator(,) ident(migrations_path)operator(,) ident(target_version) + constant(Base)operator(.)ident(connection)operator(.)ident(initialize_schema_information) + reserved(end) + + reserved(def) method(current_version) + pre_constant(self)operator(.)ident(class)operator(.)ident(current_version) + reserved(end) + + reserved(def) method(migrate) + ident(migration_classes)operator(.)ident(each) reserved(do) operator(|)operator(()ident(version)operator(,) ident(migration_class)operator(\))operator(|) + constant(Base)operator(.)ident(logger)operator(.)ident(info)operator(()string<delimiter(")content(Reached target version: )inline<inline_delimiter(#{)instance_variable(@target_version)inline_delimiter(})>delimiter(")>operator(\)) reserved(and) reserved(break) reserved(if) ident(reached_target_version?)operator(()ident(version)operator(\)) + reserved(next) reserved(if) ident(irrelevant_migration?)operator(()ident(version)operator(\)) + + constant(Base)operator(.)ident(logger)operator(.)ident(info) string<delimiter(")content(Migrating to )inline<inline_delimiter(#{)ident(migration_class)inline_delimiter(})>content( ()inline<inline_delimiter(#{)ident(version)inline_delimiter(})>content(\))delimiter(")> + ident(migration_class)operator(.)ident(migrate)operator(()instance_variable(@direction)operator(\)) + ident(set_schema_version)operator(()ident(version)operator(\)) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(migration_classes) + ident(migrations) operator(=) ident(migration_files)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(migrations)operator(,) ident(migration_file)operator(|) + ident(load)operator(()ident(migration_file)operator(\)) + ident(version)operator(,) ident(name) operator(=) ident(migration_version_and_name)operator(()ident(migration_file)operator(\)) + ident(assert_unique_migration_version)operator(()ident(migrations)operator(,) ident(version)operator(.)ident(to_i)operator(\)) + ident(migrations) operator(<<) operator([) ident(version)operator(.)ident(to_i)operator(,) ident(migration_class)operator(()ident(name)operator(\)) operator(]) + reserved(end) + + ident(down?) operator(?) ident(migrations)operator(.)ident(sort)operator(.)ident(reverse) operator(:) ident(migrations)operator(.)ident(sort) + reserved(end) + + reserved(def) method(assert_unique_migration_version)operator(()ident(migrations)operator(,) ident(version)operator(\)) + reserved(if) operator(!)ident(migrations)operator(.)ident(empty?) operator(&&) ident(migrations)operator(.)ident(transpose)operator(.)ident(first)operator(.)ident(include?)operator(()ident(version)operator(\)) + ident(raise) constant(DuplicateMigrationVersionError)operator(.)ident(new)operator(()ident(version)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(migration_files) + ident(files) operator(=) constant(Dir)operator([)string<delimiter(")inline<inline_delimiter(#{)instance_variable(@migrations_path)inline_delimiter(})>content(/[0-9]*_*.rb)delimiter(")>operator(])operator(.)ident(sort_by) reserved(do) operator(|)ident(f)operator(|) + ident(migration_version_and_name)operator(()ident(f)operator(\))operator(.)ident(first)operator(.)ident(to_i) + reserved(end) + ident(down?) operator(?) ident(files)operator(.)ident(reverse) operator(:) ident(files) + reserved(end) + + reserved(def) method(migration_class)operator(()ident(migration_name)operator(\)) + ident(migration_name)operator(.)ident(camelize)operator(.)ident(constantize) + reserved(end) + + reserved(def) method(migration_version_and_name)operator(()ident(migration_file)operator(\)) + reserved(return) operator(*)ident(migration_file)operator(.)ident(scan)operator(()regexp<delimiter(/)content(([0-9]+\)_([_a-z0-9]*\).rb)delimiter(/)>operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(set_schema_version)operator(()ident(version)operator(\)) + constant(Base)operator(.)ident(connection)operator(.)ident(update)operator(()string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)operator(.)ident(schema_info_table_name)inline_delimiter(})>content( SET version = )inline<inline_delimiter(#{)ident(down?) operator(?) ident(version)operator(.)ident(to_i) operator(-) integer(1) operator(:) ident(version)operator(.)ident(to_i)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(up?) + instance_variable(@direction) operator(==) symbol(:up) + reserved(end) + + reserved(def) method(down?) + instance_variable(@direction) operator(==) symbol(:down) + reserved(end) + + reserved(def) method(reached_target_version?)operator(()ident(version)operator(\)) + operator(()ident(up?) operator(&&) ident(version)operator(.)ident(to_i) operator(-) integer(1) operator(==) instance_variable(@target_version)operator(\)) operator(||) operator(()ident(down?) operator(&&) ident(version)operator(.)ident(to_i) operator(==) instance_variable(@target_version)operator(\)) + reserved(end) + + reserved(def) method(irrelevant_migration?)operator(()ident(version)operator(\)) + operator(()ident(up?) operator(&&) ident(version)operator(.)ident(to_i) operator(<=) ident(current_version)operator(\)) operator(||) operator(()ident(down?) operator(&&) ident(version)operator(.)ident(to_i) operator(>) ident(current_version)operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(singleton)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(module) class(Observing) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Activates the observers assigned. Examples:) + comment(#) + comment(# # Calls PersonObserver.instance) + comment(# ActiveRecord::Base.observers = :person_observer) + comment(#) + comment(# # Calls Cacher.instance and GarbageCollector.instance ) + comment(# ActiveRecord::Base.observers = :cacher, :garbage_collector) + comment(#) + comment(# # Same as above, just using explicit class references) + comment(# ActiveRecord::Base.observers = Cacher, GarbageCollector) + reserved(def) method(observers=)operator(()operator(*)ident(observers)operator(\)) + ident(observers) operator(=) operator([) ident(observers) operator(])operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(observer)operator(|) + ident(observer)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) operator(?) + ident(observer)operator(.)ident(to_s)operator(.)ident(camelize)operator(.)ident(constantize)operator(.)ident(instance) operator(:) + ident(observer)operator(.)ident(instance) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Observer classes respond to lifecycle callbacks to implement trigger-like) + comment(# behavior outside the original class. This is a great way to reduce the) + comment(# clutter that normally comes when the model class is burdened with) + comment(# functionality that doesn't pertain to the core responsibility of the) + comment(# class. Example:) + comment(#) + comment(# class CommentObserver < ActiveRecord::Observer) + comment(# def after_save(comment\)) + comment(# Notifications.deliver_comment("admin@do.com", "New comment was posted", comment\)) + comment(# end) + comment(# end) + comment(#) + comment(# This Observer sends an email when a Comment#save is finished.) + comment(#) + comment(# class ContactObserver < ActiveRecord::Observer) + comment(# def after_create(contact\)) + comment(# contact.logger.info('New contact added!'\)) + comment(# end) + comment(#) + comment(# def after_destroy(contact\)) + comment(# contact.logger.warn("Contact with an id of #{contact.id} was destroyed!"\)) + comment(# end) + comment(# end) + comment(#) + comment(# This Observer uses logger to log when specific callbacks are triggered.) + comment(#) + comment(# == Observing a class that can't be inferred) + comment(#) + comment(# Observers will by default be mapped to the class with which they share a name. So CommentObserver will) + comment(# be tied to observing Comment, ProductManagerObserver to ProductManager, and so on. If you want to name your observer) + comment(# differently than the class you're interested in observing, you can use the Observer.observe class method:) + comment(#) + comment(# class AuditObserver < ActiveRecord::Observer) + comment(# observe Account) + comment(#) + comment(# def after_update(account\)) + comment(# AuditTrail.new(account, "UPDATED"\)) + comment(# end) + comment(# end) + comment(#) + comment(# If the audit observer needs to watch more than one kind of object, this can be specified with multiple arguments:) + comment(#) + comment(# class AuditObserver < ActiveRecord::Observer) + comment(# observe Account, Balance) + comment(#) + comment(# def after_update(record\)) + comment(# AuditTrail.new(record, "UPDATED"\)) + comment(# end) + comment(# end) + comment(#) + comment(# The AuditObserver will now act on both updates to Account and Balance by treating them both as records.) + comment(#) + comment(# == Available callback methods) + comment(#) + comment(# The observer can implement callback methods for each of the methods described in the Callbacks module.) + comment(#) + comment(# == Storing Observers in Rails) + comment(# ) + comment(# If you're using Active Record within Rails, observer classes are usually stored in app/models with the) + comment(# naming convention of app/models/audit_observer.rb.) + comment(#) + comment(# == Configuration) + comment(# ) + comment(# In order to activate an observer, list it in the <tt>config.active_record.observers</tt> configuration setting in your) + comment(# <tt>config/environment.rb</tt> file.) + comment(#) + comment(# config.active_record.observers = :comment_observer, :signup_observer) + comment(#) + comment(# Observers will not be invoked unless you define these in your application configuration.) + comment(#) + reserved(class) class(Observer) + ident(include) constant(Singleton) + + comment(# Observer subclasses should be reloaded by the dispatcher in Rails) + comment(# when Dependencies.mechanism = :load.) + ident(include) constant(Reloadable)operator(::)constant(Subclasses) + + comment(# Attaches the observer to the supplied model classes.) + reserved(def) pre_constant(self)operator(.)ident(observe)operator(()operator(*)ident(models)operator(\)) + ident(define_method)operator(()symbol(:observed_class)operator(\)) operator({) ident(models) operator(}) + reserved(end) + + reserved(def) method(initialize) + ident(observed_classes) operator(=) operator([) ident(observed_class) operator(])operator(.)ident(flatten) + ident(observed_subclasses_class) operator(=) ident(observed_classes)operator(.)ident(collect) operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(send)operator(()symbol(:subclasses)operator(\)) operator(})operator(.)ident(flatten!) + operator(()ident(observed_classes) operator(+) ident(observed_subclasses_class)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(klass)operator(|) + ident(klass)operator(.)ident(add_observer)operator(()pre_constant(self)operator(\)) + ident(klass)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:after_find)operator(\)) reserved(unless) ident(klass)operator(.)ident(respond_to?)operator(()symbol(:after_find)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(update)operator(()ident(callback_method)operator(,) ident(object)operator(\)) comment(#:nodoc:) + ident(send)operator(()ident(callback_method)operator(,) ident(object)operator(\)) reserved(if) ident(respond_to?)operator(()ident(callback_method)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(observed_class) + reserved(if) pre_constant(self)operator(.)ident(class)operator(.)ident(respond_to?) string<delimiter(")content(observed_class)delimiter(")> + pre_constant(self)operator(.)ident(class)operator(.)ident(observed_class) + reserved(else) + constant(Object)operator(.)ident(const_get)operator(()ident(infer_observed_class_name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(infer_observed_class_name) + pre_constant(self)operator(.)ident(class)operator(.)ident(name)operator(.)ident(scan)operator(()regexp<delimiter(/)content((.*\)Observer)delimiter(/)>operator(\))operator([)integer(0)operator(])operator([)integer(0)operator(]) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(class) class(QueryCache) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(connection)operator(\)) + instance_variable(@connection) operator(=) ident(connection) + instance_variable(@query_cache) operator(=) operator({)operator(}) + reserved(end) + + reserved(def) method(clear_query_cache) + instance_variable(@query_cache) operator(=) operator({)operator(}) + reserved(end) + + reserved(def) method(select_all)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + operator(()instance_variable(@query_cache)operator([)ident(sql)operator(]) operator(||=) instance_variable(@connection)operator(.)ident(select_all)operator(()ident(sql)operator(,) ident(name)operator(\))operator(\))operator(.)ident(dup) + reserved(end) + + reserved(def) method(select_one)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + instance_variable(@query_cache)operator([)ident(sql)operator(]) operator(||=) instance_variable(@connection)operator(.)ident(select_one)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + instance_variable(@query_cache)operator([)string<delimiter(")content(SHOW FIELDS FROM )inline<inline_delimiter(#{)ident(table_name)inline_delimiter(})>delimiter(")>operator(]) operator(||=) instance_variable(@connection)operator(.)ident(columns)operator(()ident(table_name)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(insert)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(,) ident(pk) operator(=) pre_constant(nil)operator(,) ident(id_value) operator(=) pre_constant(nil)operator(\)) + ident(clear_query_cache) + instance_variable(@connection)operator(.)ident(insert)operator(()ident(sql)operator(,) ident(name)operator(,) ident(pk)operator(,) ident(id_value)operator(\)) + reserved(end) + + reserved(def) method(update)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(clear_query_cache) + instance_variable(@connection)operator(.)ident(update)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + reserved(def) method(delete)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + ident(clear_query_cache) + instance_variable(@connection)operator(.)ident(delete)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(proc)operator(\)) + instance_variable(@connection)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(proc)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(Base) + comment(# Set the connection for the class with caching on) + reserved(class) operator(<<) class(self) + ident(alias_method) symbol(:connection_without_query_cache=)operator(,) symbol(:connection=) + + reserved(def) method(connection=)operator(()ident(spec)operator(\)) + reserved(if) ident(spec)operator(.)ident(is_a?)operator(()constant(ConnectionSpecification)operator(\)) reserved(and) ident(spec)operator(.)ident(config)operator([)symbol(:query_cache)operator(]) + ident(spec) operator(=) constant(QueryCache)operator(.)ident(new)operator(()pre_constant(self)operator(.)ident(send)operator(()ident(spec)operator(.)ident(adapter_method)operator(,) ident(spec)operator(.)ident(config)operator(\))operator(\)) + reserved(end) + pre_constant(self)operator(.)ident(connection_without_query_cache) operator(=) ident(spec) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(AbstractAdapter) comment(#:nodoc:) + comment(# Stub method to be able to treat the connection the same whether the query cache has been turned on or not) + reserved(def) method(clear_query_cache) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(Reflection) comment(# :nodoc:) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + comment(# Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations.) + comment(# This information can, for example, be used in a form builder that took an Active Record object and created input) + comment(# fields for all of the attributes depending on their type and displayed the associations to other objects.) + comment(#) + comment(# You can find the interface for the AggregateReflection and AssociationReflection classes in the abstract MacroReflection class.) + reserved(module) class(ClassMethods) + reserved(def) method(create_reflection)operator(()ident(macro)operator(,) ident(name)operator(,) ident(options)operator(,) ident(active_record)operator(\)) + reserved(case) ident(macro) + reserved(when) symbol(:has_many)operator(,) symbol(:belongs_to)operator(,) symbol(:has_one)operator(,) symbol(:has_and_belongs_to_many) + ident(reflection) operator(=) constant(AssociationReflection)operator(.)ident(new)operator(()ident(macro)operator(,) ident(name)operator(,) ident(options)operator(,) ident(active_record)operator(\)) + reserved(when) symbol(:composed_of) + ident(reflection) operator(=) constant(AggregateReflection)operator(.)ident(new)operator(()ident(macro)operator(,) ident(name)operator(,) ident(options)operator(,) ident(active_record)operator(\)) + reserved(end) + ident(write_inheritable_hash) symbol(:reflections)operator(,) ident(name) operator(=)operator(>) ident(reflection) + ident(reflection) + reserved(end) + + reserved(def) method(reflections) + ident(read_inheritable_attribute)operator(()symbol(:reflections)operator(\)) reserved(or) ident(write_inheritable_attribute)operator(()symbol(:reflections)operator(,) operator({)operator(})operator(\)) + reserved(end) + + comment(# Returns an array of AggregateReflection objects for all the aggregations in the class.) + reserved(def) method(reflect_on_all_aggregations) + ident(reflections)operator(.)ident(values)operator(.)ident(select) operator({) operator(|)ident(reflection)operator(|) ident(reflection)operator(.)ident(is_a?)operator(()constant(AggregateReflection)operator(\)) operator(}) + reserved(end) + + comment(# Returns the AggregateReflection object for the named +aggregation+ (use the symbol\). Example:) + comment(# Account.reflect_on_aggregation(:balance\) # returns the balance AggregateReflection) + reserved(def) method(reflect_on_aggregation)operator(()ident(aggregation)operator(\)) + ident(reflections)operator([)ident(aggregation)operator(])operator(.)ident(is_a?)operator(()constant(AggregateReflection)operator(\)) operator(?) ident(reflections)operator([)ident(aggregation)operator(]) operator(:) pre_constant(nil) + reserved(end) + + comment(# Returns an array of AssociationReflection objects for all the aggregations in the class. If you only want to reflect on a) + comment(# certain association type, pass in the symbol (:has_many, :has_one, :belongs_to\) for that as the first parameter. Example:) + comment(# Account.reflect_on_all_associations # returns an array of all associations) + comment(# Account.reflect_on_all_associations(:has_many\) # returns an array of all has_many associations) + reserved(def) method(reflect_on_all_associations)operator(()ident(macro) operator(=) pre_constant(nil)operator(\)) + ident(association_reflections) operator(=) ident(reflections)operator(.)ident(values)operator(.)ident(select) operator({) operator(|)ident(reflection)operator(|) ident(reflection)operator(.)ident(is_a?)operator(()constant(AssociationReflection)operator(\)) operator(}) + ident(macro) operator(?) ident(association_reflections)operator(.)ident(select) operator({) operator(|)ident(reflection)operator(|) ident(reflection)operator(.)ident(macro) operator(==) ident(macro) operator(}) operator(:) ident(association_reflections) + reserved(end) + + comment(# Returns the AssociationReflection object for the named +aggregation+ (use the symbol\). Example:) + comment(# Account.reflect_on_association(:owner\) # returns the owner AssociationReflection) + comment(# Invoice.reflect_on_association(:line_items\).macro # returns :has_many) + reserved(def) method(reflect_on_association)operator(()ident(association)operator(\)) + ident(reflections)operator([)ident(association)operator(])operator(.)ident(is_a?)operator(()constant(AssociationReflection)operator(\)) operator(?) ident(reflections)operator([)ident(association)operator(]) operator(:) pre_constant(nil) + reserved(end) + reserved(end) + + + comment(# Abstract base class for AggregateReflection and AssociationReflection that describes the interface available for both of) + comment(# those classes. Objects of AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.) + reserved(class) class(MacroReflection) + ident(attr_reader) symbol(:active_record) + reserved(def) method(initialize)operator(()ident(macro)operator(,) ident(name)operator(,) ident(options)operator(,) ident(active_record)operator(\)) + instance_variable(@macro)operator(,) instance_variable(@name)operator(,) instance_variable(@options)operator(,) instance_variable(@active_record) operator(=) ident(macro)operator(,) ident(name)operator(,) ident(options)operator(,) ident(active_record) + reserved(end) + + comment(# Returns the name of the macro, so it would return :balance for "composed_of :balance, :class_name => 'Money'" or) + comment(# :clients for "has_many :clients".) + reserved(def) method(name) + instance_variable(@name) + reserved(end) + + comment(# Returns the name of the macro, so it would return :composed_of for) + comment(# "composed_of :balance, :class_name => 'Money'" or :has_many for "has_many :clients".) + reserved(def) method(macro) + instance_variable(@macro) + reserved(end) + + comment(# Returns the hash of options used for the macro, so it would return { :class_name => "Money" } for) + comment(# "composed_of :balance, :class_name => 'Money'" or {} for "has_many :clients".) + reserved(def) method(options) + instance_variable(@options) + reserved(end) + + comment(# Returns the class for the macro, so "composed_of :balance, :class_name => 'Money'" would return the Money class and) + comment(# "has_many :clients" would return the Client class.) + reserved(def) method(klass)operator(()operator(\)) reserved(end) + + reserved(def) method(class_name) + instance_variable(@class_name) operator(||=) ident(name_to_class_name)operator(()ident(name)operator(.)ident(id2name)operator(\)) + reserved(end) + + reserved(def) method(==)operator(()ident(other_aggregation)operator(\)) + ident(name) operator(==) ident(other_aggregation)operator(.)ident(name) operator(&&) ident(other_aggregation)operator(.)ident(options) operator(&&) ident(active_record) operator(==) ident(other_aggregation)operator(.)ident(active_record) + reserved(end) + reserved(end) + + + comment(# Holds all the meta-data about an aggregation as it was specified in the Active Record class.) + reserved(class) class(AggregateReflection) operator(<) constant(MacroReflection) comment(#:nodoc:) + reserved(def) method(klass) + instance_variable(@klass) operator(||=) constant(Object)operator(.)ident(const_get)operator(()ident(options)operator([)symbol(:class_name)operator(]) operator(||) ident(class_name)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(name_to_class_name)operator(()ident(name)operator(\)) + ident(name)operator(.)ident(capitalize)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(_(.\))delimiter(/)>operator(\)) operator({) operator(|)ident(s)operator(|) global_variable($1)operator(.)ident(capitalize) operator(}) + reserved(end) + reserved(end) + + comment(# Holds all the meta-data about an association as it was specified in the Active Record class.) + reserved(class) class(AssociationReflection) operator(<) constant(MacroReflection) comment(#:nodoc:) + reserved(def) method(klass) + instance_variable(@klass) operator(||=) ident(active_record)operator(.)ident(send)operator(()symbol(:compute_type)operator(,) ident(class_name)operator(\)) + reserved(end) + + reserved(def) method(table_name) + instance_variable(@table_name) operator(||=) ident(klass)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(primary_key_name) + reserved(return) instance_variable(@primary_key_name) reserved(if) instance_variable(@primary_key_name) + reserved(case) + reserved(when) ident(macro) operator(==) symbol(:belongs_to) + instance_variable(@primary_key_name) operator(=) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(class_name)operator(.)ident(foreign_key) + reserved(when) ident(options)operator([)symbol(:as)operator(]) + instance_variable(@primary_key_name) operator(=) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) string<delimiter(")inline<inline_delimiter(#{)ident(options)operator([)symbol(:as)operator(])inline_delimiter(})>content(_id)delimiter(")> + reserved(else) + instance_variable(@primary_key_name) operator(=) ident(options)operator([)symbol(:foreign_key)operator(]) operator(||) ident(active_record)operator(.)ident(name)operator(.)ident(foreign_key) + reserved(end) + reserved(end) + + reserved(def) method(association_foreign_key) + instance_variable(@association_foreign_key) operator(||=) instance_variable(@options)operator([)symbol(:association_foreign_key)operator(]) operator(||) ident(class_name)operator(.)ident(foreign_key) + reserved(end) + + reserved(def) method(counter_cache_column) + reserved(if) ident(options)operator([)symbol(:counter_cache)operator(]) operator(==) pre_constant(true) + string<delimiter(")inline<inline_delimiter(#{)ident(active_record)operator(.)ident(name)operator(.)ident(underscore)operator(.)ident(pluralize)inline_delimiter(})>content(_count)delimiter(")> + reserved(elsif) ident(options)operator([)symbol(:counter_cache)operator(]) + ident(options)operator([)symbol(:counter_cache)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(through_reflection) + instance_variable(@through_reflection) operator(||=) ident(options)operator([)symbol(:through)operator(]) operator(?) ident(active_record)operator(.)ident(reflect_on_association)operator(()ident(options)operator([)symbol(:through)operator(])operator(\)) operator(:) pre_constant(false) + reserved(end) + + comment(# Gets an array of possible :through source reflection names) + comment(#) + comment(# [singularized, pluralized]) + reserved(def) method(source_reflection_names) + instance_variable(@source_reflection_names) operator(||=) operator(()ident(options)operator([)symbol(:source)operator(]) operator(?) operator([)ident(options)operator([)symbol(:source)operator(])operator(]) operator(:) operator([)ident(name)operator(.)ident(to_s)operator(.)ident(singularize)operator(,) ident(name)operator(])operator(\))operator(.)ident(collect) operator({) operator(|)ident(n)operator(|) ident(n)operator(.)ident(to_sym) operator(}) + reserved(end) + + comment(# Gets the source of the through reflection. It checks both a singularized and pluralized form for :belongs_to or :has_many.) + comment(# (The :tags association on Tagging below\)) + comment(# ) + comment(# class Post) + comment(# has_many :tags, :through => :taggings) + comment(# end) + comment(#) + reserved(def) method(source_reflection) + reserved(return) pre_constant(nil) reserved(unless) ident(through_reflection) + instance_variable(@source_reflection) operator(||=) ident(source_reflection_names)operator(.)ident(collect) operator({) operator(|)ident(name)operator(|) ident(through_reflection)operator(.)ident(klass)operator(.)ident(reflect_on_association)operator(()ident(name)operator(\)) operator(})operator(.)ident(compact)operator(.)ident(first) + reserved(end) + + reserved(def) method(check_validity!) + reserved(if) ident(options)operator([)symbol(:through)operator(]) + reserved(if) ident(through_reflection)operator(.)ident(nil?) + ident(raise) constant(HasManyThroughAssociationNotFoundError)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(if) ident(source_reflection)operator(.)ident(nil?) + ident(raise) constant(HasManyThroughSourceAssociationNotFoundError)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(if) ident(source_reflection)operator(.)ident(options)operator([)symbol(:polymorphic)operator(]) + ident(raise) constant(HasManyThroughAssociationPolymorphicError)operator(.)ident(new)operator(()ident(class_name)operator(,) pre_constant(self)operator(,) ident(source_reflection)operator(\)) + reserved(end) + + reserved(unless) operator([)symbol(:belongs_to)operator(,) symbol(:has_many)operator(])operator(.)ident(include?)operator(()ident(source_reflection)operator(.)ident(macro)operator(\)) operator(&&) ident(source_reflection)operator(.)ident(options)operator([)symbol(:through)operator(])operator(.)ident(nil?) + ident(raise) constant(HasManyThroughSourceAssociationMacroError)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + ident(private) + reserved(def) method(name_to_class_name)operator(()ident(name)operator(\)) + reserved(if) ident(name) operator(=)operator(~) regexp<delimiter(/)content(::)delimiter(/)> + ident(name) + reserved(else) + reserved(if) ident(options)operator([)symbol(:class_name)operator(]) + ident(options)operator([)symbol(:class_name)operator(]) + reserved(elsif) ident(through_reflection) comment(# get the class_name of the belongs_to association of the through reflection) + ident(source_reflection)operator(.)ident(class_name) + reserved(else) + ident(class_name) operator(=) ident(name)operator(.)ident(to_s)operator(.)ident(camelize) + ident(class_name) operator(=) ident(class_name)operator(.)ident(singularize) reserved(if) operator([) symbol(:has_many)operator(,) symbol(:has_and_belongs_to_many) operator(])operator(.)ident(include?)operator(()ident(macro)operator(\)) + ident(class_name) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + comment(# Allows programmers to programmatically define a schema in a portable) + comment(# DSL. This means you can define tables, indexes, etc. without using SQL) + comment(# directly, so your applications can more easily support multiple) + comment(# databases.) + comment(#) + comment(# Usage:) + comment(#) + comment(# ActiveRecord::Schema.define do) + comment(# create_table :authors do |t|) + comment(# t.column :name, :string, :null => false) + comment(# end) + comment(#) + comment(# add_index :authors, :name, :unique) + comment(#) + comment(# create_table :posts do |t|) + comment(# t.column :author_id, :integer, :null => false) + comment(# t.column :subject, :string) + comment(# t.column :body, :text) + comment(# t.column :private, :boolean, :default => false) + comment(# end) + comment(#) + comment(# add_index :posts, :author_id) + comment(# end) + comment(#) + comment(# ActiveRecord::Schema is only supported by database adapters that also) + comment(# support migrations, the two features being very similar.) + reserved(class) class(Schema) operator(<) constant(Migration) + ident(private_class_method) symbol(:new) + + comment(# Eval the given block. All methods available to the current connection) + comment(# adapter are available within the block, so you can easily use the) + comment(# database definition DSL to build up your schema (#create_table,) + comment(# #add_index, etc.\).) + comment(#) + comment(# The +info+ hash is optional, and if given is used to define metadata) + comment(# about the current schema (like the schema's version\):) + comment(#) + comment(# ActiveRecord::Schema.define(:version => 15\) do) + comment(# ...) + comment(# end) + reserved(def) pre_constant(self)operator(.)ident(define)operator(()ident(info)operator(=)operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + ident(instance_eval)operator(()operator(&)ident(block)operator(\)) + + reserved(unless) ident(info)operator(.)ident(empty?) + ident(initialize_schema_information) + ident(cols) operator(=) ident(columns)operator(()string<delimiter(')content(schema_info)delimiter(')>operator(\)) + + ident(info) operator(=) ident(info)operator(.)ident(map) reserved(do) operator(|)ident(k)operator(,)ident(v)operator(|) + ident(v) operator(=) constant(Base)operator(.)ident(connection)operator(.)ident(quote)operator(()ident(v)operator(,) ident(cols)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) ident(k)operator(.)ident(to_s) operator(})operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content( = )inline<inline_delimiter(#{)ident(v)inline_delimiter(})>delimiter(")> + reserved(end) + + constant(Base)operator(.)ident(connection)operator(.)ident(update) string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)constant(Migrator)operator(.)ident(schema_info_table_name)inline_delimiter(})>content( SET )inline<inline_delimiter(#{)ident(info)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + comment(# This class is used to dump the database schema for some connection to some) + comment(# output format (i.e., ActiveRecord::Schema\).) + reserved(class) class(SchemaDumper) comment(#:nodoc:) + ident(private_class_method) symbol(:new) + + comment(# A list of tables which should not be dumped to the schema. ) + comment(# Acceptable values are strings as well as regexp.) + comment(# This setting is only used if ActiveRecord::Base.schema_format == :ruby) + ident(cattr_accessor) symbol(:ignore_tables) + class_variable(@@ignore_tables) operator(=) operator([)operator(]) + + reserved(def) pre_constant(self)operator(.)ident(dump)operator(()ident(connection)operator(=)constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) ident(stream)operator(=)constant(STDOUT)operator(\)) + ident(new)operator(()ident(connection)operator(\))operator(.)ident(dump)operator(()ident(stream)operator(\)) + ident(stream) + reserved(end) + + reserved(def) method(dump)operator(()ident(stream)operator(\)) + ident(header)operator(()ident(stream)operator(\)) + ident(tables)operator(()ident(stream)operator(\)) + ident(trailer)operator(()ident(stream)operator(\)) + ident(stream) + reserved(end) + + ident(private) + + reserved(def) method(initialize)operator(()ident(connection)operator(\)) + instance_variable(@connection) operator(=) ident(connection) + instance_variable(@types) operator(=) instance_variable(@connection)operator(.)ident(native_database_types) + instance_variable(@info) operator(=) instance_variable(@connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT * FROM schema_info)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(header)operator(()ident(stream)operator(\)) + ident(define_params) operator(=) instance_variable(@info) operator(?) string<delimiter(")content(:version => )inline<inline_delimiter(#{)instance_variable(@info)operator([)string<delimiter(')content(version)delimiter(')>operator(])inline_delimiter(})>delimiter(")> operator(:) string<delimiter(")delimiter(")> + + ident(stream)operator(.)ident(puts) string<delimiter(<<HEADER)>string<content( +# This file is autogenerated. Instead of editing this file, please use the +# migrations feature of ActiveRecord to incrementally modify your database, and +# then regenerate this schema definition. + +ActiveRecord::Schema.define()inline<inline_delimiter(#{)ident(define_params)inline_delimiter(})>content(\) do +)delimiter( +HEADER)> + reserved(end) + + reserved(def) method(trailer)operator(()ident(stream)operator(\)) + ident(stream)operator(.)ident(puts) string<delimiter(")content(end)delimiter(")> + reserved(end) + + reserved(def) method(tables)operator(()ident(stream)operator(\)) + instance_variable(@connection)operator(.)ident(tables)operator(.)ident(sort)operator(.)ident(each) reserved(do) operator(|)ident(tbl)operator(|) + reserved(next) reserved(if) operator([)string<delimiter(")content(schema_info)delimiter(")>operator(,) ident(ignore_tables)operator(])operator(.)ident(flatten)operator(.)ident(any?) reserved(do) operator(|)ident(ignored)operator(|) + reserved(case) ident(ignored) + reserved(when) constant(String)operator(:) ident(tbl) operator(==) ident(ignored) + reserved(when) constant(Regexp)operator(:) ident(tbl) operator(=)operator(~) ident(ignored) + reserved(else) + ident(raise) constant(StandardError)operator(,) string<delimiter(')content(ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.)delimiter(')> + reserved(end) + reserved(end) + ident(table)operator(()ident(tbl)operator(,) ident(stream)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(table)operator(()ident(table)operator(,) ident(stream)operator(\)) + ident(columns) operator(=) instance_variable(@connection)operator(.)ident(columns)operator(()ident(table)operator(\)) + reserved(begin) + ident(tbl) operator(=) constant(StringIO)operator(.)ident(new) + + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:pk_and_sequence_for)operator(\)) + ident(pk)operator(,) ident(pk_seq) operator(=) instance_variable(@connection)operator(.)ident(pk_and_sequence_for)operator(()ident(table)operator(\)) + reserved(end) + ident(pk) operator(||=) string<delimiter(')content(id)delimiter(')> + + ident(tbl)operator(.)ident(print) string<delimiter(")content( create_table )inline<inline_delimiter(#{)ident(table)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(if) ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) ident(pk) operator(}) + reserved(if) ident(pk) operator(!=) string<delimiter(')content(id)delimiter(')> + ident(tbl)operator(.)ident(print) string<delimiter(%Q()content(, :primary_key => ")inline<inline_delimiter(#{)ident(pk)inline_delimiter(})>content(")delimiter(\))> + reserved(end) + reserved(else) + ident(tbl)operator(.)ident(print) string<delimiter(")content(, :id => false)delimiter(")> + reserved(end) + ident(tbl)operator(.)ident(print) string<delimiter(")content(, :force => true)delimiter(")> + ident(tbl)operator(.)ident(puts) string<delimiter(")content( do |t|)delimiter(")> + + ident(columns)operator(.)ident(each) reserved(do) operator(|)ident(column)operator(|) + ident(raise) constant(StandardError)operator(,) string<delimiter(")content(Unknown type ')inline<inline_delimiter(#{)ident(column)operator(.)ident(sql_type)inline_delimiter(})>content(' for column ')inline<inline_delimiter(#{)ident(column)operator(.)ident(name)inline_delimiter(})>content(')delimiter(")> reserved(if) instance_variable(@types)operator([)ident(column)operator(.)ident(type)operator(])operator(.)ident(nil?) + reserved(next) reserved(if) ident(column)operator(.)ident(name) operator(==) ident(pk) + ident(tbl)operator(.)ident(print) string<delimiter(")content( t.column )inline<inline_delimiter(#{)ident(column)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(column)operator(.)ident(type)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + ident(tbl)operator(.)ident(print) string<delimiter(")content(, :limit => )inline<inline_delimiter(#{)ident(column)operator(.)ident(limit)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> reserved(if) ident(column)operator(.)ident(limit) operator(!=) instance_variable(@types)operator([)ident(column)operator(.)ident(type)operator(])operator([)symbol(:limit)operator(]) + ident(tbl)operator(.)ident(print) string<delimiter(")content(, :default => )inline<inline_delimiter(#{)ident(column)operator(.)ident(default)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> reserved(if) operator(!)ident(column)operator(.)ident(default)operator(.)ident(nil?) + ident(tbl)operator(.)ident(print) string<delimiter(")content(, :null => false)delimiter(")> reserved(if) operator(!)ident(column)operator(.)ident(null) + ident(tbl)operator(.)ident(puts) + reserved(end) + + ident(tbl)operator(.)ident(puts) string<delimiter(")content( end)delimiter(")> + ident(tbl)operator(.)ident(puts) + + ident(indexes)operator(()ident(table)operator(,) ident(tbl)operator(\)) + + ident(tbl)operator(.)ident(rewind) + ident(stream)operator(.)ident(print) ident(tbl)operator(.)ident(read) + reserved(rescue) operator(=)operator(>) ident(e) + ident(stream)operator(.)ident(puts) string<delimiter(")content(# Could not dump table )inline<inline_delimiter(#{)ident(table)operator(.)ident(inspect)inline_delimiter(})>content( because of following )inline<inline_delimiter(#{)ident(e)operator(.)ident(class)inline_delimiter(})>delimiter(")> + ident(stream)operator(.)ident(puts) string<delimiter(")content(# )inline<inline_delimiter(#{)ident(e)operator(.)ident(message)inline_delimiter(})>delimiter(")> + ident(stream)operator(.)ident(puts) + reserved(end) + + ident(stream) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table)operator(,) ident(stream)operator(\)) + ident(indexes) operator(=) instance_variable(@connection)operator(.)ident(indexes)operator(()ident(table)operator(\)) + ident(indexes)operator(.)ident(each) reserved(do) operator(|)ident(index)operator(|) + ident(stream)operator(.)ident(print) string<delimiter(")content( add_index )inline<inline_delimiter(#{)ident(index)operator(.)ident(table)operator(.)ident(inspect)inline_delimiter(})>content(, )inline<inline_delimiter(#{)ident(index)operator(.)ident(columns)operator(.)ident(inspect)inline_delimiter(})>content(, :name => )inline<inline_delimiter(#{)ident(index)operator(.)ident(name)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + ident(stream)operator(.)ident(print) string<delimiter(")content(, :unique => true)delimiter(")> reserved(if) ident(index)operator(.)ident(unique) + ident(stream)operator(.)ident(puts) + reserved(end) + ident(stream)operator(.)ident(puts) reserved(unless) ident(indexes)operator(.)ident(empty?) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + comment(# Active Records will automatically record creation and/or update timestamps of database objects) + comment(# if fields of the names created_at/created_on or updated_at/updated_on are present. This module is) + comment(# automatically included, so you don't need to do that manually.) + comment(#) + comment(# This behavior can be turned off by setting <tt>ActiveRecord::Base.record_timestamps = false</tt>.) + comment(# This behavior by default uses local time, but can use UTC by setting <tt>ActiveRecord::Base.default_timezone = :utc</tt>) + reserved(module) class(Timestamp) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:create_without_timestamps)operator(,) symbol(:create) + ident(alias_method) symbol(:create)operator(,) symbol(:create_with_timestamps) + + ident(alias_method) symbol(:update_without_timestamps)operator(,) symbol(:update) + ident(alias_method) symbol(:update)operator(,) symbol(:update_with_timestamps) + reserved(end) + reserved(end) + + reserved(def) method(create_with_timestamps) comment(#:nodoc:) + reserved(if) ident(record_timestamps) + ident(t) operator(=) operator(() pre_constant(self)operator(.)ident(class)operator(.)ident(default_timezone) operator(==) symbol(:utc) operator(?) constant(Time)operator(.)ident(now)operator(.)ident(utc) operator(:) constant(Time)operator(.)ident(now) operator(\)) + ident(write_attribute)operator(()string<delimiter(')content(created_at)delimiter(')>operator(,) ident(t)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:created_at)operator(\)) operator(&&) ident(created_at)operator(.)ident(nil?) + ident(write_attribute)operator(()string<delimiter(')content(created_on)delimiter(')>operator(,) ident(t)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:created_on)operator(\)) operator(&&) ident(created_on)operator(.)ident(nil?) + + ident(write_attribute)operator(()string<delimiter(')content(updated_at)delimiter(')>operator(,) ident(t)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:updated_at)operator(\)) + ident(write_attribute)operator(()string<delimiter(')content(updated_on)delimiter(')>operator(,) ident(t)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:updated_on)operator(\)) + reserved(end) + ident(create_without_timestamps) + reserved(end) + + reserved(def) method(update_with_timestamps) comment(#:nodoc:) + reserved(if) ident(record_timestamps) + ident(t) operator(=) operator(() pre_constant(self)operator(.)ident(class)operator(.)ident(default_timezone) operator(==) symbol(:utc) operator(?) constant(Time)operator(.)ident(now)operator(.)ident(utc) operator(:) constant(Time)operator(.)ident(now) operator(\)) + ident(write_attribute)operator(()string<delimiter(')content(updated_at)delimiter(')>operator(,) ident(t)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:updated_at)operator(\)) + ident(write_attribute)operator(()string<delimiter(')content(updated_on)delimiter(')>operator(,) ident(t)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:updated_on)operator(\)) + reserved(end) + ident(update_without_timestamps) + reserved(end) + reserved(end) + + reserved(class) class(Base) + comment(# Records the creation date and possibly time in created_on (date only\) or created_at (date and time\) and the update date and possibly) + comment(# time in updated_on and updated_at. This only happens if the object responds to either of these messages, which they will do automatically) + comment(# if the table has columns of either of these names. This feature is turned on by default.) + class_variable(@@record_timestamps) operator(=) pre_constant(true) + ident(cattr_accessor) symbol(:record_timestamps) + + comment(# deprecated: use ActiveRecord::Base.default_timezone instead.) + class_variable(@@timestamps_gmt) operator(=) pre_constant(false) + reserved(def) pre_constant(self)operator(.)ident(timestamps_gmt)operator(=)operator(() ident(gmt) operator(\)) comment(#:nodoc:) + ident(warn) string<delimiter(")content(timestamps_gmt= is deprecated. use default_timezone= instead)delimiter(")> + pre_constant(self)operator(.)ident(default_timezone) operator(=) operator(() ident(gmt) operator(?) symbol(:utc) operator(:) symbol(:local) operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(timestamps_gmt) comment(#:nodoc:) + ident(warn) string<delimiter(")content(timestamps_gmt is deprecated. use default_timezone instead)delimiter(")> + pre_constant(self)operator(.)ident(default_timezone) operator(==) symbol(:utc) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(active_record/vendor/simple.rb)delimiter(')> +constant(Transaction)operator(::)constant(Simple)operator(.)ident(send)operator(()symbol(:remove_method)operator(,) symbol(:transaction)operator(\)) +ident(require) string<delimiter(')content(thread)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(module) class(Transactions) comment(# :nodoc:) + constant(TRANSACTION_MUTEX) operator(=) constant(Mutex)operator(.)ident(new) + + reserved(class) class(TransactionError) operator(<) constant(ActiveRecordError) comment(# :nodoc:) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:destroy_without_transactions)operator(,) symbol(:destroy) + ident(alias_method) symbol(:destroy)operator(,) symbol(:destroy_with_transactions) + + ident(alias_method) symbol(:save_without_transactions)operator(,) symbol(:save) + ident(alias_method) symbol(:save)operator(,) symbol(:save_with_transactions) + reserved(end) + reserved(end) + + comment(# Transactions are protective blocks where SQL statements are only permanent if they can all succeed as one atomic action. ) + comment(# The classic example is a transfer between two accounts where you can only have a deposit if the withdrawal succeeded and) + comment(# vice versa. Transactions enforce the integrity of the database and guard the data against program errors or database break-downs.) + comment(# So basically you should use transaction blocks whenever you have a number of statements that must be executed together or) + comment(# not at all. Example:) + comment(#) + comment(# transaction do) + comment(# david.withdrawal(100\)) + comment(# mary.deposit(100\)) + comment(# end) + comment(#) + comment(# This example will only take money from David and give to Mary if neither +withdrawal+ nor +deposit+ raises an exception.) + comment(# Exceptions will force a ROLLBACK that returns the database to the state before the transaction was begun. Be aware, though,) + comment(# that the objects by default will _not_ have their instance data returned to their pre-transactional state.) + comment(#) + comment(# == Transactions are not distributed across database connections) + comment(#) + comment(# A transaction acts on a single database connection. If you have) + comment(# multiple class-specific databases, the transaction will not protect) + comment(# interaction among them. One workaround is to begin a transaction) + comment(# on each class whose models you alter:) + comment(#) + comment(# Student.transaction do) + comment(# Course.transaction do) + comment(# course.enroll(student\)) + comment(# student.units += course.units) + comment(# end) + comment(# end) + comment(#) + comment(# This is a poor solution, but full distributed transactions are beyond) + comment(# the scope of Active Record.) + comment(#) + comment(# == Save and destroy are automatically wrapped in a transaction) + comment(#) + comment(# Both Base#save and Base#destroy come wrapped in a transaction that ensures that whatever you do in validations or callbacks) + comment(# will happen under the protected cover of a transaction. So you can use validations to check for values that the transaction) + comment(# depend on or you can raise exceptions in the callbacks to rollback.) + comment(#) + comment(# == Object-level transactions) + comment(#) + comment(# You can enable object-level transactions for Active Record objects, though. You do this by naming each of the Active Records) + comment(# that you want to enable object-level transactions for, like this:) + comment(#) + comment(# Account.transaction(david, mary\) do) + comment(# david.withdrawal(100\)) + comment(# mary.deposit(100\)) + comment(# end) + comment(#) + comment(# If the transaction fails, David and Mary will be returned to their pre-transactional state. No money will have changed hands in) + comment(# neither object nor database.) + comment(#) + comment(# == Exception handling) + comment(#) + comment(# Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK\), so you) + comment(# should be ready to catch those in your application code.) + comment(#) + comment(# Tribute: Object-level transactions are implemented by Transaction::Simple by Austin Ziegler.) + reserved(module) class(ClassMethods) + reserved(def) method(transaction)operator(()operator(*)ident(objects)operator(,) operator(&)ident(block)operator(\)) + ident(previous_handler) operator(=) ident(trap)operator(()string<delimiter(')content(TERM)delimiter(')>operator(\)) operator({) ident(raise) constant(TransactionError)operator(,) string<delimiter(")content(Transaction aborted)delimiter(")> operator(}) + ident(lock_mutex) + + reserved(begin) + ident(objects)operator(.)ident(each) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(extend)operator(()constant(Transaction)operator(::)constant(Simple)operator(\)) operator(}) + ident(objects)operator(.)ident(each) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(start_transaction) operator(}) + + ident(result) operator(=) ident(connection)operator(.)ident(transaction)operator(()constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(start_db_transaction)delimiter(')>operator(])operator(,) operator(&)ident(block)operator(\)) + + ident(objects)operator(.)ident(each) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(commit_transaction) operator(}) + reserved(return) ident(result) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(object_transaction_rollback) + ident(objects)operator(.)ident(each) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(abort_transaction) operator(}) + ident(raise) + reserved(ensure) + ident(unlock_mutex) + ident(trap)operator(()string<delimiter(')content(TERM)delimiter(')>operator(,) ident(previous_handler)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(lock_mutex)comment(#:nodoc:) + constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(open_transactions)delimiter(')>operator(]) operator(||=) integer(0) + constant(TRANSACTION_MUTEX)operator(.)ident(lock) reserved(if) constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(open_transactions)delimiter(')>operator(]) operator(==) integer(0) + constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(start_db_transaction)delimiter(')>operator(]) operator(=) operator(()constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(open_transactions)delimiter(')>operator(]) operator(==) integer(0)operator(\)) + constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(open_transactions)delimiter(')>operator(]) operator(+=) integer(1) + reserved(end) + + reserved(def) method(unlock_mutex)comment(#:nodoc:) + constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(open_transactions)delimiter(')>operator(]) operator(-=) integer(1) + constant(TRANSACTION_MUTEX)operator(.)ident(unlock) reserved(if) constant(Thread)operator(.)ident(current)operator([)string<delimiter(')content(open_transactions)delimiter(')>operator(]) operator(==) integer(0) + reserved(end) + reserved(end) + + reserved(def) method(transaction)operator(()operator(*)ident(objects)operator(,) operator(&)ident(block)operator(\)) + pre_constant(self)operator(.)ident(class)operator(.)ident(transaction)operator(()operator(*)ident(objects)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(destroy_with_transactions) comment(#:nodoc:) + ident(transaction) operator({) ident(destroy_without_transactions) operator(}) + reserved(end) + + reserved(def) method(save_with_transactions)operator(()ident(perform_validation) operator(=) pre_constant(true)operator(\)) comment(#:nodoc:) + ident(transaction) operator({) ident(save_without_transactions)operator(()ident(perform_validation)operator(\)) operator(}) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + comment(# Raised by save! and create! when the record is invalid. Use the) + comment(# record method to retrieve the record which did not validate.) + comment(# begin) + comment(# complex_operation_that_calls_save!_internally) + comment(# rescue ActiveRecord::RecordInvalid => invalid) + comment(# puts invalid.record.errors) + comment(# end) + reserved(class) class(RecordInvalid) operator(<) constant(ActiveRecordError) comment(#:nodoc:) + ident(attr_reader) symbol(:record) + reserved(def) method(initialize)operator(()ident(record)operator(\)) + instance_variable(@record) operator(=) ident(record) + reserved(super)operator(()string<delimiter(")content(Validation failed: )inline<inline_delimiter(#{)instance_variable(@record)operator(.)ident(errors)operator(.)ident(full_messages)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + + comment(# Active Record validation is reported to and from this object, which is used by Base#save to) + comment(# determine whether the object in a valid state to be saved. See usage example in Validations.) + reserved(class) class(Errors) + ident(include) constant(Enumerable) + + reserved(def) method(initialize)operator(()ident(base)operator(\)) comment(# :nodoc:) + instance_variable(@base)operator(,) instance_variable(@errors) operator(=) ident(base)operator(,) operator({)operator(}) + reserved(end) + + class_variable(@@default_error_messages) operator(=) operator({) + symbol(:inclusion) operator(=)operator(>) string<delimiter(")content(is not included in the list)delimiter(")>operator(,) + symbol(:exclusion) operator(=)operator(>) string<delimiter(")content(is reserved)delimiter(")>operator(,) + symbol(:invalid) operator(=)operator(>) string<delimiter(")content(is invalid)delimiter(")>operator(,) + symbol(:confirmation) operator(=)operator(>) string<delimiter(")content(doesn't match confirmation)delimiter(")>operator(,) + symbol(:accepted) operator(=)operator(>) string<delimiter(")content(must be accepted)delimiter(")>operator(,) + symbol(:empty) operator(=)operator(>) string<delimiter(")content(can't be empty)delimiter(")>operator(,) + symbol(:blank) operator(=)operator(>) string<delimiter(")content(can't be blank)delimiter(")>operator(,) + symbol(:too_long) operator(=)operator(>) string<delimiter(")content(is too long (maximum is %d characters\))delimiter(")>operator(,) + symbol(:too_short) operator(=)operator(>) string<delimiter(")content(is too short (minimum is %d characters\))delimiter(")>operator(,) + symbol(:wrong_length) operator(=)operator(>) string<delimiter(")content(is the wrong length (should be %d characters\))delimiter(")>operator(,) + symbol(:taken) operator(=)operator(>) string<delimiter(")content(has already been taken)delimiter(")>operator(,) + symbol(:not_a_number) operator(=)operator(>) string<delimiter(")content(is not a number)delimiter(")> + operator(}) + + comment(# Holds a hash with all the default error messages, such that they can be replaced by your own copy or localizations.) + ident(cattr_accessor) symbol(:default_error_messages) + + + comment(# Adds an error to the base object instead of any particular attribute. This is used) + comment(# to report errors that don't tie to any specific attribute, but rather to the object) + comment(# as a whole. These error messages don't get prepended with any field name when iterating) + comment(# with each_full, so they should be complete sentences.) + reserved(def) method(add_to_base)operator(()ident(msg)operator(\)) + ident(add)operator(()symbol(:base)operator(,) ident(msg)operator(\)) + reserved(end) + + comment(# Adds an error message (+msg+\) to the +attribute+, which will be returned on a call to <tt>on(attribute\)</tt>) + comment(# for the same attribute and ensure that this error object returns false when asked if <tt>empty?</tt>. More than one) + comment(# error can be added to the same +attribute+ in which case an array will be returned on a call to <tt>on(attribute\)</tt>.) + comment(# If no +msg+ is supplied, "invalid" is assumed.) + reserved(def) method(add)operator(()ident(attribute)operator(,) ident(msg) operator(=) class_variable(@@default_error_messages)operator([)symbol(:invalid)operator(])operator(\)) + instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(]) operator(=) operator([)operator(]) reserved(if) instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(])operator(.)ident(nil?) + instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(]) operator(<<) ident(msg) + reserved(end) + + comment(# Will add an error message to each of the attributes in +attributes+ that is empty.) + reserved(def) method(add_on_empty)operator(()ident(attributes)operator(,) ident(msg) operator(=) class_variable(@@default_error_messages)operator([)symbol(:empty)operator(])operator(\)) + reserved(for) ident(attr) reserved(in) operator([)ident(attributes)operator(])operator(.)ident(flatten) + ident(value) operator(=) instance_variable(@base)operator(.)ident(respond_to?)operator(()ident(attr)operator(.)ident(to_s)operator(\)) operator(?) instance_variable(@base)operator(.)ident(send)operator(()ident(attr)operator(.)ident(to_s)operator(\)) operator(:) instance_variable(@base)operator([)ident(attr)operator(.)ident(to_s)operator(]) + ident(is_empty) operator(=) ident(value)operator(.)ident(respond_to?)operator(()string<delimiter(")content(empty?)delimiter(")>operator(\)) operator(?) ident(value)operator(.)ident(empty?) operator(:) pre_constant(false) + ident(add)operator(()ident(attr)operator(,) ident(msg)operator(\)) reserved(unless) operator(!)ident(value)operator(.)ident(nil?) operator(&&) operator(!)ident(is_empty) + reserved(end) + reserved(end) + + comment(# Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?\).) + reserved(def) method(add_on_blank)operator(()ident(attributes)operator(,) ident(msg) operator(=) class_variable(@@default_error_messages)operator([)symbol(:blank)operator(])operator(\)) + reserved(for) ident(attr) reserved(in) operator([)ident(attributes)operator(])operator(.)ident(flatten) + ident(value) operator(=) instance_variable(@base)operator(.)ident(respond_to?)operator(()ident(attr)operator(.)ident(to_s)operator(\)) operator(?) instance_variable(@base)operator(.)ident(send)operator(()ident(attr)operator(.)ident(to_s)operator(\)) operator(:) instance_variable(@base)operator([)ident(attr)operator(.)ident(to_s)operator(]) + ident(add)operator(()ident(attr)operator(,) ident(msg)operator(\)) reserved(if) ident(value)operator(.)ident(blank?) + reserved(end) + reserved(end) + + comment(# Will add an error message to each of the attributes in +attributes+ that has a length outside of the passed boundary +range+.) + comment(# If the length is above the boundary, the too_long_msg message will be used. If below, the too_short_msg.) + reserved(def) method(add_on_boundary_breaking)operator(()ident(attributes)operator(,) ident(range)operator(,) ident(too_long_msg) operator(=) class_variable(@@default_error_messages)operator([)symbol(:too_long)operator(])operator(,) ident(too_short_msg) operator(=) class_variable(@@default_error_messages)operator([)symbol(:too_short)operator(])operator(\)) + reserved(for) ident(attr) reserved(in) operator([)ident(attributes)operator(])operator(.)ident(flatten) + ident(value) operator(=) instance_variable(@base)operator(.)ident(respond_to?)operator(()ident(attr)operator(.)ident(to_s)operator(\)) operator(?) instance_variable(@base)operator(.)ident(send)operator(()ident(attr)operator(.)ident(to_s)operator(\)) operator(:) instance_variable(@base)operator([)ident(attr)operator(.)ident(to_s)operator(]) + ident(add)operator(()ident(attr)operator(,) ident(too_short_msg) operator(%) ident(range)operator(.)ident(begin)operator(\)) reserved(if) ident(value) operator(&&) ident(value)operator(.)ident(length) operator(<) ident(range)operator(.)ident(begin) + ident(add)operator(()ident(attr)operator(,) ident(too_long_msg) operator(%) ident(range)operator(.)ident(end)operator(\)) reserved(if) ident(value) operator(&&) ident(value)operator(.)ident(length) operator(>) ident(range)operator(.)ident(end) + reserved(end) + reserved(end) + + reserved(alias) symbol(:add_on_boundry_breaking) symbol(:add_on_boundary_breaking) + + comment(# Returns true if the specified +attribute+ has errors associated with it.) + reserved(def) method(invalid?)operator(()ident(attribute)operator(\)) + operator(!)instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(])operator(.)ident(nil?) + reserved(end) + + comment(# * Returns nil, if no errors are associated with the specified +attribute+.) + comment(# * Returns the error message, if one error is associated with the specified +attribute+.) + comment(# * Returns an array of error messages, if more than one error is associated with the specified +attribute+.) + reserved(def) method(on)operator(()ident(attribute)operator(\)) + reserved(if) instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(])operator(.)ident(nil?) + pre_constant(nil) + reserved(elsif) instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(])operator(.)ident(length) operator(==) integer(1) + instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(])operator(.)ident(first) + reserved(else) + instance_variable(@errors)operator([)ident(attribute)operator(.)ident(to_s)operator(]) + reserved(end) + reserved(end) + + reserved(alias) symbol(:[]) symbol(:on) + + comment(# Returns errors assigned to base object through add_to_base according to the normal rules of on(attribute\).) + reserved(def) method(on_base) + ident(on)operator(()symbol(:base)operator(\)) + reserved(end) + + comment(# Yields each attribute and associated message per error added.) + reserved(def) method(each) + instance_variable(@errors)operator(.)ident(each_key) operator({) operator(|)ident(attr)operator(|) instance_variable(@errors)operator([)ident(attr)operator(])operator(.)ident(each) operator({) operator(|)ident(msg)operator(|) reserved(yield) ident(attr)operator(,) ident(msg) operator(}) operator(}) + reserved(end) + + comment(# Yields each full error message added. So Person.errors.add("first_name", "can't be empty"\) will be returned) + comment(# through iteration as "First name can't be empty".) + reserved(def) method(each_full) + ident(full_messages)operator(.)ident(each) operator({) operator(|)ident(msg)operator(|) reserved(yield) ident(msg) operator(}) + reserved(end) + + comment(# Returns all the full error messages in an array.) + reserved(def) method(full_messages) + ident(full_messages) operator(=) operator([)operator(]) + + instance_variable(@errors)operator(.)ident(each_key) reserved(do) operator(|)ident(attr)operator(|) + instance_variable(@errors)operator([)ident(attr)operator(])operator(.)ident(each) reserved(do) operator(|)ident(msg)operator(|) + reserved(next) reserved(if) ident(msg)operator(.)ident(nil?) + + reserved(if) ident(attr) operator(==) string<delimiter(")content(base)delimiter(")> + ident(full_messages) operator(<<) ident(msg) + reserved(else) + ident(full_messages) operator(<<) instance_variable(@base)operator(.)ident(class)operator(.)ident(human_attribute_name)operator(()ident(attr)operator(\)) operator(+) string<delimiter(")content( )delimiter(")> operator(+) ident(msg) + reserved(end) + reserved(end) + reserved(end) + + reserved(return) ident(full_messages) + reserved(end) + + comment(# Returns true if no errors have been added.) + reserved(def) method(empty?) + reserved(return) instance_variable(@errors)operator(.)ident(empty?) + reserved(end) + + comment(# Removes all the errors that have been added.) + reserved(def) method(clear) + instance_variable(@errors) operator(=) operator({)operator(}) + reserved(end) + + comment(# Returns the total number of errors added. Two errors added to the same attribute will be counted as such) + comment(# with this as well.) + reserved(def) method(size) + ident(error_count) operator(=) integer(0) + instance_variable(@errors)operator(.)ident(each_value) operator({) operator(|)ident(attribute)operator(|) ident(error_count) operator(+=) ident(attribute)operator(.)ident(length) operator(}) + ident(error_count) + reserved(end) + + ident(alias_method) symbol(:count)operator(,) symbol(:size) + ident(alias_method) symbol(:length)operator(,) symbol(:size) + reserved(end) + + + comment(# Active Records implement validation by overwriting Base#validate (or the variations, +validate_on_create+ and) + comment(# +validate_on_update+\). Each of these methods can inspect the state of the object, which usually means ensuring) + comment(# that a number of attributes have a certain value (such as not empty, within a given range, matching a certain regular expression\).) + comment(#) + comment(# Example:) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# protected) + comment(# def validate) + comment(# errors.add_on_empty %w( first_name last_name \)) + comment(# errors.add("phone_number", "has invalid format"\) unless phone_number =~ /[0-9]*/) + comment(# end) + comment(#) + comment(# def validate_on_create # is only run the first time a new object is saved) + comment(# unless valid_discount?(membership_discount\)) + comment(# errors.add("membership_discount", "has expired"\)) + comment(# end) + comment(# end) + comment(#) + comment(# def validate_on_update) + comment(# errors.add_to_base("No changes have occurred"\) if unchanged_attributes?) + comment(# end) + comment(# end) + comment(#) + comment(# person = Person.new("first_name" => "David", "phone_number" => "what?"\)) + comment(# person.save # => false (and doesn't do the save\)) + comment(# person.errors.empty? # => false) + comment(# person.errors.count # => 2) + comment(# person.errors.on "last_name" # => "can't be empty") + comment(# person.errors.on "phone_number" # => "has invalid format") + comment(# person.errors.each_full { |msg| puts msg }) + comment(# # => "Last name can't be empty\\n" +) + comment(# "Phone number has invalid format") + comment(#) + comment(# person.attributes = { "last_name" => "Heinemeier", "phone_number" => "555-555" }) + comment(# person.save # => true (and person is now saved in the database\)) + comment(#) + comment(# An +Errors+ object is automatically created for every Active Record.) + comment(#) + comment(# Please do have a look at ActiveRecord::Validations::ClassMethods for a higher level of validations.) + reserved(module) class(Validations) + constant(VALIDATIONS) operator(=) string<delimiter(%w()content( validate validate_on_create validate_on_update )delimiter(\))> + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(# :nodoc:) + reserved(super) + ident(base)operator(.)ident(extend) constant(ClassMethods) + ident(base)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:save_without_validation)operator(,) symbol(:save) + ident(alias_method) symbol(:save)operator(,) symbol(:save_with_validation) + + ident(alias_method) symbol(:save_without_validation!)operator(,) symbol(:save!) + ident(alias_method) symbol(:save!)operator(,) symbol(:save_with_validation!) + + ident(alias_method) symbol(:update_attribute_without_validation_skipping)operator(,) symbol(:update_attribute) + ident(alias_method) symbol(:update_attribute)operator(,) symbol(:update_attribute_with_validation_skipping) + reserved(end) + reserved(end) + + comment(# All of the following validations are defined in the class scope of the model that you're interested in validating.) + comment(# They offer a more declarative way of specifying when the model is valid and when it is not. It is recommended to use) + comment(# these over the low-level calls to validate and validate_on_create when possible.) + reserved(module) class(ClassMethods) + constant(DEFAULT_VALIDATION_OPTIONS) operator(=) operator({) + symbol(:on) operator(=)operator(>) symbol(:save)operator(,) + symbol(:allow_nil) operator(=)operator(>) pre_constant(false)operator(,) + symbol(:message) operator(=)operator(>) pre_constant(nil) + operator(})operator(.)ident(freeze) + + constant(ALL_RANGE_OPTIONS) operator(=) operator([) symbol(:is)operator(,) symbol(:within)operator(,) symbol(:in)operator(,) symbol(:minimum)operator(,) symbol(:maximum) operator(])operator(.)ident(freeze) + + reserved(def) method(validate)operator(()operator(*)ident(methods)operator(,) operator(&)ident(block)operator(\)) + ident(methods) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(write_inheritable_set)operator(()symbol(:validate)operator(,) ident(methods)operator(\)) + reserved(end) + + reserved(def) method(validate_on_create)operator(()operator(*)ident(methods)operator(,) operator(&)ident(block)operator(\)) + ident(methods) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(write_inheritable_set)operator(()symbol(:validate_on_create)operator(,) ident(methods)operator(\)) + reserved(end) + + reserved(def) method(validate_on_update)operator(()operator(*)ident(methods)operator(,) operator(&)ident(block)operator(\)) + ident(methods) operator(<<) ident(block) reserved(if) ident(block_given?) + ident(write_inheritable_set)operator(()symbol(:validate_on_update)operator(,) ident(methods)operator(\)) + reserved(end) + + reserved(def) method(condition_block?)operator(()ident(condition)operator(\)) + ident(condition)operator(.)ident(respond_to?)operator(()string<delimiter(")content(call)delimiter(")>operator(\)) operator(&&) operator(()ident(condition)operator(.)ident(arity) operator(==) integer(1) operator(||) ident(condition)operator(.)ident(arity) operator(==) integer(-1)operator(\)) + reserved(end) + + comment(# Determine from the given condition (whether a block, procedure, method or string\)) + comment(# whether or not to validate the record. See #validates_each.) + reserved(def) method(evaluate_condition)operator(()ident(condition)operator(,) ident(record)operator(\)) + reserved(case) ident(condition) + reserved(when) constant(Symbol)operator(:) ident(record)operator(.)ident(send)operator(()ident(condition)operator(\)) + reserved(when) constant(String)operator(:) ident(eval)operator(()ident(condition)operator(,) ident(binding)operator(\)) + reserved(else) + reserved(if) ident(condition_block?)operator(()ident(condition)operator(\)) + ident(condition)operator(.)ident(call)operator(()ident(record)operator(\)) + reserved(else) + ident(raise)operator(() + constant(ActiveRecordError)operator(,) + string<delimiter(")content(Validations need to be either a symbol, string (to be eval'ed\), proc/method, or )delimiter(")> operator(+) + string<delimiter(")content(class implementing a static validation method)delimiter(")> + operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Validates each attribute against a block.) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_each :first_name, :last_name do |record, attr, value|) + comment(# record.errors.add attr, 'starts with z.' if value[0] == ?z) + comment(# end) + comment(# end) + comment(#) + comment(# Options:) + comment(# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>allow_nil</tt> - Skip validation if attribute is nil.) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_each)operator(()operator(*)ident(attrs)operator(\)) + ident(options) operator(=) ident(attrs)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(attrs)operator(.)ident(pop)operator(.)ident(symbolize_keys) operator(:) operator({)operator(}) + ident(attrs) operator(=) ident(attrs)operator(.)ident(flatten) + + comment(# Declare the validation.) + ident(send)operator(()ident(validation_method)operator(()ident(options)operator([)symbol(:on)operator(]) operator(||) symbol(:save)operator(\))operator(\)) reserved(do) operator(|)ident(record)operator(|) + comment(# Don't validate when there is an :if condition and that condition is false) + reserved(unless) ident(options)operator([)symbol(:if)operator(]) operator(&&) operator(!)ident(evaluate_condition)operator(()ident(options)operator([)symbol(:if)operator(])operator(,) ident(record)operator(\)) + ident(attrs)operator(.)ident(each) reserved(do) operator(|)ident(attr)operator(|) + ident(value) operator(=) ident(record)operator(.)ident(send)operator(()ident(attr)operator(\)) + reserved(next) reserved(if) ident(value)operator(.)ident(nil?) operator(&&) ident(options)operator([)symbol(:allow_nil)operator(]) + reserved(yield) ident(record)operator(,) ident(attr)operator(,) ident(value) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:) + comment(#) + comment(# Model:) + comment(# class Person < ActiveRecord::Base) + comment(# validates_confirmation_of :user_name, :password) + comment(# validates_confirmation_of :email_address, :message => "should match confirmation") + comment(# end) + comment(#) + comment(# View:) + comment(# <%= password_field "person", "password" %>) + comment(# <%= password_field "person", "password_confirmation" %>) + comment(#) + comment(# The person has to already have a password attribute (a column in the people table\), but the password_confirmation is virtual.) + comment(# It exists only as an in-memory variable for validating the password. This check is performed only if password_confirmation) + comment(# is not nil and by default on save.) + comment(#) + comment(# Configuration options:) + comment(# * <tt>message</tt> - A custom error message (default is: "doesn't match confirmation"\)) + comment(# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_confirmation_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:confirmation)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(attr_accessor) operator(*)operator(()ident(attr_names)operator(.)ident(map) operator({) operator(|)ident(n)operator(|) string<delimiter(")inline<inline_delimiter(#{)ident(n)inline_delimiter(})>content(_confirmation)delimiter(")> operator(})operator(\)) + + ident(validates_each)operator(()ident(attr_names)operator(,) ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(unless) ident(record)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(_confirmation)delimiter(")>operator(\))operator(.)ident(nil?) reserved(or) ident(value) operator(==) ident(record)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(_confirmation)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + comment(# Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement\). Example:) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_acceptance_of :terms_of_service) + comment(# validates_acceptance_of :eula, :message => "must be abided") + comment(# end) + comment(#) + comment(# The terms_of_service attribute is entirely virtual. No database column is needed. This check is performed only if) + comment(# terms_of_service is not nil and by default on save.) + comment(#) + comment(# Configuration options:) + comment(# * <tt>message</tt> - A custom error message (default is: "must be accepted"\)) + comment(# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>accept</tt> - Specifies value that is considered accepted. The default value is a string "1", which) + comment(# makes it easy to relate to an HTML checkbox.) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_acceptance_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:accepted)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true)operator(,) symbol(:accept) operator(=)operator(>) string<delimiter(")content(1)delimiter(")> operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(attr_accessor) operator(*)ident(attr_names) + + ident(validates_each)operator(()ident(attr_names)operator(,)ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(unless) ident(value) operator(==) ident(configuration)operator([)symbol(:accept)operator(]) + reserved(end) + reserved(end) + + comment(# Validates that the specified attributes are not blank (as defined by Object#blank?\). Happens by default on save. Example:) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_presence_of :first_name) + comment(# end) + comment(#) + comment(# The first_name attribute must be in the object and it cannot be blank.) + comment(# ) + comment(# Configuration options:) + comment(# * <tt>message</tt> - A custom error message (default is: "can't be blank"\)) + comment(# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + comment(#) + comment(# === Warning) + comment(# Validate the presence of the foreign key, not the instance variable itself.) + comment(# Do this:) + comment(# validate_presence_of :invoice_id) + comment(#) + comment(# Not this:) + comment(# validate_presence_of :invoice) + comment(#) + comment(# If you validate the presence of the associated object, you will get) + comment(# failures on saves when both the parent object and the child object are) + comment(# new.) + reserved(def) method(validates_presence_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:blank)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + comment(# can't use validates_each here, because it cannot cope with nonexistent attributes,) + comment(# while errors.add_on_empty can) + ident(attr_names)operator(.)ident(each) reserved(do) operator(|)ident(attr_name)operator(|) + ident(send)operator(()ident(validation_method)operator(()ident(configuration)operator([)symbol(:on)operator(])operator(\))operator(\)) reserved(do) operator(|)ident(record)operator(|) + reserved(unless) ident(configuration)operator([)symbol(:if)operator(]) reserved(and) reserved(not) ident(evaluate_condition)operator(()ident(configuration)operator([)symbol(:if)operator(])operator(,) ident(record)operator(\)) + ident(record)operator(.)ident(errors)operator(.)ident(add_on_blank)operator(()ident(attr_name)operator(,)ident(configuration)operator([)symbol(:message)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + comment(# Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time:) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_length_of :first_name, :maximum=>30) + comment(# validates_length_of :last_name, :maximum=>30, :message=>"less than %d if you don't mind") + comment(# validates_length_of :fax, :in => 7..32, :allow_nil => true) + comment(# validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name") + comment(# validates_length_of :fav_bra_size, :minimum=>1, :too_short=>"please enter at least %d character") + comment(# validates_length_of :smurf_leader, :is=>4, :message=>"papa is spelled with %d characters... don't play me.") + comment(# end) + comment(#) + comment(# Configuration options:) + comment(# * <tt>minimum</tt> - The minimum size of the attribute) + comment(# * <tt>maximum</tt> - The maximum size of the attribute) + comment(# * <tt>is</tt> - The exact size of the attribute) + comment(# * <tt>within</tt> - A range specifying the minimum and maximum size of the attribute) + comment(# * <tt>in</tt> - A synonym(or alias\) for :within) + comment(# * <tt>allow_nil</tt> - Attribute may be nil; skip validation.) + comment(#) + comment(# * <tt>too_long</tt> - The error message if the attribute goes over the maximum (default is: "is too long (maximum is %d characters\)"\)) + comment(# * <tt>too_short</tt> - The error message if the attribute goes under the minimum (default is: "is too short (min is %d characters\)"\)) + comment(# * <tt>wrong_length</tt> - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %d characters\)"\)) + comment(# * <tt>message</tt> - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message) + comment(# * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_length_of)operator(()operator(*)ident(attrs)operator(\)) + comment(# Merge given options with defaults.) + ident(options) operator(=) operator({) + symbol(:too_long) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:too_long)operator(])operator(,) + symbol(:too_short) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:too_short)operator(])operator(,) + symbol(:wrong_length) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:wrong_length)operator(]) + operator(})operator(.)ident(merge)operator(()constant(DEFAULT_VALIDATION_OPTIONS)operator(\)) + ident(options)operator(.)ident(update)operator(()ident(attrs)operator(.)ident(pop)operator(.)ident(symbolize_keys)operator(\)) reserved(if) ident(attrs)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + comment(# Ensure that one and only one range option is specified.) + ident(range_options) operator(=) constant(ALL_RANGE_OPTIONS) operator(&) ident(options)operator(.)ident(keys) + reserved(case) ident(range_options)operator(.)ident(size) + reserved(when) integer(0) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(Range unspecified. Specify the :within, :maximum, :minimum, or :is option.)delimiter(')> + reserved(when) integer(1) + comment(# Valid number of options; do nothing.) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(')content(Too many range options specified. Choose only one.)delimiter(')> + reserved(end) + + comment(# Get range option and value.) + ident(option) operator(=) ident(range_options)operator(.)ident(first) + ident(option_value) operator(=) ident(options)operator([)ident(range_options)operator(.)ident(first)operator(]) + + reserved(case) ident(option) + reserved(when) symbol(:within)operator(,) symbol(:in) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(:)inline<inline_delimiter(#{)ident(option)inline_delimiter(})>content( must be a Range)delimiter(")> reserved(unless) ident(option_value)operator(.)ident(is_a?)operator(()constant(Range)operator(\)) + + ident(too_short) operator(=) ident(options)operator([)symbol(:too_short)operator(]) operator(%) ident(option_value)operator(.)ident(begin) + ident(too_long) operator(=) ident(options)operator([)symbol(:too_long)operator(]) operator(%) ident(option_value)operator(.)ident(end) + + ident(validates_each)operator(()ident(attrs)operator(,) ident(options)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr)operator(,) ident(value)operator(|) + reserved(if) ident(value)operator(.)ident(nil?) reserved(or) ident(value)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\))operator(.)ident(size) operator(<) ident(option_value)operator(.)ident(begin) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr)operator(,) ident(too_short)operator(\)) + reserved(elsif) ident(value)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\))operator(.)ident(size) operator(>) ident(option_value)operator(.)ident(end) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr)operator(,) ident(too_long)operator(\)) + reserved(end) + reserved(end) + reserved(when) symbol(:is)operator(,) symbol(:minimum)operator(,) symbol(:maximum) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(:)inline<inline_delimiter(#{)ident(option)inline_delimiter(})>content( must be a nonnegative Integer)delimiter(")> reserved(unless) ident(option_value)operator(.)ident(is_a?)operator(()constant(Integer)operator(\)) reserved(and) ident(option_value) operator(>)operator(=) integer(0) + + comment(# Declare different validations per option.) + ident(validity_checks) operator(=) operator({) symbol(:is) operator(=)operator(>) string<delimiter(")content(==)delimiter(")>operator(,) symbol(:minimum) operator(=)operator(>) string<delimiter(")content(>=)delimiter(")>operator(,) symbol(:maximum) operator(=)operator(>) string<delimiter(")content(<=)delimiter(")> operator(}) + ident(message_options) operator(=) operator({) symbol(:is) operator(=)operator(>) symbol(:wrong_length)operator(,) symbol(:minimum) operator(=)operator(>) symbol(:too_short)operator(,) symbol(:maximum) operator(=)operator(>) symbol(:too_long) operator(}) + + ident(message) operator(=) operator(()ident(options)operator([)symbol(:message)operator(]) operator(||) ident(options)operator([)ident(message_options)operator([)ident(option)operator(])operator(])operator(\)) operator(%) ident(option_value) + + ident(validates_each)operator(()ident(attrs)operator(,) ident(options)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr)operator(,) ident(value)operator(|) + reserved(if) ident(value)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr)operator(,) ident(message)operator(\)) reserved(unless) operator(!)ident(value)operator(.)ident(nil?) reserved(and) ident(value)operator(.)ident(split)operator(()regexp<delimiter(/)delimiter(/)>operator(\))operator(.)ident(size)operator(.)ident(method)operator(()ident(validity_checks)operator([)ident(option)operator(])operator(\))operator([)ident(option_value)operator(]) + reserved(else) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr)operator(,) ident(message)operator(\)) reserved(unless) operator(!)ident(value)operator(.)ident(nil?) reserved(and) ident(value)operator(.)ident(size)operator(.)ident(method)operator(()ident(validity_checks)operator([)ident(option)operator(])operator(\))operator([)ident(option_value)operator(]) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:validates_size_of)operator(,) symbol(:validates_length_of) + + + comment(# Validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user) + comment(# can be named "davidhh".) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_uniqueness_of :user_name, :scope => :account_id) + comment(# end) + comment(#) + comment(# It can also validate whether the value of the specified attributes are unique based on multiple scope parameters. For example,) + comment(# making sure that a teacher can only be on the schedule once per semester for a particular class. ) + comment(#) + comment(# class TeacherSchedule < ActiveRecord::Base) + comment(# validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id] ) + comment(# end) + comment(#) + comment(# When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified) + comment(# attribute (that maps to a column\). When the record is updated, the same check is made but disregarding the record itself.) + comment(#) + comment(# Configuration options:) + comment(# * <tt>message</tt> - Specifies a custom error message (default is: "has already been taken"\)) + comment(# * <tt>scope</tt> - One or more columns by which to limit the scope of the uniquness constraint.) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + + reserved(def) method(validates_uniqueness_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:taken)operator(]) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(validates_each)operator(()ident(attr_names)operator(,)ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(condition_sql) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(record)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(attribute_condition)operator(()ident(value)operator(\))inline_delimiter(})>delimiter(")> + ident(condition_params) operator(=) operator([)ident(value)operator(]) + reserved(if) ident(scope) operator(=) ident(configuration)operator([)symbol(:scope)operator(]) + ident(Array)operator(()ident(scope)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(scope_item)operator(|) + ident(scope_value) operator(=) ident(record)operator(.)ident(send)operator(()ident(scope_item)operator(\)) + ident(condition_sql) operator(<<) string<delimiter(")content( AND )inline<inline_delimiter(#{)ident(record)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(scope_item)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(attribute_condition)operator(()ident(scope_value)operator(\))inline_delimiter(})>delimiter(")> + ident(condition_params) operator(<<) ident(scope_value) + reserved(end) + reserved(end) + reserved(unless) ident(record)operator(.)ident(new_record?) + ident(condition_sql) operator(<<) string<delimiter(")content( AND )inline<inline_delimiter(#{)ident(record)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(record)operator(.)ident(class)operator(.)ident(primary_key)inline_delimiter(})>content( <> ?)delimiter(")> + ident(condition_params) operator(<<) ident(record)operator(.)ident(send)operator(()symbol(:id)operator(\)) + reserved(end) + reserved(if) ident(record)operator(.)ident(class)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)ident(condition_sql)operator(,) operator(*)ident(condition_params)operator(])operator(\)) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + + comment(# Validates whether the value of the specified attribute is of the correct form by matching it against the regular expression) + comment(# provided.) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_format_of :email, :with => /^([^@\\s]+\)@((?:[-a-z0-9]+\\.\)+[a-z]{2,}\)$/i, :on => :create) + comment(# end) + comment(#) + comment(# A regular expression must be provided or else an exception will be raised.) + comment(#) + comment(# Configuration options:) + comment(# * <tt>message</tt> - A custom error message (default is: "is invalid"\)) + comment(# * <tt>with</tt> - The regular expression used to validate the format with (note: must be supplied!\)) + comment(# * <tt>on</tt> Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_format_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:invalid)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save)operator(,) symbol(:with) operator(=)operator(>) pre_constant(nil) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")content(A regular expression must be supplied as the :with option of the configuration hash)delimiter(")>operator(\)) reserved(unless) ident(configuration)operator([)symbol(:with)operator(])operator(.)ident(is_a?)operator(()constant(Regexp)operator(\)) + + ident(validates_each)operator(()ident(attr_names)operator(,) ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(unless) ident(value)operator(.)ident(to_s) operator(=)operator(~) ident(configuration)operator([)symbol(:with)operator(]) + reserved(end) + reserved(end) + + comment(# Validates whether the value of the specified attribute is available in a particular enumerable object.) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_inclusion_of :gender, :in=>%w( m f \), :message=>"woah! what are you then!??!!") + comment(# validates_inclusion_of :age, :in=>0..99) + comment(# end) + comment(#) + comment(# Configuration options:) + comment(# * <tt>in</tt> - An enumerable object of available items) + comment(# * <tt>message</tt> - Specifies a customer error message (default is: "is not included in the list"\)) + comment(# * <tt>allow_nil</tt> - If set to true, skips this validation if the attribute is null (default is: false\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_inclusion_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:inclusion)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(enum) operator(=) ident(configuration)operator([)symbol(:in)operator(]) operator(||) ident(configuration)operator([)symbol(:within)operator(]) + + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")content(An object with the method include? is required must be supplied as the :in option of the configuration hash)delimiter(")>operator(\)) reserved(unless) ident(enum)operator(.)ident(respond_to?)operator(()string<delimiter(")content(include?)delimiter(")>operator(\)) + + ident(validates_each)operator(()ident(attr_names)operator(,) ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(unless) ident(enum)operator(.)ident(include?)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) + + comment(# Validates that the value of the specified attribute is not in a particular enumerable object.) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_exclusion_of :username, :in => %w( admin superuser \), :message => "You don't belong here") + comment(# validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60") + comment(# end) + comment(#) + comment(# Configuration options:) + comment(# * <tt>in</tt> - An enumerable object of items that the value shouldn't be part of) + comment(# * <tt>message</tt> - Specifies a customer error message (default is: "is reserved"\)) + comment(# * <tt>allow_nil</tt> - If set to true, skips this validation if the attribute is null (default is: false\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_exclusion_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:exclusion)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(enum) operator(=) ident(configuration)operator([)symbol(:in)operator(]) operator(||) ident(configuration)operator([)symbol(:within)operator(]) + + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")content(An object with the method include? is required must be supplied as the :in option of the configuration hash)delimiter(")>operator(\)) reserved(unless) ident(enum)operator(.)ident(respond_to?)operator(()string<delimiter(")content(include?)delimiter(")>operator(\)) + + ident(validates_each)operator(()ident(attr_names)operator(,) ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(if) ident(enum)operator(.)ident(include?)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) + + comment(# Validates whether the associated object or objects are all valid themselves. Works with any kind of association.) + comment(#) + comment(# class Book < ActiveRecord::Base) + comment(# has_many :pages) + comment(# belongs_to :library) + comment(#) + comment(# validates_associated :pages, :library) + comment(# end) + comment(#) + comment(# Warning: If, after the above definition, you then wrote:) + comment(#) + comment(# class Page < ActiveRecord::Base) + comment(# belongs_to :book) + comment(#) + comment(# validates_associated :book) + comment(# end) + comment(#) + comment(# ...this would specify a circular dependency and cause infinite recursion.) + comment(#) + comment(# NOTE: This validation will not fail if the association hasn't been assigned. If you want to ensure that the association) + comment(# is both present and guaranteed to be valid, you also need to use validates_presence_of.) + comment(#) + comment(# Configuration options:) + comment(# * <tt>on</tt> Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_associated)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:invalid)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + ident(validates_each)operator(()ident(attr_names)operator(,) ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,) ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(unless) + operator(()ident(value)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) operator(?) ident(value) operator(:) operator([)ident(value)operator(])operator(\))operator(.)ident(all?) operator({) operator(|)ident(r)operator(|) ident(r)operator(.)ident(nil?) reserved(or) ident(r)operator(.)ident(valid?) operator(}) + reserved(end) + reserved(end) + + comment(# Validates whether the value of the specified attribute is numeric by trying to convert it to) + comment(# a float with Kernel.Float (if <tt>integer</tt> is false\) or applying it to the regular expression) + comment(# <tt>/^[\\+\\-]?\\d+$/</tt> (if <tt>integer</tt> is set to true\).) + comment(#) + comment(# class Person < ActiveRecord::Base) + comment(# validates_numericality_of :value, :on => :create) + comment(# end) + comment(#) + comment(# Configuration options:) + comment(# * <tt>message</tt> - A custom error message (default is: "is not a number"\)) + comment(# * <tt>on</tt> Specifies when this validation is active (default is :save, other options :create, :update\)) + comment(# * <tt>only_integer</tt> Specifies whether the value has to be an integer, e.g. an integral value (default is false\)) + comment(# * <tt>allow_nil</tt> Skip validation if attribute is nil (default is false\). Notice that for fixnum and float columns empty strings are converted to nil) + comment(# * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should) + comment(# occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }\). The) + comment(# method, proc or string should return or evaluate to a true or false value.) + reserved(def) method(validates_numericality_of)operator(()operator(*)ident(attr_names)operator(\)) + ident(configuration) operator(=) operator({) symbol(:message) operator(=)operator(>) constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:not_a_number)operator(])operator(,) symbol(:on) operator(=)operator(>) symbol(:save)operator(,) + symbol(:only_integer) operator(=)operator(>) pre_constant(false)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(false) operator(}) + ident(configuration)operator(.)ident(update)operator(()ident(attr_names)operator(.)ident(pop)operator(\)) reserved(if) ident(attr_names)operator(.)ident(last)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + + reserved(if) ident(configuration)operator([)symbol(:only_integer)operator(]) + ident(validates_each)operator(()ident(attr_names)operator(,)ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,)ident(value)operator(|) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) reserved(unless) ident(record)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(_before_type_cast)delimiter(")>operator(\))operator(.)ident(to_s) operator(=)operator(~) regexp<delimiter(/)content(^[+-]?)char(\\d)content(+$)delimiter(/)> + reserved(end) + reserved(else) + ident(validates_each)operator(()ident(attr_names)operator(,)ident(configuration)operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr_name)operator(,)ident(value)operator(|) + reserved(next) reserved(if) ident(configuration)operator([)symbol(:allow_nil)operator(]) reserved(and) ident(record)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(_before_type_cast)delimiter(")>operator(\))operator(.)ident(nil?) + reserved(begin) + constant(Kernel)operator(.)ident(Float)operator(()ident(record)operator(.)ident(send)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(attr_name)inline_delimiter(})>content(_before_type_cast)delimiter(")>operator(\))operator(.)ident(to_s)operator(\)) + reserved(rescue) constant(ArgumentError)operator(,) constant(TypeError) + ident(record)operator(.)ident(errors)operator(.)ident(add)operator(()ident(attr_name)operator(,) ident(configuration)operator([)symbol(:message)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + + comment(# Creates an object just like Base.create but calls save! instead of save) + comment(# so an exception is raised if the record is invalid.) + reserved(def) method(create!)operator(()ident(attributes) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(attributes)operator(.)ident(is_a?)operator(()constant(Array)operator(\)) + ident(attributes)operator(.)ident(collect) operator({) operator(|)ident(attr)operator(|) ident(create!)operator(()ident(attr)operator(\)) operator(}) + reserved(else) + ident(attributes)operator(.)ident(reverse_merge!)operator(()ident(scope)operator(()symbol(:create)operator(\))operator(\)) reserved(if) ident(scoped?)operator(()symbol(:create)operator(\)) + + ident(object) operator(=) ident(new)operator(()ident(attributes)operator(\)) + ident(object)operator(.)ident(save!) + ident(object) + reserved(end) + reserved(end) + + + ident(private) + reserved(def) method(write_inheritable_set)operator(()ident(key)operator(,) ident(methods)operator(\)) + ident(existing_methods) operator(=) ident(read_inheritable_attribute)operator(()ident(key)operator(\)) operator(||) operator([)operator(]) + ident(write_inheritable_attribute)operator(()ident(key)operator(,) ident(methods) operator(|) ident(existing_methods)operator(\)) + reserved(end) + + reserved(def) method(validation_method)operator(()ident(on)operator(\)) + reserved(case) ident(on) + reserved(when) symbol(:save) reserved(then) symbol(:validate) + reserved(when) symbol(:create) reserved(then) symbol(:validate_on_create) + reserved(when) symbol(:update) reserved(then) symbol(:validate_on_update) + reserved(end) + reserved(end) + reserved(end) + + comment(# The validation process on save can be skipped by passing false. The regular Base#save method is) + comment(# replaced with this when the validations module is mixed in, which it is by default.) + reserved(def) method(save_with_validation)operator(()ident(perform_validation) operator(=) pre_constant(true)operator(\)) + reserved(if) ident(perform_validation) operator(&&) ident(valid?) operator(||) operator(!)ident(perform_validation) + ident(save_without_validation) + reserved(else) + pre_constant(false) + reserved(end) + reserved(end) + + comment(# Attempts to save the record just like Base#save but will raise a RecordInvalid exception instead of returning false) + comment(# if the record is not valid.) + reserved(def) method(save_with_validation!) + reserved(if) ident(valid?) + ident(save_without_validation!) + reserved(else) + ident(raise) constant(RecordInvalid)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + reserved(end) + + comment(# Updates a single attribute and saves the record without going through the normal validation procedure.) + comment(# This is especially useful for boolean flags on existing records. The regular +update_attribute+ method) + comment(# in Base is replaced with this when the validations module is mixed in, which it is by default.) + reserved(def) method(update_attribute_with_validation_skipping)operator(()ident(name)operator(,) ident(value)operator(\)) + ident(send)operator(()ident(name)operator(.)ident(to_s) operator(+) string<delimiter(')content(=)delimiter(')>operator(,) ident(value)operator(\)) + ident(save)operator(()pre_constant(false)operator(\)) + reserved(end) + + comment(# Runs validate and validate_on_create or validate_on_update and returns true if no errors were added otherwise false.) + reserved(def) method(valid?) + ident(errors)operator(.)ident(clear) + + ident(run_validations)operator(()symbol(:validate)operator(\)) + ident(validate) + + reserved(if) ident(new_record?) + ident(run_validations)operator(()symbol(:validate_on_create)operator(\)) + ident(validate_on_create) + reserved(else) + ident(run_validations)operator(()symbol(:validate_on_update)operator(\)) + ident(validate_on_update) + reserved(end) + + ident(errors)operator(.)ident(empty?) + reserved(end) + + comment(# Returns the Errors object that holds all information about attribute error messages.) + reserved(def) method(errors) + instance_variable(@errors) operator(||=) constant(Errors)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + + ident(protected) + comment(# Overwrite this method for validation checks on all saves and use Errors.add(field, msg\) for invalid attributes.) + reserved(def) method(validate) comment(#:doc:) + reserved(end) + + comment(# Overwrite this method for validation checks used only on creation.) + reserved(def) method(validate_on_create) comment(#:doc:) + reserved(end) + + comment(# Overwrite this method for validation checks used only on updates.) + reserved(def) method(validate_on_update) comment(# :doc:) + reserved(end) + + ident(private) + reserved(def) method(run_validations)operator(()ident(validation_method)operator(\)) + ident(validations) operator(=) pre_constant(self)operator(.)ident(class)operator(.)ident(read_inheritable_attribute)operator(()ident(validation_method)operator(.)ident(to_sym)operator(\)) + reserved(if) ident(validations)operator(.)ident(nil?) reserved(then) reserved(return) reserved(end) + ident(validations)operator(.)ident(each) reserved(do) operator(|)ident(validation)operator(|) + reserved(if) ident(validation)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + pre_constant(self)operator(.)ident(send)operator(()ident(validation)operator(\)) + reserved(elsif) ident(validation)operator(.)ident(is_a?)operator(()constant(String)operator(\)) + ident(eval)operator(()ident(validation)operator(,) ident(binding)operator(\)) + reserved(elsif) ident(validation_block?)operator(()ident(validation)operator(\)) + ident(validation)operator(.)ident(call)operator(()pre_constant(self)operator(\)) + reserved(elsif) ident(validation_class?)operator(()ident(validation)operator(,) ident(validation_method)operator(\)) + ident(validation)operator(.)ident(send)operator(()ident(validation_method)operator(,) pre_constant(self)operator(\)) + reserved(else) + ident(raise)operator(() + constant(ActiveRecordError)operator(,) + string<delimiter(")content(Validations need to be either a symbol, string (to be eval'ed\), proc/method, or )delimiter(")> operator(+) + string<delimiter(")content(class implementing a static validation method)delimiter(")> + operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(validation_block?)operator(()ident(validation)operator(\)) + ident(validation)operator(.)ident(respond_to?)operator(()string<delimiter(")content(call)delimiter(")>operator(\)) operator(&&) operator(()ident(validation)operator(.)ident(arity) operator(==) integer(1) operator(||) ident(validation)operator(.)ident(arity) operator(==) integer(-1)operator(\)) + reserved(end) + + reserved(def) method(validation_class?)operator(()ident(validation)operator(,) ident(validation_method)operator(\)) + ident(validation)operator(.)ident(respond_to?)operator(()ident(validation_method)operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(db2/db2cli.rb)delimiter(')> + +reserved(module) class(DB2) + reserved(module) class(DB2Util) + ident(include) constant(DB2CLI) + + reserved(def) method(free)operator(()operator(\)) ident(SQLFreeHandle)operator(()instance_variable(@handle_type)operator(,) instance_variable(@handle)operator(\))operator(;) reserved(end) + reserved(def) method(handle)operator(()operator(\)) instance_variable(@handle)operator(;) reserved(end) + + reserved(def) method(check_rc)operator(()ident(rc)operator(\)) + reserved(if) operator(!)operator([)constant(SQL_SUCCESS)operator(,) constant(SQL_SUCCESS_WITH_INFO)operator(,) constant(SQL_NO_DATA_FOUND)operator(])operator(.)ident(include?)operator(()ident(rc)operator(\)) + ident(rec) operator(=) integer(1) + ident(msg) operator(=) string<delimiter(')delimiter(')> + ident(loop) reserved(do) + ident(a) operator(=) ident(SQLGetDiagRec)operator(()instance_variable(@handle_type)operator(,) instance_variable(@handle)operator(,) ident(rec)operator(,) integer(500)operator(\)) + reserved(break) reserved(if) ident(a)operator([)integer(0)operator(]) operator(!=) constant(SQL_SUCCESS) + ident(msg) operator(<<) ident(a)operator([)integer(3)operator(]) reserved(if) operator(!)ident(a)operator([)integer(3)operator(])operator(.)ident(nil?) reserved(and) ident(a)operator([)integer(3)operator(]) operator(!=) string<delimiter(')delimiter(')> comment(# Create message.) + ident(rec) operator(+=) integer(1) + reserved(end) + ident(raise) string<delimiter(")content(DB2 error: )inline<inline_delimiter(#{)ident(msg)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Environment) + ident(include) constant(DB2Util) + + reserved(def) method(initialize) + instance_variable(@handle_type) operator(=) constant(SQL_HANDLE_ENV) + ident(rc)operator(,) instance_variable(@handle) operator(=) ident(SQLAllocHandle)operator(()instance_variable(@handle_type)operator(,) constant(SQL_NULL_HANDLE)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + reserved(end) + + reserved(def) method(data_sources)operator(()ident(buffer_length) operator(=) integer(1024)operator(\)) + ident(retval) operator(=) operator([)operator(]) + ident(max_buffer_length) operator(=) ident(buffer_length) + + ident(a) operator(=) ident(SQLDataSources)operator(()instance_variable(@handle)operator(,) constant(SQL_FETCH_FIRST)operator(,) constant(SQL_MAX_DSN_LENGTH) operator(+) integer(1)operator(,) ident(buffer_length)operator(\)) + ident(retval) operator(<<) operator([)ident(a)operator([)integer(1)operator(])operator(,) ident(a)operator([)integer(3)operator(])operator(]) + ident(max_buffer_length) operator(=) operator([)ident(max_buffer_length)operator(,) ident(a)operator([)integer(4)operator(])operator(])operator(.)ident(max) + + ident(loop) reserved(do) + ident(a) operator(=) ident(SQLDataSources)operator(()instance_variable(@handle)operator(,) constant(SQL_FETCH_NEXT)operator(,) constant(SQL_MAX_DSN_LENGTH) operator(+) integer(1)operator(,) ident(buffer_length)operator(\)) + reserved(break) reserved(if) ident(a)operator([)integer(0)operator(]) operator(==) constant(SQL_NO_DATA_FOUND) + + ident(retval) operator(<<) operator([)ident(a)operator([)integer(1)operator(])operator(,) ident(a)operator([)integer(3)operator(])operator(]) + ident(max_buffer_length) operator(=) operator([)ident(max_buffer_length)operator(,) ident(a)operator([)integer(4)operator(])operator(])operator(.)ident(max) + reserved(end) + + reserved(if) ident(max_buffer_length) operator(>) ident(buffer_length) + ident(get_data_sources)operator(()ident(max_buffer_length)operator(\)) + reserved(else) + ident(retval) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Connection) + ident(include) constant(DB2Util) + + reserved(def) method(initialize)operator(()ident(environment)operator(\)) + instance_variable(@env) operator(=) ident(environment) + instance_variable(@handle_type) operator(=) constant(SQL_HANDLE_DBC) + ident(rc)operator(,) instance_variable(@handle) operator(=) ident(SQLAllocHandle)operator(()instance_variable(@handle_type)operator(,) instance_variable(@env)operator(.)ident(handle)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + reserved(end) + + reserved(def) method(connect)operator(()ident(server_name)operator(,) ident(user_name) operator(=) string<delimiter(')delimiter(')>operator(,) ident(auth) operator(=) string<delimiter(')delimiter(')>operator(\)) + ident(check_rc)operator(()ident(SQLConnect)operator(()instance_variable(@handle)operator(,) ident(server_name)operator(,) ident(user_name)operator(.)ident(to_s)operator(,) ident(auth)operator(.)ident(to_s)operator(\))operator(\)) + reserved(end) + + reserved(def) method(set_connect_attr)operator(()ident(attr)operator(,) ident(value)operator(\)) + ident(value) operator(+=) string<delimiter(")char(\\0)delimiter(")> reserved(if) ident(value)operator(.)ident(class) operator(==) constant(String) + ident(check_rc)operator(()ident(SQLSetConnectAttr)operator(()instance_variable(@handle)operator(,) ident(attr)operator(,) ident(value)operator(\))operator(\)) + reserved(end) + + reserved(def) method(set_auto_commit_on) + ident(set_connect_attr)operator(()constant(SQL_ATTR_AUTOCOMMIT)operator(,) constant(SQL_AUTOCOMMIT_ON)operator(\)) + reserved(end) + + reserved(def) method(set_auto_commit_off) + ident(set_connect_attr)operator(()constant(SQL_ATTR_AUTOCOMMIT)operator(,) constant(SQL_AUTOCOMMIT_OFF)operator(\)) + reserved(end) + + reserved(def) method(disconnect) + ident(check_rc)operator(()ident(SQLDisconnect)operator(()instance_variable(@handle)operator(\))operator(\)) + reserved(end) + + reserved(def) method(rollback) + ident(check_rc)operator(()ident(SQLEndTran)operator(()instance_variable(@handle_type)operator(,) instance_variable(@handle)operator(,) constant(SQL_ROLLBACK)operator(\))operator(\)) + reserved(end) + + reserved(def) method(commit) + ident(check_rc)operator(()ident(SQLEndTran)operator(()instance_variable(@handle_type)operator(,) instance_variable(@handle)operator(,) constant(SQL_COMMIT)operator(\))operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(Statement) + ident(include) constant(DB2Util) + + reserved(def) method(initialize)operator(()ident(connection)operator(\)) + instance_variable(@conn) operator(=) ident(connection) + instance_variable(@handle_type) operator(=) constant(SQL_HANDLE_STMT) + instance_variable(@parms) operator(=) operator([)operator(]) comment(#yun) + instance_variable(@sql) operator(=) string<delimiter(')delimiter(')> comment(#yun) + instance_variable(@numParms) operator(=) integer(0) comment(#yun) + instance_variable(@prepared) operator(=) pre_constant(false) comment(#yun) + instance_variable(@parmArray) operator(=) operator([)operator(]) comment(#yun. attributes of the parameter markers) + ident(rc)operator(,) instance_variable(@handle) operator(=) ident(SQLAllocHandle)operator(()instance_variable(@handle_type)operator(,) instance_variable(@conn)operator(.)ident(handle)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + reserved(end) + + reserved(def) method(columns)operator(()ident(table_name)operator(,) ident(schema_name) operator(=) string<delimiter(')content(%)delimiter(')>operator(\)) + ident(check_rc)operator(()ident(SQLColumns)operator(()instance_variable(@handle)operator(,) string<delimiter(')delimiter(')>operator(,) ident(schema_name)operator(.)ident(upcase)operator(,) ident(table_name)operator(.)ident(upcase)operator(,) string<delimiter(')content(%)delimiter(')>operator(\))operator(\)) + ident(fetch_all) + reserved(end) + + reserved(def) method(tables)operator(()ident(schema_name) operator(=) string<delimiter(')content(%)delimiter(')>operator(\)) + ident(check_rc)operator(()ident(SQLTables)operator(()instance_variable(@handle)operator(,) string<delimiter(')delimiter(')>operator(,) ident(schema_name)operator(.)ident(upcase)operator(,) string<delimiter(')content(%)delimiter(')>operator(,) string<delimiter(')content(TABLE)delimiter(')>operator(\))operator(\)) + ident(fetch_all) + reserved(end) + + reserved(def) method(indexes)operator(()ident(table_name)operator(,) ident(schema_name) operator(=) string<delimiter(')delimiter(')>operator(\)) + ident(check_rc)operator(()ident(SQLStatistics)operator(()instance_variable(@handle)operator(,) string<delimiter(')delimiter(')>operator(,) ident(schema_name)operator(.)ident(upcase)operator(,) ident(table_name)operator(.)ident(upcase)operator(,) constant(SQL_INDEX_ALL)operator(,) constant(SQL_ENSURE)operator(\))operator(\)) + ident(fetch_all) + reserved(end) + + reserved(def) method(prepare)operator(()ident(sql)operator(\)) + instance_variable(@sql) operator(=) ident(sql) + ident(check_rc)operator(()ident(SQLPrepare)operator(()instance_variable(@handle)operator(,) ident(sql)operator(\))operator(\)) + ident(rc)operator(,) instance_variable(@numParms) operator(=) ident(SQLNumParams)operator(()instance_variable(@handle)operator(\)) comment(#number of question marks) + ident(check_rc)operator(()ident(rc)operator(\)) + comment(#--------------------------------------------------------------------------) + comment(# parameter attributes are stored in instance variable @parmArray so that) + comment(# they are available when execute method is called.) + comment(#--------------------------------------------------------------------------) + reserved(if) instance_variable(@numParms) operator(>) integer(0) comment(# get parameter marker attributes) + integer(1)operator(.)ident(upto)operator(()instance_variable(@numParms)operator(\)) reserved(do) operator(|)ident(i)operator(|) comment(# parameter number starts from 1) + ident(rc)operator(,) ident(type)operator(,) ident(size)operator(,) ident(decimalDigits) operator(=) ident(SQLDescribeParam)operator(()instance_variable(@handle)operator(,) ident(i)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + instance_variable(@parmArray) operator(<<) constant(Parameter)operator(.)ident(new)operator(()ident(type)operator(,) ident(size)operator(,) ident(decimalDigits)operator(\)) + reserved(end) + reserved(end) + instance_variable(@prepared) operator(=) pre_constant(true) + pre_constant(self) + reserved(end) + + reserved(def) method(execute)operator(()operator(*)ident(parms)operator(\)) + ident(raise) string<delimiter(")content(The statement was not prepared)delimiter(")> reserved(if) instance_variable(@prepared) operator(==) pre_constant(false) + + reserved(if) ident(parms)operator(.)ident(size) operator(==) integer(1) reserved(and) ident(parms)operator([)integer(0)operator(])operator(.)ident(class) operator(==) constant(Array) + ident(parms) operator(=) ident(parms)operator([)integer(0)operator(]) + reserved(end) + + reserved(if) instance_variable(@numParms) operator(!=) ident(parms)operator(.)ident(size) + ident(raise) string<delimiter(")content(Number of parameters supplied does not match with the SQL statement)delimiter(")> + reserved(end) + + reserved(if) instance_variable(@numParms) operator(>) integer(0) comment(#need to bind parameters) + comment(#--------------------------------------------------------------------) + comment(#calling bindParms may not be safe. Look comment below.) + comment(#--------------------------------------------------------------------) + comment(#bindParms(parms\)) + + ident(valueArray) operator(=) operator([)operator(]) + integer(1)operator(.)ident(upto)operator(()instance_variable(@numParms)operator(\)) reserved(do) operator(|)ident(i)operator(|) comment(# parameter number starts from 1) + ident(type) operator(=) instance_variable(@parmArray)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(class) + ident(size) operator(=) instance_variable(@parmArray)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(size) + ident(decimalDigits) operator(=) instance_variable(@parmArray)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(decimalDigits) + + reserved(if) ident(parms)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(class) operator(==) constant(String) + ident(valueArray) operator(<<) ident(parms)operator([)ident(i) operator(-) integer(1)operator(]) + reserved(else) + ident(valueArray) operator(<<) ident(parms)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(to_s) + reserved(end) + + ident(rc) operator(=) ident(SQLBindParameter)operator(()instance_variable(@handle)operator(,) ident(i)operator(,) ident(type)operator(,) ident(size)operator(,) ident(decimalDigits)operator(,) ident(valueArray)operator([)ident(i) operator(-) integer(1)operator(])operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + reserved(end) + reserved(end) + + ident(check_rc)operator(()ident(SQLExecute)operator(()instance_variable(@handle)operator(\))operator(\)) + + reserved(if) instance_variable(@numParms) operator(!=) integer(0) + ident(check_rc)operator(()ident(SQLFreeStmt)operator(()instance_variable(@handle)operator(,) constant(SQL_RESET_PARAMS)operator(\))operator(\)) comment(# Reset parameters) + reserved(end) + + pre_constant(self) + reserved(end) + + comment(#-------------------------------------------------------------------------------) + comment(# The last argument(value\) to SQLBindParameter is a deferred argument, that is,) + comment(# it should be available when SQLExecute is called. Even though "value" is) + comment(# local to bindParms method, it seems that it is available when SQLExecute) + comment(# is called. I am not sure whether it would still work if garbage collection) + comment(# is done between bindParms call and SQLExecute call inside the execute method) + comment(# above.) + comment(#-------------------------------------------------------------------------------) + reserved(def) method(bindParms)operator(()ident(parms)operator(\)) comment(# This is the real thing. It uses SQLBindParms) + integer(1)operator(.)ident(upto)operator(()instance_variable(@numParms)operator(\)) reserved(do) operator(|)ident(i)operator(|) comment(# parameter number starts from 1) + ident(rc)operator(,) ident(dataType)operator(,) ident(parmSize)operator(,) ident(decimalDigits) operator(=) ident(SQLDescribeParam)operator(()instance_variable(@handle)operator(,) ident(i)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + reserved(if) ident(parms)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(class) operator(==) constant(String) + ident(value) operator(=) ident(parms)operator([)ident(i) operator(-) integer(1)operator(]) + reserved(else) + ident(value) operator(=) ident(parms)operator([)ident(i) operator(-) integer(1)operator(])operator(.)ident(to_s) + reserved(end) + ident(rc) operator(=) ident(SQLBindParameter)operator(()instance_variable(@handle)operator(,) ident(i)operator(,) ident(dataType)operator(,) ident(parmSize)operator(,) ident(decimalDigits)operator(,) ident(value)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + reserved(end) + reserved(end) + + comment(#------------------------------------------------------------------------------) + comment(# bind method does not use DB2's SQLBindParams, but replaces "?" in the) + comment(# SQL statement with the value before passing the SQL statement to DB2.) + comment(# It is not efficient and can handle only strings since it puts everything in) + comment(# quotes.) + comment(#------------------------------------------------------------------------------) + reserved(def) method(bind)operator(()ident(sql)operator(,) ident(args)operator(\)) comment(#does not use SQLBindParams) + ident(arg_index) operator(=) integer(0) + ident(result) operator(=) string<delimiter(")delimiter(")> + ident(tokens)operator(()ident(sql)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(part)operator(|) + reserved(case) ident(part) + reserved(when) string<delimiter(')content(?)delimiter(')> + ident(result) operator(<<) string<delimiter(")content(')delimiter(")> operator(+) operator(()ident(args)operator([)ident(arg_index)operator(])operator(\)) operator(+) string<delimiter(")content(')delimiter(")> comment(#put it into quotes) + ident(arg_index) operator(+=) integer(1) + reserved(when) string<delimiter(')content(??)delimiter(')> + ident(result) operator(<<) string<delimiter(")content(?)delimiter(")> + reserved(else) + ident(result) operator(<<) ident(part) + reserved(end) + reserved(end) + reserved(if) ident(arg_index) operator(<) ident(args)operator(.)ident(size) + ident(raise) string<delimiter(")content(Too many SQL parameters)delimiter(")> + reserved(elsif) ident(arg_index) operator(>) ident(args)operator(.)ident(size) + ident(raise) string<delimiter(")content(Not enough SQL parameters)delimiter(")> + reserved(end) + ident(result) + reserved(end) + + comment(## Break the sql string into parts.) + comment(#) + comment(# This is NOT a full lexer for SQL. It just breaks up the SQL) + comment(# string enough so that question marks, double question marks and) + comment(# quoted strings are separated. This is used when binding) + comment(# arguments to "?" in the SQL string. Note: comments are not) + comment(# handled.) + comment(#) + reserved(def) method(tokens)operator(()ident(sql)operator(\)) + ident(toks) operator(=) ident(sql)operator(.)ident(scan)operator(()regexp<delimiter(/)content(('([^')char(\\\\)content(]|''|)char(\\\\)content(.\)*'|"([^")char(\\\\)content(]|""|)char(\\\\)content(.\)*"|)char(\\?)char(\\?)content(?|[^'"?]+\))delimiter(/)>operator(\)) + ident(toks)operator(.)ident(collect) operator({) operator(|)ident(t)operator(|) ident(t)operator([)integer(0)operator(]) operator(}) + reserved(end) + + reserved(def) method(exec_direct)operator(()ident(sql)operator(\)) + ident(check_rc)operator(()ident(SQLExecDirect)operator(()instance_variable(@handle)operator(,) ident(sql)operator(\))operator(\)) + pre_constant(self) + reserved(end) + + reserved(def) method(set_cursor_name)operator(()ident(name)operator(\)) + ident(check_rc)operator(()ident(SQLSetCursorName)operator(()instance_variable(@handle)operator(,) ident(name)operator(\))operator(\)) + pre_constant(self) + reserved(end) + + reserved(def) method(get_cursor_name) + ident(rc)operator(,) ident(name) operator(=) ident(SQLGetCursorName)operator(()instance_variable(@handle)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + ident(name) + reserved(end) + + reserved(def) method(row_count) + ident(rc)operator(,) ident(rowcount) operator(=) ident(SQLRowCount)operator(()instance_variable(@handle)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + ident(rowcount) + reserved(end) + + reserved(def) method(num_result_cols) + ident(rc)operator(,) ident(cols) operator(=) ident(SQLNumResultCols)operator(()instance_variable(@handle)operator(\)) + ident(check_rc)operator(()ident(rc)operator(\)) + ident(cols) + reserved(end) + + reserved(def) method(fetch_all) + reserved(if) ident(block_given?) + reserved(while) ident(row) operator(=) ident(fetch) reserved(do) + reserved(yield) ident(row) + reserved(end) + reserved(else) + ident(res) operator(=) operator([)operator(]) + reserved(while) ident(row) operator(=) ident(fetch) reserved(do) + ident(res) operator(<<) ident(row) + reserved(end) + ident(res) + reserved(end) + reserved(end) + + reserved(def) method(fetch) + ident(cols) operator(=) ident(get_col_desc) + ident(rc) operator(=) ident(SQLFetch)operator(()instance_variable(@handle)operator(\)) + reserved(if) ident(rc) operator(==) constant(SQL_NO_DATA_FOUND) + ident(SQLFreeStmt)operator(()instance_variable(@handle)operator(,) constant(SQL_CLOSE)operator(\)) comment(# Close cursor) + ident(SQLFreeStmt)operator(()instance_variable(@handle)operator(,) constant(SQL_RESET_PARAMS)operator(\)) comment(# Reset parameters) + reserved(return) pre_constant(nil) + reserved(end) + ident(raise) string<delimiter(")content(ERROR)delimiter(")> reserved(unless) ident(rc) operator(==) constant(SQL_SUCCESS) + + ident(retval) operator(=) operator([)operator(]) + ident(cols)operator(.)ident(each_with_index) reserved(do) operator(|)ident(c)operator(,) ident(i)operator(|) + ident(rc)operator(,) ident(content) operator(=) ident(SQLGetData)operator(()instance_variable(@handle)operator(,) ident(i) operator(+) integer(1)operator(,) ident(c)operator([)integer(1)operator(])operator(,) ident(c)operator([)integer(2)operator(]) operator(+) integer(1)operator(\)) comment(#yun added 1 to c[2]) + ident(retval) operator(<<) ident(adjust_content)operator(()ident(content)operator(\)) + reserved(end) + ident(retval) + reserved(end) + + reserved(def) method(fetch_as_hash) + ident(cols) operator(=) ident(get_col_desc) + ident(rc) operator(=) ident(SQLFetch)operator(()instance_variable(@handle)operator(\)) + reserved(if) ident(rc) operator(==) constant(SQL_NO_DATA_FOUND) + ident(SQLFreeStmt)operator(()instance_variable(@handle)operator(,) constant(SQL_CLOSE)operator(\)) comment(# Close cursor) + ident(SQLFreeStmt)operator(()instance_variable(@handle)operator(,) constant(SQL_RESET_PARAMS)operator(\)) comment(# Reset parameters) + reserved(return) pre_constant(nil) + reserved(end) + ident(raise) string<delimiter(")content(ERROR)delimiter(")> reserved(unless) ident(rc) operator(==) constant(SQL_SUCCESS) + + ident(retval) operator(=) operator({)operator(}) + ident(cols)operator(.)ident(each_with_index) reserved(do) operator(|)ident(c)operator(,) ident(i)operator(|) + ident(rc)operator(,) ident(content) operator(=) ident(SQLGetData)operator(()instance_variable(@handle)operator(,) ident(i) operator(+) integer(1)operator(,) ident(c)operator([)integer(1)operator(])operator(,) ident(c)operator([)integer(2)operator(]) operator(+) integer(1)operator(\)) comment(#yun added 1 to c[2]) + ident(retval)operator([)ident(c)operator([)integer(0)operator(])operator(]) operator(=) ident(adjust_content)operator(()ident(content)operator(\)) + reserved(end) + ident(retval) + reserved(end) + + reserved(def) method(get_col_desc) + ident(rc)operator(,) ident(nr_cols) operator(=) ident(SQLNumResultCols)operator(()instance_variable(@handle)operator(\)) + ident(cols) operator(=) operator(()integer(1)operator(..)ident(nr_cols)operator(\))operator(.)ident(collect) reserved(do) operator(|)ident(c)operator(|) + ident(rc)operator(,) ident(name)operator(,) ident(bl)operator(,) ident(type)operator(,) ident(col_sz) operator(=) ident(SQLDescribeCol)operator(()instance_variable(@handle)operator(,) ident(c)operator(,) integer(1024)operator(\)) + operator([)ident(name)operator(.)ident(downcase)operator(,) ident(type)operator(,) ident(col_sz)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(adjust_content)operator(()ident(c)operator(\)) + reserved(case) ident(c)operator(.)ident(class)operator(.)ident(to_s) + reserved(when) string<delimiter(')content(DB2CLI::NullClass)delimiter(')> + reserved(return) pre_constant(nil) + reserved(when) string<delimiter(')content(DB2CLI::Time)delimiter(')> + string<delimiter(")content(%02d:%02d:%02d)delimiter(")> operator(%) operator([)ident(c)operator(.)ident(hour)operator(,) ident(c)operator(.)ident(minute)operator(,) ident(c)operator(.)ident(second)operator(]) + reserved(when) string<delimiter(')content(DB2CLI::Date)delimiter(')> + string<delimiter(")content(%04d-%02d-%02d)delimiter(")> operator(%) operator([)ident(c)operator(.)ident(year)operator(,) ident(c)operator(.)ident(month)operator(,) ident(c)operator(.)ident(day)operator(]) + reserved(when) string<delimiter(')content(DB2CLI::Timestamp)delimiter(')> + string<delimiter(")content(%04d-%02d-%02d %02d:%02d:%02d)delimiter(")> operator(%) operator([)ident(c)operator(.)ident(year)operator(,) ident(c)operator(.)ident(month)operator(,) ident(c)operator(.)ident(day)operator(,) ident(c)operator(.)ident(hour)operator(,) ident(c)operator(.)ident(minute)operator(,) ident(c)operator(.)ident(second)operator(]) + reserved(else) + reserved(return) ident(c) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(Parameter) + ident(attr_reader) symbol(:type)operator(,) symbol(:size)operator(,) symbol(:decimalDigits) + reserved(def) method(initialize)operator(()ident(type)operator(,) ident(size)operator(,) ident(decimalDigits)operator(\)) + instance_variable(@type)operator(,) instance_variable(@size)operator(,) instance_variable(@decimalDigits) operator(=) ident(type)operator(,) ident(size)operator(,) ident(decimalDigits) + reserved(end) + reserved(end) +reserved(end) +comment(# $Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $) +comment(#) +comment(# Copyright (C\) 2003-2005 TOMITA Masahiro) +comment(# tommy@tmtm.org) +comment(#) + +reserved(class) class(Mysql) + + constant(VERSION) operator(=) string<delimiter(")content(4.0-ruby-0.2.5)delimiter(")> + + ident(require) string<delimiter(")content(socket)delimiter(")> + ident(require) string<delimiter(")content(digest/sha1)delimiter(")> + + constant(MAX_PACKET_LENGTH) operator(=) integer(256)operator(*)integer(256)operator(*)integer(256)operator(-)integer(1) + constant(MAX_ALLOWED_PACKET) operator(=) integer(1024)operator(*)integer(1024)operator(*)integer(1024) + + constant(MYSQL_UNIX_ADDR) operator(=) string<delimiter(")content(/tmp/mysql.sock)delimiter(")> + constant(MYSQL_PORT) operator(=) integer(3306) + constant(PROTOCOL_VERSION) operator(=) integer(10) + + comment(# Command) + constant(COM_SLEEP) operator(=) integer(0) + constant(COM_QUIT) operator(=) integer(1) + constant(COM_INIT_DB) operator(=) integer(2) + constant(COM_QUERY) operator(=) integer(3) + constant(COM_FIELD_LIST) operator(=) integer(4) + constant(COM_CREATE_DB) operator(=) integer(5) + constant(COM_DROP_DB) operator(=) integer(6) + constant(COM_REFRESH) operator(=) integer(7) + constant(COM_SHUTDOWN) operator(=) integer(8) + constant(COM_STATISTICS) operator(=) integer(9) + constant(COM_PROCESS_INFO) operator(=) integer(10) + constant(COM_CONNECT) operator(=) integer(11) + constant(COM_PROCESS_KILL) operator(=) integer(12) + constant(COM_DEBUG) operator(=) integer(13) + constant(COM_PING) operator(=) integer(14) + constant(COM_TIME) operator(=) integer(15) + constant(COM_DELAYED_INSERT) operator(=) integer(16) + constant(COM_CHANGE_USER) operator(=) integer(17) + constant(COM_BINLOG_DUMP) operator(=) integer(18) + constant(COM_TABLE_DUMP) operator(=) integer(19) + constant(COM_CONNECT_OUT) operator(=) integer(20) + constant(COM_REGISTER_SLAVE) operator(=) integer(21) + + comment(# Client flag) + constant(CLIENT_LONG_PASSWORD) operator(=) integer(1) + constant(CLIENT_FOUND_ROWS) operator(=) integer(1) operator(<<) integer(1) + constant(CLIENT_LONG_FLAG) operator(=) integer(1) operator(<<) integer(2) + constant(CLIENT_CONNECT_WITH_DB)operator(=) integer(1) operator(<<) integer(3) + constant(CLIENT_NO_SCHEMA) operator(=) integer(1) operator(<<) integer(4) + constant(CLIENT_COMPRESS) operator(=) integer(1) operator(<<) integer(5) + constant(CLIENT_ODBC) operator(=) integer(1) operator(<<) integer(6) + constant(CLIENT_LOCAL_FILES) operator(=) integer(1) operator(<<) integer(7) + constant(CLIENT_IGNORE_SPACE) operator(=) integer(1) operator(<<) integer(8) + constant(CLIENT_PROTOCOL_41) operator(=) integer(1) operator(<<) integer(9) + constant(CLIENT_INTERACTIVE) operator(=) integer(1) operator(<<) integer(10) + constant(CLIENT_SSL) operator(=) integer(1) operator(<<) integer(11) + constant(CLIENT_IGNORE_SIGPIPE) operator(=) integer(1) operator(<<) integer(12) + constant(CLIENT_TRANSACTIONS) operator(=) integer(1) operator(<<) integer(13) + constant(CLIENT_RESERVED) operator(=) integer(1) operator(<<) integer(14) + constant(CLIENT_SECURE_CONNECTION) operator(=) integer(1) operator(<<) integer(15) + constant(CLIENT_CAPABILITIES) operator(=) constant(CLIENT_LONG_PASSWORD)operator(|)constant(CLIENT_LONG_FLAG)operator(|)constant(CLIENT_TRANSACTIONS) + constant(PROTO_AUTH41) operator(=) constant(CLIENT_PROTOCOL_41) operator(|) constant(CLIENT_SECURE_CONNECTION) + + comment(# Connection Option) + constant(OPT_CONNECT_TIMEOUT) operator(=) integer(0) + constant(OPT_COMPRESS) operator(=) integer(1) + constant(OPT_NAMED_PIPE) operator(=) integer(2) + constant(INIT_COMMAND) operator(=) integer(3) + constant(READ_DEFAULT_FILE) operator(=) integer(4) + constant(READ_DEFAULT_GROUP) operator(=) integer(5) + constant(SET_CHARSET_DIR) operator(=) integer(6) + constant(SET_CHARSET_NAME) operator(=) integer(7) + constant(OPT_LOCAL_INFILE) operator(=) integer(8) + + comment(# Server Status) + constant(SERVER_STATUS_IN_TRANS) operator(=) integer(1) + constant(SERVER_STATUS_AUTOCOMMIT) operator(=) integer(2) + + comment(# Refresh parameter) + constant(REFRESH_GRANT) operator(=) integer(1) + constant(REFRESH_LOG) operator(=) integer(2) + constant(REFRESH_TABLES) operator(=) integer(4) + constant(REFRESH_HOSTS) operator(=) integer(8) + constant(REFRESH_STATUS) operator(=) integer(16) + constant(REFRESH_THREADS) operator(=) integer(32) + constant(REFRESH_SLAVE) operator(=) integer(64) + constant(REFRESH_MASTER) operator(=) integer(128) + + reserved(def) method(initialize)operator(()operator(*)ident(args)operator(\)) + instance_variable(@client_flag) operator(=) integer(0) + instance_variable(@max_allowed_packet) operator(=) constant(MAX_ALLOWED_PACKET) + instance_variable(@query_with_result) operator(=) pre_constant(true) + instance_variable(@status) operator(=) symbol(:STATUS_READY) + reserved(if) ident(args)operator([)integer(0)operator(]) operator(!=) symbol(:INIT) reserved(then) + ident(real_connect)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(real_connect)operator(()ident(host)operator(=)pre_constant(nil)operator(,) ident(user)operator(=)pre_constant(nil)operator(,) ident(passwd)operator(=)pre_constant(nil)operator(,) ident(db)operator(=)pre_constant(nil)operator(,) ident(port)operator(=)pre_constant(nil)operator(,) ident(socket)operator(=)pre_constant(nil)operator(,) ident(flag)operator(=)pre_constant(nil)operator(\)) + instance_variable(@server_status) operator(=) constant(SERVER_STATUS_AUTOCOMMIT) + reserved(if) operator(()ident(host) operator(==) pre_constant(nil) reserved(or) ident(host) operator(==) string<delimiter(")content(localhost)delimiter(")>operator(\)) reserved(and) reserved(defined?) constant(UNIXSocket) reserved(then) + ident(unix_socket) operator(=) ident(socket) operator(||) constant(ENV)operator([)string<delimiter(")content(MYSQL_UNIX_PORT)delimiter(")>operator(]) operator(||) constant(MYSQL_UNIX_ADDR) + ident(sock) operator(=) constant(UNIXSocket)operator(::)ident(new)operator(()ident(unix_socket)operator(\)) + instance_variable(@host_info) operator(=) constant(Error)operator(::)ident(err)operator(()constant(Error)operator(::)constant(CR_LOCALHOST_CONNECTION)operator(\)) + instance_variable(@unix_socket) operator(=) ident(unix_socket) + reserved(else) + ident(sock) operator(=) constant(TCPSocket)operator(::)ident(new)operator(()ident(host)operator(,) ident(port)operator(||)constant(ENV)operator([)string<delimiter(")content(MYSQL_TCP_PORT)delimiter(")>operator(])operator(||)operator(()constant(Socket)operator(::)ident(getservbyname)operator(()string<delimiter(")content(mysql)delimiter(")>operator(,)string<delimiter(")content(tcp)delimiter(")>operator(\)) reserved(rescue) constant(MYSQL_PORT)operator(\))operator(\)) + instance_variable(@host_info) operator(=) ident(sprintf) constant(Error)operator(::)ident(err)operator(()constant(Error)operator(::)constant(CR_TCP_CONNECTION)operator(\))operator(,) ident(host) + reserved(end) + instance_variable(@host) operator(=) ident(host) operator(?) ident(host)operator(.)ident(dup) operator(:) pre_constant(nil) + ident(sock)operator(.)ident(setsockopt) constant(Socket)operator(::)constant(SOL_SOCKET)operator(,) constant(Socket)operator(::)constant(SO_KEEPALIVE)operator(,) pre_constant(true) + instance_variable(@net) operator(=) constant(Net)operator(::)ident(new) ident(sock) + + ident(a) operator(=) ident(read) + instance_variable(@protocol_version) operator(=) ident(a)operator(.)ident(slice!)operator(()integer(0)operator(\)) + instance_variable(@server_version)operator(,) ident(a) operator(=) ident(a)operator(.)ident(split)operator(()regexp<delimiter(/)char(\\0)delimiter(/)>operator(,)integer(2)operator(\)) + instance_variable(@thread_id)operator(,) instance_variable(@scramble_buff) operator(=) ident(a)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(13)operator(\))operator(.)ident(unpack)operator(()string<delimiter(")content(La8)delimiter(")>operator(\)) + reserved(if) ident(a)operator(.)ident(size) operator(>)operator(=) integer(2) reserved(then) + instance_variable(@server_capabilities)operator(,) operator(=) ident(a)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(2)operator(\))operator(.)ident(unpack)operator(()string<delimiter(")content(v)delimiter(")>operator(\)) + reserved(end) + reserved(if) ident(a)operator(.)ident(size) operator(>)operator(=) integer(16) reserved(then) + instance_variable(@server_language)operator(,) instance_variable(@server_status) operator(=) ident(a)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(3)operator(\))operator(.)ident(unpack)operator(()string<delimiter(")content(cv)delimiter(")>operator(\)) + reserved(end) + + ident(flag) operator(=) integer(0) reserved(if) ident(flag) operator(==) pre_constant(nil) + ident(flag) operator(|=) instance_variable(@client_flag) operator(|) constant(CLIENT_CAPABILITIES) + ident(flag) operator(|=) constant(CLIENT_CONNECT_WITH_DB) reserved(if) ident(db) + + instance_variable(@pre_411) operator(=) operator(()integer(0) operator(==) instance_variable(@server_capabilities) operator(&) constant(PROTO_AUTH41)operator(\)) + reserved(if) instance_variable(@pre_411) + ident(data) operator(=) constant(Net)operator(::)ident(int2str)operator(()ident(flag)operator(\))operator(+)constant(Net)operator(::)ident(int3str)operator(()instance_variable(@max_allowed_packet)operator(\))operator(+) + operator(()ident(user)operator(||)string<delimiter(")delimiter(")>operator(\))operator(+)string<delimiter(")char(\\0)delimiter(")>operator(+) + ident(scramble)operator(()ident(passwd)operator(,) instance_variable(@scramble_buff)operator(,) instance_variable(@protocol_version)operator(==)integer(9)operator(\)) + reserved(else) + ident(dummy)operator(,) instance_variable(@salt2) operator(=) ident(a)operator(.)ident(unpack)operator(()string<delimiter(")content(a13a12)delimiter(")>operator(\)) + instance_variable(@scramble_buff) operator(+=) instance_variable(@salt2) + ident(flag) operator(|=) constant(PROTO_AUTH41) + ident(data) operator(=) constant(Net)operator(::)ident(int4str)operator(()ident(flag)operator(\)) operator(+) constant(Net)operator(::)ident(int4str)operator(()instance_variable(@max_allowed_packet)operator(\)) operator(+) + operator(()operator([)integer(8)operator(]) operator(+) constant(Array)operator(.)ident(new)operator(()integer(23)operator(,) integer(0)operator(\))operator(\))operator(.)ident(pack)operator(()string<delimiter(")content(c24)delimiter(")>operator(\)) operator(+) operator(()ident(user)operator(||)string<delimiter(")delimiter(")>operator(\))operator(+)string<delimiter(")char(\\0)delimiter(")>operator(+) + ident(scramble41)operator(()ident(passwd)operator(,) instance_variable(@scramble_buff)operator(\)) + reserved(end) + + reserved(if) ident(db) reserved(and) instance_variable(@server_capabilities) operator(&) constant(CLIENT_CONNECT_WITH_DB) operator(!=) integer(0) + ident(data) operator(<<) string<delimiter(")char(\\0)delimiter(")> reserved(if) instance_variable(@pre_411) + ident(data) operator(<<) ident(db) + instance_variable(@db) operator(=) ident(db)operator(.)ident(dup) + reserved(end) + ident(write) ident(data) + ident(read) + constant(ObjectSpace)operator(.)ident(define_finalizer)operator(()pre_constant(self)operator(,) constant(Mysql)operator(.)ident(finalizer)operator(()instance_variable(@net)operator(\))operator(\)) + pre_constant(self) + reserved(end) + reserved(alias) symbol(:connect) symbol(:real_connect) + + reserved(def) method(escape_string)operator(()ident(str)operator(\)) + constant(Mysql)operator(::)ident(escape_string) ident(str) + reserved(end) + reserved(alias) symbol(:quote) symbol(:escape_string) + + reserved(def) method(get_client_info)operator(()operator(\)) + constant(VERSION) + reserved(end) + reserved(alias) symbol(:client_info) symbol(:get_client_info) + + reserved(def) method(options)operator(()ident(option)operator(,) ident(arg)operator(=)pre_constant(nil)operator(\)) + reserved(if) ident(option) operator(==) constant(OPT_LOCAL_INFILE) reserved(then) + reserved(if) ident(arg) operator(==) pre_constant(false) reserved(or) ident(arg) operator(==) integer(0) reserved(then) + instance_variable(@client_flag) operator(&=) operator(~)constant(CLIENT_LOCAL_FILES) + reserved(else) + instance_variable(@client_flag) operator(|=) constant(CLIENT_LOCAL_FILES) + reserved(end) + reserved(else) + ident(raise) string<delimiter(")content(not implemented)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(real_query)operator(()ident(query)operator(\)) + ident(command) constant(COM_QUERY)operator(,) ident(query)operator(,) pre_constant(true) + ident(read_query_result) + pre_constant(self) + reserved(end) + + reserved(def) method(use_result)operator(()operator(\)) + reserved(if) instance_variable(@status) operator(!=) symbol(:STATUS_GET_RESULT) reserved(then) + ident(error) constant(Error)operator(::)constant(CR_COMMANDS_OUT_OF_SYNC) + reserved(end) + ident(res) operator(=) constant(Result)operator(::)ident(new) pre_constant(self)operator(,) instance_variable(@fields)operator(,) instance_variable(@field_count) + instance_variable(@status) operator(=) symbol(:STATUS_USE_RESULT) + ident(res) + reserved(end) + + reserved(def) method(store_result)operator(()operator(\)) + reserved(if) instance_variable(@status) operator(!=) symbol(:STATUS_GET_RESULT) reserved(then) + ident(error) constant(Error)operator(::)constant(CR_COMMANDS_OUT_OF_SYNC) + reserved(end) + instance_variable(@status) operator(=) symbol(:STATUS_READY) + ident(data) operator(=) ident(read_rows) instance_variable(@field_count) + ident(res) operator(=) constant(Result)operator(::)ident(new) pre_constant(self)operator(,) instance_variable(@fields)operator(,) instance_variable(@field_count)operator(,) ident(data) + instance_variable(@fields) operator(=) pre_constant(nil) + instance_variable(@affected_rows) operator(=) ident(data)operator(.)ident(length) + ident(res) + reserved(end) + + reserved(def) method(change_user)operator(()ident(user)operator(=)string<delimiter(")delimiter(")>operator(,) ident(passwd)operator(=)string<delimiter(")delimiter(")>operator(,) ident(db)operator(=)string<delimiter(")delimiter(")>operator(\)) + reserved(if) instance_variable(@pre_411) + ident(data) operator(=) ident(user)operator(+)string<delimiter(")char(\\0)delimiter(")>operator(+)ident(scramble)operator(()ident(passwd)operator(,) instance_variable(@scramble_buff)operator(,) instance_variable(@protocol_version)operator(==)integer(9)operator(\))operator(+)string<delimiter(")char(\\0)delimiter(")>operator(+)ident(db) + reserved(else) + ident(data) operator(=) ident(user)operator(+)string<delimiter(")char(\\0)delimiter(")>operator(+)ident(scramble41)operator(()ident(passwd)operator(,) instance_variable(@scramble_buff)operator(\))operator(+)ident(db) + reserved(end) + ident(command) constant(COM_CHANGE_USER)operator(,) ident(data) + instance_variable(@user) operator(=) ident(user) + instance_variable(@passwd) operator(=) ident(passwd) + instance_variable(@db) operator(=) ident(db) + reserved(end) + + reserved(def) method(character_set_name)operator(()operator(\)) + ident(raise) string<delimiter(")content(not implemented)delimiter(")> + reserved(end) + + reserved(def) method(close)operator(()operator(\)) + instance_variable(@status) operator(=) symbol(:STATUS_READY) + ident(command) constant(COM_QUIT)operator(,) pre_constant(nil)operator(,) pre_constant(true) + instance_variable(@net)operator(.)ident(close) + pre_constant(self) + reserved(end) + + reserved(def) method(create_db)operator(()ident(db)operator(\)) + ident(command) constant(COM_CREATE_DB)operator(,) ident(db) + pre_constant(self) + reserved(end) + + reserved(def) method(drop_db)operator(()ident(db)operator(\)) + ident(command) constant(COM_DROP_DB)operator(,) ident(db) + pre_constant(self) + reserved(end) + + reserved(def) method(dump_debug_info)operator(()operator(\)) + ident(command) constant(COM_DEBUG) + pre_constant(self) + reserved(end) + + reserved(def) method(get_host_info)operator(()operator(\)) + instance_variable(@host_info) + reserved(end) + reserved(alias) symbol(:host_info) symbol(:get_host_info) + + reserved(def) method(get_proto_info)operator(()operator(\)) + instance_variable(@protocol_version) + reserved(end) + reserved(alias) symbol(:proto_info) symbol(:get_proto_info) + + reserved(def) method(get_server_info)operator(()operator(\)) + instance_variable(@server_version) + reserved(end) + reserved(alias) symbol(:server_info) symbol(:get_server_info) + + reserved(def) method(kill)operator(()ident(id)operator(\)) + ident(command) constant(COM_PROCESS_KILL)operator(,) constant(Net)operator(::)ident(int4str)operator(()ident(id)operator(\)) + pre_constant(self) + reserved(end) + + reserved(def) method(list_dbs)operator(()ident(db)operator(=)pre_constant(nil)operator(\)) + ident(real_query) string<delimiter(")content(show databases )inline<inline_delimiter(#{)ident(db)inline_delimiter(})>delimiter(")> + instance_variable(@status) operator(=) symbol(:STATUS_READY) + ident(read_rows)operator(()integer(1)operator(\))operator(.)ident(flatten) + reserved(end) + + reserved(def) method(list_fields)operator(()ident(table)operator(,) ident(field)operator(=)pre_constant(nil)operator(\)) + ident(command) constant(COM_FIELD_LIST)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(table)inline_delimiter(})>char(\\0)inline<inline_delimiter(#{)ident(field)inline_delimiter(})>delimiter(")>operator(,) pre_constant(true) + reserved(if) instance_variable(@pre_411) + ident(f) operator(=) ident(read_rows) integer(6) + reserved(else) + ident(f) operator(=) ident(read_rows) integer(7) + reserved(end) + ident(fields) operator(=) ident(unpack_fields)operator(()ident(f)operator(,) instance_variable(@server_capabilities) operator(&) constant(CLIENT_LONG_FLAG) operator(!=) integer(0)operator(\)) + ident(res) operator(=) constant(Result)operator(::)ident(new) pre_constant(self)operator(,) ident(fields)operator(,) ident(f)operator(.)ident(length) + ident(res)operator(.)ident(eof) operator(=) pre_constant(true) + ident(res) + reserved(end) + + reserved(def) method(list_processes)operator(()operator(\)) + ident(data) operator(=) ident(command) constant(COM_PROCESS_INFO) + instance_variable(@field_count) operator(=) ident(get_length) ident(data) + reserved(if) instance_variable(@pre_411) + ident(fields) operator(=) ident(read_rows) integer(5) + reserved(else) + ident(fields) operator(=) ident(read_rows) integer(7) + reserved(end) + instance_variable(@fields) operator(=) ident(unpack_fields)operator(()ident(fields)operator(,) instance_variable(@server_capabilities) operator(&) constant(CLIENT_LONG_FLAG) operator(!=) integer(0)operator(\)) + instance_variable(@status) operator(=) symbol(:STATUS_GET_RESULT) + ident(store_result) + reserved(end) + + reserved(def) method(list_tables)operator(()ident(table)operator(=)pre_constant(nil)operator(\)) + ident(real_query) string<delimiter(")content(show tables )inline<inline_delimiter(#{)ident(table)inline_delimiter(})>delimiter(")> + instance_variable(@status) operator(=) symbol(:STATUS_READY) + ident(read_rows)operator(()integer(1)operator(\))operator(.)ident(flatten) + reserved(end) + + reserved(def) method(ping)operator(()operator(\)) + ident(command) constant(COM_PING) + pre_constant(self) + reserved(end) + + reserved(def) method(query)operator(()ident(query)operator(\)) + ident(real_query) ident(query) + reserved(if) reserved(not) instance_variable(@query_with_result) reserved(then) + reserved(return) pre_constant(self) + reserved(end) + reserved(if) instance_variable(@field_count) operator(==) integer(0) reserved(then) + reserved(return) pre_constant(nil) + reserved(end) + ident(store_result) + reserved(end) + + reserved(def) method(refresh)operator(()ident(r)operator(\)) + ident(command) constant(COM_REFRESH)operator(,) ident(r)operator(.)ident(chr) + pre_constant(self) + reserved(end) + + reserved(def) method(reload)operator(()operator(\)) + ident(refresh) constant(REFRESH_GRANT) + pre_constant(self) + reserved(end) + + reserved(def) method(select_db)operator(()ident(db)operator(\)) + ident(command) constant(COM_INIT_DB)operator(,) ident(db) + instance_variable(@db) operator(=) ident(db) + pre_constant(self) + reserved(end) + + reserved(def) method(shutdown)operator(()operator(\)) + ident(command) constant(COM_SHUTDOWN) + pre_constant(self) + reserved(end) + + reserved(def) method(stat)operator(()operator(\)) + ident(command) constant(COM_STATISTICS) + reserved(end) + + ident(attr_reader) symbol(:info)operator(,) symbol(:insert_id)operator(,) symbol(:affected_rows)operator(,) symbol(:field_count)operator(,) symbol(:thread_id) + ident(attr_accessor) symbol(:query_with_result)operator(,) symbol(:status) + + reserved(def) method(read_one_row)operator(()ident(field_count)operator(\)) + ident(data) operator(=) ident(read) + reserved(if) ident(data)operator([)integer(0)operator(]) operator(==) integer(254) reserved(and) ident(data)operator(.)ident(length) operator(==) integer(1) comment(## EOF) + reserved(return) + reserved(elsif) ident(data)operator([)integer(0)operator(]) operator(==) integer(254) reserved(and) ident(data)operator(.)ident(length) operator(==) integer(5) + reserved(return) + reserved(end) + ident(rec) operator(=) operator([)operator(]) + ident(field_count)operator(.)ident(times) reserved(do) + ident(len) operator(=) ident(get_length) ident(data) + reserved(if) ident(len) operator(==) pre_constant(nil) reserved(then) + ident(rec) operator(<<) ident(len) + reserved(else) + ident(rec) operator(<<) ident(data)operator(.)ident(slice!)operator(()integer(0)operator(,)ident(len)operator(\)) + reserved(end) + reserved(end) + ident(rec) + reserved(end) + + reserved(def) method(skip_result)operator(()operator(\)) + reserved(if) instance_variable(@status) operator(==) symbol(:STATUS_USE_RESULT) reserved(then) + ident(loop) reserved(do) + ident(data) operator(=) ident(read) + reserved(break) reserved(if) ident(data)operator([)integer(0)operator(]) operator(==) integer(254) reserved(and) ident(data)operator(.)ident(length) operator(==) integer(1) + reserved(end) + instance_variable(@status) operator(=) symbol(:STATUS_READY) + reserved(end) + reserved(end) + + reserved(def) method(inspect)operator(()operator(\)) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + ident(private) + + reserved(def) method(read_query_result)operator(()operator(\)) + ident(data) operator(=) ident(read) + instance_variable(@field_count) operator(=) ident(get_length)operator(()ident(data)operator(\)) + reserved(if) instance_variable(@field_count) operator(==) pre_constant(nil) reserved(then) comment(# LOAD DATA LOCAL INFILE) + constant(File)operator(::)ident(open)operator(()ident(data)operator(\)) reserved(do) operator(|)ident(f)operator(|) + ident(write) ident(f)operator(.)ident(read) + reserved(end) + ident(write) string<delimiter(")delimiter(")> comment(# mark EOF) + ident(data) operator(=) ident(read) + instance_variable(@field_count) operator(=) ident(get_length)operator(()ident(data)operator(\)) + reserved(end) + reserved(if) instance_variable(@field_count) operator(==) integer(0) reserved(then) + instance_variable(@affected_rows) operator(=) ident(get_length)operator(()ident(data)operator(,) pre_constant(true)operator(\)) + instance_variable(@insert_id) operator(=) ident(get_length)operator(()ident(data)operator(,) pre_constant(true)operator(\)) + reserved(if) instance_variable(@server_capabilities) operator(&) constant(CLIENT_TRANSACTIONS) operator(!=) integer(0) reserved(then) + ident(a) operator(=) ident(data)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(2)operator(\)) + instance_variable(@server_status) operator(=) ident(a)operator([)integer(0)operator(])operator(+)ident(a)operator([)integer(1)operator(])operator(*)integer(256) + reserved(end) + reserved(if) ident(data)operator(.)ident(size) operator(>) integer(0) reserved(and) ident(get_length)operator(()ident(data)operator(\)) reserved(then) + instance_variable(@info) operator(=) ident(data) + reserved(end) + reserved(else) + instance_variable(@extra_info) operator(=) ident(get_length)operator(()ident(data)operator(,) pre_constant(true)operator(\)) + reserved(if) instance_variable(@pre_411) + ident(fields) operator(=) ident(read_rows)operator(()integer(5)operator(\)) + reserved(else) + ident(fields) operator(=) ident(read_rows)operator(()integer(7)operator(\)) + reserved(end) + instance_variable(@fields) operator(=) ident(unpack_fields)operator(()ident(fields)operator(,) instance_variable(@server_capabilities) operator(&) constant(CLIENT_LONG_FLAG) operator(!=) integer(0)operator(\)) + instance_variable(@status) operator(=) symbol(:STATUS_GET_RESULT) + reserved(end) + pre_constant(self) + reserved(end) + + reserved(def) method(unpack_fields)operator(()ident(data)operator(,) ident(long_flag_protocol)operator(\)) + ident(ret) operator(=) operator([)operator(]) + ident(data)operator(.)ident(each) reserved(do) operator(|)ident(f)operator(|) + reserved(if) instance_variable(@pre_411) + ident(table) operator(=) ident(org_table) operator(=) ident(f)operator([)integer(0)operator(]) + ident(name) operator(=) ident(f)operator([)integer(1)operator(]) + ident(length) operator(=) ident(f)operator([)integer(2)operator(])operator([)integer(0)operator(])operator(+)ident(f)operator([)integer(2)operator(])operator([)integer(1)operator(])operator(*)integer(256)operator(+)ident(f)operator([)integer(2)operator(])operator([)integer(2)operator(])operator(*)integer(256)operator(*)integer(256) + ident(type) operator(=) ident(f)operator([)integer(3)operator(])operator([)integer(0)operator(]) + reserved(if) ident(long_flag_protocol) reserved(then) + ident(flags) operator(=) ident(f)operator([)integer(4)operator(])operator([)integer(0)operator(])operator(+)ident(f)operator([)integer(4)operator(])operator([)integer(1)operator(])operator(*)integer(256) + ident(decimals) operator(=) ident(f)operator([)integer(4)operator(])operator([)integer(2)operator(]) + reserved(else) + ident(flags) operator(=) ident(f)operator([)integer(4)operator(])operator([)integer(0)operator(]) + ident(decimals) operator(=) ident(f)operator([)integer(4)operator(])operator([)integer(1)operator(]) + reserved(end) + ident(def_value) operator(=) ident(f)operator([)integer(5)operator(]) + ident(max_length) operator(=) integer(0) + reserved(else) + ident(catalog) operator(=) ident(f)operator([)integer(0)operator(]) + ident(db) operator(=) ident(f)operator([)integer(1)operator(]) + ident(table) operator(=) ident(f)operator([)integer(2)operator(]) + ident(org_table) operator(=) ident(f)operator([)integer(3)operator(]) + ident(name) operator(=) ident(f)operator([)integer(4)operator(]) + ident(org_name) operator(=) ident(f)operator([)integer(5)operator(]) + ident(length) operator(=) ident(f)operator([)integer(6)operator(])operator([)integer(2)operator(])operator(+)ident(f)operator([)integer(6)operator(])operator([)integer(3)operator(])operator(*)integer(256)operator(+)ident(f)operator([)integer(6)operator(])operator([)integer(4)operator(])operator(*)integer(256)operator(*)integer(256) + ident(type) operator(=) ident(f)operator([)integer(6)operator(])operator([)integer(6)operator(]) + ident(flags) operator(=) ident(f)operator([)integer(6)operator(])operator([)integer(7)operator(])operator(+)ident(f)operator([)integer(6)operator(])operator([)integer(8)operator(])operator(*)integer(256) + ident(decimals) operator(=) ident(f)operator([)integer(6)operator(])operator([)integer(9)operator(]) + ident(def_value) operator(=) string<delimiter(")delimiter(")> + ident(max_length) operator(=) integer(0) + reserved(end) + ident(ret) operator(<<) constant(Field)operator(::)ident(new)operator(()ident(table)operator(,) ident(org_table)operator(,) ident(name)operator(,) ident(length)operator(,) ident(type)operator(,) ident(flags)operator(,) ident(decimals)operator(,) ident(def_value)operator(,) ident(max_length)operator(\)) + reserved(end) + ident(ret) + reserved(end) + + reserved(def) method(read_rows)operator(()ident(field_count)operator(\)) + ident(ret) operator(=) operator([)operator(]) + reserved(while) ident(rec) operator(=) ident(read_one_row)operator(()ident(field_count)operator(\)) reserved(do) + ident(ret) operator(<<) ident(rec) + reserved(end) + ident(ret) + reserved(end) + + reserved(def) method(get_length)operator(()ident(data)operator(,) ident(longlong)operator(=)pre_constant(nil)operator(\)) + reserved(return) reserved(if) ident(data)operator(.)ident(length) operator(==) integer(0) + ident(c) operator(=) ident(data)operator(.)ident(slice!)operator(()integer(0)operator(\)) + reserved(case) ident(c) + reserved(when) integer(251) + reserved(return) pre_constant(nil) + reserved(when) integer(252) + ident(a) operator(=) ident(data)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(2)operator(\)) + reserved(return) ident(a)operator([)integer(0)operator(])operator(+)ident(a)operator([)integer(1)operator(])operator(*)integer(256) + reserved(when) integer(253) + ident(a) operator(=) ident(data)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(3)operator(\)) + reserved(return) ident(a)operator([)integer(0)operator(])operator(+)ident(a)operator([)integer(1)operator(])operator(*)integer(256)operator(+)ident(a)operator([)integer(2)operator(])operator(*)integer(256)operator(**)integer(2) + reserved(when) integer(254) + ident(a) operator(=) ident(data)operator(.)ident(slice!)operator(()integer(0)operator(,)integer(8)operator(\)) + reserved(if) ident(longlong) reserved(then) + reserved(return) ident(a)operator([)integer(0)operator(])operator(+)ident(a)operator([)integer(1)operator(])operator(*)integer(256)operator(+)ident(a)operator([)integer(2)operator(])operator(*)integer(256)operator(**)integer(2)operator(+)ident(a)operator([)integer(3)operator(])operator(*)integer(256)operator(**)integer(3)operator(+) + ident(a)operator([)integer(4)operator(])operator(*)integer(256)operator(**)integer(4)operator(+)ident(a)operator([)integer(5)operator(])operator(*)integer(256)operator(**)integer(5)operator(+)ident(a)operator([)integer(6)operator(])operator(*)integer(256)operator(**)integer(6)operator(+)ident(a)operator([)integer(7)operator(])operator(*)integer(256)operator(**)integer(7) + reserved(else) + reserved(return) ident(a)operator([)integer(0)operator(])operator(+)ident(a)operator([)integer(1)operator(])operator(*)integer(256)operator(+)ident(a)operator([)integer(2)operator(])operator(*)integer(256)operator(**)integer(2)operator(+)ident(a)operator([)integer(3)operator(])operator(*)integer(256)operator(**)integer(3) + reserved(end) + reserved(else) + ident(c) + reserved(end) + reserved(end) + + reserved(def) method(command)operator(()ident(cmd)operator(,) ident(arg)operator(=)pre_constant(nil)operator(,) ident(skip_check)operator(=)pre_constant(nil)operator(\)) + reserved(unless) instance_variable(@net) reserved(then) + ident(error) constant(Error)operator(::)constant(CR_SERVER_GONE_ERROR) + reserved(end) + reserved(if) instance_variable(@status) operator(!=) symbol(:STATUS_READY) reserved(then) + ident(error) constant(Error)operator(::)constant(CR_COMMANDS_OUT_OF_SYNC) + reserved(end) + instance_variable(@net)operator(.)ident(clear) + ident(write) ident(cmd)operator(.)ident(chr)operator(+)operator(()ident(arg)operator(||)string<delimiter(")delimiter(")>operator(\)) + ident(read) reserved(unless) ident(skip_check) + reserved(end) + + reserved(def) method(read)operator(()operator(\)) + reserved(unless) instance_variable(@net) reserved(then) + ident(error) constant(Error)operator(::)constant(CR_SERVER_GONE_ERROR) + reserved(end) + ident(a) operator(=) instance_variable(@net)operator(.)ident(read) + reserved(if) ident(a)operator([)integer(0)operator(]) operator(==) integer(255) reserved(then) + reserved(if) ident(a)operator(.)ident(length) operator(>) integer(3) reserved(then) + instance_variable(@errno) operator(=) ident(a)operator([)integer(1)operator(])operator(+)ident(a)operator([)integer(2)operator(])operator(*)integer(256) + instance_variable(@error) operator(=) ident(a)operator([)integer(3) operator(..) integer(-1)operator(]) + reserved(else) + instance_variable(@errno) operator(=) constant(Error)operator(::)constant(CR_UNKNOWN_ERROR) + instance_variable(@error) operator(=) constant(Error)operator(::)ident(err) instance_variable(@errno) + reserved(end) + ident(raise) constant(Error)operator(::)ident(new)operator(()instance_variable(@errno)operator(,) instance_variable(@error)operator(\)) + reserved(end) + ident(a) + reserved(end) + + reserved(def) method(write)operator(()ident(arg)operator(\)) + reserved(unless) instance_variable(@net) reserved(then) + ident(error) constant(Error)operator(::)constant(CR_SERVER_GONE_ERROR) + reserved(end) + instance_variable(@net)operator(.)ident(write) ident(arg) + reserved(end) + + reserved(def) method(hash_password)operator(()ident(password)operator(\)) + ident(nr) operator(=) integer(1345345333) + ident(add) operator(=) integer(7) + ident(nr2) operator(=) integer(0x12345671) + ident(password)operator(.)ident(each_byte) reserved(do) operator(|)ident(i)operator(|) + reserved(next) reserved(if) ident(i) operator(==) integer(0x20) reserved(or) ident(i) operator(==) integer(9) + ident(nr) operator(^=) operator(()operator(()operator(()ident(nr) operator(&) integer(63)operator(\)) operator(+) ident(add)operator(\)) operator(*) ident(i)operator(\)) operator(+) operator(()ident(nr) operator(<<) integer(8)operator(\)) + ident(nr2) operator(+=) operator(()ident(nr2) operator(<<) integer(8)operator(\)) operator(^) ident(nr) + ident(add) operator(+=) ident(i) + reserved(end) + operator([)ident(nr) operator(&) operator(()operator(()integer(1) operator(<<) integer(31)operator(\)) operator(-) integer(1)operator(\))operator(,) ident(nr2) operator(&) operator(()operator(()integer(1) operator(<<) integer(31)operator(\)) operator(-) integer(1)operator(\))operator(]) + reserved(end) + + reserved(def) method(scramble)operator(()ident(password)operator(,) ident(message)operator(,) ident(old_ver)operator(\)) + reserved(return) string<delimiter(")delimiter(")> reserved(if) ident(password) operator(==) pre_constant(nil) reserved(or) ident(password) operator(==) string<delimiter(")delimiter(")> + ident(raise) string<delimiter(")content(old version password is not implemented)delimiter(")> reserved(if) ident(old_ver) + ident(hash_pass) operator(=) ident(hash_password) ident(password) + ident(hash_message) operator(=) ident(hash_password) ident(message) + ident(rnd) operator(=) constant(Random)operator(::)ident(new) ident(hash_pass)operator([)integer(0)operator(]) operator(^) ident(hash_message)operator([)integer(0)operator(])operator(,) ident(hash_pass)operator([)integer(1)operator(]) operator(^) ident(hash_message)operator([)integer(1)operator(]) + ident(to) operator(=) operator([)operator(]) + integer(1)operator(.)ident(upto)operator(()ident(message)operator(.)ident(length)operator(\)) reserved(do) + ident(to) operator(<<) operator(()operator(()ident(rnd)operator(.)ident(rnd)operator(*)integer(31)operator(\))operator(+)integer(64)operator(\))operator(.)ident(floor) + reserved(end) + ident(extra) operator(=) operator(()ident(rnd)operator(.)ident(rnd)operator(*)integer(31)operator(\))operator(.)ident(floor) + ident(to)operator(.)ident(map!) reserved(do) operator(|)ident(t)operator(|) operator(()ident(t) operator(^) ident(extra)operator(\))operator(.)ident(chr) reserved(end) + ident(to)operator(.)ident(join) + reserved(end) + + reserved(def) method(scramble41)operator(()ident(password)operator(,) ident(message)operator(\)) + reserved(return) integer(0x00)operator(.)ident(chr) reserved(if) ident(password)operator(.)ident(nil?) reserved(or) ident(password)operator(.)ident(empty?) + ident(buf) operator(=) operator([)integer(0x14)operator(]) + ident(s1) operator(=) constant(Digest)operator(::)constant(SHA1)operator(.)ident(new)operator(()ident(password)operator(\))operator(.)ident(digest) + ident(s2) operator(=) constant(Digest)operator(::)constant(SHA1)operator(.)ident(new)operator(()ident(s1)operator(\))operator(.)ident(digest) + ident(x) operator(=) constant(Digest)operator(::)constant(SHA1)operator(.)ident(new)operator(()ident(message) operator(+) ident(s2)operator(\))operator(.)ident(digest) + operator(()integer(0)operator(..)ident(s1)operator(.)ident(length) operator(-) integer(1)operator(\))operator(.)ident(each) operator({)operator(|)ident(i)operator(|) ident(buf)operator(.)ident(push)operator(()ident(s1)operator([)ident(i)operator(]) operator(^) ident(x)operator([)ident(i)operator(])operator(\))operator(}) + ident(buf)operator(.)ident(pack)operator(()string<delimiter(")content(C*)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(error)operator(()ident(errno)operator(\)) + instance_variable(@errno) operator(=) ident(errno) + instance_variable(@error) operator(=) constant(Error)operator(::)ident(err) ident(errno) + ident(raise) constant(Error)operator(::)ident(new)operator(()instance_variable(@errno)operator(,) instance_variable(@error)operator(\)) + reserved(end) + + reserved(class) class(Result) + reserved(def) method(initialize)operator(()ident(mysql)operator(,) ident(fields)operator(,) ident(field_count)operator(,) ident(data)operator(=)pre_constant(nil)operator(\)) + instance_variable(@handle) operator(=) ident(mysql) + instance_variable(@fields) operator(=) ident(fields) + instance_variable(@field_count) operator(=) ident(field_count) + instance_variable(@data) operator(=) ident(data) + instance_variable(@current_field) operator(=) integer(0) + instance_variable(@current_row) operator(=) integer(0) + instance_variable(@eof) operator(=) pre_constant(false) + instance_variable(@row_count) operator(=) integer(0) + reserved(end) + ident(attr_accessor) symbol(:eof) + + reserved(def) method(data_seek)operator(()ident(n)operator(\)) + instance_variable(@current_row) operator(=) ident(n) + reserved(end) + + reserved(def) method(fetch_field)operator(()operator(\)) + reserved(return) reserved(if) instance_variable(@current_field) operator(>)operator(=) instance_variable(@field_count) + ident(f) operator(=) instance_variable(@fields)operator([)instance_variable(@current_field)operator(]) + instance_variable(@current_field) operator(+=) integer(1) + ident(f) + reserved(end) + + reserved(def) method(fetch_fields)operator(()operator(\)) + instance_variable(@fields) + reserved(end) + + reserved(def) method(fetch_field_direct)operator(()ident(n)operator(\)) + instance_variable(@fields)operator([)ident(n)operator(]) + reserved(end) + + reserved(def) method(fetch_lengths)operator(()operator(\)) + instance_variable(@data) operator(?) instance_variable(@data)operator([)instance_variable(@current_row)operator(])operator(.)ident(map)operator({)operator(|)ident(i)operator(|) ident(i) operator(?) ident(i)operator(.)ident(length) operator(:) integer(0)operator(}) operator(:) instance_variable(@lengths) + reserved(end) + + reserved(def) method(fetch_row)operator(()operator(\)) + reserved(if) instance_variable(@data) reserved(then) + reserved(if) instance_variable(@current_row) operator(>)operator(=) instance_variable(@data)operator(.)ident(length) reserved(then) + instance_variable(@handle)operator(.)ident(status) operator(=) symbol(:STATUS_READY) + reserved(return) + reserved(end) + ident(ret) operator(=) instance_variable(@data)operator([)instance_variable(@current_row)operator(]) + instance_variable(@current_row) operator(+=) integer(1) + reserved(else) + reserved(return) reserved(if) instance_variable(@eof) + ident(ret) operator(=) instance_variable(@handle)operator(.)ident(read_one_row) instance_variable(@field_count) + reserved(if) ident(ret) operator(==) pre_constant(nil) reserved(then) + instance_variable(@eof) operator(=) pre_constant(true) + reserved(return) + reserved(end) + instance_variable(@lengths) operator(=) ident(ret)operator(.)ident(map)operator({)operator(|)ident(i)operator(|) ident(i) operator(?) ident(i)operator(.)ident(length) operator(:) integer(0)operator(}) + instance_variable(@row_count) operator(+=) integer(1) + reserved(end) + ident(ret) + reserved(end) + + reserved(def) method(fetch_hash)operator(()ident(with_table)operator(=)pre_constant(nil)operator(\)) + ident(row) operator(=) ident(fetch_row) + reserved(return) reserved(if) ident(row) operator(==) pre_constant(nil) + ident(hash) operator(=) operator({)operator(}) + instance_variable(@fields)operator(.)ident(each_index) reserved(do) operator(|)ident(i)operator(|) + ident(f) operator(=) ident(with_table) operator(?) instance_variable(@fields)operator([)ident(i)operator(])operator(.)ident(table)operator(+)string<delimiter(")content(.)delimiter(")>operator(+)instance_variable(@fields)operator([)ident(i)operator(])operator(.)ident(name) operator(:) instance_variable(@fields)operator([)ident(i)operator(])operator(.)ident(name) + ident(hash)operator([)ident(f)operator(]) operator(=) ident(row)operator([)ident(i)operator(]) + reserved(end) + ident(hash) + reserved(end) + + reserved(def) method(field_seek)operator(()ident(n)operator(\)) + instance_variable(@current_field) operator(=) ident(n) + reserved(end) + + reserved(def) method(field_tell)operator(()operator(\)) + instance_variable(@current_field) + reserved(end) + + reserved(def) method(free)operator(()operator(\)) + instance_variable(@handle)operator(.)ident(skip_result) + instance_variable(@handle) operator(=) instance_variable(@fields) operator(=) instance_variable(@data) operator(=) pre_constant(nil) + reserved(end) + + reserved(def) method(num_fields)operator(()operator(\)) + instance_variable(@field_count) + reserved(end) + + reserved(def) method(num_rows)operator(()operator(\)) + instance_variable(@data) operator(?) instance_variable(@data)operator(.)ident(length) operator(:) instance_variable(@row_count) + reserved(end) + + reserved(def) method(row_seek)operator(()ident(n)operator(\)) + instance_variable(@current_row) operator(=) ident(n) + reserved(end) + + reserved(def) method(row_tell)operator(()operator(\)) + instance_variable(@current_row) + reserved(end) + + reserved(def) method(each)operator(()operator(\)) + reserved(while) ident(row) operator(=) ident(fetch_row) reserved(do) + reserved(yield) ident(row) + reserved(end) + reserved(end) + + reserved(def) method(each_hash)operator(()ident(with_table)operator(=)pre_constant(nil)operator(\)) + reserved(while) ident(hash) operator(=) ident(fetch_hash)operator(()ident(with_table)operator(\)) reserved(do) + reserved(yield) ident(hash) + reserved(end) + reserved(end) + + reserved(def) method(inspect)operator(()operator(\)) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(end) + + reserved(class) class(Field) + comment(# Field type) + constant(TYPE_DECIMAL) operator(=) integer(0) + constant(TYPE_TINY) operator(=) integer(1) + constant(TYPE_SHORT) operator(=) integer(2) + constant(TYPE_LONG) operator(=) integer(3) + constant(TYPE_FLOAT) operator(=) integer(4) + constant(TYPE_DOUBLE) operator(=) integer(5) + constant(TYPE_NULL) operator(=) integer(6) + constant(TYPE_TIMESTAMP) operator(=) integer(7) + constant(TYPE_LONGLONG) operator(=) integer(8) + constant(TYPE_INT24) operator(=) integer(9) + constant(TYPE_DATE) operator(=) integer(10) + constant(TYPE_TIME) operator(=) integer(11) + constant(TYPE_DATETIME) operator(=) integer(12) + constant(TYPE_YEAR) operator(=) integer(13) + constant(TYPE_NEWDATE) operator(=) integer(14) + constant(TYPE_ENUM) operator(=) integer(247) + constant(TYPE_SET) operator(=) integer(248) + constant(TYPE_TINY_BLOB) operator(=) integer(249) + constant(TYPE_MEDIUM_BLOB) operator(=) integer(250) + constant(TYPE_LONG_BLOB) operator(=) integer(251) + constant(TYPE_BLOB) operator(=) integer(252) + constant(TYPE_VAR_STRING) operator(=) integer(253) + constant(TYPE_STRING) operator(=) integer(254) + constant(TYPE_GEOMETRY) operator(=) integer(255) + constant(TYPE_CHAR) operator(=) constant(TYPE_TINY) + constant(TYPE_INTERVAL) operator(=) constant(TYPE_ENUM) + + comment(# Flag) + constant(NOT_NULL_FLAG) operator(=) integer(1) + constant(PRI_KEY_FLAG) operator(=) integer(2) + constant(UNIQUE_KEY_FLAG) operator(=) integer(4) + constant(MULTIPLE_KEY_FLAG) operator(=) integer(8) + constant(BLOB_FLAG) operator(=) integer(16) + constant(UNSIGNED_FLAG) operator(=) integer(32) + constant(ZEROFILL_FLAG) operator(=) integer(64) + constant(BINARY_FLAG) operator(=) integer(128) + constant(ENUM_FLAG) operator(=) integer(256) + constant(AUTO_INCREMENT_FLAG) operator(=) integer(512) + constant(TIMESTAMP_FLAG) operator(=) integer(1024) + constant(SET_FLAG) operator(=) integer(2048) + constant(NUM_FLAG) operator(=) integer(32768) + constant(PART_KEY_FLAG) operator(=) integer(16384) + constant(GROUP_FLAG) operator(=) integer(32768) + constant(UNIQUE_FLAG) operator(=) integer(65536) + + reserved(def) method(initialize)operator(()ident(table)operator(,) ident(org_table)operator(,) ident(name)operator(,) ident(length)operator(,) ident(type)operator(,) ident(flags)operator(,) ident(decimals)operator(,) ident(def_value)operator(,) ident(max_length)operator(\)) + instance_variable(@table) operator(=) ident(table) + instance_variable(@org_table) operator(=) ident(org_table) + instance_variable(@name) operator(=) ident(name) + instance_variable(@length) operator(=) ident(length) + instance_variable(@type) operator(=) ident(type) + instance_variable(@flags) operator(=) ident(flags) + instance_variable(@decimals) operator(=) ident(decimals) + instance_variable(@def) operator(=) ident(def_value) + instance_variable(@max_length) operator(=) ident(max_length) + reserved(if) operator(()ident(type) operator(<=) constant(TYPE_INT24) reserved(and) operator(()ident(type) operator(!=) constant(TYPE_TIMESTAMP) reserved(or) ident(length) operator(==) integer(14) reserved(or) ident(length) operator(==) integer(8)operator(\))operator(\)) reserved(or) ident(type) operator(==) constant(TYPE_YEAR) reserved(then) + instance_variable(@flags) operator(|=) constant(NUM_FLAG) + reserved(end) + reserved(end) + ident(attr_reader) symbol(:table)operator(,) symbol(:org_table)operator(,) symbol(:name)operator(,) symbol(:length)operator(,) symbol(:type)operator(,) symbol(:flags)operator(,) symbol(:decimals)operator(,) symbol(:def)operator(,) symbol(:max_length) + + reserved(def) method(inspect)operator(()operator(\)) + string<delimiter(")content(#<)inline<inline_delimiter(#{)pre_constant(self)operator(.)ident(class)inline_delimiter(})>content(:)inline<inline_delimiter(#{)instance_variable(@name)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + reserved(end) + + reserved(class) class(Error) operator(<) constant(StandardError) + comment(# Server Error) + constant(ER_HASHCHK) operator(=) integer(1000) + constant(ER_NISAMCHK) operator(=) integer(1001) + constant(ER_NO) operator(=) integer(1002) + constant(ER_YES) operator(=) integer(1003) + constant(ER_CANT_CREATE_FILE) operator(=) integer(1004) + constant(ER_CANT_CREATE_TABLE) operator(=) integer(1005) + constant(ER_CANT_CREATE_DB) operator(=) integer(1006) + constant(ER_DB_CREATE_EXISTS) operator(=) integer(1007) + constant(ER_DB_DROP_EXISTS) operator(=) integer(1008) + constant(ER_DB_DROP_DELETE) operator(=) integer(1009) + constant(ER_DB_DROP_RMDIR) operator(=) integer(1010) + constant(ER_CANT_DELETE_FILE) operator(=) integer(1011) + constant(ER_CANT_FIND_SYSTEM_REC) operator(=) integer(1012) + constant(ER_CANT_GET_STAT) operator(=) integer(1013) + constant(ER_CANT_GET_WD) operator(=) integer(1014) + constant(ER_CANT_LOCK) operator(=) integer(1015) + constant(ER_CANT_OPEN_FILE) operator(=) integer(1016) + constant(ER_FILE_NOT_FOUND) operator(=) integer(1017) + constant(ER_CANT_READ_DIR) operator(=) integer(1018) + constant(ER_CANT_SET_WD) operator(=) integer(1019) + constant(ER_CHECKREAD) operator(=) integer(1020) + constant(ER_DISK_FULL) operator(=) integer(1021) + constant(ER_DUP_KEY) operator(=) integer(1022) + constant(ER_ERROR_ON_CLOSE) operator(=) integer(1023) + constant(ER_ERROR_ON_READ) operator(=) integer(1024) + constant(ER_ERROR_ON_RENAME) operator(=) integer(1025) + constant(ER_ERROR_ON_WRITE) operator(=) integer(1026) + constant(ER_FILE_USED) operator(=) integer(1027) + constant(ER_FILSORT_ABORT) operator(=) integer(1028) + constant(ER_FORM_NOT_FOUND) operator(=) integer(1029) + constant(ER_GET_ERRNO) operator(=) integer(1030) + constant(ER_ILLEGAL_HA) operator(=) integer(1031) + constant(ER_KEY_NOT_FOUND) operator(=) integer(1032) + constant(ER_NOT_FORM_FILE) operator(=) integer(1033) + constant(ER_NOT_KEYFILE) operator(=) integer(1034) + constant(ER_OLD_KEYFILE) operator(=) integer(1035) + constant(ER_OPEN_AS_READONLY) operator(=) integer(1036) + constant(ER_OUTOFMEMORY) operator(=) integer(1037) + constant(ER_OUT_OF_SORTMEMORY) operator(=) integer(1038) + constant(ER_UNEXPECTED_EOF) operator(=) integer(1039) + constant(ER_CON_COUNT_ERROR) operator(=) integer(1040) + constant(ER_OUT_OF_RESOURCES) operator(=) integer(1041) + constant(ER_BAD_HOST_ERROR) operator(=) integer(1042) + constant(ER_HANDSHAKE_ERROR) operator(=) integer(1043) + constant(ER_DBACCESS_DENIED_ERROR) operator(=) integer(1044) + constant(ER_ACCESS_DENIED_ERROR) operator(=) integer(1045) + constant(ER_NO_DB_ERROR) operator(=) integer(1046) + constant(ER_UNKNOWN_COM_ERROR) operator(=) integer(1047) + constant(ER_BAD_NULL_ERROR) operator(=) integer(1048) + constant(ER_BAD_DB_ERROR) operator(=) integer(1049) + constant(ER_TABLE_EXISTS_ERROR) operator(=) integer(1050) + constant(ER_BAD_TABLE_ERROR) operator(=) integer(1051) + constant(ER_NON_UNIQ_ERROR) operator(=) integer(1052) + constant(ER_SERVER_SHUTDOWN) operator(=) integer(1053) + constant(ER_BAD_FIELD_ERROR) operator(=) integer(1054) + constant(ER_WRONG_FIELD_WITH_GROUP) operator(=) integer(1055) + constant(ER_WRONG_GROUP_FIELD) operator(=) integer(1056) + constant(ER_WRONG_SUM_SELECT) operator(=) integer(1057) + constant(ER_WRONG_VALUE_COUNT) operator(=) integer(1058) + constant(ER_TOO_LONG_IDENT) operator(=) integer(1059) + constant(ER_DUP_FIELDNAME) operator(=) integer(1060) + constant(ER_DUP_KEYNAME) operator(=) integer(1061) + constant(ER_DUP_ENTRY) operator(=) integer(1062) + constant(ER_WRONG_FIELD_SPEC) operator(=) integer(1063) + constant(ER_PARSE_ERROR) operator(=) integer(1064) + constant(ER_EMPTY_QUERY) operator(=) integer(1065) + constant(ER_NONUNIQ_TABLE) operator(=) integer(1066) + constant(ER_INVALID_DEFAULT) operator(=) integer(1067) + constant(ER_MULTIPLE_PRI_KEY) operator(=) integer(1068) + constant(ER_TOO_MANY_KEYS) operator(=) integer(1069) + constant(ER_TOO_MANY_KEY_PARTS) operator(=) integer(1070) + constant(ER_TOO_LONG_KEY) operator(=) integer(1071) + constant(ER_KEY_COLUMN_DOES_NOT_EXITS) operator(=) integer(1072) + constant(ER_BLOB_USED_AS_KEY) operator(=) integer(1073) + constant(ER_TOO_BIG_FIELDLENGTH) operator(=) integer(1074) + constant(ER_WRONG_AUTO_KEY) operator(=) integer(1075) + constant(ER_READY) operator(=) integer(1076) + constant(ER_NORMAL_SHUTDOWN) operator(=) integer(1077) + constant(ER_GOT_SIGNAL) operator(=) integer(1078) + constant(ER_SHUTDOWN_COMPLETE) operator(=) integer(1079) + constant(ER_FORCING_CLOSE) operator(=) integer(1080) + constant(ER_IPSOCK_ERROR) operator(=) integer(1081) + constant(ER_NO_SUCH_INDEX) operator(=) integer(1082) + constant(ER_WRONG_FIELD_TERMINATORS) operator(=) integer(1083) + constant(ER_BLOBS_AND_NO_TERMINATED) operator(=) integer(1084) + constant(ER_TEXTFILE_NOT_READABLE) operator(=) integer(1085) + constant(ER_FILE_EXISTS_ERROR) operator(=) integer(1086) + constant(ER_LOAD_INFO) operator(=) integer(1087) + constant(ER_ALTER_INFO) operator(=) integer(1088) + constant(ER_WRONG_SUB_KEY) operator(=) integer(1089) + constant(ER_CANT_REMOVE_ALL_FIELDS) operator(=) integer(1090) + constant(ER_CANT_DROP_FIELD_OR_KEY) operator(=) integer(1091) + constant(ER_INSERT_INFO) operator(=) integer(1092) + constant(ER_INSERT_TABLE_USED) operator(=) integer(1093) + constant(ER_NO_SUCH_THREAD) operator(=) integer(1094) + constant(ER_KILL_DENIED_ERROR) operator(=) integer(1095) + constant(ER_NO_TABLES_USED) operator(=) integer(1096) + constant(ER_TOO_BIG_SET) operator(=) integer(1097) + constant(ER_NO_UNIQUE_LOGFILE) operator(=) integer(1098) + constant(ER_TABLE_NOT_LOCKED_FOR_WRITE) operator(=) integer(1099) + constant(ER_TABLE_NOT_LOCKED) operator(=) integer(1100) + constant(ER_BLOB_CANT_HAVE_DEFAULT) operator(=) integer(1101) + constant(ER_WRONG_DB_NAME) operator(=) integer(1102) + constant(ER_WRONG_TABLE_NAME) operator(=) integer(1103) + constant(ER_TOO_BIG_SELECT) operator(=) integer(1104) + constant(ER_UNKNOWN_ERROR) operator(=) integer(1105) + constant(ER_UNKNOWN_PROCEDURE) operator(=) integer(1106) + constant(ER_WRONG_PARAMCOUNT_TO_PROCEDURE) operator(=) integer(1107) + constant(ER_WRONG_PARAMETERS_TO_PROCEDURE) operator(=) integer(1108) + constant(ER_UNKNOWN_TABLE) operator(=) integer(1109) + constant(ER_FIELD_SPECIFIED_TWICE) operator(=) integer(1110) + constant(ER_INVALID_GROUP_FUNC_USE) operator(=) integer(1111) + constant(ER_UNSUPPORTED_EXTENSION) operator(=) integer(1112) + constant(ER_TABLE_MUST_HAVE_COLUMNS) operator(=) integer(1113) + constant(ER_RECORD_FILE_FULL) operator(=) integer(1114) + constant(ER_UNKNOWN_CHARACTER_SET) operator(=) integer(1115) + constant(ER_TOO_MANY_TABLES) operator(=) integer(1116) + constant(ER_TOO_MANY_FIELDS) operator(=) integer(1117) + constant(ER_TOO_BIG_ROWSIZE) operator(=) integer(1118) + constant(ER_STACK_OVERRUN) operator(=) integer(1119) + constant(ER_WRONG_OUTER_JOIN) operator(=) integer(1120) + constant(ER_NULL_COLUMN_IN_INDEX) operator(=) integer(1121) + constant(ER_CANT_FIND_UDF) operator(=) integer(1122) + constant(ER_CANT_INITIALIZE_UDF) operator(=) integer(1123) + constant(ER_UDF_NO_PATHS) operator(=) integer(1124) + constant(ER_UDF_EXISTS) operator(=) integer(1125) + constant(ER_CANT_OPEN_LIBRARY) operator(=) integer(1126) + constant(ER_CANT_FIND_DL_ENTRY) operator(=) integer(1127) + constant(ER_FUNCTION_NOT_DEFINED) operator(=) integer(1128) + constant(ER_HOST_IS_BLOCKED) operator(=) integer(1129) + constant(ER_HOST_NOT_PRIVILEGED) operator(=) integer(1130) + constant(ER_PASSWORD_ANONYMOUS_USER) operator(=) integer(1131) + constant(ER_PASSWORD_NOT_ALLOWED) operator(=) integer(1132) + constant(ER_PASSWORD_NO_MATCH) operator(=) integer(1133) + constant(ER_UPDATE_INFO) operator(=) integer(1134) + constant(ER_CANT_CREATE_THREAD) operator(=) integer(1135) + constant(ER_WRONG_VALUE_COUNT_ON_ROW) operator(=) integer(1136) + constant(ER_CANT_REOPEN_TABLE) operator(=) integer(1137) + constant(ER_INVALID_USE_OF_NULL) operator(=) integer(1138) + constant(ER_REGEXP_ERROR) operator(=) integer(1139) + constant(ER_MIX_OF_GROUP_FUNC_AND_FIELDS) operator(=) integer(1140) + constant(ER_NONEXISTING_GRANT) operator(=) integer(1141) + constant(ER_TABLEACCESS_DENIED_ERROR) operator(=) integer(1142) + constant(ER_COLUMNACCESS_DENIED_ERROR) operator(=) integer(1143) + constant(ER_ILLEGAL_GRANT_FOR_TABLE) operator(=) integer(1144) + constant(ER_GRANT_WRONG_HOST_OR_USER) operator(=) integer(1145) + constant(ER_NO_SUCH_TABLE) operator(=) integer(1146) + constant(ER_NONEXISTING_TABLE_GRANT) operator(=) integer(1147) + constant(ER_NOT_ALLOWED_COMMAND) operator(=) integer(1148) + constant(ER_SYNTAX_ERROR) operator(=) integer(1149) + constant(ER_DELAYED_CANT_CHANGE_LOCK) operator(=) integer(1150) + constant(ER_TOO_MANY_DELAYED_THREADS) operator(=) integer(1151) + constant(ER_ABORTING_CONNECTION) operator(=) integer(1152) + constant(ER_NET_PACKET_TOO_LARGE) operator(=) integer(1153) + constant(ER_NET_READ_ERROR_FROM_PIPE) operator(=) integer(1154) + constant(ER_NET_FCNTL_ERROR) operator(=) integer(1155) + constant(ER_NET_PACKETS_OUT_OF_ORDER) operator(=) integer(1156) + constant(ER_NET_UNCOMPRESS_ERROR) operator(=) integer(1157) + constant(ER_NET_READ_ERROR) operator(=) integer(1158) + constant(ER_NET_READ_INTERRUPTED) operator(=) integer(1159) + constant(ER_NET_ERROR_ON_WRITE) operator(=) integer(1160) + constant(ER_NET_WRITE_INTERRUPTED) operator(=) integer(1161) + constant(ER_TOO_LONG_STRING) operator(=) integer(1162) + constant(ER_TABLE_CANT_HANDLE_BLOB) operator(=) integer(1163) + constant(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT) operator(=) integer(1164) + constant(ER_DELAYED_INSERT_TABLE_LOCKED) operator(=) integer(1165) + constant(ER_WRONG_COLUMN_NAME) operator(=) integer(1166) + constant(ER_WRONG_KEY_COLUMN) operator(=) integer(1167) + constant(ER_WRONG_MRG_TABLE) operator(=) integer(1168) + constant(ER_DUP_UNIQUE) operator(=) integer(1169) + constant(ER_BLOB_KEY_WITHOUT_LENGTH) operator(=) integer(1170) + constant(ER_PRIMARY_CANT_HAVE_NULL) operator(=) integer(1171) + constant(ER_TOO_MANY_ROWS) operator(=) integer(1172) + constant(ER_REQUIRES_PRIMARY_KEY) operator(=) integer(1173) + constant(ER_NO_RAID_COMPILED) operator(=) integer(1174) + constant(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE) operator(=) integer(1175) + constant(ER_KEY_DOES_NOT_EXITS) operator(=) integer(1176) + constant(ER_CHECK_NO_SUCH_TABLE) operator(=) integer(1177) + constant(ER_CHECK_NOT_IMPLEMENTED) operator(=) integer(1178) + constant(ER_CANT_DO_THIS_DURING_AN_TRANSACTION) operator(=) integer(1179) + constant(ER_ERROR_DURING_COMMIT) operator(=) integer(1180) + constant(ER_ERROR_DURING_ROLLBACK) operator(=) integer(1181) + constant(ER_ERROR_DURING_FLUSH_LOGS) operator(=) integer(1182) + constant(ER_ERROR_DURING_CHECKPOINT) operator(=) integer(1183) + constant(ER_NEW_ABORTING_CONNECTION) operator(=) integer(1184) + constant(ER_DUMP_NOT_IMPLEMENTED) operator(=) integer(1185) + constant(ER_FLUSH_MASTER_BINLOG_CLOSED) operator(=) integer(1186) + constant(ER_INDEX_REBUILD) operator(=) integer(1187) + constant(ER_MASTER) operator(=) integer(1188) + constant(ER_MASTER_NET_READ) operator(=) integer(1189) + constant(ER_MASTER_NET_WRITE) operator(=) integer(1190) + constant(ER_FT_MATCHING_KEY_NOT_FOUND) operator(=) integer(1191) + constant(ER_LOCK_OR_ACTIVE_TRANSACTION) operator(=) integer(1192) + constant(ER_UNKNOWN_SYSTEM_VARIABLE) operator(=) integer(1193) + constant(ER_CRASHED_ON_USAGE) operator(=) integer(1194) + constant(ER_CRASHED_ON_REPAIR) operator(=) integer(1195) + constant(ER_WARNING_NOT_COMPLETE_ROLLBACK) operator(=) integer(1196) + constant(ER_TRANS_CACHE_FULL) operator(=) integer(1197) + constant(ER_SLAVE_MUST_STOP) operator(=) integer(1198) + constant(ER_SLAVE_NOT_RUNNING) operator(=) integer(1199) + constant(ER_BAD_SLAVE) operator(=) integer(1200) + constant(ER_MASTER_INFO) operator(=) integer(1201) + constant(ER_SLAVE_THREAD) operator(=) integer(1202) + constant(ER_TOO_MANY_USER_CONNECTIONS) operator(=) integer(1203) + constant(ER_SET_CONSTANTS_ONLY) operator(=) integer(1204) + constant(ER_LOCK_WAIT_TIMEOUT) operator(=) integer(1205) + constant(ER_LOCK_TABLE_FULL) operator(=) integer(1206) + constant(ER_READ_ONLY_TRANSACTION) operator(=) integer(1207) + constant(ER_DROP_DB_WITH_READ_LOCK) operator(=) integer(1208) + constant(ER_CREATE_DB_WITH_READ_LOCK) operator(=) integer(1209) + constant(ER_WRONG_ARGUMENTS) operator(=) integer(1210) + constant(ER_NO_PERMISSION_TO_CREATE_USER) operator(=) integer(1211) + constant(ER_UNION_TABLES_IN_DIFFERENT_DIR) operator(=) integer(1212) + constant(ER_LOCK_DEADLOCK) operator(=) integer(1213) + constant(ER_TABLE_CANT_HANDLE_FULLTEXT) operator(=) integer(1214) + constant(ER_CANNOT_ADD_FOREIGN) operator(=) integer(1215) + constant(ER_NO_REFERENCED_ROW) operator(=) integer(1216) + constant(ER_ROW_IS_REFERENCED) operator(=) integer(1217) + constant(ER_CONNECT_TO_MASTER) operator(=) integer(1218) + constant(ER_QUERY_ON_MASTER) operator(=) integer(1219) + constant(ER_ERROR_WHEN_EXECUTING_COMMAND) operator(=) integer(1220) + constant(ER_WRONG_USAGE) operator(=) integer(1221) + constant(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT) operator(=) integer(1222) + constant(ER_CANT_UPDATE_WITH_READLOCK) operator(=) integer(1223) + constant(ER_MIXING_NOT_ALLOWED) operator(=) integer(1224) + constant(ER_DUP_ARGUMENT) operator(=) integer(1225) + constant(ER_USER_LIMIT_REACHED) operator(=) integer(1226) + constant(ER_SPECIFIC_ACCESS_DENIED_ERROR) operator(=) integer(1227) + constant(ER_LOCAL_VARIABLE) operator(=) integer(1228) + constant(ER_GLOBAL_VARIABLE) operator(=) integer(1229) + constant(ER_NO_DEFAULT) operator(=) integer(1230) + constant(ER_WRONG_VALUE_FOR_VAR) operator(=) integer(1231) + constant(ER_WRONG_TYPE_FOR_VAR) operator(=) integer(1232) + constant(ER_VAR_CANT_BE_READ) operator(=) integer(1233) + constant(ER_CANT_USE_OPTION_HERE) operator(=) integer(1234) + constant(ER_NOT_SUPPORTED_YET) operator(=) integer(1235) + constant(ER_MASTER_FATAL_ERROR_READING_BINLOG) operator(=) integer(1236) + constant(ER_SLAVE_IGNORED_TABLE) operator(=) integer(1237) + constant(ER_ERROR_MESSAGES) operator(=) integer(238) + + comment(# Client Error) + constant(CR_MIN_ERROR) operator(=) integer(2000) + constant(CR_MAX_ERROR) operator(=) integer(2999) + constant(CR_UNKNOWN_ERROR) operator(=) integer(2000) + constant(CR_SOCKET_CREATE_ERROR) operator(=) integer(2001) + constant(CR_CONNECTION_ERROR) operator(=) integer(2002) + constant(CR_CONN_HOST_ERROR) operator(=) integer(2003) + constant(CR_IPSOCK_ERROR) operator(=) integer(2004) + constant(CR_UNKNOWN_HOST) operator(=) integer(2005) + constant(CR_SERVER_GONE_ERROR) operator(=) integer(2006) + constant(CR_VERSION_ERROR) operator(=) integer(2007) + constant(CR_OUT_OF_MEMORY) operator(=) integer(2008) + constant(CR_WRONG_HOST_INFO) operator(=) integer(2009) + constant(CR_LOCALHOST_CONNECTION) operator(=) integer(2010) + constant(CR_TCP_CONNECTION) operator(=) integer(2011) + constant(CR_SERVER_HANDSHAKE_ERR) operator(=) integer(2012) + constant(CR_SERVER_LOST) operator(=) integer(2013) + constant(CR_COMMANDS_OUT_OF_SYNC) operator(=) integer(2014) + constant(CR_NAMEDPIPE_CONNECTION) operator(=) integer(2015) + constant(CR_NAMEDPIPEWAIT_ERROR) operator(=) integer(2016) + constant(CR_NAMEDPIPEOPEN_ERROR) operator(=) integer(2017) + constant(CR_NAMEDPIPESETSTATE_ERROR) operator(=) integer(2018) + constant(CR_CANT_READ_CHARSET) operator(=) integer(2019) + constant(CR_NET_PACKET_TOO_LARGE) operator(=) integer(2020) + constant(CR_EMBEDDED_CONNECTION) operator(=) integer(2021) + constant(CR_PROBE_SLAVE_STATUS) operator(=) integer(2022) + constant(CR_PROBE_SLAVE_HOSTS) operator(=) integer(2023) + constant(CR_PROBE_SLAVE_CONNECT) operator(=) integer(2024) + constant(CR_PROBE_MASTER_CONNECT) operator(=) integer(2025) + constant(CR_SSL_CONNECTION_ERROR) operator(=) integer(2026) + constant(CR_MALFORMED_PACKET) operator(=) integer(2027) + + constant(CLIENT_ERRORS) operator(=) operator([) + string<delimiter(")content(Unknown MySQL error)delimiter(")>operator(,) + string<delimiter(")content(Can't create UNIX socket (%d\))delimiter(")>operator(,) + string<delimiter(")content(Can't connect to local MySQL server through socket '%-.64s' (%d\))delimiter(")>operator(,) + string<delimiter(")content(Can't connect to MySQL server on '%-.64s' (%d\))delimiter(")>operator(,) + string<delimiter(")content(Can't create TCP/IP socket (%d\))delimiter(")>operator(,) + string<delimiter(")content(Unknown MySQL Server Host '%-.64s' (%d\))delimiter(")>operator(,) + string<delimiter(")content(MySQL server has gone away)delimiter(")>operator(,) + string<delimiter(")content(Protocol mismatch. Server Version = %d Client Version = %d)delimiter(")>operator(,) + string<delimiter(")content(MySQL client run out of memory)delimiter(")>operator(,) + string<delimiter(")content(Wrong host info)delimiter(")>operator(,) + string<delimiter(")content(Localhost via UNIX socket)delimiter(")>operator(,) + string<delimiter(")content(%-.64s via TCP/IP)delimiter(")>operator(,) + string<delimiter(")content(Error in server handshake)delimiter(")>operator(,) + string<delimiter(")content(Lost connection to MySQL server during query)delimiter(")>operator(,) + string<delimiter(")content(Commands out of sync; You can't run this command now)delimiter(")>operator(,) + string<delimiter(")content(%-.64s via named pipe)delimiter(")>operator(,) + string<delimiter(")content(Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu\))delimiter(")>operator(,) + string<delimiter(")content(Can't open named pipe to host: %-.64s pipe: %-.32s (%lu\))delimiter(")>operator(,) + string<delimiter(")content(Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu\))delimiter(")>operator(,) + string<delimiter(")content(Can't initialize character set %-.64s (path: %-.64s\))delimiter(")>operator(,) + string<delimiter(")content(Got packet bigger than 'max_allowed_packet')delimiter(")>operator(,) + string<delimiter(")content(Embedded server)delimiter(")>operator(,) + string<delimiter(")content(Error on SHOW SLAVE STATUS:)delimiter(")>operator(,) + string<delimiter(")content(Error on SHOW SLAVE HOSTS:)delimiter(")>operator(,) + string<delimiter(")content(Error connecting to slave:)delimiter(")>operator(,) + string<delimiter(")content(Error connecting to master:)delimiter(")>operator(,) + string<delimiter(")content(SSL connection error)delimiter(")>operator(,) + string<delimiter(")content(Malformed packet)delimiter(")> + operator(]) + + reserved(def) method(initialize)operator(()ident(errno)operator(,) ident(error)operator(\)) + instance_variable(@errno) operator(=) ident(errno) + instance_variable(@error) operator(=) ident(error) + reserved(super) ident(error) + reserved(end) + ident(attr_reader) symbol(:errno)operator(,) symbol(:error) + + reserved(def) constant(Error)operator(::)ident(err)operator(()ident(errno)operator(\)) + constant(CLIENT_ERRORS)operator([)ident(errno) operator(-) constant(Error)operator(::)constant(CR_MIN_ERROR)operator(]) + reserved(end) + reserved(end) + + reserved(class) class(Net) + reserved(def) method(initialize)operator(()ident(sock)operator(\)) + instance_variable(@sock) operator(=) ident(sock) + instance_variable(@pkt_nr) operator(=) integer(0) + reserved(end) + + reserved(def) method(clear)operator(()operator(\)) + instance_variable(@pkt_nr) operator(=) integer(0) + reserved(end) + + reserved(def) method(read)operator(()operator(\)) + ident(buf) operator(=) operator([)operator(]) + ident(len) operator(=) pre_constant(nil) + instance_variable(@sock)operator(.)ident(sync) operator(=) pre_constant(false) + reserved(while) ident(len) operator(==) pre_constant(nil) reserved(or) ident(len) operator(==) constant(MAX_PACKET_LENGTH) reserved(do) + ident(a) operator(=) instance_variable(@sock)operator(.)ident(read)operator(()integer(4)operator(\)) + ident(len) operator(=) ident(a)operator([)integer(0)operator(])operator(+)ident(a)operator([)integer(1)operator(])operator(*)integer(256)operator(+)ident(a)operator([)integer(2)operator(])operator(*)integer(256)operator(*)integer(256) + ident(pkt_nr) operator(=) ident(a)operator([)integer(3)operator(]) + reserved(if) instance_variable(@pkt_nr) operator(!=) ident(pkt_nr) reserved(then) + ident(raise) string<delimiter(")content(Packets out of order: )inline<inline_delimiter(#{)instance_variable(@pkt_nr)inline_delimiter(})>content(<>)inline<inline_delimiter(#{)ident(pkt_nr)inline_delimiter(})>delimiter(")> + reserved(end) + instance_variable(@pkt_nr) operator(=) instance_variable(@pkt_nr) operator(+) integer(1) operator(&) integer(0xff) + ident(buf) operator(<<) instance_variable(@sock)operator(.)ident(read)operator(()ident(len)operator(\)) + reserved(end) + instance_variable(@sock)operator(.)ident(sync) operator(=) pre_constant(true) + ident(buf)operator(.)ident(join) + reserved(rescue) + ident(errno) operator(=) constant(Error)operator(::)constant(CR_SERVER_LOST) + ident(raise) constant(Error)operator(::)ident(new)operator(()ident(errno)operator(,) constant(Error)operator(::)ident(err)operator(()ident(errno)operator(\))operator(\)) + reserved(end) + + reserved(def) method(write)operator(()ident(data)operator(\)) + reserved(if) ident(data)operator(.)ident(is_a?) constant(Array) reserved(then) + ident(data) operator(=) ident(data)operator(.)ident(join) + reserved(end) + instance_variable(@sock)operator(.)ident(sync) operator(=) pre_constant(false) + ident(ptr) operator(=) integer(0) + reserved(while) ident(data)operator(.)ident(length) operator(>)operator(=) constant(MAX_PACKET_LENGTH) reserved(do) + instance_variable(@sock)operator(.)ident(write) constant(Net)operator(::)ident(int3str)operator(()constant(MAX_PACKET_LENGTH)operator(\))operator(+)instance_variable(@pkt_nr)operator(.)ident(chr)operator(+)ident(data)operator([)ident(ptr)operator(,) constant(MAX_PACKET_LENGTH)operator(]) + instance_variable(@pkt_nr) operator(=) instance_variable(@pkt_nr) operator(+) integer(1) operator(&) integer(0xff) + ident(ptr) operator(+=) constant(MAX_PACKET_LENGTH) + reserved(end) + instance_variable(@sock)operator(.)ident(write) constant(Net)operator(::)ident(int3str)operator(()ident(data)operator(.)ident(length)operator(-)ident(ptr)operator(\))operator(+)instance_variable(@pkt_nr)operator(.)ident(chr)operator(+)ident(data)operator([)ident(ptr) operator(..) integer(-1)operator(]) + instance_variable(@pkt_nr) operator(=) instance_variable(@pkt_nr) operator(+) integer(1) operator(&) integer(0xff) + instance_variable(@sock)operator(.)ident(sync) operator(=) pre_constant(true) + instance_variable(@sock)operator(.)ident(flush) + reserved(rescue) + ident(errno) operator(=) constant(Error)operator(::)constant(CR_SERVER_LOST) + ident(raise) constant(Error)operator(::)ident(new)operator(()ident(errno)operator(,) constant(Error)operator(::)ident(err)operator(()ident(errno)operator(\))operator(\)) + reserved(end) + + reserved(def) method(close)operator(()operator(\)) + instance_variable(@sock)operator(.)ident(close) + reserved(end) + + reserved(def) constant(Net)operator(::)ident(int2str)operator(()ident(n)operator(\)) + operator([)ident(n)operator(])operator(.)ident(pack)operator(()string<delimiter(")content(v)delimiter(")>operator(\)) + reserved(end) + + reserved(def) constant(Net)operator(::)ident(int3str)operator(()ident(n)operator(\)) + operator([)ident(n)operator(%)integer(256)operator(,) ident(n)operator(>>)integer(8)operator(])operator(.)ident(pack)operator(()string<delimiter(")content(cv)delimiter(")>operator(\)) + reserved(end) + + reserved(def) constant(Net)operator(::)ident(int4str)operator(()ident(n)operator(\)) + operator([)ident(n)operator(])operator(.)ident(pack)operator(()string<delimiter(")content(V)delimiter(")>operator(\)) + reserved(end) + + reserved(end) + + reserved(class) class(Random) + reserved(def) method(initialize)operator(()ident(seed1)operator(,) ident(seed2)operator(\)) + instance_variable(@max_value) operator(=) integer(0x3FFFFFFF) + instance_variable(@seed1) operator(=) ident(seed1) operator(%) instance_variable(@max_value) + instance_variable(@seed2) operator(=) ident(seed2) operator(%) instance_variable(@max_value) + reserved(end) + + reserved(def) method(rnd)operator(()operator(\)) + instance_variable(@seed1) operator(=) operator(()instance_variable(@seed1)operator(*)integer(3)operator(+)instance_variable(@seed2)operator(\)) operator(%) instance_variable(@max_value) + instance_variable(@seed2) operator(=) operator(()instance_variable(@seed1)operator(+)instance_variable(@seed2)operator(+)integer(33)operator(\)) operator(%) instance_variable(@max_value) + instance_variable(@seed1)operator(.)ident(to_f) operator(/) instance_variable(@max_value) + reserved(end) + reserved(end) + +reserved(end) + +reserved(class) operator(<<) class(Mysql) + reserved(def) method(init)operator(()operator(\)) + constant(Mysql)operator(::)ident(new) symbol(:INIT) + reserved(end) + + reserved(def) method(real_connect)operator(()operator(*)ident(args)operator(\)) + constant(Mysql)operator(::)ident(new)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(alias) symbol(:connect) symbol(:real_connect) + + reserved(def) method(finalizer)operator(()ident(net)operator(\)) + ident(proc) operator({) + ident(net)operator(.)ident(clear) + ident(net)operator(.)ident(write) constant(Mysql)operator(::)constant(COM_QUIT)operator(.)ident(chr) + operator(}) + reserved(end) + + reserved(def) method(escape_string)operator(()ident(str)operator(\)) + ident(str)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(([)char(\\0)char(\\n)char(\\r)char(\\032)char(\\')char(\\")char(\\\\)content(]\))delimiter(/)>operator(\)) reserved(do) + reserved(case) global_variable($1) + reserved(when) string<delimiter(")char(\\0)delimiter(")> reserved(then) string<delimiter(")char(\\\\)content(0)delimiter(")> + reserved(when) string<delimiter(")char(\\n)delimiter(")> reserved(then) string<delimiter(")char(\\\\)content(n)delimiter(")> + reserved(when) string<delimiter(")char(\\r)delimiter(")> reserved(then) string<delimiter(")char(\\\\)content(r)delimiter(")> + reserved(when) string<delimiter(")char(\\032)delimiter(")> reserved(then) string<delimiter(")char(\\\\)content(Z)delimiter(")> + reserved(else) string<delimiter(")char(\\\\)delimiter(")>operator(+)global_variable($1) + reserved(end) + reserved(end) + reserved(end) + reserved(alias) symbol(:quote) symbol(:escape_string) + + reserved(def) method(get_client_info)operator(()operator(\)) + constant(Mysql)operator(::)constant(VERSION) + reserved(end) + reserved(alias) symbol(:client_info) symbol(:get_client_info) + + reserved(def) method(debug)operator(()ident(str)operator(\)) + ident(raise) string<delimiter(")content(not implemented)delimiter(")> + reserved(end) +reserved(end) + +comment(#) +comment(# for compatibility) +comment(#) + +constant(MysqlRes) operator(=) constant(Mysql)operator(::)constant(Result) +constant(MysqlField) operator(=) constant(Mysql)operator(::)constant(Field) +constant(MysqlError) operator(=) constant(Mysql)operator(::)constant(Error) +comment(# :title: Transaction::Simple -- Active Object Transaction Support for Ruby) +comment(# :main: Transaction::Simple) +comment(#) +comment(# == Licence) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining a) +comment(# copy of this software and associated documentation files (the "Software"\),) +comment(# to deal in the Software without restriction, including without limitation) +comment(# the rights to use, copy, modify, merge, publish, distribute, sublicense,) +comment(# and/or sell copies of the Software, and to permit persons to whom the) +comment(# Software is furnished to do so, subject to the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be included in) +comment(# all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR) +comment(# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,) +comment(# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL) +comment(# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER) +comment(# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING) +comment(# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER) +comment(# DEALINGS IN THE SOFTWARE.) +comment(#--) +comment(# Transaction::Simple) +comment(# Simple object transaction support for Ruby) +comment(# Version 1.3.0) +comment(#) +comment(# Copyright (c\) 2003 - 2005 Austin Ziegler) +comment(#) +comment(# $Id: simple.rb,v 1.5 2005/05/05 16:16:49 austin Exp $) +comment(#++) + comment(# The "Transaction" namespace can be used for additional transaction) + comment(# support objects and modules.) +reserved(module) class(Transaction) + comment(# A standard exception for transaction errors.) + reserved(class) class(TransactionError) operator(<) constant(StandardError)operator(;) reserved(end) + comment(# The TransactionAborted exception is used to indicate when a) + comment(# transaction has been aborted in the block form.) + reserved(class) class(TransactionAborted) operator(<) constant(Exception)operator(;) reserved(end) + comment(# The TransactionCommitted exception is used to indicate when a) + comment(# transaction has been committed in the block form.) + reserved(class) class(TransactionCommitted) operator(<) constant(Exception)operator(;) reserved(end) + + ident(te) operator(=) string<delimiter(")content(Transaction Error: %s)delimiter(")> + + constant(Messages) operator(=) operator({) + symbol(:bad_debug_object) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(the transaction debug object must respond to #<<.)delimiter(")>operator(,) + symbol(:unique_names) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(named transactions must be unique.)delimiter(")>operator(,) + symbol(:no_transaction_open) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(no transaction open.)delimiter(")>operator(,) + symbol(:cannot_rewind_no_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot rewind; there is no current transaction.)delimiter(")>operator(,) + symbol(:cannot_rewind_named_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot rewind to transaction %s because it does not exist.)delimiter(")>operator(,) + symbol(:cannot_rewind_transaction_before_block) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot rewind a transaction started before the execution block.)delimiter(")>operator(,) + symbol(:cannot_abort_no_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot abort; there is no current transaction.)delimiter(")>operator(,) + symbol(:cannot_abort_transaction_before_block) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot abort a transaction started before the execution block.)delimiter(")>operator(,) + symbol(:cannot_abort_named_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot abort nonexistant transaction %s.)delimiter(")>operator(,) + symbol(:cannot_commit_no_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot commit; there is no current transaction.)delimiter(")>operator(,) + symbol(:cannot_commit_transaction_before_block) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot commit a transaction started before the execution block.)delimiter(")>operator(,) + symbol(:cannot_commit_named_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot commit nonexistant transaction %s.)delimiter(")>operator(,) + symbol(:cannot_start_empty_block_transaction) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot start a block transaction with no objects.)delimiter(")>operator(,) + symbol(:cannot_obtain_transaction_lock) operator(=)operator(>) + ident(te) operator(%) string<delimiter(")content(cannot obtain transaction lock for #%s.)delimiter(")>operator(,) + operator(}) + + comment(# = Transaction::Simple for Ruby) + comment(# Simple object transaction support for Ruby) + comment(#) + comment(# == Introduction) + comment(# Transaction::Simple provides a generic way to add active transaction) + comment(# support to objects. The transaction methods added by this module will) + comment(# work with most objects, excluding those that cannot be) + comment(# <i>Marshal</i>ed (bindings, procedure objects, IO instances, or) + comment(# singleton objects\).) + comment(#) + comment(# The transactions supported by Transaction::Simple are not backed) + comment(# transactions; they are not associated with any sort of data store.) + comment(# They are "live" transactions occurring in memory and in the object) + comment(# itself. This is to allow "test" changes to be made to an object) + comment(# before making the changes permanent.) + comment(#) + comment(# Transaction::Simple can handle an "infinite" number of transaction) + comment(# levels (limited only by memory\). If I open two transactions, commit) + comment(# the second, but abort the first, the object will revert to the) + comment(# original version.) + comment(# ) + comment(# Transaction::Simple supports "named" transactions, so that multiple) + comment(# levels of transactions can be committed, aborted, or rewound by) + comment(# referring to the appropriate name of the transaction. Names may be any) + comment(# object *except* +nil+. As with Hash keys, String names will be) + comment(# duplicated and frozen before using.) + comment(#) + comment(# Copyright:: Copyright © 2003 - 2005 by Austin Ziegler) + comment(# Version:: 1.3.0) + comment(# Licence:: MIT-Style) + comment(#) + comment(# Thanks to David Black for help with the initial concept that led to) + comment(# this library.) + comment(#) + comment(# == Usage) + comment(# include 'transaction/simple') + comment(#) + comment(# v = "Hello, you." # -> "Hello, you.") + comment(# v.extend(Transaction::Simple\) # -> "Hello, you.") + comment(#) + comment(# v.start_transaction # -> ... (a Marshal string\)) + comment(# v.transaction_open? # -> true) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(#) + comment(# v.rewind_transaction # -> "Hello, you.") + comment(# v.transaction_open? # -> true) + comment(#) + comment(# v.gsub!(/you/, "HAL"\) # -> "Hello, HAL.") + comment(# v.abort_transaction # -> "Hello, you.") + comment(# v.transaction_open? # -> false) + comment(#) + comment(# v.start_transaction # -> ... (a Marshal string\)) + comment(# v.start_transaction # -> ... (a Marshal string\)) + comment(#) + comment(# v.transaction_open? # -> true) + comment(# v.gsub!(/you/, "HAL"\) # -> "Hello, HAL.") + comment(#) + comment(# v.commit_transaction # -> "Hello, HAL.") + comment(# v.transaction_open? # -> true) + comment(# v.abort_transaction # -> "Hello, you.") + comment(# v.transaction_open? # -> false) + comment(#) + comment(# == Named Transaction Usage) + comment(# v = "Hello, you." # -> "Hello, you.") + comment(# v.extend(Transaction::Simple\) # -> "Hello, you.") + comment(# ) + comment(# v.start_transaction(:first\) # -> ... (a Marshal string\)) + comment(# v.transaction_open? # -> true) + comment(# v.transaction_open?(:first\) # -> true) + comment(# v.transaction_open?(:second\) # -> false) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(# ) + comment(# v.start_transaction(:second\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/world/, "HAL"\) # -> "Hello, HAL.") + comment(# v.rewind_transaction(:first\) # -> "Hello, you.") + comment(# v.transaction_open? # -> true) + comment(# v.transaction_open?(:first\) # -> true) + comment(# v.transaction_open?(:second\) # -> false) + comment(# ) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(# v.start_transaction(:second\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/world/, "HAL"\) # -> "Hello, HAL.") + comment(# v.transaction_name # -> :second) + comment(# v.abort_transaction(:first\) # -> "Hello, you.") + comment(# v.transaction_open? # -> false) + comment(# ) + comment(# v.start_transaction(:first\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(# v.start_transaction(:second\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/world/, "HAL"\) # -> "Hello, HAL.") + comment(# ) + comment(# v.commit_transaction(:first\) # -> "Hello, HAL.") + comment(# v.transaction_open? # -> false) + comment(#) + comment(# == Block Usage) + comment(# v = "Hello, you." # -> "Hello, you.") + comment(# Transaction::Simple.start(v\) do |tv|) + comment(# # v has been extended with Transaction::Simple and an unnamed) + comment(# # transaction has been started.) + comment(# tv.transaction_open? # -> true) + comment(# tv.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(#) + comment(# tv.rewind_transaction # -> "Hello, you.") + comment(# tv.transaction_open? # -> true) + comment(#) + comment(# tv.gsub!(/you/, "HAL"\) # -> "Hello, HAL.") + comment(# # The following breaks out of the transaction block after) + comment(# # aborting the transaction.) + comment(# tv.abort_transaction # -> "Hello, you.") + comment(# end) + comment(# # v still has Transaction::Simple applied from here on out.) + comment(# v.transaction_open? # -> false) + comment(#) + comment(# Transaction::Simple.start(v\) do |tv|) + comment(# tv.start_transaction # -> ... (a Marshal string\)) + comment(#) + comment(# tv.transaction_open? # -> true) + comment(# tv.gsub!(/you/, "HAL"\) # -> "Hello, HAL.") + comment(#) + comment(# # If #commit_transaction were called without having started a) + comment(# # second transaction, then it would break out of the transaction) + comment(# # block after committing the transaction.) + comment(# tv.commit_transaction # -> "Hello, HAL.") + comment(# tv.transaction_open? # -> true) + comment(# tv.abort_transaction # -> "Hello, you.") + comment(# end) + comment(# v.transaction_open? # -> false) + comment(#) + comment(# == Named Transaction Usage) + comment(# v = "Hello, you." # -> "Hello, you.") + comment(# v.extend(Transaction::Simple\) # -> "Hello, you.") + comment(# ) + comment(# v.start_transaction(:first\) # -> ... (a Marshal string\)) + comment(# v.transaction_open? # -> true) + comment(# v.transaction_open?(:first\) # -> true) + comment(# v.transaction_open?(:second\) # -> false) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(# ) + comment(# v.start_transaction(:second\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/world/, "HAL"\) # -> "Hello, HAL.") + comment(# v.rewind_transaction(:first\) # -> "Hello, you.") + comment(# v.transaction_open? # -> true) + comment(# v.transaction_open?(:first\) # -> true) + comment(# v.transaction_open?(:second\) # -> false) + comment(# ) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(# v.start_transaction(:second\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/world/, "HAL"\) # -> "Hello, HAL.") + comment(# v.transaction_name # -> :second) + comment(# v.abort_transaction(:first\) # -> "Hello, you.") + comment(# v.transaction_open? # -> false) + comment(# ) + comment(# v.start_transaction(:first\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/you/, "world"\) # -> "Hello, world.") + comment(# v.start_transaction(:second\) # -> ... (a Marshal string\)) + comment(# v.gsub!(/world/, "HAL"\) # -> "Hello, HAL.") + comment(# ) + comment(# v.commit_transaction(:first\) # -> "Hello, HAL.") + comment(# v.transaction_open? # -> false) + comment(#) + comment(# == Thread Safety) + comment(# Threadsafe version of Transaction::Simple and) + comment(# Transaction::Simple::Group exist; these are loaded from) + comment(# 'transaction/simple/threadsafe' and) + comment(# 'transaction/simple/threadsafe/group', respectively, and are) + comment(# represented in Ruby code as Transaction::Simple::ThreadSafe and) + comment(# Transaction::Simple::ThreadSafe::Group, respectively.) + comment(#) + comment(# == Contraindications) + comment(# While Transaction::Simple is very useful, it has some severe) + comment(# limitations that must be understood. Transaction::Simple:) + comment(#) + comment(# * uses Marshal. Thus, any object which cannot be <i>Marshal</i>ed) + comment(# cannot use Transaction::Simple. In my experience, this affects) + comment(# singleton objects more often than any other object. It may be that) + comment(# Ruby 2.0 will solve this problem.) + comment(# * does not manage resources. Resources external to the object and its) + comment(# instance variables are not managed at all. However, all instance) + comment(# variables and objects "belonging" to those instance variables are) + comment(# managed. If there are object reference counts to be handled,) + comment(# Transaction::Simple will probably cause problems.) + comment(# * is not inherently thread-safe. In the ACID ("atomic, consistent,) + comment(# isolated, durable"\) test, Transaction::Simple provides CD, but it is) + comment(# up to the user of Transaction::Simple to provide isolation and) + comment(# atomicity. Transactions should be considered "critical sections" in) + comment(# multi-threaded applications. If thread safety and atomicity is) + comment(# absolutely required, use Transaction::Simple::ThreadSafe, which uses) + comment(# a Mutex object to synchronize the accesses on the object during the) + comment(# transaction operations.) + comment(# * does not necessarily maintain Object#__id__ values on rewind or) + comment(# abort. This may change for future versions that will be Ruby 1.8 or) + comment(# better *only*. Certain objects that support #replace will maintain) + comment(# Object#__id__.) + comment(# * Can be a memory hog if you use many levels of transactions on many) + comment(# objects.) + comment(#) + reserved(module) class(Simple) + constant(TRANSACTION_SIMPLE_VERSION) operator(=) string<delimiter(')content(1.3.0)delimiter(')> + + comment(# Sets the Transaction::Simple debug object. It must respond to #<<.) + comment(# Sets the transaction debug object. Debugging will be performed) + comment(# automatically if there's a debug object. The generic transaction) + comment(# error class.) + reserved(def) pre_constant(self)operator(.)ident(debug_io)operator(=)operator(()ident(io)operator(\)) + reserved(if) ident(io)operator(.)ident(nil?) + instance_variable(@tdi) operator(=) pre_constant(nil) + instance_variable(@debugging) operator(=) pre_constant(false) + reserved(else) + reserved(unless) ident(io)operator(.)ident(respond_to?)operator(()symbol(:<<)operator(\)) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:bad_debug_object)operator(]) + reserved(end) + instance_variable(@tdi) operator(=) ident(io) + instance_variable(@debugging) operator(=) pre_constant(true) + reserved(end) + reserved(end) + + comment(# Returns +true+ if we are debugging.) + reserved(def) pre_constant(self)operator(.)ident(debugging?) + instance_variable(@debugging) + reserved(end) + + comment(# Returns the Transaction::Simple debug object. It must respond to) + comment(# #<<.) + reserved(def) pre_constant(self)operator(.)ident(debug_io) + instance_variable(@tdi) operator(||=) string<delimiter(")delimiter(")> + instance_variable(@tdi) + reserved(end) + + comment(# If +name+ is +nil+ (default\), then returns +true+ if there is) + comment(# currently a transaction open.) + comment(#) + comment(# If +name+ is specified, then returns +true+ if there is currently a) + comment(# transaction that responds to +name+ open.) + reserved(def) method(transaction_open?)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(if) ident(name)operator(.)ident(nil?) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")content(Transaction )delimiter(")> operator(<<) + string<delimiter(")content([)inline<inline_delimiter(#{)operator(()instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?)operator(\)) operator(?) string<delimiter(')content(closed)delimiter(')> operator(:) string<delimiter(')content(open)delimiter(')>inline_delimiter(})>content(])char(\\n)delimiter(")> + reserved(end) + reserved(return) operator(()reserved(not) instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?)operator(\)) + reserved(else) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")content(Transaction()inline<inline_delimiter(#{)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(\) )delimiter(")> operator(<<) + string<delimiter(")content([)inline<inline_delimiter(#{)operator(()instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?)operator(\)) operator(?) string<delimiter(')content(closed)delimiter(')> operator(:) string<delimiter(')content(open)delimiter(')>inline_delimiter(})>content(])char(\\n)delimiter(")> + reserved(end) + reserved(return) operator(()operator(()reserved(not) instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?)operator(\)) reserved(and) instance_variable(@__transaction_names__)operator(.)ident(include?)operator(()ident(name)operator(\))operator(\)) + reserved(end) + reserved(end) + + comment(# Returns the current name of the transaction. Transactions not) + comment(# explicitly named are named +nil+.) + reserved(def) method(transaction_name) + reserved(if) instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:no_transaction_open)operator(]) + reserved(end) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(|)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Transaction Name: )inline<inline_delimiter(#{)instance_variable(@__transaction_names__)operator([)integer(-1)operator(])operator(.)ident(inspect)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + reserved(if) instance_variable(@__transaction_names__)operator([)integer(-1)operator(])operator(.)ident(kind_of?)operator(()constant(String)operator(\)) + instance_variable(@__transaction_names__)operator([)integer(-1)operator(])operator(.)ident(dup) + reserved(else) + instance_variable(@__transaction_names__)operator([)integer(-1)operator(]) + reserved(end) + reserved(end) + + comment(# Starts a transaction. Stores the current object state. If a) + comment(# transaction name is specified, the transaction will be named.) + comment(# Transaction names must be unique. Transaction names of +nil+ will be) + comment(# treated as unnamed transactions.) + reserved(def) method(start_transaction)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + instance_variable(@__transaction_level__) operator(||=) integer(0) + instance_variable(@__transaction_names__) operator(||=) operator([)operator(]) + + reserved(if) ident(name)operator(.)ident(nil?) + instance_variable(@__transaction_names__) operator(<<) pre_constant(nil) + ident(ss) operator(=) string<delimiter(")delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + reserved(else) + reserved(if) instance_variable(@__transaction_names__)operator(.)ident(include?)operator(()ident(name)operator(\)) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:unique_names)operator(]) + reserved(end) + ident(name) operator(=) ident(name)operator(.)ident(dup)operator(.)ident(freeze) reserved(if) ident(name)operator(.)ident(kind_of?)operator(()constant(String)operator(\)) + instance_variable(@__transaction_names__) operator(<<) ident(name) + ident(ss) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + reserved(end) + + instance_variable(@__transaction_level__) operator(+=) integer(1) + + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(>)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Start Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + + instance_variable(@__transaction_checkpoint__) operator(=) constant(Marshal)operator(.)ident(dump)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Rewinds the transaction. If +name+ is specified, then the) + comment(# intervening transactions will be aborted and the named transaction) + comment(# will be rewound. Otherwise, only the current transaction is rewound.) + reserved(def) method(rewind_transaction)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(if) instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_rewind_no_transaction)operator(]) + reserved(end) + + comment(# Check to see if we are trying to rewind a transaction that is) + comment(# outside of the current transaction block.) + reserved(if) instance_variable(@__transaction_block__) reserved(and) ident(name) + ident(nix) operator(=) instance_variable(@__transaction_names__)operator(.)ident(index)operator(()ident(name)operator(\)) operator(+) integer(1) + reserved(if) ident(nix) operator(<) instance_variable(@__transaction_block__) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_rewind_transaction_before_block)operator(]) + reserved(end) + reserved(end) + + reserved(if) ident(name)operator(.)ident(nil?) + ident(__rewind_this_transaction) + ident(ss) operator(=) string<delimiter(")delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + reserved(else) + reserved(unless) instance_variable(@__transaction_names__)operator(.)ident(include?)operator(()ident(name)operator(\)) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_rewind_named_transaction)operator(]) operator(%) ident(name)operator(.)ident(inspect) + reserved(end) + ident(ss) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(\))delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + + reserved(while) instance_variable(@__transaction_names__)operator([)integer(-1)operator(]) operator(!=) ident(name) + instance_variable(@__transaction_checkpoint__) operator(=) ident(__rewind_this_transaction) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(|)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Rewind Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + instance_variable(@__transaction_level__) operator(-=) integer(1) + instance_variable(@__transaction_names__)operator(.)ident(pop) + reserved(end) + ident(__rewind_this_transaction) + reserved(end) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(|)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Rewind Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + pre_constant(self) + reserved(end) + + comment(# Aborts the transaction. Resets the object state to what it was) + comment(# before the transaction was started and closes the transaction. If) + comment(# +name+ is specified, then the intervening transactions and the named) + comment(# transaction will be aborted. Otherwise, only the current transaction) + comment(# is aborted.) + comment(#) + comment(# If the current or named transaction has been started by a block) + comment(# (Transaction::Simple.start\), then the execution of the block will be) + comment(# halted with +break+ +self+.) + reserved(def) method(abort_transaction)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(if) instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_abort_no_transaction)operator(]) + reserved(end) + + comment(# Check to see if we are trying to abort a transaction that is) + comment(# outside of the current transaction block. Otherwise, raise) + comment(# TransactionAborted if they are the same.) + reserved(if) instance_variable(@__transaction_block__) reserved(and) ident(name) + ident(nix) operator(=) instance_variable(@__transaction_names__)operator(.)ident(index)operator(()ident(name)operator(\)) operator(+) integer(1) + reserved(if) ident(nix) operator(<) instance_variable(@__transaction_block__) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_abort_transaction_before_block)operator(]) + reserved(end) + + ident(raise) constant(TransactionAborted) reserved(if) instance_variable(@__transaction_block__) operator(==) ident(nix) + reserved(end) + + ident(raise) constant(TransactionAborted) reserved(if) instance_variable(@__transaction_block__) operator(==) instance_variable(@__transaction_level__) + + reserved(if) ident(name)operator(.)ident(nil?) + ident(__abort_transaction)operator(()ident(name)operator(\)) + reserved(else) + reserved(unless) instance_variable(@__transaction_names__)operator(.)ident(include?)operator(()ident(name)operator(\)) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_abort_named_transaction)operator(]) operator(%) ident(name)operator(.)ident(inspect) + reserved(end) + ident(__abort_transaction)operator(()ident(name)operator(\)) reserved(while) instance_variable(@__transaction_names__)operator(.)ident(include?)operator(()ident(name)operator(\)) + reserved(end) + pre_constant(self) + reserved(end) + + comment(# If +name+ is +nil+ (default\), the current transaction level is) + comment(# closed out and the changes are committed.) + comment(#) + comment(# If +name+ is specified and +name+ is in the list of named) + comment(# transactions, then all transactions are closed and committed until) + comment(# the named transaction is reached.) + reserved(def) method(commit_transaction)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(if) instance_variable(@__transaction_checkpoint__)operator(.)ident(nil?) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_commit_no_transaction)operator(]) + reserved(end) + instance_variable(@__transaction_block__) operator(||=) pre_constant(nil) + + comment(# Check to see if we are trying to commit a transaction that is) + comment(# outside of the current transaction block. Otherwise, raise) + comment(# TransactionCommitted if they are the same.) + reserved(if) instance_variable(@__transaction_block__) reserved(and) ident(name) + ident(nix) operator(=) instance_variable(@__transaction_names__)operator(.)ident(index)operator(()ident(name)operator(\)) operator(+) integer(1) + reserved(if) ident(nix) operator(<) instance_variable(@__transaction_block__) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_commit_transaction_before_block)operator(]) + reserved(end) + + ident(raise) constant(TransactionCommitted) reserved(if) instance_variable(@__transaction_block__) operator(==) ident(nix) + reserved(end) + + ident(raise) constant(TransactionCommitted) reserved(if) instance_variable(@__transaction_block__) operator(==) instance_variable(@__transaction_level__) + + reserved(if) ident(name)operator(.)ident(nil?) + ident(ss) operator(=) string<delimiter(")delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + ident(__commit_transaction) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(<)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Commit Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + reserved(else) + reserved(unless) instance_variable(@__transaction_names__)operator(.)ident(include?)operator(()ident(name)operator(\)) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_commit_named_transaction)operator(]) operator(%) ident(name)operator(.)ident(inspect) + reserved(end) + ident(ss) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(\))delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + + reserved(while) instance_variable(@__transaction_names__)operator([)integer(-1)operator(]) operator(!=) ident(name) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(<)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Commit Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + ident(__commit_transaction) + reserved(end) + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(<)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Commit Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + ident(__commit_transaction) + reserved(end) + + pre_constant(self) + reserved(end) + + comment(# Alternative method for calling the transaction methods. An optional) + comment(# name can be specified for named transaction support.) + comment(#) + comment(# #transaction(:start\):: #start_transaction) + comment(# #transaction(:rewind\):: #rewind_transaction) + comment(# #transaction(:abort\):: #abort_transaction) + comment(# #transaction(:commit\):: #commit_transaction) + comment(# #transaction(:name\):: #transaction_name) + comment(# #transaction:: #transaction_open?) + reserved(def) method(transaction)operator(()ident(action) operator(=) pre_constant(nil)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + reserved(case) ident(action) + reserved(when) symbol(:start) + ident(start_transaction)operator(()ident(name)operator(\)) + reserved(when) symbol(:rewind) + ident(rewind_transaction)operator(()ident(name)operator(\)) + reserved(when) symbol(:abort) + ident(abort_transaction)operator(()ident(name)operator(\)) + reserved(when) symbol(:commit) + ident(commit_transaction)operator(()ident(name)operator(\)) + reserved(when) symbol(:name) + ident(transaction_name) + reserved(when) pre_constant(nil) + ident(transaction_open?)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) + + comment(# Allows specific variables to be excluded from transaction support.) + comment(# Must be done after extending the object but before starting the) + comment(# first transaction on the object.) + comment(#) + comment(# vv.transaction_exclusions << "@io") + reserved(def) method(transaction_exclusions) + instance_variable(@transaction_exclusions) operator(||=) operator([)operator(]) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(def) method(__common_start)operator(()ident(name)operator(,) ident(vars)operator(,) operator(&)ident(block)operator(\)) + reserved(if) ident(vars)operator(.)ident(empty?) + ident(raise) constant(TransactionError)operator(,) constant(Messages)operator([)symbol(:cannot_start_empty_block_transaction)operator(]) + reserved(end) + + reserved(if) ident(block) + reserved(begin) + ident(vlevel) operator(=) operator({)operator(}) + + ident(vars)operator(.)ident(each) reserved(do) operator(|)ident(vv)operator(|) + ident(vv)operator(.)ident(extend)operator(()constant(Transaction)operator(::)constant(Simple)operator(\)) + ident(vv)operator(.)ident(start_transaction)operator(()ident(name)operator(\)) + ident(vlevel)operator([)ident(vv)operator(.)ident(__id__)operator(]) operator(=) ident(vv)operator(.)ident(instance_variable_get)operator(()symbol(:@__transaction_level__)operator(\)) + ident(vv)operator(.)ident(instance_variable_set)operator(()symbol(:@__transaction_block__)operator(,) ident(vlevel)operator([)ident(vv)operator(.)ident(__id__)operator(])operator(\)) + reserved(end) + + reserved(yield)operator(()operator(*)ident(vars)operator(\)) + reserved(rescue) constant(TransactionAborted) + ident(vars)operator(.)ident(each) reserved(do) operator(|)ident(vv)operator(|) + reserved(if) ident(name)operator(.)ident(nil?) reserved(and) ident(vv)operator(.)ident(transaction_open?) + ident(loop) reserved(do) + ident(tlevel) operator(=) ident(vv)operator(.)ident(instance_variable_get)operator(()symbol(:@__transaction_level__)operator(\)) operator(||) integer(-1) + ident(vv)operator(.)ident(instance_variable_set)operator(()symbol(:@__transaction_block__)operator(,) integer(-1)operator(\)) + reserved(break) reserved(if) ident(tlevel) operator(<) ident(vlevel)operator([)ident(vv)operator(.)ident(__id__)operator(]) + ident(vv)operator(.)ident(abort_transaction) reserved(if) ident(vv)operator(.)ident(transaction_open?) + reserved(end) + reserved(elsif) ident(vv)operator(.)ident(transaction_open?)operator(()ident(name)operator(\)) + ident(vv)operator(.)ident(instance_variable_set)operator(()symbol(:@__transaction_block__)operator(,) integer(-1)operator(\)) + ident(vv)operator(.)ident(abort_transaction)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(rescue) constant(TransactionCommitted) + pre_constant(nil) + reserved(ensure) + ident(vars)operator(.)ident(each) reserved(do) operator(|)ident(vv)operator(|) + reserved(if) ident(name)operator(.)ident(nil?) reserved(and) ident(vv)operator(.)ident(transaction_open?) + ident(loop) reserved(do) + ident(tlevel) operator(=) ident(vv)operator(.)ident(instance_variable_get)operator(()symbol(:@__transaction_level__)operator(\)) operator(||) integer(-1) + reserved(break) reserved(if) ident(tlevel) operator(<) ident(vlevel)operator([)ident(vv)operator(.)ident(__id__)operator(]) + ident(vv)operator(.)ident(instance_variable_set)operator(()symbol(:@__transaction_block__)operator(,) integer(-1)operator(\)) + ident(vv)operator(.)ident(commit_transaction) reserved(if) ident(vv)operator(.)ident(transaction_open?) + reserved(end) + reserved(elsif) ident(vv)operator(.)ident(transaction_open?)operator(()ident(name)operator(\)) + ident(vv)operator(.)ident(instance_variable_set)operator(()symbol(:@__transaction_block__)operator(,) integer(-1)operator(\)) + ident(vv)operator(.)ident(commit_transaction)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(else) + ident(vars)operator(.)ident(each) reserved(do) operator(|)ident(vv)operator(|) + ident(vv)operator(.)ident(extend)operator(()constant(Transaction)operator(::)constant(Simple)operator(\)) + ident(vv)operator(.)ident(start_transaction)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + ident(private) symbol(:__common_start) + + reserved(def) method(start_named)operator(()ident(name)operator(,) operator(*)ident(vars)operator(,) operator(&)ident(block)operator(\)) + ident(__common_start)operator(()ident(name)operator(,) ident(vars)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(start)operator(()operator(*)ident(vars)operator(,) operator(&)ident(block)operator(\)) + ident(__common_start)operator(()pre_constant(nil)operator(,) ident(vars)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(__abort_transaction)operator(()ident(name) operator(=) pre_constant(nil)operator(\)) comment(#:nodoc:) + instance_variable(@__transaction_checkpoint__) operator(=) ident(__rewind_this_transaction) + + reserved(if) ident(name)operator(.)ident(nil?) + ident(ss) operator(=) string<delimiter(")delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + reserved(else) + ident(ss) operator(=) string<delimiter(")content(()inline<inline_delimiter(#{)ident(name)operator(.)ident(inspect)inline_delimiter(})>content(\))delimiter(")> reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + reserved(end) + + reserved(if) constant(Transaction)operator(::)constant(Simple)operator(.)ident(debugging?) + constant(Transaction)operator(::)constant(Simple)operator(.)ident(debug_io) operator(<<) string<delimiter(")inline<inline_delimiter(#{)string<delimiter(')content(<)delimiter(')> operator(*) instance_variable(@__transaction_level__)inline_delimiter(})>content( )delimiter(")> operator(<<) + string<delimiter(")content(Abort Transaction)inline<inline_delimiter(#{)ident(ss)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + instance_variable(@__transaction_level__) operator(-=) integer(1) + instance_variable(@__transaction_names__)operator(.)ident(pop) + reserved(if) instance_variable(@__transaction_level__) operator(<) integer(1) + instance_variable(@__transaction_level__) operator(=) integer(0) + instance_variable(@__transaction_names__) operator(=) operator([)operator(]) + reserved(end) + reserved(end) + + constant(TRANSACTION_CHECKPOINT) operator(=) string<delimiter(")content(@__transaction_checkpoint__)delimiter(")> comment(#:nodoc:) + constant(SKIP_TRANSACTION_VARS) operator(=) operator([)constant(TRANSACTION_CHECKPOINT)operator(,) string<delimiter(")content(@__transaction_level__)delimiter(")>operator(]) comment(#:nodoc:) + + reserved(def) method(__rewind_this_transaction) comment(#:nodoc:) + ident(rr) operator(=) constant(Marshal)operator(.)ident(restore)operator(()instance_variable(@__transaction_checkpoint__)operator(\)) + + reserved(begin) + pre_constant(self)operator(.)ident(replace)operator(()ident(rr)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:replace)operator(\)) + reserved(rescue) + pre_constant(nil) + reserved(end) + + ident(rr)operator(.)ident(instance_variables)operator(.)ident(each) reserved(do) operator(|)ident(vv)operator(|) + reserved(next) reserved(if) constant(SKIP_TRANSACTION_VARS)operator(.)ident(include?)operator(()ident(vv)operator(\)) + reserved(next) reserved(if) pre_constant(self)operator(.)ident(transaction_exclusions)operator(.)ident(include?)operator(()ident(vv)operator(\)) + reserved(if) ident(respond_to?)operator(()symbol(:instance_variable_get)operator(\)) + ident(instance_variable_set)operator(()ident(vv)operator(,) ident(rr)operator(.)ident(instance_variable_get)operator(()ident(vv)operator(\))operator(\)) + reserved(else) + ident(instance_eval)operator(()string<delimiter(%q|)content(#{vv} = rr.instance_eval("#{vv}"\))delimiter(|)>operator(\)) + reserved(end) + reserved(end) + + ident(new_ivar) operator(=) ident(instance_variables) operator(-) ident(rr)operator(.)ident(instance_variables) operator(-) constant(SKIP_TRANSACTION_VARS) + ident(new_ivar)operator(.)ident(each) reserved(do) operator(|)ident(vv)operator(|) + reserved(if) ident(respond_to?)operator(()symbol(:instance_variable_set)operator(\)) + ident(instance_variable_set)operator(()ident(vv)operator(,) pre_constant(nil)operator(\)) + reserved(else) + ident(instance_eval)operator(()string<delimiter(%q|)content(#{vv} = nil)delimiter(|)>operator(\)) + reserved(end) + reserved(end) + + reserved(if) ident(respond_to?)operator(()symbol(:instance_variable_get)operator(\)) + ident(rr)operator(.)ident(instance_variable_get)operator(()constant(TRANSACTION_CHECKPOINT)operator(\)) + reserved(else) + ident(rr)operator(.)ident(instance_eval)operator(()constant(TRANSACTION_CHECKPOINT)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(__commit_transaction) comment(#:nodoc:) + reserved(if) ident(respond_to?)operator(()symbol(:instance_variable_get)operator(\)) + instance_variable(@__transaction_checkpoint__) operator(=) constant(Marshal)operator(.)ident(restore)operator(()instance_variable(@__transaction_checkpoint__)operator(\))operator(.)ident(instance_variable_get)operator(()constant(TRANSACTION_CHECKPOINT)operator(\)) + reserved(else) + instance_variable(@__transaction_checkpoint__) operator(=) constant(Marshal)operator(.)ident(restore)operator(()instance_variable(@__transaction_checkpoint__)operator(\))operator(.)ident(instance_eval)operator(()constant(TRANSACTION_CHECKPOINT)operator(\)) + reserved(end) + + instance_variable(@__transaction_level__) operator(-=) integer(1) + instance_variable(@__transaction_names__)operator(.)ident(pop) + + reserved(if) instance_variable(@__transaction_level__) operator(<) integer(1) + instance_variable(@__transaction_level__) operator(=) integer(0) + instance_variable(@__transaction_names__) operator(=) operator([)operator(]) + reserved(end) + reserved(end) + + ident(private) symbol(:__abort_transaction) + ident(private) symbol(:__rewind_this_transaction) + ident(private) symbol(:__commit_transaction) + reserved(end) +reserved(end) +reserved(module) class(ActiveRecord) + reserved(module) class(VERSION) comment(#:nodoc:) + constant(MAJOR) operator(=) integer(1) + constant(MINOR) operator(=) integer(14) + constant(TINY) operator(=) integer(4) + + constant(STRING) operator(=) operator([)constant(MAJOR)operator(,) constant(MINOR)operator(,) constant(TINY)operator(])operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(yaml)delimiter(')> + +reserved(module) class(ActiveRecord) + reserved(module) class(Wrappings) comment(#:nodoc:) + reserved(class) class(YamlWrapper) operator(<) constant(AbstractWrapper) comment(#:nodoc:) + reserved(def) method(wrap)operator(()ident(attribute)operator(\)) ident(attribute)operator(.)ident(to_yaml) reserved(end) + reserved(def) method(unwrap)operator(()ident(attribute)operator(\)) constant(YAML)operator(::)ident(load)operator(()ident(attribute)operator(\)) reserved(end) + reserved(end) + + reserved(module) class(ClassMethods) comment(#:nodoc:) + comment(# Wraps the attribute in Yaml encoding) + reserved(def) method(wrap_in_yaml)operator(()operator(*)ident(attributes)operator(\)) ident(wrap_with)operator(()constant(YamlWrapper)operator(,) ident(attributes)operator(\)) reserved(end) + reserved(end) + reserved(end) +ident(endmodule) constant(ActiveRecord) + comment(# A plugin framework for wrapping attribute values before they go in and unwrapping them after they go out of the database.) + comment(# This was intended primarily for YAML wrapping of arrays and hashes, but this behavior is now native in the Base class.) + comment(# So for now this framework is laying dormant until a need pops up.) + reserved(module) class(Wrappings) comment(#:nodoc:) + reserved(module) class(ClassMethods) comment(#:nodoc:) + reserved(def) method(wrap_with)operator(()ident(wrapper)operator(,) operator(*)ident(attributes)operator(\)) + operator([) ident(attributes) operator(])operator(.)ident(flat)operator(.)ident(each) operator({) operator(|)ident(attribute)operator(|) ident(wrapper)operator(.)ident(wrap)operator(()ident(attribute)operator(\)) operator(}) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(class) class(AbstractWrapper) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(wrap)operator(()ident(attribute)operator(,) ident(record_binding)operator(\)) comment(#:nodoc:) + string<delimiter(%w()content( before_save after_save after_initialize )delimiter(\))>operator(.)ident(each) reserved(do) operator(|)ident(callback)operator(|) + ident(eval) string<delimiter(")inline<inline_delimiter(#{)ident(callback)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(.new(')inline<inline_delimiter(#{)ident(attribute)inline_delimiter(})>content('\))delimiter(")>operator(,) ident(record_binding) + reserved(end) + reserved(end) + + reserved(def) method(initialize)operator(()ident(attribute)operator(\)) comment(#:nodoc:) + instance_variable(@attribute) operator(=) ident(attribute) + reserved(end) + + reserved(def) method(save_wrapped_attribute)operator(()ident(record)operator(\)) comment(#:nodoc:) + reserved(if) ident(record)operator(.)ident(attribute_present?)operator(()instance_variable(@attribute)operator(\)) + ident(record)operator(.)ident(send)operator(() + string<delimiter(")content(write_attribute)delimiter(")>operator(,) + instance_variable(@attribute)operator(,) + ident(wrap)operator(()ident(record)operator(.)ident(send)operator(()string<delimiter(")content(read_attribute)delimiter(")>operator(,) instance_variable(@attribute)operator(\))operator(\)) + operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(load_wrapped_attribute)operator(()ident(record)operator(\)) comment(#:nodoc:) + reserved(if) ident(record)operator(.)ident(attribute_present?)operator(()instance_variable(@attribute)operator(\)) + ident(record)operator(.)ident(send)operator(() + string<delimiter(")content(write_attribute)delimiter(")>operator(,) + instance_variable(@attribute)operator(,) + ident(unwrap)operator(()ident(record)operator(.)ident(send)operator(()string<delimiter(")content(read_attribute)delimiter(")>operator(,) instance_variable(@attribute)operator(\))operator(\)) + operator(\)) + reserved(end) + reserved(end) + + ident(alias_method) symbol(:before_save)operator(,) symbol(:save_wrapped_attribute) comment(#:nodoc:) + ident(alias_method) symbol(:after_save)operator(,) symbol(:load_wrapped_attribute) comment(#:nodoc:) + ident(alias_method) symbol(:after_initialize)operator(,) symbol(:after_save) comment(#:nodoc:) + + comment(# Overwrite to implement the logic that'll take the regular attribute and wrap it.) + reserved(def) method(wrap)operator(()ident(attribute)operator(\)) reserved(end) + + comment(# Overwrite to implement the logic that'll take the wrapped attribute and unwrap it.) + reserved(def) method(unwrap)operator(()ident(attribute)operator(\)) reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(#--) +comment(# Copyright (c\) 2004 David Heinemeier Hansson) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\)) reserved(unless) + global_variable($:)operator(.)ident(include?)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\)) operator(||) global_variable($:)operator(.)ident(include?)operator(()constant(File)operator(.)ident(expand_path)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\))operator(\)) + +reserved(unless) reserved(defined?)operator(()constant(ActiveSupport)operator(\)) + reserved(begin) + global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/../../activesupport/lib)delimiter(")>operator(\)) + ident(require) string<delimiter(')content(active_support)delimiter(')> + reserved(rescue) constant(LoadError) + ident(require) string<delimiter(')content(rubygems)delimiter(')> + ident(require_gem) string<delimiter(')content(activesupport)delimiter(')> + reserved(end) +reserved(end) + +ident(require) string<delimiter(')content(active_record/base)delimiter(')> +ident(require) string<delimiter(')content(active_record/observer)delimiter(')> +ident(require) string<delimiter(')content(active_record/validations)delimiter(')> +ident(require) string<delimiter(')content(active_record/callbacks)delimiter(')> +ident(require) string<delimiter(')content(active_record/reflection)delimiter(')> +ident(require) string<delimiter(')content(active_record/associations)delimiter(')> +ident(require) string<delimiter(')content(active_record/aggregations)delimiter(')> +ident(require) string<delimiter(')content(active_record/transactions)delimiter(')> +ident(require) string<delimiter(')content(active_record/timestamp)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/list)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/tree)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/nested_set)delimiter(')> +ident(require) string<delimiter(')content(active_record/locking)delimiter(')> +ident(require) string<delimiter(')content(active_record/migration)delimiter(')> +ident(require) string<delimiter(')content(active_record/schema)delimiter(')> +ident(require) string<delimiter(')content(active_record/calculations)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_eval) reserved(do) + ident(include) constant(ActiveRecord)operator(::)constant(Validations) + ident(include) constant(ActiveRecord)operator(::)constant(Locking) + ident(include) constant(ActiveRecord)operator(::)constant(Callbacks) + ident(include) constant(ActiveRecord)operator(::)constant(Observing) + ident(include) constant(ActiveRecord)operator(::)constant(Timestamp) + ident(include) constant(ActiveRecord)operator(::)constant(Associations) + ident(include) constant(ActiveRecord)operator(::)constant(Aggregations) + ident(include) constant(ActiveRecord)operator(::)constant(Transactions) + ident(include) constant(ActiveRecord)operator(::)constant(Reflection) + ident(include) constant(ActiveRecord)operator(::)constant(Acts)operator(::)constant(Tree) + ident(include) constant(ActiveRecord)operator(::)constant(Acts)operator(::)constant(List) + ident(include) constant(ActiveRecord)operator(::)constant(Acts)operator(::)constant(NestedSet) + ident(include) constant(ActiveRecord)operator(::)constant(Calculations) +reserved(end) + +reserved(unless) reserved(defined?)operator(()constant(RAILS_CONNECTION_ADAPTERS)operator(\)) + constant(RAILS_CONNECTION_ADAPTERS) operator(=) string<delimiter(%w()content( mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase )delimiter(\))> +reserved(end) + +constant(RAILS_CONNECTION_ADAPTERS)operator(.)ident(each) reserved(do) operator(|)ident(adapter)operator(|) + ident(require) string<delimiter(")content(active_record/connection_adapters/)delimiter(")> operator(+) ident(adapter) operator(+) string<delimiter(")content(_adapter)delimiter(")> +reserved(end) + +ident(require) string<delimiter(')content(active_record/query_cache)delimiter(')> +ident(require) string<delimiter(')content(active_record/schema_dumper)delimiter(')> +comment(# The filename begins with "aaa" to ensure this is the first test.) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(AAACreateTablesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + reserved(def) method(setup) + instance_variable(@base_path) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/db_definitions)delimiter(")> + reserved(end) + + reserved(def) method(test_drop_and_create_main_tables) + ident(recreate) constant(ActiveRecord)operator(::)constant(Base) + ident(assert) pre_constant(true) + reserved(end) + + reserved(def) method(test_load_schema) + ident(eval)operator(()constant(File)operator(.)ident(read)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/fixtures/db_definitions/schema.rb)delimiter(")>operator(\))operator(\)) + ident(assert) pre_constant(true) + reserved(end) + + reserved(def) method(test_drop_and_create_courses_table) + ident(recreate) constant(Course)operator(,) string<delimiter(')content(2)delimiter(')> + ident(assert) pre_constant(true) + reserved(end) + + ident(private) + reserved(def) method(recreate)operator(()ident(base)operator(,) ident(suffix) operator(=) pre_constant(nil)operator(\)) + ident(connection) operator(=) ident(base)operator(.)ident(connection) + ident(adapter_name) operator(=) ident(connection)operator(.)ident(adapter_name)operator(.)ident(downcase) operator(+) ident(suffix)operator(.)ident(to_s) + ident(execute_sql_file) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@base_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(adapter_name)inline_delimiter(})>content(.drop.sql)delimiter(")>operator(,) ident(connection) + ident(execute_sql_file) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@base_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(adapter_name)inline_delimiter(})>content(.sql)delimiter(")>operator(,) ident(connection) + reserved(end) + + reserved(def) method(execute_sql_file)operator(()ident(path)operator(,) ident(connection)operator(\)) + comment(# OpenBase has a different format for sql files) + reserved(if) ident(current_adapter?)operator(()symbol(:OpenBaseAdapter)operator(\)) reserved(then) + constant(File)operator(.)ident(read)operator(()ident(path)operator(\))operator(.)ident(split)operator(()string<delimiter(")content(go)delimiter(")>operator(\))operator(.)ident(each_with_index) reserved(do) operator(|)ident(sql)operator(,) ident(i)operator(|) + reserved(begin) + comment(# OpenBase does not support comments embedded in sql) + ident(connection)operator(.)ident(execute)operator(()ident(sql)operator(,)string<delimiter(")content(SQL statement #)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")>operator(\)) reserved(unless) ident(sql)operator(.)ident(blank?) + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) + comment(#$stderr.puts "warning: #{$!}") + reserved(end) + reserved(end) + reserved(else) + constant(File)operator(.)ident(read)operator(()ident(path)operator(\))operator(.)ident(split)operator(()string<delimiter(')content(;)delimiter(')>operator(\))operator(.)ident(each_with_index) reserved(do) operator(|)ident(sql)operator(,) ident(i)operator(|) + reserved(begin) + ident(connection)operator(.)ident(execute)operator(()string<delimiter(")char(\\n)char(\\n)content(-- statement #)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>char(\\n)inline<inline_delimiter(#{)ident(sql)inline_delimiter(})>char(\\n)delimiter(")>operator(\)) reserved(unless) ident(sql)operator(.)ident(blank?) + reserved(rescue) constant(ActiveRecord)operator(::)constant(StatementInvalid) + comment(#$stderr.puts "warning: #{$!}") + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../lib)delimiter(')>operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../activesupport/lib)delimiter(')>operator(\)) + +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(active_record)delimiter(')> +ident(require) string<delimiter(')content(active_record/fixtures)delimiter(')> +ident(require) string<delimiter(')content(active_support/binding_of_caller)delimiter(')> +ident(require) string<delimiter(')content(active_support/breakpoint)delimiter(')> +ident(require) string<delimiter(')content(connection)delimiter(')> + +constant(QUOTED_TYPE) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(quote_column_name)operator(()string<delimiter(')content(type)delimiter(')>operator(\)) reserved(unless) constant(Object)operator(.)ident(const_defined?)operator(()symbol(:QUOTED_TYPE)operator(\)) + +reserved(class) class(Test::Unit::TestCase) comment(#:nodoc:) + pre_constant(self)operator(.)ident(fixture_path) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/)delimiter(")> + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) pre_constant(false) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) operator(()constant(ENV)operator([)string<delimiter(')content(AR_NO_TX_FIXTURES)delimiter(')>operator(]) operator(!=) string<delimiter(")content(yes)delimiter(")>operator(\)) + + reserved(def) method(create_fixtures)operator(()operator(*)ident(table_names)operator(,) operator(&)ident(block)operator(\)) + constant(Fixtures)operator(.)ident(create_fixtures)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/)delimiter(")>operator(,) ident(table_names)operator(,) operator({)operator(})operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(assert_date_from_db)operator(()ident(expected)operator(,) ident(actual)operator(,) ident(message) operator(=) pre_constant(nil)operator(\)) + comment(# SQL Server doesn't have a separate column type just for dates, ) + comment(# so the time is in the string and incorrectly formatted) + reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) + ident(assert_equal) ident(expected)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y/%m/%d 00:00:00)delimiter(")>operator(\))operator(,) ident(actual)operator(.)ident(strftime)operator(()string<delimiter(")content(%Y/%m/%d 00:00:00)delimiter(")>operator(\)) + reserved(elsif) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + ident(assert_equal) ident(expected)operator(.)ident(to_s)operator(,) ident(actual)operator(.)ident(to_date)operator(.)ident(to_s)operator(,) ident(message) + reserved(else) + ident(assert_equal) ident(expected)operator(.)ident(to_s)operator(,) ident(actual)operator(.)ident(to_s)operator(,) ident(message) + reserved(end) + reserved(end) + + reserved(def) method(assert_queries)operator(()ident(num) operator(=) integer(1)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(class)operator(.)ident(class_eval) reserved(do) + pre_constant(self)operator(.)ident(query_count) operator(=) integer(0) + ident(alias_method) symbol(:execute)operator(,) symbol(:execute_with_query_counting) + reserved(end) + reserved(yield) + reserved(ensure) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(class)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:execute)operator(,) symbol(:execute_without_query_counting) + reserved(end) + ident(assert_equal) ident(num)operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(query_count)operator(,) string<delimiter(")inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(query_count)inline_delimiter(})>content( instead of )inline<inline_delimiter(#{)ident(num)inline_delimiter(})>content( queries were executed.)delimiter(")> + reserved(end) + + reserved(def) method(assert_no_queries)operator(()operator(&)ident(block)operator(\)) + ident(assert_queries)operator(()integer(0)operator(,) operator(&)ident(block)operator(\)) + reserved(end) +reserved(end) + +reserved(def) method(current_adapter?)operator(()ident(type)operator(\)) + constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(.)ident(const_defined?)operator(()ident(type)operator(\)) operator(&&) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(instance_of?)operator(()constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(.)ident(const_get)operator(()ident(type)operator(\))operator(\)) +reserved(end) + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(class)operator(.)ident(class_eval) reserved(do) + ident(cattr_accessor) symbol(:query_count) + ident(alias_method) symbol(:execute_without_query_counting)operator(,) symbol(:execute) + reserved(def) method(execute_with_query_counting)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) + pre_constant(self)operator(.)ident(query_count) operator(+=) integer(1) + ident(execute_without_query_counting)operator(()ident(sql)operator(,) ident(name)operator(\)) + reserved(end) +reserved(end) + +comment(#ActiveRecord::Base.logger = Logger.new(STDOUT\)) +comment(#ActiveRecord::Base.colorize_logging = false) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(ActiveSchemaTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(MysqlAdapter)operator(.)ident(class_eval) reserved(do) + ident(alias_method) symbol(:real_execute)operator(,) symbol(:execute) + reserved(def) method(execute)operator(()ident(sql)operator(,) ident(name) operator(=) pre_constant(nil)operator(\)) reserved(return) ident(sql) reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(teardown) + constant(ActiveRecord)operator(::)constant(ConnectionAdapters)operator(::)constant(MysqlAdapter)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:execute)operator(,) symbol(:real_execute)operator(\)) + reserved(end) + + reserved(def) method(test_drop_table) + ident(assert_equal) string<delimiter(")content(DROP TABLE people)delimiter(")>operator(,) ident(drop_table)operator(()symbol(:people)operator(\)) + reserved(end) + + reserved(def) method(test_add_column) + ident(assert_equal) string<delimiter(")content(ALTER TABLE people ADD last_name varchar(255\))delimiter(")>operator(,) ident(add_column)operator(()symbol(:people)operator(,) symbol(:last_name)operator(,) symbol(:string)operator(\)) + reserved(end) + + reserved(def) method(test_add_column_with_limit) + ident(assert_equal) string<delimiter(")content(ALTER TABLE people ADD key varchar(32\))delimiter(")>operator(,) ident(add_column)operator(()symbol(:people)operator(,) symbol(:key)operator(,) symbol(:string)operator(,) symbol(:limit) operator(=)operator(>) integer(32)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method_symbol)operator(,) operator(*)ident(arguments)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(send)operator(()ident(method_symbol)operator(,) operator(*)ident(arguments)operator(\)) + reserved(end) +ident(endrequire) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(AdapterTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(setup) + instance_variable(@connection) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + reserved(end) + + reserved(def) method(test_tables) + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:tables)operator(\)) + ident(tables) operator(=) instance_variable(@connection)operator(.)ident(tables) + ident(assert) ident(tables)operator(.)ident(include?)operator(()string<delimiter(")content(accounts)delimiter(")>operator(\)) + ident(assert) ident(tables)operator(.)ident(include?)operator(()string<delimiter(")content(authors)delimiter(")>operator(\)) + ident(assert) ident(tables)operator(.)ident(include?)operator(()string<delimiter(")content(tasks)delimiter(")>operator(\)) + ident(assert) ident(tables)operator(.)ident(include?)operator(()string<delimiter(")content(topics)delimiter(")>operator(\)) + reserved(else) + ident(warn) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@connection)operator(.)ident(class)inline_delimiter(})>content( does not respond to #tables)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_indexes) + ident(idx_name) operator(=) string<delimiter(")content(accounts_idx)delimiter(")> + + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:indexes)operator(\)) + ident(indexes) operator(=) instance_variable(@connection)operator(.)ident(indexes)operator(()string<delimiter(")content(accounts)delimiter(")>operator(\)) + ident(assert) ident(indexes)operator(.)ident(empty?) + + instance_variable(@connection)operator(.)ident(add_index) symbol(:accounts)operator(,) symbol(:firm_id)operator(,) symbol(:name) operator(=)operator(>) ident(idx_name) + ident(indexes) operator(=) instance_variable(@connection)operator(.)ident(indexes)operator(()string<delimiter(")content(accounts)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(accounts)delimiter(")>operator(,) ident(indexes)operator(.)ident(first)operator(.)ident(table) + comment(# OpenBase does not have the concept of a named index) + comment(# Indexes are merely properties of columns.) + ident(assert_equal) ident(idx_name)operator(,) ident(indexes)operator(.)ident(first)operator(.)ident(name) reserved(unless) ident(current_adapter?)operator(()symbol(:OpenBaseAdapter)operator(\)) + ident(assert) operator(!)ident(indexes)operator(.)ident(first)operator(.)ident(unique) + ident(assert_equal) operator([)string<delimiter(")content(firm_id)delimiter(")>operator(])operator(,) ident(indexes)operator(.)ident(first)operator(.)ident(columns) + reserved(else) + ident(warn) string<delimiter(")inline<inline_delimiter(#{)instance_variable(@connection)operator(.)ident(class)inline_delimiter(})>content( does not respond to #indexes)delimiter(")> + reserved(end) + + reserved(ensure) + instance_variable(@connection)operator(.)ident(remove_index)operator(()symbol(:accounts)operator(,) symbol(:name) operator(=)operator(>) ident(idx_name)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_current_database) + reserved(if) instance_variable(@connection)operator(.)ident(respond_to?)operator(()symbol(:current_database)operator(\)) + ident(assert_equal) constant(ENV)operator([)string<delimiter(')content(ARUNIT_DB_NAME)delimiter(')>operator(]) operator(||) string<delimiter(")content(activerecord_unittest)delimiter(")>operator(,) instance_variable(@connection)operator(.)ident(current_database) + reserved(end) + reserved(end) + + reserved(def) method(test_table_alias) + reserved(def) instance_variable(@connection)operator(.)ident(test_table_alias_length)operator(()operator(\)) integer(10)operator(;) reserved(end) + reserved(class) operator(<<) instance_variable(@connection) + ident(alias_method) symbol(:old_table_alias_length)operator(,) symbol(:table_alias_length) + ident(alias_method) symbol(:table_alias_length)operator(,) symbol(:test_table_alias_length) + reserved(end) + + ident(assert_equal) string<delimiter(')content(posts)delimiter(')>operator(,) instance_variable(@connection)operator(.)ident(table_alias_for)operator(()string<delimiter(')content(posts)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(posts_comm)delimiter(')>operator(,) instance_variable(@connection)operator(.)ident(table_alias_for)operator(()string<delimiter(')content(posts_comments)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(dbo_posts)delimiter(')>operator(,) instance_variable(@connection)operator(.)ident(table_alias_for)operator(()string<delimiter(')content(dbo.posts)delimiter(')>operator(\)) + + reserved(class) operator(<<) instance_variable(@connection) + ident(alias_method) symbol(:table_alias_length)operator(,) symbol(:old_table_alias_length) + reserved(end) + reserved(end) + + comment(# test resetting sequences in odd tables in postgreSQL) + reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(respond_to?)operator(()symbol(:reset_pk_sequence!)operator(\)) + ident(require) string<delimiter(')content(fixtures/movie)delimiter(')> + ident(require) string<delimiter(')content(fixtures/subscriber)delimiter(')> + reserved(def) method(test_reset_empty_table_with_custom_pk) + constant(Movie)operator(.)ident(delete_all) + constant(Movie)operator(.)ident(connection)operator(.)ident(reset_pk_sequence!) string<delimiter(')content(movies)delimiter(')> + ident(assert_equal) integer(1)operator(,) constant(Movie)operator(.)ident(create)operator(()symbol(:name) operator(=)operator(>) string<delimiter(')content(fight club)delimiter(')>operator(\))operator(.)ident(id) + reserved(end) + + reserved(def) method(test_reset_table_with_non_integer_pk) + constant(Subscriber)operator(.)ident(delete_all) + constant(Subscriber)operator(.)ident(connection)operator(.)ident(reset_pk_sequence!) string<delimiter(')content(subscribers)delimiter(')> + + ident(sub) operator(=) constant(Subscriber)operator(.)ident(new)operator(()symbol(:name) operator(=)operator(>) string<delimiter(')content(robert drake)delimiter(')>operator(\)) + ident(sub)operator(.)ident(id) operator(=) string<delimiter(')content(bob drake)delimiter(')> + ident(assert_nothing_raised) operator({) ident(sub)operator(.)ident(save!) operator(}) + reserved(end) + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/customer)delimiter(')> + +reserved(class) class(AggregationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:customers) + + reserved(def) method(test_find_single_value_object) + ident(assert_equal) integer(50)operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(balance)operator(.)ident(amount) + ident(assert_kind_of) constant(Money)operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(balance) + ident(assert_equal) integer(300)operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(balance)operator(.)ident(exchange_to)operator(()string<delimiter(")content(DKK)delimiter(")>operator(\))operator(.)ident(amount) + reserved(end) + + reserved(def) method(test_find_multiple_value_object) + ident(assert_equal) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(address_street)operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(address)operator(.)ident(street) + ident(assert)operator(() + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(address)operator(.)ident(close_to?)operator(()constant(Address)operator(.)ident(new)operator(()string<delimiter(")content(Different Street)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(address_city)operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(address_country)operator(\))operator(\)) + operator(\)) + reserved(end) + + reserved(def) method(test_change_single_value_object) + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(balance) operator(=) constant(Money)operator(.)ident(new)operator(()integer(100)operator(\)) + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(save) + ident(assert_equal) integer(100)operator(,) constant(Customer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(balance)operator(.)ident(amount) + reserved(end) + + reserved(def) method(test_immutable_value_objects) + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(balance) operator(=) constant(Money)operator(.)ident(new)operator(()integer(100)operator(\)) + ident(assert_raises)operator(()constant(TypeError)operator(\)) operator({) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(balance)operator(.)ident(instance_eval) operator({) instance_variable(@amount) operator(=) integer(20) operator(}) operator(}) + reserved(end) + + reserved(def) method(test_inferred_mapping) + ident(assert_equal) string<delimiter(")content(35.544623640962634)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(latitude) + ident(assert_equal) string<delimiter(")content(-105.9309951055148)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(longitude) + + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location) operator(=) constant(GpsLocation)operator(.)ident(new)operator(()string<delimiter(")content(39x-110)delimiter(")>operator(\)) + + ident(assert_equal) string<delimiter(")content(39)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(latitude) + ident(assert_equal) string<delimiter(")content(-110)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(longitude) + + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(save) + + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(reload) + + ident(assert_equal) string<delimiter(")content(39)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(latitude) + ident(assert_equal) string<delimiter(")content(-110)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(longitude) + reserved(end) + + reserved(def) method(test_reloaded_instance_refreshes_aggregations) + ident(assert_equal) string<delimiter(")content(35.544623640962634)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(latitude) + ident(assert_equal) string<delimiter(")content(-105.9309951055148)delimiter(")>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location)operator(.)ident(longitude) + + constant(Customer)operator(.)ident(update_all)operator(()string<delimiter(")content(gps_location = '24x113')delimiter(")>operator(\)) + ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(reload) + ident(assert_equal) string<delimiter(')content(24x113)delimiter(')>operator(,) ident(customers)operator(()symbol(:david)operator(\))operator([)string<delimiter(')content(gps_location)delimiter(')>operator(]) + + ident(assert_equal) constant(GpsLocation)operator(.)ident(new)operator(()string<delimiter(')content(24x113)delimiter(')>operator(\))operator(,) ident(customers)operator(()symbol(:david)operator(\))operator(.)ident(gps_location) + reserved(end) + + reserved(def) method(test_gps_equality) + ident(assert) constant(GpsLocation)operator(.)ident(new)operator(()string<delimiter(')content(39x110)delimiter(')>operator(\)) operator(==) constant(GpsLocation)operator(.)ident(new)operator(()string<delimiter(')content(39x110)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_gps_inequality) + ident(assert) constant(GpsLocation)operator(.)ident(new)operator(()string<delimiter(')content(39x110)delimiter(')>operator(\)) operator(!=) constant(GpsLocation)operator(.)ident(new)operator(()string<delimiter(')content(39x111)delimiter(')>operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../lib/active_record/schema)delimiter(")> + +reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(supports_migrations?) + + reserved(class) class(ActiveRecordSchemaTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + reserved(def) method(setup) + instance_variable(@connection) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + reserved(end) + + reserved(def) method(teardown) + instance_variable(@connection)operator(.)ident(drop_table) symbol(:fruits) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_schema_define) + constant(ActiveRecord)operator(::)constant(Schema)operator(.)ident(define)operator(()symbol(:version) operator(=)operator(>) integer(7)operator(\)) reserved(do) + ident(create_table) symbol(:fruits) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:color)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:fruit_size)operator(,) symbol(:string) comment(# NOTE: "size" is reserved in Oracle) + ident(t)operator(.)ident(column) symbol(:texture)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:flavor)operator(,) symbol(:string) + reserved(end) + reserved(end) + + ident(assert_nothing_raised) operator({) instance_variable(@connection)operator(.)ident(select_all) string<delimiter(")content(SELECT * FROM fruits)delimiter(")> operator(}) + ident(assert_nothing_raised) operator({) instance_variable(@connection)operator(.)ident(select_all) string<delimiter(")content(SELECT * FROM schema_info)delimiter(")> operator(}) + ident(assert_equal) integer(7)operator(,) instance_variable(@connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT version FROM schema_info)delimiter(")>operator(\))operator([)string<delimiter(')content(version)delimiter(')>operator(])operator(.)ident(to_i) + reserved(end) + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/author)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> + +reserved(class) class(AssociationCallbacksTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:posts)operator(,) symbol(:authors)operator(,) symbol(:projects)operator(,) symbol(:developers) + + reserved(def) method(setup) + instance_variable(@david) operator(=) ident(authors)operator(()symbol(:david)operator(\)) + instance_variable(@thinking) operator(=) ident(posts)operator(()symbol(:thinking)operator(\)) + instance_variable(@authorless) operator(=) ident(posts)operator(()symbol(:authorless)operator(\)) + ident(assert) instance_variable(@david)operator(.)ident(post_log)operator(.)ident(empty?) + reserved(end) + + reserved(def) method(test_adding_macro_callbacks) + instance_variable(@david)operator(.)ident(posts_with_callbacks) operator(<<) instance_variable(@thinking) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + instance_variable(@david)operator(.)ident(posts_with_callbacks) operator(<<) instance_variable(@thinking) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + reserved(end) + + reserved(def) method(test_adding_with_proc_callbacks) + instance_variable(@david)operator(.)ident(posts_with_proc_callbacks) operator(<<) instance_variable(@thinking) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + instance_variable(@david)operator(.)ident(posts_with_proc_callbacks) operator(<<) instance_variable(@thinking) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + reserved(end) + + reserved(def) method(test_removing_with_macro_callbacks) + ident(first_post)operator(,) ident(second_post) operator(=) instance_variable(@david)operator(.)ident(posts_with_callbacks)operator([)integer(0)operator(,) integer(2)operator(]) + instance_variable(@david)operator(.)ident(posts_with_callbacks)operator(.)ident(delete)operator(()ident(first_post)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + instance_variable(@david)operator(.)ident(posts_with_callbacks)operator(.)ident(delete)operator(()ident(second_post)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(second_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(second_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + reserved(end) + + reserved(def) method(test_removing_with_proc_callbacks) + ident(first_post)operator(,) ident(second_post) operator(=) instance_variable(@david)operator(.)ident(posts_with_callbacks)operator([)integer(0)operator(,) integer(2)operator(]) + instance_variable(@david)operator(.)ident(posts_with_proc_callbacks)operator(.)ident(delete)operator(()ident(first_post)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + instance_variable(@david)operator(.)ident(posts_with_proc_callbacks)operator(.)ident(delete)operator(()ident(second_post)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(first_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(second_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(second_post)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + reserved(end) + + reserved(def) method(test_multiple_callbacks) + instance_variable(@david)operator(.)ident(posts_with_multiple_callbacks) operator(<<) instance_variable(@thinking) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding_proc)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding_proc)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + instance_variable(@david)operator(.)ident(posts_with_multiple_callbacks) operator(<<) instance_variable(@thinking) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding_proc)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding_proc)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding_proc)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding_proc)inline<inline_delimiter(#{)instance_variable(@thinking)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) instance_variable(@david)operator(.)ident(post_log) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_add_callback) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(ar) operator(=) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(assert) ident(ar)operator(.)ident(developers_log)operator(.)ident(empty?) + ident(ar)operator(.)ident(developers_with_callbacks) operator(<<) ident(david) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) ident(ar)operator(.)ident(developers_log) + ident(ar)operator(.)ident(developers_with_callbacks) operator(<<) ident(david) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) ident(ar)operator(.)ident(developers_log) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_remove_callback) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(jamis) operator(=) ident(developers)operator(()symbol(:jamis)operator(\)) + ident(activerecord) operator(=) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(assert) ident(activerecord)operator(.)ident(developers_log)operator(.)ident(empty?) + ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(delete)operator(()ident(david)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) ident(activerecord)operator(.)ident(developers_log) + + ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(delete)operator(()ident(jamis)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(jamis)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(jamis)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) ident(activerecord)operator(.)ident(developers_log) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_remove_callback_on_clear) + ident(activerecord) operator(=) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(assert) ident(activerecord)operator(.)ident(developers_log)operator(.)ident(empty?) + reserved(if) ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(size) operator(==) integer(0) + ident(activerecord)operator(.)ident(developers) operator(<<) ident(developers)operator(()symbol(:david)operator(\)) + ident(activerecord)operator(.)ident(developers) operator(<<) ident(developers)operator(()symbol(:jamis)operator(\)) + ident(activerecord)operator(.)ident(reload) + ident(assert) ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(size) operator(==) integer(2) + reserved(end) + ident(log_array) operator(=) ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(collect) operator({)operator(|)ident(d)operator(|) operator([)string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(d)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,)string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(d)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(})operator(.)ident(flatten)operator(.)ident(sort) + ident(assert) ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(clear) + ident(assert_equal) ident(log_array)operator(,) ident(activerecord)operator(.)ident(developers_log)operator(.)ident(sort) + reserved(end) + + reserved(def) method(test_dont_add_if_before_callback_raises_exception) + ident(assert) operator(!)instance_variable(@david)operator(.)ident(unchangable_posts)operator(.)ident(include?)operator(()instance_variable(@authorless)operator(\)) + reserved(begin) + instance_variable(@david)operator(.)ident(unchangable_posts) operator(<<) instance_variable(@authorless) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + reserved(end) + ident(assert) instance_variable(@david)operator(.)ident(post_log)operator(.)ident(empty?) + ident(assert) operator(!)instance_variable(@david)operator(.)ident(unchangable_posts)operator(.)ident(include?)operator(()instance_variable(@authorless)operator(\)) + instance_variable(@david)operator(.)ident(reload) + ident(assert) operator(!)instance_variable(@david)operator(.)ident(unchangable_posts)operator(.)ident(include?)operator(()instance_variable(@authorless)operator(\)) + reserved(end) + + reserved(def) method(test_push_with_attributes) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(activerecord) operator(=) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(assert) ident(activerecord)operator(.)ident(developers_log)operator(.)ident(empty?) + ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(push_with_attributes)operator(()ident(david)operator(,) operator({)operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) ident(activerecord)operator(.)ident(developers_log) + ident(activerecord)operator(.)ident(developers_with_callbacks)operator(.)ident(push_with_attributes)operator(()ident(david)operator(,) operator({)operator(})operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(david)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(])operator(,) ident(activerecord)operator(.)ident(developers_log) + reserved(end) +reserved(end) + +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> + +reserved(class) class(AssociationInheritanceReloadTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:companies) + + reserved(def) method(test_set_attributes) + ident(assert_equal) operator([)string<delimiter(")content(errors.add_on_empty('name', )char(\\")content(can't be empty)char(\\")content(\))delimiter(")>operator(])operator(,) constant(Firm)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(validate)delimiter(")>operator(\))operator(,) string<delimiter(")content(Second run)delimiter(")> + comment(# ActiveRecord::Base.reset_column_information_and_inheritable_attributes_for_all_subclasses) + ident(remove_subclass_of)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(\)) + ident(load) string<delimiter(')content(fixtures/company.rb)delimiter(')> + ident(assert_equal) operator([)string<delimiter(")content(errors.add_on_empty('name', )char(\\")content(can't be empty)char(\\")content(\))delimiter(")>operator(])operator(,) constant(Firm)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(validate)delimiter(")>operator(\))operator(,) string<delimiter(")content(Second run)delimiter(")> + reserved(end) +ident(endrequire) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/list)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/author)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> +ident(require) string<delimiter(')content(fixtures/categorization)delimiter(')> +ident(require) string<delimiter(')content(fixtures/mixin)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> + +reserved(class) class(CascadedEagerLoadingTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:authors)operator(,) symbol(:mixins)operator(,) symbol(:companies)operator(,) symbol(:posts)operator(,) symbol(:categorizations)operator(,) symbol(:topics) + + reserved(def) method(test_eager_association_loading_with_cascaded_two_levels) + ident(authors) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)operator({)symbol(:posts)operator(=)operator(>)symbol(:comments)operator(})operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(authors.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(authors)operator(.)ident(size) + ident(assert_equal) integer(5)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(authors)operator([)integer(1)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) integer(9)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(collect)operator({)operator(|)ident(post)operator(|) ident(post)operator(.)ident(comments)operator(.)ident(size) operator(})operator(.)ident(inject)operator(()integer(0)operator(\))operator({)operator(|)ident(sum)operator(,)ident(i)operator(|) ident(sum)operator(+)ident(i)operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_cascaded_two_levels_and_one_level) + ident(authors) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)operator([)operator({)symbol(:posts)operator(=)operator(>)symbol(:comments)operator(})operator(,) symbol(:categorizations)operator(])operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(authors.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(authors)operator(.)ident(size) + ident(assert_equal) integer(5)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(authors)operator([)integer(1)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) integer(9)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(collect)operator({)operator(|)ident(post)operator(|) ident(post)operator(.)ident(comments)operator(.)ident(size) operator(})operator(.)ident(inject)operator(()integer(0)operator(\))operator({)operator(|)ident(sum)operator(,)ident(i)operator(|) ident(sum)operator(+)ident(i)operator(}) + ident(assert_equal) integer(1)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(categorizations)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(authors)operator([)integer(1)operator(])operator(.)ident(categorizations)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations) + ident(authors) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)operator({)symbol(:posts)operator(=)operator(>)operator([)symbol(:comments)operator(,) symbol(:categorizations)operator(])operator(})operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(authors.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(authors)operator(.)ident(size) + ident(assert_equal) integer(5)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(authors)operator([)integer(1)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) integer(9)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(collect)operator({)operator(|)ident(post)operator(|) ident(post)operator(.)ident(comments)operator(.)ident(size) operator(})operator(.)ident(inject)operator(()integer(0)operator(\))operator({)operator(|)ident(sum)operator(,)ident(i)operator(|) ident(sum)operator(+)ident(i)operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference) + ident(authors) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)operator({)symbol(:posts)operator(=)operator(>)operator([)symbol(:comments)operator(,) symbol(:author)operator(])operator(})operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(authors.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(authors)operator(.)ident(size) + ident(assert_equal) integer(5)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(size) + ident(assert_equal) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(name)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(name) + ident(assert_equal) operator([)ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(name)operator(])operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(collect)operator({)operator(|)ident(post)operator(|) ident(post)operator(.)ident(author)operator(.)ident(name)operator(})operator(.)ident(uniq) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_cascaded_two_levels_with_condition) + ident(authors) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)operator({)symbol(:posts)operator(=)operator(>)symbol(:comments)operator(})operator(,) symbol(:conditions)operator(=)operator(>)string<delimiter(")content(authors.id=1)delimiter(")>operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(authors.id)delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) ident(authors)operator(.)ident(size) + ident(assert_equal) integer(5)operator(,) ident(authors)operator([)integer(0)operator(])operator(.)ident(posts)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_acts_as_tree) + ident(roots) operator(=) constant(TreeMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)string<delimiter(")content(children)delimiter(")>operator(,) symbol(:conditions)operator(=)operator(>)string<delimiter(")content(mixins.parent_id IS NULL)delimiter(")>operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(mixins.id)delimiter(")>operator(\)) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) ident(roots) + ident(assert_no_queries) reserved(do) + ident(assert_equal) integer(2)operator(,) ident(roots)operator([)integer(0)operator(])operator(.)ident(children)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(roots)operator([)integer(1)operator(])operator(.)ident(children)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(roots)operator([)integer(2)operator(])operator(.)ident(children)operator(.)ident(size) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_cascaded_three_levels_by_ping_pong) + ident(firms) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include)operator(=)operator(>)operator({)symbol(:account)operator(=)operator(>)operator({)symbol(:firm)operator(=)operator(>)symbol(:account)operator(})operator(})operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")content(companies.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(firms)operator(.)ident(size) + ident(assert_equal) ident(firms)operator(.)ident(first)operator(.)ident(account)operator(,) ident(firms)operator(.)ident(first)operator(.)ident(account)operator(.)ident(firm)operator(.)ident(account) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account)operator(,) ident(assert_no_queries) operator({) ident(firms)operator(.)ident(first)operator(.)ident(account)operator(.)ident(firm)operator(.)ident(account) operator(}) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account)operator(.)ident(firm)operator(.)ident(account)operator(,) ident(assert_no_queries) operator({) ident(firms)operator(.)ident(first)operator(.)ident(account)operator(.)ident(firm)operator(.)ident(account) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_has_many_sti) + ident(topics) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:replies)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(topics.id)delimiter(')>operator(\)) + ident(assert_equal) operator([)ident(topics)operator(()symbol(:first)operator(\))operator(,) ident(topics)operator(()symbol(:second)operator(\))operator(])operator(,) ident(topics) + ident(assert_no_queries) reserved(do) + ident(assert_equal) integer(1)operator(,) ident(topics)operator([)integer(0)operator(])operator(.)ident(replies)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(topics)operator([)integer(1)operator(])operator(.)ident(replies)operator(.)ident(size) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_sti) + ident(replies) operator(=) constant(Reply)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:topic)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(topics.id)delimiter(')>operator(\)) + ident(assert_equal) operator([)ident(topics)operator(()symbol(:second)operator(\))operator(])operator(,) ident(replies) + ident(assert_equal) ident(topics)operator(()symbol(:first)operator(\))operator(,) ident(assert_no_queries) operator({) ident(replies)operator(.)ident(first)operator(.)ident(topic) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_multiple_stis_and_order) + ident(author) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:include) operator(=)operator(>) operator({) symbol(:posts) operator(=)operator(>) operator([) symbol(:special_comments) operator(,) symbol(:very_special_comment) operator(]) operator(})operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(authors.name, comments.body, very_special_comments_posts.body)delimiter(')>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(posts.id = 4)delimiter(')>operator(\)) + ident(assert_equal) ident(authors)operator(()symbol(:david)operator(\))operator(,) ident(author) + ident(assert_no_queries) reserved(do) + ident(author)operator(.)ident(posts)operator(.)ident(first)operator(.)ident(special_comments) + ident(author)operator(.)ident(posts)operator(.)ident(first)operator(.)ident(very_special_comment) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_association_loading_of_stis_with_multiple_references) + ident(authors) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator({) symbol(:posts) operator(=)operator(>) operator({) symbol(:special_comments) operator(=)operator(>) operator({) symbol(:post) operator(=)operator(>) operator([) symbol(:special_comments)operator(,) symbol(:very_special_comment) operator(]) operator(}) operator(}) operator(})operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.body, very_special_comments_posts.body)delimiter(')>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(posts.id = 4)delimiter(')>operator(\)) + ident(assert_equal) operator([)ident(authors)operator(()symbol(:david)operator(\))operator(])operator(,) ident(authors) + ident(assert_no_queries) reserved(do) + ident(authors)operator(.)ident(first)operator(.)ident(posts)operator(.)ident(first)operator(.)ident(special_comments)operator(.)ident(first)operator(.)ident(post)operator(.)ident(special_comments) + ident(authors)operator(.)ident(first)operator(.)ident(posts)operator(.)ident(first)operator(.)ident(special_comments)operator(.)ident(first)operator(.)ident(post)operator(.)ident(very_special_comment) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> + +reserved(class) class(AssociationsExtensionsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:projects)operator(,) symbol(:developers)operator(,) symbol(:developers_projects)operator(,) symbol(:comments)operator(,) symbol(:posts) + + reserved(def) method(test_extension_on_has_many) + ident(assert_equal) ident(comments)operator(()symbol(:more_greetings)operator(\))operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(comments)operator(.)ident(find_most_recent) + reserved(end) + + reserved(def) method(test_extension_on_habtm) + ident(assert_equal) ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(projects)operator(.)ident(find_most_recent) + reserved(end) + + reserved(def) method(test_named_extension_on_habtm) + ident(assert_equal) ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(projects_extended_by_name)operator(.)ident(find_most_recent) + reserved(end) + + reserved(def) method(test_marshalling_extensions) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(assert_equal) ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) ident(david)operator(.)ident(projects)operator(.)ident(find_most_recent) + + ident(david) operator(=) constant(Marshal)operator(.)ident(load)operator(()constant(Marshal)operator(.)ident(dump)operator(()ident(david)operator(\))operator(\)) + ident(assert_equal) ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) ident(david)operator(.)ident(projects)operator(.)ident(find_most_recent) + reserved(end) + + reserved(def) method(test_marshalling_named_extensions) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(assert_equal) ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) ident(david)operator(.)ident(projects_extended_by_name)operator(.)ident(find_most_recent) + + ident(david) operator(=) constant(Marshal)operator(.)ident(load)operator(()constant(Marshal)operator(.)ident(dump)operator(()ident(david)operator(\))operator(\)) + ident(assert_equal) ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) ident(david)operator(.)ident(projects_extended_by_name)operator(.)ident(find_most_recent) + reserved(end) +ident(endrequire) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/author)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/person)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reader)delimiter(')> + +reserved(class) class(EagerAssociationTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:posts)operator(,) symbol(:comments)operator(,) symbol(:authors)operator(,) symbol(:categories)operator(,) symbol(:categories_posts)operator(,) + symbol(:companies)operator(,) symbol(:accounts)operator(,) symbol(:tags)operator(,) symbol(:people)operator(,) symbol(:readers) + + reserved(def) method(test_loading_with_one_association) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(\)) + ident(post) operator(=) ident(posts)operator(.)ident(find) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(==) integer(1) operator(}) + ident(assert_equal) integer(2)operator(,) ident(post)operator(.)ident(comments)operator(.)ident(size) + ident(assert) ident(post)operator(.)ident(comments)operator(.)ident(include?)operator(()ident(comments)operator(()symbol(:greetings)operator(\))operator(\)) + + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(posts.title = 'Welcome to the weblog')delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(post)operator(.)ident(comments)operator(.)ident(size) + ident(assert) ident(post)operator(.)ident(comments)operator(.)ident(include?)operator(()ident(comments)operator(()symbol(:greetings)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_loading_conditions_with_or) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'SpecialComment')delimiter(")>operator(\)) + ident(assert_nil) ident(posts)operator(.)ident(detect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(author_id) operator(!=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(id) operator(})operator(,) + string<delimiter(")content(expected to find only david's posts)delimiter(")> + reserved(end) + + reserved(def) method(test_with_ordering) + ident(list) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id DESC)delimiter(")>operator(\)) + operator([)symbol(:eager_other)operator(,) symbol(:sti_habtm)operator(,) symbol(:sti_post_and_comments)operator(,) symbol(:sti_comments)operator(,) + symbol(:authorless)operator(,) symbol(:thinking)operator(,) symbol(:welcome) + operator(])operator(.)ident(each_with_index) reserved(do) operator(|)ident(post)operator(,) ident(index)operator(|) + ident(assert_equal) ident(posts)operator(()ident(post)operator(\))operator(,) ident(list)operator([)ident(index)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(test_loading_with_multiple_associations) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:comments)operator(,) symbol(:author)operator(,) symbol(:categories) operator(])operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(first)operator(.)ident(comments)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(first)operator(.)ident(categories)operator(.)ident(size) + ident(assert) ident(posts)operator(.)ident(first)operator(.)ident(comments)operator(.)ident(include?)operator(()ident(comments)operator(()symbol(:greetings)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_loading_from_an_association) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(first)operator(.)ident(comments)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_loading_with_no_associations) + ident(assert_nil) constant(Post)operator(.)ident(find)operator(()ident(posts)operator(()symbol(:authorless)operator(\))operator(.)ident(id)operator(,) symbol(:include) operator(=)operator(>) symbol(:author)operator(\))operator(.)ident(author) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to) + ident(comments) operator(=) constant(Comment)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:post)operator(\)) + ident(assert_equal) integer(10)operator(,) ident(comments)operator(.)ident(length) + ident(titles) operator(=) ident(comments)operator(.)ident(map) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(post)operator(.)ident(title) operator(}) + ident(assert) ident(titles)operator(.)ident(include?)operator(()ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(title)operator(\)) + ident(assert) ident(titles)operator(.)ident(include?)operator(()ident(posts)operator(()symbol(:sti_post_and_comments)operator(\))operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit) + ident(comments) operator(=) constant(Comment)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:post)operator(,) symbol(:limit) operator(=)operator(>) integer(5)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + ident(assert_equal) integer(5)operator(,) ident(comments)operator(.)ident(length) + ident(assert_equal) operator([)integer(1)operator(,)integer(2)operator(,)integer(3)operator(,)integer(5)operator(,)integer(6)operator(])operator(,) ident(comments)operator(.)ident(collect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit_and_conditions) + ident(comments) operator(=) constant(Comment)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:post)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(post_id = 4)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + ident(assert_equal) integer(3)operator(,) ident(comments)operator(.)ident(length) + ident(assert_equal) operator([)integer(5)operator(,)integer(6)operator(,)integer(7)operator(])operator(,) ident(comments)operator(.)ident(collect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit_and_offset) + ident(comments) operator(=) constant(Comment)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:post)operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(2)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + ident(assert_equal) integer(3)operator(,) ident(comments)operator(.)ident(length) + ident(assert_equal) operator([)integer(3)operator(,)integer(5)operator(,)integer(6)operator(])operator(,) ident(comments)operator(.)ident(collect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions) + ident(comments) operator(=) constant(Comment)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:post)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(post_id = 4)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(1)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + ident(assert_equal) integer(3)operator(,) ident(comments)operator(.)ident(length) + ident(assert_equal) operator([)integer(6)operator(,)integer(7)operator(,)integer(8)operator(])operator(,) ident(comments)operator(.)ident(collect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array) + ident(comments) operator(=) constant(Comment)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:post)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(post_id = ?)delimiter(')>operator(,)integer(4)operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(1)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + ident(assert_equal) integer(3)operator(,) ident(comments)operator(.)ident(length) + ident(assert_equal) operator([)integer(6)operator(,)integer(7)operator(,)integer(8)operator(])operator(,) ident(comments)operator(.)ident(collect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([)symbol(:author)operator(,) symbol(:very_special_comment)operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(1)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(.)ident(length) + ident(assert_equal) operator([)integer(1)operator(])operator(,) ident(posts)operator(.)ident(collect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([)symbol(:author)operator(,) symbol(:very_special_comment)operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(1)operator(,) symbol(:offset) operator(=)operator(>) integer(1)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(.)ident(length) + ident(assert_equal) operator([)integer(2)operator(])operator(,) ident(posts)operator(.)ident(collect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_with_has_many_through) + ident(posts_with_comments) operator(=) ident(people)operator(()symbol(:michael)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments) operator(\)) + ident(posts_with_author) operator(=) ident(people)operator(()symbol(:michael)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:author) operator(\)) + ident(posts_with_comments_and_author) operator(=) ident(people)operator(()symbol(:michael)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:comments)operator(,) symbol(:author) operator(])operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts_with_comments)operator(.)ident(inject)operator(()integer(0)operator(\)) operator({) operator(|)ident(sum)operator(,) ident(post)operator(|) ident(sum) operator(+=) ident(post)operator(.)ident(comments)operator(.)ident(size) operator(}) + ident(assert_equal) ident(authors)operator(()symbol(:david)operator(\))operator(,) ident(assert_no_queries) operator({) ident(posts_with_author)operator(.)ident(first)operator(.)ident(author) operator(}) + ident(assert_equal) ident(authors)operator(()symbol(:david)operator(\))operator(,) ident(assert_no_queries) operator({) ident(posts_with_comments_and_author)operator(.)ident(first)operator(.)ident(author) operator(}) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id asc)delimiter(')>operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) integer(3)operator(,) ident(posts)operator(.)ident(inject)operator(()integer(0)operator(\)) operator({) operator(|)ident(sum)operator(,) ident(post)operator(|) ident(sum) operator(+=) ident(post)operator(.)ident(comments)operator(.)ident(size) operator(}) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_and_conditions) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(posts.body = 'hello')delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) operator([)integer(4)operator(,)integer(5)operator(])operator(,) ident(posts)operator(.)ident(collect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_and_conditions_array) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:conditions) operator(=)operator(>) operator([) string<delimiter(")content(posts.body = ?)delimiter(")>operator(,) string<delimiter(')content(hello)delimiter(')> operator(])operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) operator([)integer(4)operator(,)integer(5)operator(])operator(,) ident(posts)operator(.)ident(collect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:conditions) operator(=)operator(>) operator([) string<delimiter(")content(authors.name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')> operator(])operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + + ident(count) operator(=) constant(Post)operator(.)ident(count)operator(()symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:conditions) operator(=)operator(>) operator([) string<delimiter(")content(authors.name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')> operator(])operator(\)) + ident(assert_equal) ident(count)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_ond_high_offset) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:offset) operator(=)operator(>) integer(10)operator(,) symbol(:conditions) operator(=)operator(>) operator([) string<delimiter(")content(authors.name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')> operator(])operator(\)) + ident(assert_equal) integer(0)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_count_eager_with_has_many_and_limit_ond_high_offset) + ident(posts) operator(=) constant(Post)operator(.)ident(count)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:offset) operator(=)operator(>) integer(10)operator(,) symbol(:conditions) operator(=)operator(>) operator([) string<delimiter(")content(authors.name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')> operator(])operator(\)) + ident(assert_equal) integer(0)operator(,) ident(posts) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_with_no_results) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:author)operator(,) symbol(:comments) operator(])operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(posts.title = 'magic forest')delimiter(")>operator(\)) + ident(assert_equal) integer(0)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_eager_with_has_and_belongs_to_many_and_limit) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:categories)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(posts)operator([)integer(0)operator(])operator(.)ident(categories)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(posts)operator([)integer(1)operator(])operator(.)ident(categories)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(posts)operator([)integer(2)operator(])operator(.)ident(categories)operator(.)ident(size) + ident(assert) ident(posts)operator([)integer(0)operator(])operator(.)ident(categories)operator(.)ident(include?)operator(()ident(categories)operator(()symbol(:technology)operator(\))operator(\)) + ident(assert) ident(posts)operator([)integer(1)operator(])operator(.)ident(categories)operator(.)ident(include?)operator(()ident(categories)operator(()symbol(:general)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_and_conditions_on_the_eagers) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) + symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(= 'SpecialComment')delimiter(")>operator(,) + symbol(:limit) operator(=)operator(>) integer(2) + operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + + ident(count) operator(=) constant(Post)operator(.)ident(count)operator(() + symbol(:include) operator(=)operator(>) operator([) symbol(:comments)operator(,) symbol(:author) operator(])operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(authors.name = 'David' AND (comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(= 'SpecialComment'\))delimiter(")>operator(,) + symbol(:limit) operator(=)operator(>) integer(2) + operator(\)) + ident(assert_equal) ident(count)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers) + ident(posts) operator(=) pre_constant(nil) + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) + symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(= 'SpecialComment')delimiter(")> + operator(})operator(\)) reserved(do) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) + symbol(:include) operator(=)operator(>) operator([) symbol(:comments)operator(,) symbol(:author) operator(])operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(authors.name = 'David' AND (comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(= 'SpecialComment'\))delimiter(")> + operator(})operator(\)) reserved(do) + ident(count) operator(=) constant(Post)operator(.)ident(count)operator(()symbol(:limit) operator(=)operator(>) integer(2)operator(\)) + ident(assert_equal) ident(count)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the_eagers) + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(1=1)delimiter(")> operator(})operator(\)) reserved(do) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts)operator(.)ident(find)operator(()symbol(:all)operator(,) + symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(= 'SpecialComment')delimiter(")>operator(,) + symbol(:limit) operator(=)operator(>) integer(2) + operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator(.)ident(size) + + ident(count) operator(=) constant(Post)operator(.)ident(count)operator(() + symbol(:include) operator(=)operator(>) operator([) symbol(:comments)operator(,) symbol(:author) operator(])operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(authors.name = 'David' AND (comments.body like 'Normal%' OR comments.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(= 'SpecialComment'\))delimiter(")>operator(,) + symbol(:limit) operator(=)operator(>) integer(2) + operator(\)) + ident(assert_equal) ident(count)operator(,) ident(posts)operator(.)ident(size) + reserved(end) + reserved(end) + reserved(def) method(test_eager_association_loading_with_habtm) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:categories)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(posts)operator([)integer(0)operator(])operator(.)ident(categories)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(posts)operator([)integer(1)operator(])operator(.)ident(categories)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(posts)operator([)integer(2)operator(])operator(.)ident(categories)operator(.)ident(size) + ident(assert) ident(posts)operator([)integer(0)operator(])operator(.)ident(categories)operator(.)ident(include?)operator(()ident(categories)operator(()symbol(:technology)operator(\))operator(\)) + ident(assert) ident(posts)operator([)integer(1)operator(])operator(.)ident(categories)operator(.)ident(include?)operator(()ident(categories)operator(()symbol(:general)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_eager_with_inheritance) + ident(posts) operator(=) constant(SpecialPost)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:comments) operator(])operator(\)) + reserved(end) + + reserved(def) method(test_eager_has_one_with_association_inheritance) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(4)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:very_special_comment) operator(])operator(\)) + ident(assert_equal) string<delimiter(")content(VerySpecialComment)delimiter(")>operator(,) ident(post)operator(.)ident(very_special_comment)operator(.)ident(class)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_eager_has_many_with_association_inheritance) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(4)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:special_comments) operator(])operator(\)) + ident(post)operator(.)ident(special_comments)operator(.)ident(each) reserved(do) operator(|)ident(special_comment)operator(|) + ident(assert_equal) string<delimiter(")content(SpecialComment)delimiter(")>operator(,) ident(special_comment)operator(.)ident(class)operator(.)ident(to_s) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_habtm_with_association_inheritance) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(6)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:special_categories) operator(])operator(\)) + ident(assert_equal) integer(1)operator(,) ident(post)operator(.)ident(special_categories)operator(.)ident(size) + ident(post)operator(.)ident(special_categories)operator(.)ident(each) reserved(do) operator(|)ident(special_category)operator(|) + ident(assert_equal) string<delimiter(")content(SpecialCategory)delimiter(")>operator(,) ident(special_category)operator(.)ident(class)operator(.)ident(to_s) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_with_has_one_dependent_does_not_destroy_dependent) + ident(assert_not_nil) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) + ident(f) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:include) operator(=)operator(>) symbol(:account)operator(,) + symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(companies.name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals)delimiter(")>operator(])operator(\)) + ident(assert_not_nil) ident(f)operator(.)ident(account) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(,) symbol(:reload)operator(\))operator(.)ident(account)operator(,) ident(f)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_eager_with_invalid_association_reference) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(ConfigurationError)operator(,) string<delimiter(")content(Association was not found; perhaps you misspelled it? You specified :include => :monkeys)delimiter(")>operator(\)) operator({) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(6)operator(,) symbol(:include)operator(=)operator(>) symbol(:monkeys) operator(\)) + operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(ConfigurationError)operator(,) string<delimiter(")content(Association was not found; perhaps you misspelled it? You specified :include => :monkeys)delimiter(")>operator(\)) operator({) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(6)operator(,) symbol(:include)operator(=)operator(>)operator([) symbol(:monkeys) operator(])operator(\)) + operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(ConfigurationError)operator(,) string<delimiter(")content(Association was not found; perhaps you misspelled it? You specified :include => :monkeys)delimiter(")>operator(\)) operator({) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(6)operator(,) symbol(:include)operator(=)operator(>)operator([) string<delimiter(')content(monkeys)delimiter(')> operator(])operator(\)) + operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(ConfigurationError)operator(,) string<delimiter(")content(Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants)delimiter(")>operator(\)) operator({) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(6)operator(,) symbol(:include)operator(=)operator(>)operator([) symbol(:monkeys)operator(,) symbol(:elephants) operator(])operator(\)) + operator(}) + reserved(end) + + reserved(def) method(find_all_ordered)operator(()ident(className)operator(,) ident(include)operator(=)pre_constant(nil)operator(\)) + ident(className)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order)operator(=)operator(>)string<delimiter(")inline<inline_delimiter(#{)ident(className)operator(.)ident(table_name)inline_delimiter(})>content(.)inline<inline_delimiter(#{)ident(className)operator(.)ident(primary_key)inline_delimiter(})>delimiter(")>operator(,) symbol(:include)operator(=)operator(>)ident(include)operator(\)) + reserved(end) + + reserved(def) method(test_eager_with_multiple_associations_with_same_table_has_many_and_habtm) + comment(# Eager includes of has many and habtm associations aren't necessarily sorted in the same way) + reserved(def) method(assert_equal_after_sort)operator(()ident(item1)operator(,) ident(item2)operator(,) ident(item3) operator(=) pre_constant(nil)operator(\)) + ident(assert_equal)operator(()ident(item1)operator(.)ident(sort)operator({)operator(|)ident(a)operator(,)ident(b)operator(|) ident(a)operator(.)ident(id) operator(<=>) ident(b)operator(.)ident(id)operator(})operator(,) ident(item2)operator(.)ident(sort)operator({)operator(|)ident(a)operator(,)ident(b)operator(|) ident(a)operator(.)ident(id) operator(<=>) ident(b)operator(.)ident(id)operator(})operator(\)) + ident(assert_equal)operator(()ident(item3)operator(.)ident(sort)operator({)operator(|)ident(a)operator(,)ident(b)operator(|) ident(a)operator(.)ident(id) operator(<=>) ident(b)operator(.)ident(id)operator(})operator(,) ident(item2)operator(.)ident(sort)operator({)operator(|)ident(a)operator(,)ident(b)operator(|) ident(a)operator(.)ident(id) operator(<=>) ident(b)operator(.)ident(id)operator(})operator(\)) reserved(if) ident(item3) + reserved(end) + comment(# Test regular association, association with conditions, association with) + comment(# STI, and association with conditions assured not to be true) + ident(post_types) operator(=) operator([)symbol(:posts)operator(,) symbol(:hello_posts)operator(,) symbol(:special_posts)operator(,) symbol(:nonexistent_posts)operator(]) + comment(# test both has_many and has_and_belongs_to_many) + operator([)constant(Author)operator(,) constant(Category)operator(])operator(.)ident(each) reserved(do) operator(|)ident(className)operator(|) + ident(d1) operator(=) ident(find_all_ordered)operator(()ident(className)operator(\)) + comment(# test including all post types at once) + ident(d2) operator(=) ident(find_all_ordered)operator(()ident(className)operator(,) ident(post_types)operator(\)) + ident(d1)operator(.)ident(each_index) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal)operator(()ident(d1)operator([)ident(i)operator(])operator(,) ident(d2)operator([)ident(i)operator(])operator(\)) + ident(assert_equal_after_sort)operator(()ident(d1)operator([)ident(i)operator(])operator(.)ident(posts)operator(,) ident(d2)operator([)ident(i)operator(])operator(.)ident(posts)operator(\)) + ident(post_types)operator([)integer(1)operator(..)integer(-1)operator(])operator(.)ident(each) reserved(do) operator(|)ident(post_type)operator(|) + comment(# test including post_types together) + ident(d3) operator(=) ident(find_all_ordered)operator(()ident(className)operator(,) operator([)symbol(:posts)operator(,) ident(post_type)operator(])operator(\)) + ident(assert_equal)operator(()ident(d1)operator([)ident(i)operator(])operator(,) ident(d3)operator([)ident(i)operator(])operator(\)) + ident(assert_equal_after_sort)operator(()ident(d1)operator([)ident(i)operator(])operator(.)ident(posts)operator(,) ident(d3)operator([)ident(i)operator(])operator(.)ident(posts)operator(\)) + ident(assert_equal_after_sort)operator(()ident(d1)operator([)ident(i)operator(])operator(.)ident(send)operator(()ident(post_type)operator(\))operator(,) ident(d2)operator([)ident(i)operator(])operator(.)ident(send)operator(()ident(post_type)operator(\))operator(,) ident(d3)operator([)ident(i)operator(])operator(.)ident(send)operator(()ident(post_type)operator(\))operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_with_multiple_associations_with_same_table_has_one) + ident(d1) operator(=) ident(find_all_ordered)operator(()constant(Firm)operator(\)) + ident(d2) operator(=) ident(find_all_ordered)operator(()constant(Firm)operator(,) symbol(:account)operator(\)) + ident(d1)operator(.)ident(each_index) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal)operator(()ident(d1)operator([)ident(i)operator(])operator(,) ident(d2)operator([)ident(i)operator(])operator(\)) + ident(assert_equal)operator(()ident(d1)operator([)ident(i)operator(])operator(.)ident(account)operator(,) ident(d2)operator([)ident(i)operator(])operator(.)ident(account)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_with_multiple_associations_with_same_table_belongs_to) + ident(firm_types) operator(=) operator([)symbol(:firm)operator(,) symbol(:firm_with_basic_id)operator(,) symbol(:firm_with_other_name)operator(,) symbol(:firm_with_condition)operator(]) + ident(d1) operator(=) ident(find_all_ordered)operator(()constant(Client)operator(\)) + ident(d2) operator(=) ident(find_all_ordered)operator(()constant(Client)operator(,) ident(firm_types)operator(\)) + ident(d1)operator(.)ident(each_index) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal)operator(()ident(d1)operator([)ident(i)operator(])operator(,) ident(d2)operator([)ident(i)operator(])operator(\)) + ident(firm_types)operator(.)ident(each) operator({) operator(|)ident(type)operator(|) ident(assert_equal)operator(()ident(d1)operator([)ident(i)operator(])operator(.)ident(send)operator(()ident(type)operator(\))operator(,) ident(d2)operator([)ident(i)operator(])operator(.)ident(send)operator(()ident(type)operator(\))operator(\)) operator(}) + reserved(end) + reserved(end) + reserved(def) method(test_eager_with_valid_association_as_string_not_symbol) + ident(assert_nothing_raised) operator({) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) string<delimiter(')content(comments)delimiter(')>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_preconfigured_includes_with_belongs_to) + ident(author) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(author_with_posts) + ident(assert_equal) integer(5)operator(,) ident(author)operator(.)ident(posts)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_preconfigured_includes_with_has_one) + ident(comment) operator(=) ident(posts)operator(()symbol(:sti_comments)operator(\))operator(.)ident(very_special_comment_with_post) + ident(assert_equal) ident(posts)operator(()symbol(:sti_comments)operator(\))operator(,) ident(comment)operator(.)ident(post) + reserved(end) + + reserved(def) method(test_preconfigured_includes_with_has_many) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts_with_comments) + ident(one) operator(=) ident(posts)operator(.)ident(detect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(==) integer(1) operator(}) + ident(assert_equal) integer(5)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(one)operator(.)ident(comments)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_preconfigured_includes_with_habtm) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts_with_categories) + ident(one) operator(=) ident(posts)operator(.)ident(detect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(==) integer(1) operator(}) + ident(assert_equal) integer(5)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(one)operator(.)ident(categories)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_preconfigured_includes_with_has_many_and_habtm) + ident(posts) operator(=) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(posts_with_comments_and_categories) + ident(one) operator(=) ident(posts)operator(.)ident(detect) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(id) operator(==) integer(1) operator(}) + ident(assert_equal) integer(5)operator(,) ident(posts)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(one)operator(.)ident(comments)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(one)operator(.)ident(categories)operator(.)ident(size) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/tag)delimiter(')> +ident(require) string<delimiter(')content(fixtures/tagging)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/author)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> +ident(require) string<delimiter(')content(fixtures/categorization)delimiter(')> + +reserved(class) class(AssociationsJoinModelTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + ident(fixtures) symbol(:posts)operator(,) symbol(:authors)operator(,) symbol(:categories)operator(,) symbol(:categorizations)operator(,) symbol(:comments)operator(,) symbol(:tags)operator(,) symbol(:taggings)operator(,) symbol(:author_favorites) + + reserved(def) method(test_has_many) + ident(assert_equal) ident(categories)operator(()symbol(:general)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(categories)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_has_many_inherited) + ident(assert_equal) ident(categories)operator(()symbol(:sti_test)operator(\))operator(,) ident(authors)operator(()symbol(:mary)operator(\))operator(.)ident(categories)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_inherited_has_many) + ident(assert_equal) ident(authors)operator(()symbol(:mary)operator(\))operator(,) ident(categories)operator(()symbol(:sti_test)operator(\))operator(.)ident(authors)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_polymorphic_has_many) + ident(assert_equal) ident(taggings)operator(()symbol(:welcome_general)operator(\))operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_polymorphic_has_one) + ident(assert_equal) ident(taggings)operator(()symbol(:welcome_general)operator(\))operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging) + reserved(end) + + reserved(def) method(test_polymorphic_belongs_to) + ident(assert_equal) ident(posts)operator(()symbol(:welcome)operator(\))operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(first)operator(.)ident(taggable) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(tag) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tags)operator(.)ident(first) + ident(assert_no_queries) reserved(do) + ident(tag)operator(.)ident(tagging) + reserved(end) + reserved(end) + + reserved(def) method(test_count_polymorphic_has_many) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tags)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_find) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(tag) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tags)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(assert_no_queries) reserved(do) + ident(tag)operator(.)ident(tagging) + reserved(end) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(tag) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(funky_tags)operator(.)ident(first) + ident(assert_no_queries) reserved(do) + ident(tag)operator(.)ident(tagging) + reserved(end) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(tag) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(funky_tags)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(assert_no_queries) reserved(do) + ident(tag)operator(.)ident(tagging) + reserved(end) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_disabled_include) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(tag) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tags)operator(.)ident(add_joins_and_select)operator(.)ident(first) + ident(assert_queries) integer(1) reserved(do) + ident(tag)operator(.)ident(tagging) + reserved(end) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(tag) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tags)operator(.)ident(add_joins_and_select)operator(.)ident(first) + ident(tag)operator(.)ident(author_id) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key) + ident(assert_equal) ident(tags)operator(()symbol(:misc)operator(\))operator(,) ident(taggings)operator(()symbol(:welcome_general)operator(\))operator(.)ident(super_tag) + ident(assert_equal) ident(tags)operator(()symbol(:misc)operator(\))operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(super_tags)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class) + ident(post) operator(=) constant(SubStiPost)operator(.)ident(create) symbol(:title) operator(=)operator(>) string<delimiter(')content(SubStiPost)delimiter(')>operator(,) symbol(:body) operator(=)operator(>) string<delimiter(')content(SubStiPost body)delimiter(')> + ident(assert_instance_of) constant(SubStiPost)operator(,) ident(post) + + ident(tagging) operator(=) ident(tags)operator(()symbol(:misc)operator(\))operator(.)ident(taggings)operator(.)ident(create)operator(()symbol(:taggable) operator(=)operator(>) ident(post)operator(\)) + ident(assert_equal) string<delimiter(")content(SubStiPost)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_inheritance) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(posts)operator(()symbol(:thinking)operator(\))operator(.)ident(tags)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name) + ident(assert_equal) ident(tags)operator(()symbol(:general)operator(\))operator(,) ident(posts)operator(()symbol(:thinking)operator(\))operator(.)ident(funky_tags)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_polymorphic_has_many_create_model_with_inheritance) + ident(post) operator(=) ident(posts)operator(()symbol(:thinking)operator(\)) + ident(assert_instance_of) constant(SpecialPost)operator(,) ident(post) + + ident(tagging) operator(=) ident(tags)operator(()symbol(:misc)operator(\))operator(.)ident(taggings)operator(.)ident(create)operator(()symbol(:taggable) operator(=)operator(>) ident(post)operator(\)) + ident(assert_equal) string<delimiter(")content(Post)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + reserved(end) + + reserved(def) method(test_polymorphic_has_one_create_model_with_inheritance) + ident(tagging) operator(=) ident(tags)operator(()symbol(:misc)operator(\))operator(.)ident(create_tagging)operator(()symbol(:taggable) operator(=)operator(>) ident(posts)operator(()symbol(:thinking)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(Post)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + reserved(end) + + reserved(def) method(test_set_polymorphic_has_many) + ident(tagging) operator(=) ident(tags)operator(()symbol(:misc)operator(\))operator(.)ident(taggings)operator(.)ident(create) + ident(posts)operator(()symbol(:thinking)operator(\))operator(.)ident(taggings) operator(<<) ident(tagging) + ident(assert_equal) string<delimiter(")content(Post)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + reserved(end) + + reserved(def) method(test_set_polymorphic_has_one) + ident(tagging) operator(=) ident(tags)operator(()symbol(:misc)operator(\))operator(.)ident(taggings)operator(.)ident(create) + ident(posts)operator(()symbol(:thinking)operator(\))operator(.)ident(tagging) operator(=) ident(tagging) + ident(assert_equal) string<delimiter(")content(Post)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + reserved(end) + + reserved(def) method(test_create_polymorphic_has_many_with_scope) + ident(old_count) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + ident(tagging) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(create)operator(()symbol(:tag) operator(=)operator(>) ident(tags)operator(()symbol(:misc)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(Post)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + ident(assert_equal) ident(old_count)operator(+)integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_create_polymorphic_has_one_with_scope) + ident(old_count) operator(=) constant(Tagging)operator(.)ident(count) + ident(tagging) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging)operator(.)ident(create)operator(()symbol(:tag) operator(=)operator(>) ident(tags)operator(()symbol(:misc)operator(\))operator(\)) + ident(assert_equal) string<delimiter(")content(Post)delimiter(")>operator(,) ident(tagging)operator(.)ident(taggable_type) + ident(assert_equal) ident(old_count)operator(+)integer(1)operator(,) constant(Tagging)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_delete_polymorphic_has_many_with_delete_all) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(first)operator(.)ident(update_attribute) symbol(:taggable_type)operator(,) string<delimiter(')content(PostWithHasManyDeleteAll)delimiter(')> + ident(post) operator(=) ident(find_post_with_dependency)operator(()integer(1)operator(,) symbol(:has_many)operator(,) symbol(:taggings)operator(,) symbol(:delete_all)operator(\)) + + ident(old_count) operator(=) constant(Tagging)operator(.)ident(count) + ident(post)operator(.)ident(destroy) + ident(assert_equal) ident(old_count)operator(-)integer(1)operator(,) constant(Tagging)operator(.)ident(count) + ident(assert_equal) integer(0)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_delete_polymorphic_has_many_with_destroy) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(first)operator(.)ident(update_attribute) symbol(:taggable_type)operator(,) string<delimiter(')content(PostWithHasManyDestroy)delimiter(')> + ident(post) operator(=) ident(find_post_with_dependency)operator(()integer(1)operator(,) symbol(:has_many)operator(,) symbol(:taggings)operator(,) symbol(:destroy)operator(\)) + + ident(old_count) operator(=) constant(Tagging)operator(.)ident(count) + ident(post)operator(.)ident(destroy) + ident(assert_equal) ident(old_count)operator(-)integer(1)operator(,) constant(Tagging)operator(.)ident(count) + ident(assert_equal) integer(0)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_delete_polymorphic_has_many_with_nullify) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(first)operator(.)ident(update_attribute) symbol(:taggable_type)operator(,) string<delimiter(')content(PostWithHasManyNullify)delimiter(')> + ident(post) operator(=) ident(find_post_with_dependency)operator(()integer(1)operator(,) symbol(:has_many)operator(,) symbol(:taggings)operator(,) symbol(:nullify)operator(\)) + + ident(old_count) operator(=) constant(Tagging)operator(.)ident(count) + ident(post)operator(.)ident(destroy) + ident(assert_equal) ident(old_count)operator(,) constant(Tagging)operator(.)ident(count) + ident(assert_equal) integer(0)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_delete_polymorphic_has_one_with_destroy) + ident(assert) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging) + ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging)operator(.)ident(update_attribute) symbol(:taggable_type)operator(,) string<delimiter(')content(PostWithHasOneDestroy)delimiter(')> + ident(post) operator(=) ident(find_post_with_dependency)operator(()integer(1)operator(,) symbol(:has_one)operator(,) symbol(:tagging)operator(,) symbol(:destroy)operator(\)) + + ident(old_count) operator(=) constant(Tagging)operator(.)ident(count) + ident(post)operator(.)ident(destroy) + ident(assert_equal) ident(old_count)operator(-)integer(1)operator(,) constant(Tagging)operator(.)ident(count) + ident(assert_nil) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_delete_polymorphic_has_one_with_nullify) + ident(assert) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging) + ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging)operator(.)ident(update_attribute) symbol(:taggable_type)operator(,) string<delimiter(')content(PostWithHasOneNullify)delimiter(')> + ident(post) operator(=) ident(find_post_with_dependency)operator(()integer(1)operator(,) symbol(:has_one)operator(,) symbol(:tagging)operator(,) symbol(:nullify)operator(\)) + + ident(old_count) operator(=) constant(Tagging)operator(.)ident(count) + ident(post)operator(.)ident(destroy) + ident(assert_equal) ident(old_count)operator(,) constant(Tagging)operator(.)ident(count) + ident(assert_nil) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(tagging)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_has_many_with_piggyback) + ident(assert_equal) string<delimiter(")content(2)delimiter(")>operator(,) ident(categories)operator(()symbol(:sti_test)operator(\))operator(.)ident(authors)operator(.)ident(first)operator(.)ident(post_id)operator(.)ident(to_s) + reserved(end) + + reserved(def) method(test_include_has_many_through) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(posts_with_authors) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:authors)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(assert_equal) ident(posts)operator(.)ident(length)operator(,) ident(posts_with_authors)operator(.)ident(length) + ident(posts)operator(.)ident(length)operator(.)ident(times) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal) ident(posts)operator([)ident(i)operator(])operator(.)ident(authors)operator(.)ident(length)operator(,) ident(assert_no_queries) operator({) ident(posts_with_authors)operator([)ident(i)operator(])operator(.)ident(authors)operator(.)ident(length) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_include_polymorphic_has_one) + ident(post) operator(=) constant(Post)operator(.)ident(find_by_id)operator(()ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(id)operator(,) symbol(:include) operator(=)operator(>) symbol(:tagging)operator(\)) + ident(tagging) operator(=) ident(taggings)operator(()symbol(:welcome_general)operator(\)) + ident(assert_no_queries) reserved(do) + ident(assert_equal) ident(tagging)operator(,) ident(post)operator(.)ident(tagging) + reserved(end) + reserved(end) + + reserved(def) method(test_include_polymorphic_has_many_through) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(posts_with_tags) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:tags)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(assert_equal) ident(posts)operator(.)ident(length)operator(,) ident(posts_with_tags)operator(.)ident(length) + ident(posts)operator(.)ident(length)operator(.)ident(times) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal) ident(posts)operator([)ident(i)operator(])operator(.)ident(tags)operator(.)ident(length)operator(,) ident(assert_no_queries) operator({) ident(posts_with_tags)operator([)ident(i)operator(])operator(.)ident(tags)operator(.)ident(length) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_include_polymorphic_has_many) + ident(posts) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(posts_with_taggings) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:taggings)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(posts.id)delimiter(')>operator(\)) + ident(assert_equal) ident(posts)operator(.)ident(length)operator(,) ident(posts_with_taggings)operator(.)ident(length) + ident(posts)operator(.)ident(length)operator(.)ident(times) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal) ident(posts)operator([)ident(i)operator(])operator(.)ident(taggings)operator(.)ident(length)operator(,) ident(assert_no_queries) operator({) ident(posts_with_taggings)operator([)ident(i)operator(])operator(.)ident(taggings)operator(.)ident(length) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_has_many_find_all) + ident(assert_equal) operator([)ident(categories)operator(()symbol(:general)operator(\))operator(])operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(categories)operator(.)ident(find)operator(()symbol(:all)operator(\)) + reserved(end) + + reserved(def) method(test_has_many_find_first) + ident(assert_equal) ident(categories)operator(()symbol(:general)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(categories)operator(.)ident(find)operator(()symbol(:first)operator(\)) + reserved(end) + + reserved(def) method(test_has_many_find_conditions) + ident(assert_equal) ident(categories)operator(()symbol(:general)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(categories)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(categories.name = 'General')delimiter(")>operator(\)) + ident(assert_equal) pre_constant(nil)operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(categories)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(categories.name = 'Technology')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_has_many_class_methods_called_by_method_missing) + ident(assert_equal) ident(categories)operator(()symbol(:general)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(categories)operator(.)ident(find_all_by_name)operator(()string<delimiter(')content(General)delimiter(')>operator(\))operator(.)ident(first) +comment(# assert_equal nil, authors(:david\).categories.find_by_name('Technology'\)) + reserved(end) + + reserved(def) method(test_has_many_going_through_join_model_with_custom_foreign_key) + ident(assert_equal) operator([)operator(])operator(,) ident(posts)operator(()symbol(:thinking)operator(\))operator(.)ident(authors) + ident(assert_equal) operator([)ident(authors)operator(()symbol(:mary)operator(\))operator(])operator(,) ident(posts)operator(()symbol(:authorless)operator(\))operator(.)ident(authors) + reserved(end) + + reserved(def) method(test_belongs_to_polymorphic_with_counter_cache) + ident(assert_equal) integer(0)operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator([)symbol(:taggings_count)operator(]) + ident(tagging) operator(=) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(taggings)operator(.)ident(create)operator(()symbol(:tag) operator(=)operator(>) ident(tags)operator(()symbol(:general)operator(\))operator(\)) + ident(assert_equal) integer(1)operator(,) ident(posts)operator(()symbol(:welcome)operator(,) symbol(:reload)operator(\))operator([)symbol(:taggings_count)operator(]) + ident(tagging)operator(.)ident(destroy) + ident(assert) ident(posts)operator(()symbol(:welcome)operator(,) symbol(:reload)operator(\))operator([)symbol(:taggings_count)operator(])operator(.)ident(zero?) + reserved(end) + + reserved(def) method(test_unavailable_through_reflection) + ident(assert_raises) operator(()constant(ActiveRecord)operator(::)constant(HasManyThroughAssociationNotFoundError)operator(\)) operator({) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(nothings) operator(}) + reserved(end) + + reserved(def) method(test_has_many_through_join_model_with_conditions) + ident(assert_equal) operator([)operator(])operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(invalid_taggings) + ident(assert_equal) operator([)operator(])operator(,) ident(posts)operator(()symbol(:welcome)operator(\))operator(.)ident(invalid_tags) + reserved(end) + + reserved(def) method(test_has_many_polymorphic) + ident(assert_raises) constant(ActiveRecord)operator(::)constant(HasManyThroughAssociationPolymorphicError) reserved(do) + ident(assert_equal) operator([)ident(posts)operator(()symbol(:welcome)operator(\))operator(,) ident(posts)operator(()symbol(:thinking)operator(\))operator(])operator(,) ident(tags)operator(()symbol(:general)operator(\))operator(.)ident(taggables) + reserved(end) + ident(assert_raises) constant(ActiveRecord)operator(::)constant(EagerLoadPolymorphicError) reserved(do) + ident(assert_equal) operator([)ident(posts)operator(()symbol(:welcome)operator(\))operator(,) ident(posts)operator(()symbol(:thinking)operator(\))operator(])operator(,) ident(tags)operator(()symbol(:general)operator(\))operator(.)ident(taggings)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) symbol(:taggable)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_has_many_through_has_many_find_all) + ident(assert_equal) ident(comments)operator(()symbol(:greetings)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(comments)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(test_has_many_through_has_many_find_all_with_custom_class) + ident(assert_equal) ident(comments)operator(()symbol(:greetings)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(funky_comments)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(test_has_many_through_has_many_find_first) + ident(assert_equal) ident(comments)operator(()symbol(:greetings)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(comments)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_has_many_through_has_many_find_conditions) + ident(assert_equal) ident(comments)operator(()symbol(:does_it_hurt)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(comments)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(comments.type='SpecialComment')delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_has_many_through_has_many_find_by_id) + ident(assert_equal) ident(comments)operator(()symbol(:more_greetings)operator(\))operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(comments)operator(.)ident(find)operator(()integer(2)operator(\)) + reserved(end) + + reserved(def) method(test_has_many_through_polymorphic_has_one) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(HasManyThroughSourceAssociationMacroError)operator(\)) operator({) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(tagging) operator(}) + reserved(end) + + reserved(def) method(test_has_many_through_polymorphic_has_many) + ident(assert_equal) operator([)ident(taggings)operator(()symbol(:welcome_general)operator(\))operator(,) ident(taggings)operator(()symbol(:thinking_general)operator(\))operator(])operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(taggings)operator(.)ident(uniq)operator(.)ident(sort_by) operator({) operator(|)ident(t)operator(|) ident(t)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_include_has_many_through_polymorphic_has_many) + ident(author) operator(=) constant(Author)operator(.)ident(find_by_id)operator(()ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(,) symbol(:include) operator(=)operator(>) symbol(:taggings)operator(\)) + ident(expected_taggings) operator(=) operator([)ident(taggings)operator(()symbol(:welcome_general)operator(\))operator(,) ident(taggings)operator(()symbol(:thinking_general)operator(\))operator(]) + ident(assert_no_queries) reserved(do) + ident(assert_equal) ident(expected_taggings)operator(,) ident(author)operator(.)ident(taggings)operator(.)ident(uniq)operator(.)ident(sort_by) operator({) operator(|)ident(t)operator(|) ident(t)operator(.)ident(id) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_has_many_through_has_many_through) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(HasManyThroughSourceAssociationMacroError)operator(\)) operator({) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(tags) operator(}) + reserved(end) + + reserved(def) method(test_has_many_through_habtm) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(HasManyThroughSourceAssociationMacroError)operator(\)) operator({) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(post_categories) operator(}) + reserved(end) + + reserved(def) method(test_eager_load_has_many_through_has_many) + ident(author) operator(=) constant(Author)operator(.)ident(find) symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(name = ?)delimiter(')>operator(,) string<delimiter(')content(David)delimiter(')>operator(])operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(comments.id)delimiter(')> + constant(SpecialComment)operator(.)ident(new)operator(;) constant(VerySpecialComment)operator(.)ident(new) + ident(assert_no_queries) reserved(do) + ident(assert_equal) operator([)integer(1)operator(,)integer(2)operator(,)integer(3)operator(,)integer(5)operator(,)integer(6)operator(,)integer(7)operator(,)integer(8)operator(,)integer(9)operator(,)integer(10)operator(])operator(,) ident(author)operator(.)ident(comments)operator(.)ident(collect)operator(()operator(&)symbol(:id)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_eager_belongs_to_and_has_one_not_singularized) + ident(assert_nothing_raised) reserved(do) + constant(Author)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:include) operator(=)operator(>) symbol(:author_address)operator(\)) + constant(AuthorAddress)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:include) operator(=)operator(>) symbol(:author)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_self_referential_has_many_through) + ident(assert_equal) operator([)ident(authors)operator(()symbol(:mary)operator(\))operator(])operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(favorite_authors) + ident(assert_equal) operator([)operator(])operator(,) ident(authors)operator(()symbol(:mary)operator(\))operator(.)ident(favorite_authors) + reserved(end) + + reserved(def) method(test_add_to_self_referential_has_many_through) + ident(new_author) operator(=) constant(Author)operator(.)ident(create)operator(()symbol(:name) operator(=)operator(>) string<delimiter(")content(Bob)delimiter(")>operator(\)) + ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(author_favorites)operator(.)ident(create) symbol(:favorite_author) operator(=)operator(>) ident(new_author) + ident(assert_equal) ident(new_author)operator(,) ident(authors)operator(()symbol(:david)operator(\))operator(.)ident(reload)operator(.)ident(favorite_authors)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_has_many_through_uses_correct_attributes) + ident(assert_nil) ident(posts)operator(()symbol(:thinking)operator(\))operator(.)ident(tags)operator(.)ident(find_by_name)operator(()string<delimiter(")content(General)delimiter(")>operator(\))operator(.)ident(attributes)operator([)string<delimiter(")content(tag_id)delimiter(")>operator(]) + reserved(end) + + ident(private) + comment(# create dynamic Post models to allow different dependency options) + reserved(def) method(find_post_with_dependency)operator(()ident(post_id)operator(,) ident(association)operator(,) ident(association_name)operator(,) ident(dependency)operator(\)) + ident(class_name) operator(=) string<delimiter(")content(PostWith)inline<inline_delimiter(#{)ident(association)operator(.)ident(to_s)operator(.)ident(classify)inline_delimiter(})>inline<inline_delimiter(#{)ident(dependency)operator(.)ident(to_s)operator(.)ident(classify)inline_delimiter(})>delimiter(")> + constant(Post)operator(.)ident(find)operator(()ident(post_id)operator(\))operator(.)ident(update_attribute) symbol(:type)operator(,) ident(class_name) + ident(klass) operator(=) constant(Object)operator(.)ident(const_set)operator(()ident(class_name)operator(,) constant(Class)operator(.)ident(new)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(\))operator(\)) + ident(klass)operator(.)ident(set_table_name) string<delimiter(')content(posts)delimiter(')> + ident(klass)operator(.)ident(send)operator(()ident(association)operator(,) ident(association_name)operator(,) symbol(:as) operator(=)operator(>) symbol(:taggable)operator(,) symbol(:dependent) operator(=)operator(>) ident(dependency)operator(\)) + ident(klass)operator(.)ident(find)operator(()ident(post_id)operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> +ident(require) string<delimiter(')content(fixtures/computer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/customer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/order)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/author)delimiter(')> + +comment(# Can't declare new classes in test case methods, so tests before that) +ident(bad_collection_keys) operator(=) pre_constant(false) +reserved(begin) + reserved(class) class(Car) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) ident(has_many) symbol(:wheels)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(wheels)delimiter(")>operator(;) reserved(end) +reserved(rescue) constant(ArgumentError) + ident(bad_collection_keys) operator(=) pre_constant(true) +reserved(end) +ident(raise) string<delimiter(")content(ActiveRecord should have barked on bad collection keys)delimiter(")> reserved(unless) ident(bad_collection_keys) + + +reserved(class) class(AssociationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:developers_projects)operator(,) + symbol(:computers) + + reserved(def) method(test_force_reload) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(A New Firm, Inc)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + ident(firm)operator(.)ident(clients)operator(.)ident(each) operator({)operator(|)ident(c)operator(|)operator(}) comment(# forcing to load all clients) + ident(assert) ident(firm)operator(.)ident(clients)operator(.)ident(empty?)operator(,) string<delimiter(")content(New firm shouldn't have client objects)delimiter(")> + ident(assert) operator(!)ident(firm)operator(.)ident(has_clients?)operator(,) string<delimiter(")content(New firm shouldn't have clients)delimiter(")> + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(size)operator(,) string<delimiter(")content(New firm should have 0 clients)delimiter(")> + + ident(client) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(TheClient.com)delimiter(")>operator(,) string<delimiter(")content(firm_id)delimiter(")> operator(=)operator(>) ident(firm)operator(.)ident(id)operator(\)) + ident(client)operator(.)ident(save) + + ident(assert) ident(firm)operator(.)ident(clients)operator(.)ident(empty?)operator(,) string<delimiter(")content(New firm should have cached no client objects)delimiter(")> + ident(assert) operator(!)ident(firm)operator(.)ident(has_clients?)operator(,) string<delimiter(")content(New firm should have cached a no-clients response)delimiter(")> + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(size)operator(,) string<delimiter(")content(New firm should have cached 0 clients count)delimiter(")> + + ident(assert) operator(!)ident(firm)operator(.)ident(clients)operator(()pre_constant(true)operator(\))operator(.)ident(empty?)operator(,) string<delimiter(")content(New firm should have reloaded client objects)delimiter(")> + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients)operator(()pre_constant(true)operator(\))operator(.)ident(size)operator(,) string<delimiter(")content(New firm should have reloaded clients count)delimiter(")> + reserved(end) + + reserved(def) method(test_storing_in_pstore) + ident(require) string<delimiter(")content(tmpdir)delimiter(")> + ident(store_filename) operator(=) constant(File)operator(.)ident(join)operator(()constant(Dir)operator(.)ident(tmpdir)operator(,) string<delimiter(")content(ar-pstore-association-test)delimiter(")>operator(\)) + constant(File)operator(.)ident(delete)operator(()ident(store_filename)operator(\)) reserved(if) constant(File)operator(.)ident(exists?)operator(()ident(store_filename)operator(\)) + ident(require) string<delimiter(")content(pstore)delimiter(")> + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(natural) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Natural Company)delimiter(")>operator(\)) + ident(apple)operator(.)ident(clients) operator(<<) ident(natural) + + ident(db) operator(=) constant(PStore)operator(.)ident(new)operator(()ident(store_filename)operator(\)) + ident(db)operator(.)ident(transaction) reserved(do) + ident(db)operator([)string<delimiter(")content(apple)delimiter(")>operator(]) operator(=) ident(apple) + reserved(end) + + ident(db) operator(=) constant(PStore)operator(.)ident(new)operator(()ident(store_filename)operator(\)) + ident(db)operator(.)ident(transaction) reserved(do) + ident(assert_equal) string<delimiter(")content(Natural Company)delimiter(")>operator(,) ident(db)operator([)string<delimiter(")content(apple)delimiter(")>operator(])operator(.)ident(clients)operator(.)ident(first)operator(.)ident(name) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(HasOneAssociationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:developers_projects) + + reserved(def) method(test_has_one) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account)operator(,) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(credit_limit)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account)operator(.)ident(credit_limit) + reserved(end) + + reserved(def) method(test_proxy_assignment) + ident(company) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(assert_nothing_raised) operator({) ident(company)operator(.)ident(account) operator(=) ident(company)operator(.)ident(account) operator(}) + reserved(end) + + reserved(def) method(test_triple_equality) + ident(assert) constant(Account) operator(===) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) operator(===) constant(Account) + reserved(end) + + reserved(def) method(test_type_mismatch) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) operator(=) integer(1) operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_natural_assignment) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(apple)operator(.)ident(account) operator(=) ident(citibank) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_natural_assignment_to_nil) + ident(old_account_id) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account)operator(.)ident(id) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) operator(=) pre_constant(nil) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(save) + ident(assert_nil) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account) + comment(# account is dependent, therefore is destroyed when reference to owner is lost) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Account)operator(.)ident(find)operator(()ident(old_account_id)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_assignment_without_replacement) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(apple)operator(.)ident(account) operator(=) ident(citibank) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + + ident(hsbc) operator(=) ident(apple)operator(.)ident(build_account)operator(()operator({) symbol(:credit_limit) operator(=)operator(>) integer(20)operator(})operator(,) pre_constant(false)operator(\)) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(hsbc)operator(.)ident(firm_id) + ident(hsbc)operator(.)ident(save) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + + ident(nykredit) operator(=) ident(apple)operator(.)ident(create_account)operator(()operator({) symbol(:credit_limit) operator(=)operator(>) integer(30)operator(})operator(,) pre_constant(false)operator(\)) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(nykredit)operator(.)ident(firm_id) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(hsbc)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_assignment_without_replacement_on_create) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(apple)operator(.)ident(account) operator(=) ident(citibank) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + + ident(hsbc) operator(=) ident(apple)operator(.)ident(create_account)operator(()operator({)symbol(:credit_limit) operator(=)operator(>) integer(10)operator(})operator(,) pre_constant(false)operator(\)) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(hsbc)operator(.)ident(firm_id) + ident(hsbc)operator(.)ident(save) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_dependence) + ident(num_accounts) operator(=) constant(Account)operator(.)ident(count) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(firm)operator(.)ident(account)operator(.)ident(nil?) + ident(firm)operator(.)ident(destroy) + ident(assert_equal) ident(num_accounts) operator(-) integer(1)operator(,) constant(Account)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_succesful_build_association) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + + ident(account) operator(=) ident(firm)operator(.)ident(build_account)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert) ident(account)operator(.)ident(save) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_failing_build_association) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + + ident(account) operator(=) ident(firm)operator(.)ident(build_account) + ident(assert) operator(!)ident(account)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(can't be empty)delimiter(")>operator(,) ident(account)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(credit_limit)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_build_association_twice_without_saving_affects_nothing) + ident(count_of_account) operator(=) constant(Account)operator(.)ident(count) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(account1) operator(=) ident(firm)operator(.)ident(build_account)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(account2) operator(=) ident(firm)operator(.)ident(build_account)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(2000)operator(\)) + + ident(assert_equal) ident(count_of_account)operator(,) constant(Account)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_create_association) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + ident(assert_equal) ident(firm)operator(.)ident(create_account)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\))operator(,) ident(firm)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_build) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + + ident(firm)operator(.)ident(account) operator(=) ident(account) operator(=) constant(Account)operator(.)ident(new)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert) ident(account)operator(.)ident(save) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_build_before_child_saved) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + + ident(account) operator(=) ident(firm)operator(.)ident(account)operator(.)ident(build)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert) ident(account)operator(.)ident(new_record?) + ident(assert) ident(firm)operator(.)ident(save) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert) operator(!)ident(account)operator(.)ident(new_record?) + reserved(end) + + reserved(def) method(test_build_before_either_saved) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + + ident(firm)operator(.)ident(account) operator(=) ident(account) operator(=) constant(Account)operator(.)ident(new)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert) ident(account)operator(.)ident(new_record?) + ident(assert) ident(firm)operator(.)ident(save) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert) operator(!)ident(account)operator(.)ident(new_record?) + reserved(end) + + reserved(def) method(test_failing_build_association) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + + ident(firm)operator(.)ident(account) operator(=) ident(account) operator(=) constant(Account)operator(.)ident(new) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert) operator(!)ident(account)operator(.)ident(save) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + ident(assert_equal) string<delimiter(")content(can't be empty)delimiter(")>operator(,) ident(account)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(credit_limit)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_create) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + ident(firm)operator(.)ident(account) operator(=) ident(account) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_create_before_save) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(account) operator(=) ident(account) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_dependence_with_missing_association) + constant(Account)operator(.)ident(destroy_all) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(firm)operator(.)ident(account)operator(.)ident(nil?) + ident(firm)operator(.)ident(destroy) + reserved(end) + + reserved(def) method(test_assignment_before_parent_saved) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(account) operator(=) ident(a) operator(=) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(firm)operator(.)ident(new_record?) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account) + ident(assert) ident(firm)operator(.)ident(save) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_assignment_before_child_saved) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(firm)operator(.)ident(account) operator(=) ident(a) operator(=) constant(Account)operator(.)ident(new)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert) operator(!)ident(a)operator(.)ident(new_record?) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_assignment_before_either_saved) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(account) operator(=) ident(a) operator(=) constant(Account)operator(.)ident(new)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert) ident(firm)operator(.)ident(new_record?) + ident(assert) ident(a)operator(.)ident(new_record?) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account) + ident(assert) ident(firm)operator(.)ident(save) + ident(assert) operator(!)ident(firm)operator(.)ident(new_record?) + ident(assert) operator(!)ident(a)operator(.)ident(new_record?) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account) + ident(assert_equal) ident(a)operator(,) ident(firm)operator(.)ident(account)operator(()pre_constant(true)operator(\)) + reserved(end) +reserved(end) + + +reserved(class) class(HasManyAssociationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) + symbol(:developers_projects)operator(,) symbol(:topics) + + reserved(def) method(setup) + constant(Client)operator(.)ident(destroyed_client_ids)operator(.)ident(clear) + reserved(end) + + reserved(def) method(force_signal37_to_load_all_clients_of_firm) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(each) operator({)operator(|)ident(f)operator(|) operator(}) + reserved(end) + + reserved(def) method(test_counting) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_finding) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_find_many_with_merged_options) + ident(assert_equal) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(limited_clients)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(limited_clients)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(limited_clients)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:limit) operator(=)operator(>) pre_constant(nil)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_triple_equality) + ident(assert) operator(!)operator(()constant(Array) operator(===) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients)operator(\)) + ident(assert) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients) operator(===) constant(Array) + reserved(end) + + reserved(def) method(test_finding_default_orders) + ident(assert_equal) string<delimiter(")content(Summit)delimiter(")>operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_finding_with_different_class_name_and_order) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients_sorted_desc)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_finding_with_foreign_key) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_finding_with_condition) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients_like_ms)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_finding_using_sql) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(first_client) operator(=) ident(firm)operator(.)ident(clients_using_sql)operator(.)ident(first) + ident(assert_not_nil) ident(first_client) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) ident(first_client)operator(.)ident(name) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients_using_sql)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients_using_sql)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_counting_using_sql) + ident(assert_equal) integer(1)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients_using_counter_sql)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients_using_zero_counter_sql)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_counting_non_existant_items_using_sql) + ident(assert_equal) integer(0)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(no_clients_using_counter_sql)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_belongs_to_sanity) + ident(c) operator(=) constant(Client)operator(.)ident(new) + ident(assert_nil) ident(c)operator(.)ident(firm) + + reserved(if) ident(c)operator(.)ident(firm) + ident(assert) pre_constant(false)operator(,) string<delimiter(")content(belongs_to failed if check)delimiter(")> + reserved(end) + + reserved(unless) ident(c)operator(.)ident(firm) + reserved(else) + ident(assert) pre_constant(false)operator(,) string<delimiter(")content(belongs_to failed unless check)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_find_ids) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(firm)operator(.)ident(clients)operator(.)ident(find) operator(}) + + ident(client) operator(=) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_kind_of) constant(Client)operator(,) ident(client) + + ident(client_ary) operator(=) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()operator([)integer(2)operator(])operator(\)) + ident(assert_kind_of) constant(Array)operator(,) ident(client_ary) + ident(assert_equal) ident(client)operator(,) ident(client_ary)operator(.)ident(first) + + ident(client_ary) operator(=) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()integer(2)operator(,) integer(3)operator(\)) + ident(assert_kind_of) constant(Array)operator(,) ident(client_ary) + ident(assert_equal) integer(2)operator(,) ident(client_ary)operator(.)ident(size) + ident(assert_equal) ident(client)operator(,) ident(client_ary)operator(.)ident(first) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()integer(2)operator(,) integer(99)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_find_all) + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(assert_equal) ident(firm)operator(.)ident(clients)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find_all) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Client')delimiter(")>operator(\))operator(.)ident(length) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Summit')delimiter(")>operator(\))operator(.)ident(length) + reserved(end) + + reserved(def) method(test_find_all_sanitized) + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(assert_equal) ident(firm)operator(.)ident(clients)operator(.)ident(find_all)operator(()string<delimiter(")content(name = 'Summit')delimiter(")>operator(\))operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find_all)operator(()operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(Summit)delimiter(")>operator(])operator(\)) + ident(summit) operator(=) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Summit')delimiter(")>operator(\)) + ident(assert_equal) ident(summit)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(Summit)delimiter(")>operator(])operator(\)) + ident(assert_equal) ident(summit)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(Summit)delimiter(")> operator(})operator(])operator(\)) + reserved(end) + + reserved(def) method(test_find_first) + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(client2) operator(=) constant(Client)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal) ident(firm)operator(.)ident(clients)operator(.)ident(first)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find_first) + ident(assert_equal) ident(client2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find_first)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Client')delimiter(")>operator(\)) + ident(assert_equal) ident(client2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Client')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_first_sanitized) + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(client2) operator(=) constant(Client)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal) ident(client2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find_first)operator(()operator([)string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = ?)delimiter(")>operator(,) string<delimiter(")content(Client)delimiter(")>operator(])operator(\)) + ident(assert_equal) ident(client2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = ?)delimiter(")>operator(,) string<delimiter(')content(Client)delimiter(')>operator(])operator(\)) + ident(assert_equal) ident(client2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = :type)delimiter(")>operator(,) operator({) symbol(:type) operator(=)operator(>) string<delimiter(')content(Client)delimiter(')> operator(})operator(])operator(\)) + reserved(end) + + reserved(def) method(test_find_in_collection) + ident(assert_equal) constant(Client)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(name)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(name) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(find)operator(()integer(6)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_find_grouped) + ident(all_clients_of_firm1) operator(=) constant(Client)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(firm_id = 1)delimiter(")>operator(\)) + ident(grouped_clients_of_firm1) operator(=) constant(Client)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(firm_id = 1)delimiter(")>operator(,) symbol(:group) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:select) operator(=)operator(>) string<delimiter(')content(firm_id, count(id\) as clients_count)delimiter(')>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(all_clients_of_firm1)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(grouped_clients_of_firm1)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding) + ident(force_signal37_to_load_all_clients_of_firm) + ident(natural) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Natural Company)delimiter(")>operator(\)) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm) operator(<<) ident(natural) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) comment(# checking via the collection) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) comment(# checking using the db) + ident(assert_equal) ident(natural)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(last) + reserved(end) + + reserved(def) method(test_adding_a_mismatch_class) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm) operator(<<) pre_constant(nil) operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm) operator(<<) integer(1) operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm) operator(<<) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_adding_a_collection) + ident(force_signal37_to_load_all_clients_of_firm) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(concat)operator(()operator([)constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Natural Company)delimiter(")>operator(\))operator(,) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\))operator(])operator(\)) + ident(assert_equal) integer(3)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(3)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding_before_save) + ident(no_of_firms) operator(=) constant(Firm)operator(.)ident(count) + ident(no_of_clients) operator(=) constant(Client)operator(.)ident(count) + ident(new_firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(A New Firm, Inc)delimiter(")>operator(\)) + ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(push) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Natural Company)delimiter(")>operator(\)) + ident(new_firm)operator(.)ident(clients_of_firm) operator(<<) operator(()ident(c) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\))operator(\)) + ident(assert) ident(new_firm)operator(.)ident(new_record?) + ident(assert) ident(c)operator(.)ident(new_record?) + ident(assert_equal) integer(2)operator(,) ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) ident(no_of_firms)operator(,) constant(Firm)operator(.)ident(count) comment(# Firm was not saved to database.) + ident(assert_equal) ident(no_of_clients)operator(,) constant(Client)operator(.)ident(count) comment(# Clients were not saved to database.) + ident(assert) ident(new_firm)operator(.)ident(save) + ident(assert) operator(!)ident(new_firm)operator(.)ident(new_record?) + ident(assert) operator(!)ident(c)operator(.)ident(new_record?) + ident(assert_equal) ident(new_firm)operator(,) ident(c)operator(.)ident(firm) + ident(assert_equal) ident(no_of_firms)operator(+)integer(1)operator(,) constant(Firm)operator(.)ident(count) comment(# Firm was saved to database.) + ident(assert_equal) ident(no_of_clients)operator(+)integer(2)operator(,) constant(Client)operator(.)ident(count) comment(# Clients were saved to database.) + ident(assert_equal) integer(2)operator(,) ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(new_firm)operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_invalid_adding) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)operator(()ident(firm)operator(.)ident(clients_of_firm) operator(<<) ident(c) operator(=) constant(Client)operator(.)ident(new)operator(\)) + ident(assert) ident(c)operator(.)ident(new_record?) + ident(assert) operator(!)ident(firm)operator(.)ident(valid?) + ident(assert) operator(!)ident(firm)operator(.)ident(save) + ident(assert) ident(c)operator(.)ident(new_record?) + reserved(end) + + reserved(def) method(test_invalid_adding_before_save) + ident(no_of_firms) operator(=) constant(Firm)operator(.)ident(count) + ident(no_of_clients) operator(=) constant(Client)operator(.)ident(count) + ident(new_firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(A New Firm, Inc)delimiter(")>operator(\)) + ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(concat)operator(()operator([)ident(c) operator(=) constant(Client)operator(.)ident(new)operator(,) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\))operator(])operator(\)) + ident(assert) ident(c)operator(.)ident(new_record?) + ident(assert) operator(!)ident(c)operator(.)ident(valid?) + ident(assert) operator(!)ident(new_firm)operator(.)ident(valid?) + ident(assert) operator(!)ident(new_firm)operator(.)ident(save) + ident(assert) ident(c)operator(.)ident(new_record?) + ident(assert) ident(new_firm)operator(.)ident(new_record?) + reserved(end) + + reserved(def) method(test_build) + ident(new_client) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(build)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Another Client)delimiter(")>operator(,) ident(new_client)operator(.)ident(name) + ident(assert) ident(new_client)operator(.)ident(new_record?) + ident(assert_equal) ident(new_client)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(last) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(save) + ident(assert) operator(!)ident(new_client)operator(.)ident(new_record?) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_build_many) + ident(new_clients) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(build)operator(()operator([)operator({)string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(})operator(,) operator({)string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client II)delimiter(")>operator(})operator(])operator(\)) + ident(assert_equal) integer(2)operator(,) ident(new_clients)operator(.)ident(size) + + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(save) + ident(assert_equal) integer(3)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_invalid_build) + ident(new_client) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(build) + ident(assert) ident(new_client)operator(.)ident(new_record?) + ident(assert) operator(!)ident(new_client)operator(.)ident(valid?) + ident(assert_equal) ident(new_client)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(last) + ident(assert) operator(!)ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(save) + ident(assert) ident(new_client)operator(.)ident(new_record?) + ident(assert_equal) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_create) + ident(force_signal37_to_load_all_clients_of_firm) + ident(new_client) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert) operator(!)ident(new_client)operator(.)ident(new_record?) + ident(assert_equal) ident(new_client)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(last) + ident(assert_equal) ident(new_client)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(last) + reserved(end) + + reserved(def) method(test_create_many) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(create)operator(()operator([)operator({)string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(})operator(,) operator({)string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client II)delimiter(")>operator(})operator(])operator(\)) + ident(assert_equal) integer(3)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_find_or_create) + ident(number_of_clients) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(size) + ident(the_client) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(find_or_create_by_name)operator(()string<delimiter(")content(Yet another client)delimiter(")>operator(\)) + ident(assert_equal) ident(number_of_clients) operator(+) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(,) symbol(:refresh)operator(\))operator(.)ident(clients)operator(.)ident(size) + ident(assert_equal) ident(the_client)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(find_or_create_by_name)operator(()string<delimiter(")content(Yet another client)delimiter(")>operator(\)) + ident(assert_equal) ident(number_of_clients) operator(+) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(,) symbol(:refresh)operator(\))operator(.)ident(clients)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting) + ident(force_signal37_to_load_all_clients_of_firm) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(delete)operator(()ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(first)operator(\)) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_before_save) + ident(new_firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(A New Firm, Inc.)delimiter(")>operator(\)) + ident(new_client) operator(=) ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(build)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(delete)operator(()ident(new_client)operator(\)) + ident(assert_equal) integer(0)operator(,) ident(new_firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_a_collection) + ident(force_signal37_to_load_all_clients_of_firm) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(delete)operator(()operator([)ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator([)integer(0)operator(])operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator([)integer(1)operator(])operator(])operator(\)) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_delete_all) + ident(force_signal37_to_load_all_clients_of_firm) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(delete_all) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_delete_all_with_not_yet_loaded_association_collection) + ident(force_signal37_to_load_all_clients_of_firm) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(reset) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(delete_all) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_clearing_an_association_collection) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(client_id) operator(=) ident(firm)operator(.)ident(clients_of_firm)operator(.)ident(first)operator(.)ident(id) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + + ident(firm)operator(.)ident(clients_of_firm)operator(.)ident(clear) + + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) operator([)operator(])operator(,) constant(Client)operator(.)ident(destroyed_client_ids)operator([)ident(firm)operator(.)ident(id)operator(]) + + comment(# Should not be destroyed since the association is not dependent.) + ident(assert_nothing_raised) reserved(do) + ident(assert) constant(Client)operator(.)ident(find)operator(()ident(client_id)operator(\))operator(.)ident(firm)operator(.)ident(nil?) + reserved(end) + reserved(end) + + reserved(def) method(test_clearing_a_dependent_association_collection) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(client_id) operator(=) ident(firm)operator(.)ident(dependent_clients_of_firm)operator(.)ident(first)operator(.)ident(id) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(dependent_clients_of_firm)operator(.)ident(size) + + comment(# :dependent means destroy is called on each client) + ident(firm)operator(.)ident(dependent_clients_of_firm)operator(.)ident(clear) + + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(dependent_clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(dependent_clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) operator([)ident(client_id)operator(])operator(,) constant(Client)operator(.)ident(destroyed_client_ids)operator([)ident(firm)operator(.)ident(id)operator(]) + + comment(# Should be destroyed since the association is dependent.) + ident(assert) constant(Client)operator(.)ident(find_by_id)operator(()ident(client_id)operator(\))operator(.)ident(nil?) + reserved(end) + + reserved(def) method(test_clearing_an_exclusively_dependent_association_collection) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(client_id) operator(=) ident(firm)operator(.)ident(exclusively_dependent_clients_of_firm)operator(.)ident(first)operator(.)ident(id) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(exclusively_dependent_clients_of_firm)operator(.)ident(size) + + ident(assert_equal) operator([)operator(])operator(,) constant(Client)operator(.)ident(destroyed_client_ids)operator([)ident(firm)operator(.)ident(id)operator(]) + + comment(# :exclusively_dependent means each client is deleted directly from) + comment(# the database without looping through them calling destroy.) + ident(firm)operator(.)ident(exclusively_dependent_clients_of_firm)operator(.)ident(clear) + + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(exclusively_dependent_clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(exclusively_dependent_clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) operator([)integer(3)operator(])operator(,) constant(Client)operator(.)ident(destroyed_client_ids)operator([)ident(firm)operator(.)ident(id)operator(]) + + comment(# Should be destroyed since the association is exclusively dependent.) + ident(assert) constant(Client)operator(.)ident(find_by_id)operator(()ident(client_id)operator(\))operator(.)ident(nil?) + reserved(end) + + reserved(def) method(test_clearing_without_initial_access) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + + ident(firm)operator(.)ident(clients_of_firm)operator(.)ident(clear) + + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_a_item_which_is_not_in_the_collection) + ident(force_signal37_to_load_all_clients_of_firm) + ident(summit) operator(=) constant(Client)operator(.)ident(find_first)operator(()string<delimiter(")content(name = 'Summit')delimiter(")>operator(\)) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(delete)operator(()ident(summit)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(summit)operator(.)ident(client_of) + reserved(end) + + reserved(def) method(test_deleting_type_mismatch) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(projects)operator(.)ident(reload) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(david)operator(.)ident(projects)operator(.)ident(delete)operator(()integer(1)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_deleting_self_type_mismatch) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(projects)operator(.)ident(reload) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(david)operator(.)ident(projects)operator(.)ident(delete)operator(()constant(Project)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(developers)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_destroy_all) + ident(force_signal37_to_load_all_clients_of_firm) + ident(assert) operator(!)ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(empty?)operator(,) string<delimiter(")content(37signals has clients after load)delimiter(")> + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(destroy_all) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(.)ident(empty?)operator(,) string<delimiter(")content(37signals has no clients after destroy all)delimiter(")> + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(empty?)operator(,) string<delimiter(")content(37signals has no clients after destroy all and refresh)delimiter(")> + reserved(end) + + reserved(def) method(test_dependence) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(size) + ident(firm)operator(.)ident(destroy) + ident(assert) constant(Client)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(firm_id=)inline<inline_delimiter(#{)ident(firm)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(empty?) + reserved(end) + + reserved(def) method(test_destroy_dependent_when_deleted_from_association) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(size) + + ident(client) operator(=) ident(firm)operator(.)ident(clients)operator(.)ident(first) + ident(firm)operator(.)ident(clients)operator(.)ident(delete)operator(()ident(client)operator(\)) + + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Client)operator(.)ident(find)operator(()ident(client)operator(.)ident(id)operator(\)) operator(}) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()ident(client)operator(.)ident(id)operator(\)) operator(}) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_three_levels_of_dependence) + ident(topic) operator(=) constant(Topic)operator(.)ident(create) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(neat and simple)delimiter(")> + ident(reply) operator(=) ident(topic)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(neat and simple)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(still digging it)delimiter(")> + ident(silly_reply) operator(=) ident(reply)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(neat and simple)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(ain't complaining)delimiter(")> + + ident(assert_nothing_raised) operator({) ident(topic)operator(.)ident(destroy) operator(}) + reserved(end) + + ident(uses_transaction) symbol(:test_dependence_with_transaction_support_on_failure) + reserved(def) method(test_dependence_with_transaction_support_on_failure) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(clients) operator(=) ident(firm)operator(.)ident(clients) + ident(assert_equal) integer(2)operator(,) ident(clients)operator(.)ident(length) + ident(clients)operator(.)ident(last)operator(.)ident(instance_eval) operator({) reserved(def) method(before_destroy)operator(()operator(\)) ident(raise) string<delimiter(")content(Trigger rollback)delimiter(")> reserved(end) operator(}) + + ident(firm)operator(.)ident(destroy) reserved(rescue) string<delimiter(")content(do nothing)delimiter(")> + + ident(assert_equal) integer(2)operator(,) constant(Client)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(firm_id=)inline<inline_delimiter(#{)ident(firm)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_dependence_on_account) + ident(num_accounts) operator(=) constant(Account)operator(.)ident(count) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(destroy) + ident(assert_equal) ident(num_accounts) operator(-) integer(1)operator(,) constant(Account)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_depends_and_nullify) + ident(num_accounts) operator(=) constant(Account)operator(.)ident(count) + ident(num_companies) operator(=) constant(Company)operator(.)ident(count) + + ident(core) operator(=) ident(companies)operator(()symbol(:rails_core)operator(\)) + ident(assert_equal) ident(accounts)operator(()symbol(:rails_core_account)operator(\))operator(,) ident(core)operator(.)ident(account) + ident(assert_equal) operator([)ident(companies)operator(()symbol(:leetsoft)operator(\))operator(,) ident(companies)operator(()symbol(:jadedpixel)operator(\))operator(])operator(,) ident(core)operator(.)ident(companies) + ident(core)operator(.)ident(destroy) + ident(assert_nil) ident(accounts)operator(()symbol(:rails_core_account)operator(\))operator(.)ident(reload)operator(.)ident(firm_id) + ident(assert_nil) ident(companies)operator(()symbol(:leetsoft)operator(\))operator(.)ident(reload)operator(.)ident(client_of) + ident(assert_nil) ident(companies)operator(()symbol(:jadedpixel)operator(\))operator(.)ident(reload)operator(.)ident(client_of) + + + ident(assert_equal) ident(num_accounts)operator(,) constant(Account)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_included_in_collection) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(include?)operator(()constant(Client)operator(.)ident(find)operator(()integer(2)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_adding_array_and_collection) + ident(assert_nothing_raised) operator({) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(clients) operator(+) constant(Firm)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(last)operator(.)ident(clients) operator(}) + reserved(end) + + reserved(def) method(test_find_all_without_conditions) + ident(firm) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(length) + reserved(end) + + reserved(def) method(test_replace_with_less) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(firm)operator(.)ident(clients) operator(=) operator([)ident(companies)operator(()symbol(:first_client)operator(\))operator(]) + ident(assert) ident(firm)operator(.)ident(save)operator(,) string<delimiter(")content(Could not save firm)delimiter(")> + ident(firm)operator(.)ident(reload) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(length) + reserved(end) + + + reserved(def) method(test_replace_with_new) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(new_client) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(New Client)delimiter(")>operator(\)) + ident(firm)operator(.)ident(clients) operator(=) operator([)ident(companies)operator(()symbol(:second_client)operator(\))operator(,)ident(new_client)operator(]) + ident(firm)operator(.)ident(save) + ident(firm)operator(.)ident(reload) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(length) + ident(assert) operator(!)ident(firm)operator(.)ident(clients)operator(.)ident(include?)operator(()symbol(:first_client)operator(\)) + reserved(end) + + reserved(def) method(test_replace_on_new_object) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(New Firm)delimiter(")>operator(\)) + ident(firm)operator(.)ident(clients) operator(=) operator([)ident(companies)operator(()symbol(:second_client)operator(\))operator(,) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(New Client)delimiter(")>operator(\))operator(]) + ident(assert) ident(firm)operator(.)ident(save) + ident(firm)operator(.)ident(reload) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(length) + ident(assert) ident(firm)operator(.)ident(clients)operator(.)ident(include?)operator(()constant(Client)operator(.)ident(find_by_name)operator(()string<delimiter(")content(New Client)delimiter(")>operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_assign_ids) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(firm)operator(.)ident(client_ids) operator(=) operator([)ident(companies)operator(()symbol(:first_client)operator(\))operator(.)ident(id)operator(,) ident(companies)operator(()symbol(:second_client)operator(\))operator(.)ident(id)operator(]) + ident(firm)operator(.)ident(save) + ident(firm)operator(.)ident(reload) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(length) + ident(assert) ident(firm)operator(.)ident(clients)operator(.)ident(include?)operator(()ident(companies)operator(()symbol(:second_client)operator(\))operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(BelongsToAssociationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:topics)operator(,) + symbol(:developers_projects)operator(,) symbol(:computers)operator(,) symbol(:authors)operator(,) symbol(:posts) + + reserved(def) method(test_belongs_to) + constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm)operator(.)ident(name) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(name)operator(,) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm)operator(.)ident(name) + ident(assert) operator(!)constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm)operator(.)ident(nil?)operator(,) string<delimiter(")content(Microsoft should have a firm)delimiter(")> + reserved(end) + + reserved(def) method(test_proxy_assignment) + ident(account) operator(=) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_nothing_raised) operator({) ident(account)operator(.)ident(firm) operator(=) ident(account)operator(.)ident(firm) operator(}) + reserved(end) + + reserved(def) method(test_triple_equality) + ident(assert) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm) operator(===) constant(Firm) + ident(assert) constant(Firm) operator(===) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm) + reserved(end) + + reserved(def) method(test_type_mismatch) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(firm) operator(=) integer(1) operator(}) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(firm) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_natural_assignment) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(citibank)operator(.)ident(firm) operator(=) ident(apple) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_creating_the_belonging_object) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(apple) operator(=) ident(citibank)operator(.)ident(create_firm)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(assert_equal) ident(apple)operator(,) ident(citibank)operator(.)ident(firm) + ident(citibank)operator(.)ident(save) + ident(citibank)operator(.)ident(reload) + ident(assert_equal) ident(apple)operator(,) ident(citibank)operator(.)ident(firm) + reserved(end) + + reserved(def) method(test_building_the_belonging_object) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(apple) operator(=) ident(citibank)operator(.)ident(build_firm)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank)operator(.)ident(save) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_natural_assignment_to_nil) + ident(client) operator(=) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\)) + ident(client)operator(.)ident(firm) operator(=) pre_constant(nil) + ident(client)operator(.)ident(save) + ident(assert_nil) ident(client)operator(.)ident(firm)operator(()pre_constant(true)operator(\)) + ident(assert_nil) ident(client)operator(.)ident(client_of) + reserved(end) + + reserved(def) method(test_with_different_class_name) + ident(assert_equal) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(name)operator(,) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm_with_other_name)operator(.)ident(name) + ident(assert_not_nil) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm_with_other_name)operator(,) string<delimiter(")content(Microsoft should have a firm)delimiter(")> + reserved(end) + + reserved(def) method(test_with_condition) + ident(assert_equal) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(name)operator(,) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm_with_condition)operator(.)ident(name) + ident(assert_not_nil) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm_with_condition)operator(,) string<delimiter(")content(Microsoft should have a firm)delimiter(")> + reserved(end) + + reserved(def) method(test_belongs_to_counter) + ident(debate) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(debate)delimiter(")>operator(\)) + ident(assert_equal) integer(0)operator(,) ident(debate)operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(replies_count)delimiter(")>operator(\))operator(,) string<delimiter(")content(No replies yet)delimiter(")> + + ident(trash) operator(=) ident(debate)operator(.)ident(replies)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(blah!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(world around!)delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(debate)operator(.)ident(id)operator(\))operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(replies_count)delimiter(")>operator(\))operator(,) string<delimiter(")content(First reply created)delimiter(")> + + ident(trash)operator(.)ident(destroy) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(debate)operator(.)ident(id)operator(\))operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(replies_count)delimiter(")>operator(\))operator(,) string<delimiter(")content(First reply deleted)delimiter(")> + reserved(end) + + reserved(def) method(test_belongs_to_counter_with_reassigning) + ident(t1) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(t1)delimiter(")>operator(\)) + ident(t2) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(t2)delimiter(")>operator(\)) + ident(r1) operator(=) constant(Reply)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(r1)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(r1)delimiter(")>operator(\)) + ident(r1)operator(.)ident(topic) operator(=) ident(t1) + + ident(assert) ident(r1)operator(.)ident(save) + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t1)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t2)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + + ident(r1)operator(.)ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(t2)operator(.)ident(id)operator(\)) + + ident(assert) ident(r1)operator(.)ident(save) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t1)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t2)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + + ident(r1)operator(.)ident(topic) operator(=) pre_constant(nil) + + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t1)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t2)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + + ident(r1)operator(.)ident(topic) operator(=) ident(t1) + + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t1)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t2)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + + ident(r1)operator(.)ident(destroy) + + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t1)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(t2)operator(.)ident(id)operator(\))operator(.)ident(replies)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_assignment_before_parent_saved) + ident(client) operator(=) constant(Client)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(apple) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(client)operator(.)ident(firm) operator(=) ident(apple) + ident(assert_equal) ident(apple)operator(,) ident(client)operator(.)ident(firm) + ident(assert) ident(apple)operator(.)ident(new_record?) + ident(assert) ident(client)operator(.)ident(save) + ident(assert) ident(apple)operator(.)ident(save) + ident(assert) operator(!)ident(apple)operator(.)ident(new_record?) + ident(assert_equal) ident(apple)operator(,) ident(client)operator(.)ident(firm) + ident(assert_equal) ident(apple)operator(,) ident(client)operator(.)ident(firm)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_assignment_before_child_saved) + ident(final_cut) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Final Cut)delimiter(")>operator(\)) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(final_cut)operator(.)ident(firm) operator(=) ident(firm) + ident(assert) ident(final_cut)operator(.)ident(new_record?) + ident(assert) ident(final_cut)operator(.)ident(save) + ident(assert) operator(!)ident(final_cut)operator(.)ident(new_record?) + ident(assert) operator(!)ident(firm)operator(.)ident(new_record?) + ident(assert_equal) ident(firm)operator(,) ident(final_cut)operator(.)ident(firm) + ident(assert_equal) ident(firm)operator(,) ident(final_cut)operator(.)ident(firm)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_assignment_before_either_saved) + ident(final_cut) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Final Cut)delimiter(")>operator(\)) + ident(apple) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(final_cut)operator(.)ident(firm) operator(=) ident(apple) + ident(assert) ident(final_cut)operator(.)ident(new_record?) + ident(assert) ident(apple)operator(.)ident(new_record?) + ident(assert) ident(final_cut)operator(.)ident(save) + ident(assert) operator(!)ident(final_cut)operator(.)ident(new_record?) + ident(assert) operator(!)ident(apple)operator(.)ident(new_record?) + ident(assert_equal) ident(apple)operator(,) ident(final_cut)operator(.)ident(firm) + ident(assert_equal) ident(apple)operator(,) ident(final_cut)operator(.)ident(firm)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_new_record_with_foreign_key_but_no_object) + ident(c) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(firm_id)delimiter(")> operator(=)operator(>) integer(1)operator(\)) + ident(assert_equal) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(,) ident(c)operator(.)ident(firm_with_basic_id) + reserved(end) + + reserved(def) method(test_forgetting_the_load_when_foreign_key_enters_late) + ident(c) operator(=) constant(Client)operator(.)ident(new) + ident(assert_nil) ident(c)operator(.)ident(firm_with_basic_id) + + ident(c)operator(.)ident(firm_id) operator(=) integer(1) + ident(assert_equal) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(,) ident(c)operator(.)ident(firm_with_basic_id) + reserved(end) + + reserved(def) method(test_field_name_same_as_foreign_key) + ident(computer) operator(=) constant(Computer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_not_nil) ident(computer)operator(.)ident(developer)operator(,) string<delimiter(")content(:foreign key == attribute didn't lock up)delimiter(")> comment(# ') + reserved(end) + + reserved(def) method(test_counter_cache) + ident(topic) operator(=) constant(Topic)operator(.)ident(create) symbol(:title) operator(=)operator(>) string<delimiter(")content(Zoom-zoom-zoom)delimiter(")> + ident(assert_equal) integer(0)operator(,) ident(topic)operator([)symbol(:replies_count)operator(]) + + ident(reply) operator(=) constant(Reply)operator(.)ident(create)operator(()symbol(:title) operator(=)operator(>) string<delimiter(")content(re: zoom)delimiter(")>operator(,) symbol(:content) operator(=)operator(>) string<delimiter(")content(speedy quick!)delimiter(")>operator(\)) + ident(reply)operator(.)ident(topic) operator(=) ident(topic) + + ident(assert_equal) integer(1)operator(,) ident(topic)operator(.)ident(reload)operator([)symbol(:replies_count)operator(]) + ident(assert_equal) integer(1)operator(,) ident(topic)operator(.)ident(replies)operator(.)ident(size) + + ident(topic)operator([)symbol(:replies_count)operator(]) operator(=) integer(15) + ident(assert_equal) integer(15)operator(,) ident(topic)operator(.)ident(replies)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_custom_counter_cache) + ident(reply) operator(=) constant(Reply)operator(.)ident(create)operator(()symbol(:title) operator(=)operator(>) string<delimiter(")content(re: zoom)delimiter(")>operator(,) symbol(:content) operator(=)operator(>) string<delimiter(")content(speedy quick!)delimiter(")>operator(\)) + ident(assert_equal) integer(0)operator(,) ident(reply)operator([)symbol(:replies_count)operator(]) + + ident(silly) operator(=) constant(SillyReply)operator(.)ident(create)operator(()symbol(:title) operator(=)operator(>) string<delimiter(")content(gaga)delimiter(")>operator(,) symbol(:content) operator(=)operator(>) string<delimiter(")content(boo-boo)delimiter(")>operator(\)) + ident(silly)operator(.)ident(reply) operator(=) ident(reply) + + ident(assert_equal) integer(1)operator(,) ident(reply)operator(.)ident(reload)operator([)symbol(:replies_count)operator(]) + ident(assert_equal) integer(1)operator(,) ident(reply)operator(.)ident(replies)operator(.)ident(size) + + ident(reply)operator([)symbol(:replies_count)operator(]) operator(=) integer(17) + ident(assert_equal) integer(17)operator(,) ident(reply)operator(.)ident(replies)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_store_two_association_with_one_save) + ident(num_orders) operator(=) constant(Order)operator(.)ident(count) + ident(num_customers) operator(=) constant(Customer)operator(.)ident(count) + ident(order) operator(=) constant(Order)operator(.)ident(new) + + ident(customer1) operator(=) ident(order)operator(.)ident(billing) operator(=) constant(Customer)operator(.)ident(new) + ident(customer2) operator(=) ident(order)operator(.)ident(shipping) operator(=) constant(Customer)operator(.)ident(new) + ident(assert) ident(order)operator(.)ident(save) + ident(assert_equal) ident(customer1)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer2)operator(,) ident(order)operator(.)ident(shipping) + + ident(order)operator(.)ident(reload) + + ident(assert_equal) ident(customer1)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer2)operator(,) ident(order)operator(.)ident(shipping) + + ident(assert_equal) ident(num_orders) integer(+1)operator(,) constant(Order)operator(.)ident(count) + ident(assert_equal) ident(num_customers) integer(+2)operator(,) constant(Customer)operator(.)ident(count) + reserved(end) + + + reserved(def) method(test_store_association_in_two_relations_with_one_save) + ident(num_orders) operator(=) constant(Order)operator(.)ident(count) + ident(num_customers) operator(=) constant(Customer)operator(.)ident(count) + ident(order) operator(=) constant(Order)operator(.)ident(new) + + ident(customer) operator(=) ident(order)operator(.)ident(billing) operator(=) ident(order)operator(.)ident(shipping) operator(=) constant(Customer)operator(.)ident(new) + ident(assert) ident(order)operator(.)ident(save) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(shipping) + + ident(order)operator(.)ident(reload) + + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(shipping) + + ident(assert_equal) ident(num_orders) integer(+1)operator(,) constant(Order)operator(.)ident(count) + ident(assert_equal) ident(num_customers) integer(+1)operator(,) constant(Customer)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_store_association_in_two_relations_with_one_save_in_existing_object) + ident(num_orders) operator(=) constant(Order)operator(.)ident(count) + ident(num_customers) operator(=) constant(Customer)operator(.)ident(count) + ident(order) operator(=) constant(Order)operator(.)ident(create) + + ident(customer) operator(=) ident(order)operator(.)ident(billing) operator(=) ident(order)operator(.)ident(shipping) operator(=) constant(Customer)operator(.)ident(new) + ident(assert) ident(order)operator(.)ident(save) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(shipping) + + ident(order)operator(.)ident(reload) + + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(shipping) + + ident(assert_equal) ident(num_orders) integer(+1)operator(,) constant(Order)operator(.)ident(count) + ident(assert_equal) ident(num_customers) integer(+1)operator(,) constant(Customer)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_store_association_in_two_relations_with_one_save_in_existing_object_with_values) + ident(num_orders) operator(=) constant(Order)operator(.)ident(count) + ident(num_customers) operator(=) constant(Customer)operator(.)ident(count) + ident(order) operator(=) constant(Order)operator(.)ident(create) + + ident(customer) operator(=) ident(order)operator(.)ident(billing) operator(=) ident(order)operator(.)ident(shipping) operator(=) constant(Customer)operator(.)ident(new) + ident(assert) ident(order)operator(.)ident(save) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(shipping) + + ident(order)operator(.)ident(reload) + + ident(customer) operator(=) ident(order)operator(.)ident(billing) operator(=) ident(order)operator(.)ident(shipping) operator(=) constant(Customer)operator(.)ident(new) + + ident(assert) ident(order)operator(.)ident(save) + ident(order)operator(.)ident(reload) + + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(billing) + ident(assert_equal) ident(customer)operator(,) ident(order)operator(.)ident(shipping) + + ident(assert_equal) ident(num_orders) integer(+1)operator(,) constant(Order)operator(.)ident(count) + ident(assert_equal) ident(num_customers) integer(+2)operator(,) constant(Customer)operator(.)ident(count) + reserved(end) + + + reserved(def) method(test_association_assignment_sticks) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()symbol(:first)operator(\)) + + ident(author1)operator(,) ident(author2) operator(=) constant(Author)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(\)) + ident(assert_not_nil) ident(author1) + ident(assert_not_nil) ident(author2) + + comment(# make sure the association is loaded) + ident(post)operator(.)ident(author) + + comment(# set the association by id, directly) + ident(post)operator(.)ident(author_id) operator(=) ident(author2)operator(.)ident(id) + + comment(# save and reload) + ident(post)operator(.)ident(save!) + ident(post)operator(.)ident(reload) + + comment(# the author id of the post should be the id we set) + ident(assert_equal) ident(post)operator(.)ident(author_id)operator(,) ident(author2)operator(.)ident(id) + reserved(end) + +reserved(end) + + +reserved(class) class(ProjectWithAfterCreateHook) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(projects)delimiter(')> + ident(has_and_belongs_to_many) symbol(:developers)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(")content(DeveloperForProjectWithAfterCreateHook)delimiter(")>operator(,) + symbol(:join_table) operator(=)operator(>) string<delimiter(")content(developers_projects)delimiter(")>operator(,) + symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(project_id)delimiter(")>operator(,) + symbol(:association_foreign_key) operator(=)operator(>) string<delimiter(")content(developer_id)delimiter(")> + + ident(after_create) symbol(:add_david) + + reserved(def) method(add_david) + ident(david) operator(=) constant(DeveloperForProjectWithAfterCreateHook)operator(.)ident(find_by_name)operator(()string<delimiter(')content(David)delimiter(')>operator(\)) + ident(david)operator(.)ident(projects) operator(<<) pre_constant(self) + reserved(end) +reserved(end) + +reserved(class) class(DeveloperForProjectWithAfterCreateHook) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(developers)delimiter(')> + ident(has_and_belongs_to_many) symbol(:projects)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(")content(ProjectWithAfterCreateHook)delimiter(")>operator(,) + symbol(:join_table) operator(=)operator(>) string<delimiter(")content(developers_projects)delimiter(")>operator(,) + symbol(:association_foreign_key) operator(=)operator(>) string<delimiter(")content(project_id)delimiter(")>operator(,) + symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(developer_id)delimiter(")> +reserved(end) + + +reserved(class) class(HasAndBelongsToManyAssociationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:categories)operator(,) symbol(:posts)operator(,) symbol(:categories_posts)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:developers_projects) + + reserved(def) method(test_has_and_belongs_to_many) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + + ident(assert) operator(!)ident(david)operator(.)ident(projects)operator(.)ident(empty?) + ident(assert_equal) integer(2)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(size) + + ident(active_record) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(active_record)operator(.)ident(developers)operator(.)ident(empty?) + ident(assert_equal) integer(3)operator(,) ident(active_record)operator(.)ident(developers)operator(.)ident(size) + ident(assert) ident(active_record)operator(.)ident(developers)operator(.)ident(include?)operator(()ident(david)operator(\)) + reserved(end) + + reserved(def) method(test_triple_equality) + ident(assert) operator(!)operator(()constant(Array) operator(===) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(projects)operator(\)) + ident(assert) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(projects) operator(===) constant(Array) + reserved(end) + + reserved(def) method(test_adding_single) + ident(jamis) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(jamis)operator(.)ident(projects)operator(.)ident(reload) comment(# causing the collection to load ) + ident(action_controller) operator(=) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(jamis)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(action_controller)operator(.)ident(developers)operator(.)ident(size) + + ident(jamis)operator(.)ident(projects) operator(<<) ident(action_controller) + + ident(assert_equal) integer(2)operator(,) ident(jamis)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(jamis)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding_type_mismatch) + ident(jamis) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(jamis)operator(.)ident(projects) operator(<<) pre_constant(nil) operator(}) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(AssociationTypeMismatch)operator(\)) operator({) ident(jamis)operator(.)ident(projects) operator(<<) integer(1) operator(}) + reserved(end) + + reserved(def) method(test_adding_from_the_project) + ident(jamis) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(action_controller) operator(=) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(action_controller)operator(.)ident(developers)operator(.)ident(reload) + ident(assert_equal) integer(1)operator(,) ident(jamis)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(action_controller)operator(.)ident(developers)operator(.)ident(size) + + ident(action_controller)operator(.)ident(developers) operator(<<) ident(jamis) + + ident(assert_equal) integer(2)operator(,) ident(jamis)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding_from_the_project_fixed_timestamp) + ident(jamis) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(action_controller) operator(=) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(action_controller)operator(.)ident(developers)operator(.)ident(reload) + ident(assert_equal) integer(1)operator(,) ident(jamis)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(action_controller)operator(.)ident(developers)operator(.)ident(size) + ident(updated_at) operator(=) ident(jamis)operator(.)ident(updated_at) + + ident(action_controller)operator(.)ident(developers) operator(<<) ident(jamis) + + ident(assert_equal) ident(updated_at)operator(,) ident(jamis)operator(.)ident(updated_at) + ident(assert_equal) integer(2)operator(,) ident(jamis)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding_multiple) + ident(aredridel) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Aredridel)delimiter(")>operator(\)) + ident(aredridel)operator(.)ident(save) + ident(aredridel)operator(.)ident(projects)operator(.)ident(reload) + ident(aredridel)operator(.)ident(projects)operator(.)ident(push)operator(()constant(Project)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\))operator(\)) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding_a_collection) + ident(aredridel) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Aredridel)delimiter(")>operator(\)) + ident(aredridel)operator(.)ident(save) + ident(aredridel)operator(.)ident(projects)operator(.)ident(reload) + ident(aredridel)operator(.)ident(projects)operator(.)ident(concat)operator(()operator([)constant(Project)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\))operator(])operator(\)) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_adding_uses_default_values_on_join_table) + ident(ac) operator(=) ident(projects)operator(()symbol(:action_controller)operator(\)) + ident(assert) operator(!)ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(include?)operator(()ident(ac)operator(\)) + ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects) operator(<<) ident(ac) + + ident(assert) ident(developers)operator(()symbol(:jamis)operator(,) symbol(:reload)operator(\))operator(.)ident(projects)operator(.)ident(include?)operator(()ident(ac)operator(\)) + ident(project) operator(=) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(detect) operator({) operator(|)ident(p)operator(|) ident(p) operator(==) ident(ac) operator(}) + ident(assert_equal) integer(1)operator(,) ident(project)operator(.)ident(access_level)operator(.)ident(to_i) + reserved(end) + + reserved(def) method(test_adding_uses_explicit_values_on_join_table) + ident(ac) operator(=) ident(projects)operator(()symbol(:action_controller)operator(\)) + ident(assert) operator(!)ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(include?)operator(()ident(ac)operator(\)) + ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(push_with_attributes)operator(()ident(ac)operator(,) symbol(:access_level) operator(=)operator(>) integer(3)operator(\)) + + ident(assert) ident(developers)operator(()symbol(:jamis)operator(,) symbol(:reload)operator(\))operator(.)ident(projects)operator(.)ident(include?)operator(()ident(ac)operator(\)) + ident(project) operator(=) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(detect) operator({) operator(|)ident(p)operator(|) ident(p) operator(==) ident(ac) operator(}) + ident(assert_equal) integer(3)operator(,) ident(project)operator(.)ident(access_level)operator(.)ident(to_i) + reserved(end) + + reserved(def) method(test_hatbm_attribute_access_and_respond_to) + ident(project) operator(=) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator([)integer(0)operator(]) + ident(assert) ident(project)operator(.)ident(has_attribute?)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(has_attribute?)operator(()string<delimiter(")content(joined_on)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(has_attribute?)operator(()string<delimiter(")content(access_level)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(name=)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(name?)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(joined_on)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(joined_on=)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(joined_on?)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(access_level)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(access_level=)delimiter(")>operator(\)) + ident(assert) ident(project)operator(.)ident(respond_to?)operator(()string<delimiter(")content(access_level?)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_habtm_adding_before_save) + ident(no_of_devels) operator(=) constant(Developer)operator(.)ident(count) + ident(no_of_projects) operator(=) constant(Project)operator(.)ident(count) + ident(aredridel) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Aredridel)delimiter(")>operator(\)) + ident(aredridel)operator(.)ident(projects)operator(.)ident(concat)operator(()operator([)constant(Project)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) ident(p) operator(=) constant(Project)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Projekt)delimiter(")>operator(\))operator(])operator(\)) + ident(assert) ident(aredridel)operator(.)ident(new_record?) + ident(assert) ident(p)operator(.)ident(new_record?) + ident(assert) ident(aredridel)operator(.)ident(save) + ident(assert) operator(!)ident(aredridel)operator(.)ident(new_record?) + ident(assert_equal) ident(no_of_devels)operator(+)integer(1)operator(,) constant(Developer)operator(.)ident(count) + ident(assert_equal) ident(no_of_projects)operator(+)integer(1)operator(,) constant(Project)operator(.)ident(count) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_habtm_adding_before_save_with_join_attributes) + ident(no_of_devels) operator(=) constant(Developer)operator(.)ident(count) + ident(no_of_projects) operator(=) constant(Project)operator(.)ident(count) + ident(now) operator(=) constant(Date)operator(.)ident(today) + ident(ken) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Ken)delimiter(")>operator(\)) + ident(ken)operator(.)ident(projects)operator(.)ident(push_with_attributes)operator(() constant(Project)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) symbol(:joined_on) operator(=)operator(>) ident(now) operator(\)) + ident(p) operator(=) constant(Project)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Foomatic)delimiter(")>operator(\)) + ident(ken)operator(.)ident(projects)operator(.)ident(push_with_attributes)operator(() ident(p)operator(,) symbol(:joined_on) operator(=)operator(>) ident(now) operator(\)) + ident(assert) ident(ken)operator(.)ident(new_record?) + ident(assert) ident(p)operator(.)ident(new_record?) + ident(assert) ident(ken)operator(.)ident(save) + ident(assert) operator(!)ident(ken)operator(.)ident(new_record?) + ident(assert_equal) ident(no_of_devels)operator(+)integer(1)operator(,) constant(Developer)operator(.)ident(count) + ident(assert_equal) ident(no_of_projects)operator(+)integer(1)operator(,) constant(Project)operator(.)ident(count) + ident(assert_equal) integer(2)operator(,) ident(ken)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(ken)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + + ident(kenReloaded) operator(=) constant(Developer)operator(.)ident(find_by_name) string<delimiter(')content(Ken)delimiter(')> + ident(kenReloaded)operator(.)ident(projects)operator(.)ident(each) operator({)operator(|)ident(prj)operator(|) ident(assert_date_from_db)operator(()ident(now)operator(,) ident(prj)operator(.)ident(joined_on)operator(\))operator(}) + reserved(end) + + reserved(def) method(test_habtm_saving_multiple_relationships) + ident(new_project) operator(=) constant(Project)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Grimetime)delimiter(")>operator(\)) + ident(amount_of_developers) operator(=) integer(4) + ident(developers) operator(=) operator(()integer(0)operator(..)ident(amount_of_developers)operator(\))operator(.)ident(collect) operator({)operator(|)ident(i)operator(|) constant(Developer)operator(.)ident(create)operator(()symbol(:name) operator(=)operator(>) string<delimiter(")content(JME )inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")>operator(\)) operator(}) + + ident(new_project)operator(.)ident(developer_ids) operator(=) operator([)ident(developers)operator([)integer(0)operator(])operator(.)ident(id)operator(,) ident(developers)operator([)integer(1)operator(])operator(.)ident(id)operator(]) + ident(new_project)operator(.)ident(developers_with_callback_ids) operator(=) operator([)ident(developers)operator([)integer(2)operator(])operator(.)ident(id)operator(,) ident(developers)operator([)integer(3)operator(])operator(.)ident(id)operator(]) + ident(assert) ident(new_project)operator(.)ident(save) + + ident(new_project)operator(.)ident(reload) + ident(assert_equal) ident(amount_of_developers)operator(,) ident(new_project)operator(.)ident(developers)operator(.)ident(size) + ident(amount_of_developers)operator(.)ident(times) reserved(do) operator(|)ident(i)operator(|) + ident(assert_equal) ident(developers)operator([)ident(i)operator(])operator(.)ident(name)operator(,) ident(new_project)operator(.)ident(developers)operator([)ident(i)operator(])operator(.)ident(name) + reserved(end) + reserved(end) + + reserved(def) method(test_build) + ident(devel) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(proj) operator(=) ident(devel)operator(.)ident(projects)operator(.)ident(build)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Projekt)delimiter(")>operator(\)) + ident(assert_equal) ident(devel)operator(.)ident(projects)operator(.)ident(last)operator(,) ident(proj) + ident(assert) ident(proj)operator(.)ident(new_record?) + ident(devel)operator(.)ident(save) + ident(assert) operator(!)ident(proj)operator(.)ident(new_record?) + ident(assert_equal) ident(devel)operator(.)ident(projects)operator(.)ident(last)operator(,) ident(proj) + reserved(end) + + reserved(def) method(test_create) + ident(devel) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(proj) operator(=) ident(devel)operator(.)ident(projects)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Projekt)delimiter(")>operator(\)) + ident(assert_equal) ident(devel)operator(.)ident(projects)operator(.)ident(last)operator(,) ident(proj) + ident(assert) operator(!)ident(proj)operator(.)ident(new_record?) + reserved(end) + + reserved(def) method(test_uniq_after_the_fact) + ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects) operator(<<) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects) operator(<<) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(uniq)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_uniq_before_the_fact) + ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers) operator(<<) ident(developers)operator(()symbol(:jamis)operator(\)) + ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers) operator(<<) ident(developers)operator(()symbol(:david)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(projects)operator(()symbol(:active_record)operator(,) symbol(:reload)operator(\))operator(.)ident(developers)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(active_record) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(projects)operator(.)ident(reload) + ident(assert_equal) integer(2)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(3)operator(,) ident(active_record)operator(.)ident(developers)operator(.)ident(size) + + ident(david)operator(.)ident(projects)operator(.)ident(delete)operator(()ident(active_record)operator(\)) + + ident(assert_equal) integer(1)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(david)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) ident(active_record)operator(.)ident(developers)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_array) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(projects)operator(.)ident(reload) + ident(david)operator(.)ident(projects)operator(.)ident(delete)operator(()constant(Project)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(\)) + ident(assert_equal) integer(0)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(david)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_with_sql) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(active_record) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(active_record)operator(.)ident(developers)operator(.)ident(reload) + ident(assert_equal) integer(3)operator(,) ident(active_record)operator(.)ident(developers_by_sql)operator(.)ident(size) + + ident(active_record)operator(.)ident(developers_by_sql)operator(.)ident(delete)operator(()ident(david)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(active_record)operator(.)ident(developers_by_sql)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_array_with_sql) + ident(active_record) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(active_record)operator(.)ident(developers)operator(.)ident(reload) + ident(assert_equal) integer(3)operator(,) ident(active_record)operator(.)ident(developers_by_sql)operator(.)ident(size) + + ident(active_record)operator(.)ident(developers_by_sql)operator(.)ident(delete)operator(()constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(\)) + ident(assert_equal) integer(0)operator(,) ident(active_record)operator(.)ident(developers_by_sql)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_deleting_all) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(projects)operator(.)ident(reload) + ident(david)operator(.)ident(projects)operator(.)ident(clear) + ident(assert_equal) integer(0)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) ident(david)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_removing_associations_on_destroy) + ident(david) operator(=) constant(DeveloperWithBeforeDestroyRaise)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(david)operator(.)ident(projects)operator(.)ident(empty?) + ident(assert_nothing_raised) operator({) ident(david)operator(.)ident(destroy) operator(}) + ident(assert) ident(david)operator(.)ident(projects)operator(.)ident(empty?) + ident(assert) constant(DeveloperWithBeforeDestroyRaise)operator(.)ident(connection)operator(.)ident(select_all)operator(()string<delimiter(")content(SELECT * FROM developers_projects WHERE developer_id = 1)delimiter(")>operator(\))operator(.)ident(empty?) + reserved(end) + + reserved(def) method(test_additional_columns_from_join_table) + ident(assert_date_from_db) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(10)operator(,) integer(10)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(projects)operator(.)ident(first)operator(.)ident(joined_on) + reserved(end) + + reserved(def) method(test_destroy_all) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(projects)operator(.)ident(reload) + ident(assert) operator(!)ident(david)operator(.)ident(projects)operator(.)ident(empty?) + ident(david)operator(.)ident(projects)operator(.)ident(destroy_all) + ident(assert) ident(david)operator(.)ident(projects)operator(.)ident(empty?) + ident(assert) ident(david)operator(.)ident(projects)operator(()pre_constant(true)operator(\))operator(.)ident(empty?) + reserved(end) + + reserved(def) method(test_rich_association) + ident(jamis) operator(=) ident(developers)operator(()symbol(:jamis)operator(\)) + ident(jamis)operator(.)ident(projects)operator(.)ident(push_with_attributes)operator(()ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) symbol(:joined_on) operator(=)operator(>) constant(Date)operator(.)ident(today)operator(\)) + + ident(assert_date_from_db) constant(Date)operator(.)ident(today)operator(,) ident(jamis)operator(.)ident(projects)operator(.)ident(select) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(name) operator(==) ident(projects)operator(()symbol(:action_controller)operator(\))operator(.)ident(name) operator(})operator(.)ident(first)operator(.)ident(joined_on) + ident(assert_date_from_db) constant(Date)operator(.)ident(today)operator(,) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(projects)operator(.)ident(select) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(name) operator(==) ident(projects)operator(()symbol(:action_controller)operator(\))operator(.)ident(name) operator(})operator(.)ident(first)operator(.)ident(joined_on) + reserved(end) + + reserved(def) method(test_associations_with_conditions) + ident(assert_equal) integer(3)operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers_named_david)operator(.)ident(size) + + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers_named_david)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(\)) + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(salaried_developers)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(\)) + + ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers_named_david)operator(.)ident(clear) + ident(assert_equal) integer(2)operator(,) ident(projects)operator(()symbol(:active_record)operator(,) symbol(:reload)operator(\))operator(.)ident(developers)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_find_in_association) + comment(# Using sql) + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(\))operator(,) string<delimiter(")content(SQL find)delimiter(")> + + comment(# Using ruby) + ident(active_record) operator(=) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(active_record)operator(.)ident(developers)operator(.)ident(reload) + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(active_record)operator(.)ident(developers)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(\))operator(,) string<delimiter(")content(Ruby find)delimiter(")> + reserved(end) + + reserved(def) method(test_find_in_association_with_custom_finder_sql) + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers_with_finder_sql)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(\))operator(,) string<delimiter(")content(SQL find)delimiter(")> + + ident(active_record) operator(=) ident(projects)operator(()symbol(:active_record)operator(\)) + ident(active_record)operator(.)ident(developers_with_finder_sql)operator(.)ident(reload) + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(active_record)operator(.)ident(developers_with_finder_sql)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(\))operator(,) string<delimiter(")content(Ruby find)delimiter(")> + reserved(end) + + reserved(def) method(test_find_in_association_with_custom_finder_sql_and_string_id) + ident(assert_equal) ident(developers)operator(()symbol(:david)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers_with_finder_sql)operator(.)ident(find)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(.)ident(id)operator(.)ident(to_s)operator(\))operator(,) string<delimiter(")content(SQL find)delimiter(")> + reserved(end) + + reserved(def) method(test_find_with_merged_options) + ident(assert_equal) integer(1)operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(limited_developers)operator(.)ident(size) + ident(assert_equal) integer(1)operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(limited_developers)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(size) + ident(assert_equal) integer(3)operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(limited_developers)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:limit) operator(=)operator(>) pre_constant(nil)operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_new_with_values_in_collection) + ident(jamis) operator(=) constant(DeveloperForProjectWithAfterCreateHook)operator(.)ident(find_by_name)operator(()string<delimiter(')content(Jamis)delimiter(')>operator(\)) + ident(david) operator(=) constant(DeveloperForProjectWithAfterCreateHook)operator(.)ident(find_by_name)operator(()string<delimiter(')content(David)delimiter(')>operator(\)) + ident(project) operator(=) constant(ProjectWithAfterCreateHook)operator(.)ident(new)operator(()symbol(:name) operator(=)operator(>) string<delimiter(")content(Cooking with Bertie)delimiter(")>operator(\)) + ident(project)operator(.)ident(developers) operator(<<) ident(jamis) + ident(project)operator(.)ident(save!) + ident(project)operator(.)ident(reload) + + ident(assert) ident(project)operator(.)ident(developers)operator(.)ident(include?)operator(()ident(jamis)operator(\)) + ident(assert) ident(project)operator(.)ident(developers)operator(.)ident(include?)operator(()ident(david)operator(\)) + reserved(end) + + reserved(def) method(test_find_in_association_with_options) + ident(developers) operator(=) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()symbol(:all)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(developers)operator(.)ident(size) + + ident(assert_equal) ident(developers)operator(()symbol(:poor_jamis)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary < 10000)delimiter(")>operator(\)) + ident(assert_equal) ident(developers)operator(()symbol(:jamis)operator(\))operator(,) ident(projects)operator(()symbol(:active_record)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(salary DESC)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_replace_with_less) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(david)operator(.)ident(projects) operator(=) operator([)ident(projects)operator(()symbol(:action_controller)operator(\))operator(]) + ident(assert) ident(david)operator(.)ident(save) + ident(assert_equal) integer(1)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_replace_with_new) + ident(david) operator(=) ident(developers)operator(()symbol(:david)operator(\)) + ident(david)operator(.)ident(projects) operator(=) operator([)ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) constant(Project)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(ActionWebSearch)delimiter(")>operator(\))operator(]) + ident(david)operator(.)ident(save) + ident(assert_equal) integer(2)operator(,) ident(david)operator(.)ident(projects)operator(.)ident(length) + ident(assert) operator(!)ident(david)operator(.)ident(projects)operator(.)ident(include?)operator(()ident(projects)operator(()symbol(:active_record)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_replace_on_new_object) + ident(new_developer) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Matz)delimiter(")>operator(\)) + ident(new_developer)operator(.)ident(projects) operator(=) operator([)ident(projects)operator(()symbol(:action_controller)operator(\))operator(,) constant(Project)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(ActionWebSearch)delimiter(")>operator(\))operator(]) + ident(new_developer)operator(.)ident(save) + ident(assert_equal) integer(2)operator(,) ident(new_developer)operator(.)ident(projects)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_consider_type) + ident(developer) operator(=) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(special_project) operator(=) constant(SpecialProject)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Special Project)delimiter(")>operator(\)) + + ident(other_project) operator(=) ident(developer)operator(.)ident(projects)operator(.)ident(first) + ident(developer)operator(.)ident(special_projects) operator(<<) ident(special_project) + ident(developer)operator(.)ident(reload) + + ident(assert) ident(developer)operator(.)ident(projects)operator(.)ident(include?)operator(()ident(special_project)operator(\)) + ident(assert) ident(developer)operator(.)ident(special_projects)operator(.)ident(include?)operator(()ident(special_project)operator(\)) + ident(assert) operator(!)ident(developer)operator(.)ident(special_projects)operator(.)ident(include?)operator(()ident(other_project)operator(\)) + reserved(end) + + reserved(def) method(test_update_attributes_after_push_without_duplicate_join_table_rows) + ident(developer) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Kano)delimiter(")>operator(\)) + ident(project) operator(=) constant(SpecialProject)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Special Project)delimiter(")>operator(\)) + ident(assert) ident(developer)operator(.)ident(save) + ident(developer)operator(.)ident(projects) operator(<<) ident(project) + ident(developer)operator(.)ident(update_attribute)operator(()string<delimiter(")content(name)delimiter(")>operator(,) string<delimiter(")content(Bruza)delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(connection)operator(.)ident(select_value)operator(()string<delimiter(<<-end_sql)>operator(\))operator(.)ident(to_i)string<content( + SELECT count(*\) FROM developers_projects + WHERE project_id = )inline<inline_delimiter(#{)ident(project)operator(.)ident(id)inline_delimiter(})>content( + AND developer_id = )inline<inline_delimiter(#{)ident(developer)operator(.)ident(id)inline_delimiter(})>delimiter( + end_sql)> + reserved(end) + + reserved(def) method(test_updating_attributes_on_non_rich_associations) + ident(welcome) operator(=) ident(categories)operator(()symbol(:technology)operator(\))operator(.)ident(posts)operator(.)ident(first) + ident(welcome)operator(.)ident(title) operator(=) string<delimiter(")content(Something else)delimiter(")> + ident(assert) ident(welcome)operator(.)ident(save!) + reserved(end) + + reserved(def) method(test_updating_attributes_on_rich_associations) + ident(david) operator(=) ident(projects)operator(()symbol(:action_controller)operator(\))operator(.)ident(developers)operator(.)ident(first) + ident(david)operator(.)ident(name) operator(=) string<delimiter(")content(DHH)delimiter(")> + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(ReadOnlyRecord)operator(\)) operator({) ident(david)operator(.)ident(save!) operator(}) + reserved(end) + + + reserved(def) method(test_updating_attributes_on_rich_associations_with_limited_find) + ident(david) operator(=) ident(projects)operator(()symbol(:action_controller)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:select) operator(=)operator(>) string<delimiter(")content(developers.*)delimiter(")>operator(\))operator(.)ident(first) + ident(david)operator(.)ident(name) operator(=) string<delimiter(")content(DHH)delimiter(")> + ident(assert) ident(david)operator(.)ident(save!) + reserved(end) + + reserved(def) method(test_join_table_alias) + ident(assert_equal) integer(3)operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:include) operator(=)operator(>) operator({)symbol(:projects) operator(=)operator(>) symbol(:developers)operator(})operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(developers_projects_join.joined_on IS NOT NULL)delimiter(')>operator(\))operator(.)ident(size) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/customer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/default)delimiter(')> +ident(require) string<delimiter(')content(fixtures/auto_id)delimiter(')> +ident(require) string<delimiter(')content(fixtures/column_name)delimiter(')> +ident(require) string<delimiter(')content(fixtures/subscriber)delimiter(')> +ident(require) string<delimiter(')content(fixtures/keyboard)delimiter(')> + +reserved(class) class(Category) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(Smarts) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(CreditCard) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(MasterCreditCard) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(Post) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(Computer) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(NonExistentTable) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) +reserved(class) class(TestOracleDefault) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) + +reserved(class) class(LoosePerson) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(attr_protected) symbol(:credit_rating)operator(,) symbol(:administrator) + pre_constant(self)operator(.)ident(abstract_class) operator(=) pre_constant(true) +reserved(end) + +reserved(class) class(LooseDescendant) operator(<) constant(LoosePerson) + ident(attr_protected) symbol(:phone_number) +reserved(end) + +reserved(class) class(TightPerson) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(attr_accessible) symbol(:name)operator(,) symbol(:address) +reserved(end) + +reserved(class) class(TightDescendant) operator(<) constant(TightPerson) + ident(attr_accessible) symbol(:phone_number) +reserved(end) + +reserved(class) class(Booleantest) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) + +reserved(class) class(Task) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(attr_protected) symbol(:starting) +reserved(end) + +reserved(class) class(BasicsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:companies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:computers) + + reserved(def) method(test_table_exists) + ident(assert) operator(!)constant(NonExistentTable)operator(.)ident(table_exists?) + ident(assert) constant(Topic)operator(.)ident(table_exists?) + reserved(end) + + reserved(def) method(test_set_attributes) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) operator({) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(Budget)delimiter(")>operator(,) string<delimiter(")content(author_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Jason)delimiter(")> operator(}) + ident(topic)operator(.)ident(save) + ident(assert_equal)operator(()string<delimiter(")content(Budget)delimiter(")>operator(,) ident(topic)operator(.)ident(title)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(Jason)delimiter(")>operator(,) ident(topic)operator(.)ident(author_name)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(author_email_address)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(author_email_address)operator(\)) + reserved(end) + + reserved(def) method(test_integers_as_nil) + ident(test) operator(=) constant(AutoId)operator(.)ident(create)operator(()string<delimiter(')content(value)delimiter(')> operator(=)operator(>) string<delimiter(')delimiter(')>operator(\)) + ident(assert_nil) constant(AutoId)operator(.)ident(find)operator(()ident(test)operator(.)ident(id)operator(\))operator(.)ident(value) + reserved(end) + + reserved(def) method(test_set_attributes_with_block) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(Budget)delimiter(")> + ident(t)operator(.)ident(author_name) operator(=) string<delimiter(")content(Jason)delimiter(")> + reserved(end) + + ident(assert_equal)operator(()string<delimiter(")content(Budget)delimiter(")>operator(,) ident(topic)operator(.)ident(title)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(Jason)delimiter(")>operator(,) ident(topic)operator(.)ident(author_name)operator(\)) + reserved(end) + + reserved(def) method(test_respond_to?) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(title?)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(title=)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()symbol(:title)operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()symbol(:title?)operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()symbol(:title=)operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(author_name)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(attribute_names)delimiter(")>operator(\)) + ident(assert) operator(!)ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(nothingness)delimiter(")>operator(\)) + ident(assert) operator(!)ident(topic)operator(.)ident(respond_to?)operator(()symbol(:nothingness)operator(\)) + reserved(end) + + reserved(def) method(test_array_content) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(content) operator(=) string<delimiter(%w()content( one two three )delimiter(\))> + ident(topic)operator(.)ident(save) + + ident(assert_equal)operator(()string<delimiter(%w()content( one two three )delimiter(\))>operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(content)operator(\)) + reserved(end) + + reserved(def) method(test_hash_content) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(content) operator(=) operator({) string<delimiter(")content(one)delimiter(")> operator(=)operator(>) integer(1)operator(,) string<delimiter(")content(two)delimiter(")> operator(=)operator(>) integer(2) operator(}) + ident(topic)operator(.)ident(save) + + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(content)operator([)string<delimiter(")content(two)delimiter(")>operator(]) + + ident(topic)operator(.)ident(content)operator([)string<delimiter(")content(three)delimiter(")>operator(]) operator(=) integer(3) + ident(topic)operator(.)ident(save) + + ident(assert_equal) integer(3)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(content)operator([)string<delimiter(")content(three)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_update_array_content) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(content) operator(=) string<delimiter(%w()content( one two three )delimiter(\))> + + ident(topic)operator(.)ident(content)operator(.)ident(push) string<delimiter(")content(four)delimiter(")> + ident(assert_equal)operator(()string<delimiter(%w()content( one two three four )delimiter(\))>operator(,) ident(topic)operator(.)ident(content)operator(\)) + + ident(topic)operator(.)ident(save) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(topic)operator(.)ident(content) operator(<<) string<delimiter(")content(five)delimiter(")> + ident(assert_equal)operator(()string<delimiter(%w()content( one two three four five )delimiter(\))>operator(,) ident(topic)operator(.)ident(content)operator(\)) + reserved(end) + + reserved(def) method(test_case_sensitive_attributes_hash) + comment(# DB2 is not case-sensitive) + reserved(return) pre_constant(true) reserved(if) ident(current_adapter?)operator(()symbol(:DB2Adapter)operator(\)) + + ident(assert_equal) instance_variable(@loaded_fixtures)operator([)string<delimiter(')content(computers)delimiter(')>operator(])operator([)string<delimiter(')content(workstation)delimiter(')>operator(])operator(.)ident(to_hash)operator(,) constant(Computer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(attributes) + reserved(end) + + reserved(def) method(test_create) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(New Topic)delimiter(")> + ident(topic)operator(.)ident(save) + ident(topic_reloaded) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(New Topic)delimiter(")>operator(,) ident(topic_reloaded)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_save!) + ident(topic) operator(=) constant(Topic)operator(.)ident(new)operator(()symbol(:title) operator(=)operator(>) string<delimiter(")content(New Topic)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(save!) + reserved(end) + + reserved(def) method(test_hashes_not_mangled) + ident(new_topic) operator(=) operator({) symbol(:title) operator(=)operator(>) string<delimiter(")content(New Topic)delimiter(")> operator(}) + ident(new_topic_values) operator(=) operator({) symbol(:title) operator(=)operator(>) string<delimiter(")content(AnotherTopic)delimiter(")> operator(}) + + ident(topic) operator(=) constant(Topic)operator(.)ident(new)operator(()ident(new_topic)operator(\)) + ident(assert_equal) ident(new_topic)operator([)symbol(:title)operator(])operator(,) ident(topic)operator(.)ident(title) + + ident(topic)operator(.)ident(attributes)operator(=) ident(new_topic_values) + ident(assert_equal) ident(new_topic_values)operator([)symbol(:title)operator(])operator(,) ident(topic)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_create_many) + ident(topics) operator(=) constant(Topic)operator(.)ident(create)operator(()operator([) operator({) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(first)delimiter(")> operator(})operator(,) operator({) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(second)delimiter(")> operator(})operator(])operator(\)) + ident(assert_equal) integer(2)operator(,) ident(topics)operator(.)ident(size) + ident(assert_equal) string<delimiter(")content(first)delimiter(")>operator(,) ident(topics)operator(.)ident(first)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_create_columns_not_equal_attributes) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(')content(Another New Topic)delimiter(')> + ident(topic)operator(.)ident(send) symbol(:write_attribute)operator(,) string<delimiter(')content(does_not_exist)delimiter(')>operator(,) string<delimiter(')content(test)delimiter(')> + ident(assert_nothing_raised) operator({) ident(topic)operator(.)ident(save) operator(}) + reserved(end) + + reserved(def) method(test_create_through_factory) + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(New Topic)delimiter(")>operator(\)) + ident(topicReloaded) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(assert_equal)operator(()ident(topic)operator(,) ident(topicReloaded)operator(\)) + reserved(end) + + reserved(def) method(test_update) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(Another New Topic)delimiter(")> + ident(topic)operator(.)ident(written_on) operator(=) string<delimiter(")content(2003-12-12 23:23:00)delimiter(")> + ident(topic)operator(.)ident(save) + ident(topicReloaded) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(Another New Topic)delimiter(")>operator(,) ident(topicReloaded)operator(.)ident(title)operator(\)) + + ident(topicReloaded)operator(.)ident(title) operator(=) string<delimiter(")content(Updated topic)delimiter(")> + ident(topicReloaded)operator(.)ident(save) + + ident(topicReloadedAgain) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + + ident(assert_equal)operator(()string<delimiter(")content(Updated topic)delimiter(")>operator(,) ident(topicReloadedAgain)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_update_columns_not_equal_attributes) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(Still another topic)delimiter(")> + ident(topic)operator(.)ident(save) + + ident(topicReloaded) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(topicReloaded)operator(.)ident(title) operator(=) string<delimiter(")content(A New Topic)delimiter(")> + ident(topicReloaded)operator(.)ident(send) symbol(:write_attribute)operator(,) string<delimiter(')content(does_not_exist)delimiter(')>operator(,) string<delimiter(')content(test)delimiter(')> + ident(assert_nothing_raised) operator({) ident(topicReloaded)operator(.)ident(save) operator(}) + reserved(end) + + reserved(def) method(test_write_attribute) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(send)operator(()symbol(:write_attribute)operator(,) symbol(:title)operator(,) string<delimiter(")content(Still another topic)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Still another topic)delimiter(")>operator(,) ident(topic)operator(.)ident(title) + + ident(topic)operator(.)ident(send)operator(()symbol(:write_attribute)operator(,) string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Still another topic: part 2)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Still another topic: part 2)delimiter(")>operator(,) ident(topic)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_read_attribute) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(Don't change the topic)delimiter(")> + ident(assert_equal) string<delimiter(")content(Don't change the topic)delimiter(")>operator(,) ident(topic)operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(title)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Don't change the topic)delimiter(")>operator(,) ident(topic)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + + ident(assert_equal) string<delimiter(")content(Don't change the topic)delimiter(")>operator(,) ident(topic)operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(Don't change the topic)delimiter(")>operator(,) ident(topic)operator([)symbol(:title)operator(]) + reserved(end) + + reserved(def) method(test_read_attribute_when_false) + ident(topic) operator(=) ident(topics)operator(()symbol(:first)operator(\)) + ident(topic)operator(.)ident(approved) operator(=) pre_constant(false) + ident(assert) operator(!)ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be false)delimiter(")> + ident(topic)operator(.)ident(approved) operator(=) string<delimiter(")content(false)delimiter(")> + ident(assert) operator(!)ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be false)delimiter(")> + reserved(end) + + reserved(def) method(test_read_attribute_when_true) + ident(topic) operator(=) ident(topics)operator(()symbol(:first)operator(\)) + ident(topic)operator(.)ident(approved) operator(=) pre_constant(true) + ident(assert) ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be true)delimiter(")> + ident(topic)operator(.)ident(approved) operator(=) string<delimiter(")content(true)delimiter(")> + ident(assert) ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be true)delimiter(")> + reserved(end) + + reserved(def) method(test_read_write_boolean_attribute) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + comment(# puts "") + comment(# puts "New Topic") + comment(# puts topic.inspect) + ident(topic)operator(.)ident(approved) operator(=) string<delimiter(")content(false)delimiter(")> + comment(# puts "Expecting false") + comment(# puts topic.inspect) + ident(assert) operator(!)ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be false)delimiter(")> + ident(topic)operator(.)ident(approved) operator(=) string<delimiter(")content(false)delimiter(")> + comment(# puts "Expecting false") + comment(# puts topic.inspect) + ident(assert) operator(!)ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be false)delimiter(")> + ident(topic)operator(.)ident(approved) operator(=) string<delimiter(")content(true)delimiter(")> + comment(# puts "Expecting true") + comment(# puts topic.inspect) + ident(assert) ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be true)delimiter(")> + ident(topic)operator(.)ident(approved) operator(=) string<delimiter(")content(true)delimiter(")> + comment(# puts "Expecting true") + comment(# puts topic.inspect) + ident(assert) ident(topic)operator(.)ident(approved?)operator(,) string<delimiter(")content(approved should be true)delimiter(")> + comment(# puts "") + reserved(end) + + reserved(def) method(test_reader_generation) + constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(title) + constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name) + constant(Client)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name) + reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(generate_read_methods) + ident(assert_readers)operator(()constant(Topic)operator(,) string<delimiter(%w()content(type replies_count)delimiter(\))>operator(\)) + ident(assert_readers)operator(()constant(Firm)operator(,) string<delimiter(%w()content(type)delimiter(\))>operator(\)) + ident(assert_readers)operator(()constant(Client)operator(,) string<delimiter(%w()content(type ruby_type rating?)delimiter(\))>operator(\)) + reserved(else) + operator([)constant(Topic)operator(,) constant(Firm)operator(,) constant(Client)operator(])operator(.)ident(each) operator({)operator(|)ident(klass)operator(|) ident(assert_equal) ident(klass)operator(.)ident(read_methods)operator(,) operator({)operator(})operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_reader_for_invalid_column_names) + comment(# column names which aren't legal ruby ids) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(topic)operator(.)ident(send)operator(()symbol(:define_read_method)operator(,) string<delimiter(")content(mumub-jumbo)delimiter(")>operator(.)ident(to_sym)operator(,) string<delimiter(")content(mumub-jumbo)delimiter(")>operator(,) pre_constant(nil)operator(\)) + ident(assert) operator(!)constant(Topic)operator(.)ident(read_methods)operator(.)ident(include?)operator(()string<delimiter(")content(mumub-jumbo)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_non_attribute_access_and_assignment) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(assert) operator(!)ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(mumbo)delimiter(")>operator(\)) + ident(assert_raises)operator(()constant(NoMethodError)operator(\)) operator({) ident(topic)operator(.)ident(mumbo) operator(}) + ident(assert_raises)operator(()constant(NoMethodError)operator(\)) operator({) ident(topic)operator(.)ident(mumbo) operator(=) integer(5) operator(}) + reserved(end) + + reserved(def) method(test_preserving_date_objects) + comment(# SQL Server doesn't have a separate column type just for dates, so all are returned as time) + reserved(return) pre_constant(true) reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) + + reserved(if) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + comment(# Sybase ctlib does not (yet?\) support the date type; use datetime instead.) + ident(assert_kind_of)operator(() + constant(Time)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(last_read)operator(,) + string<delimiter(")content(The last_read attribute should be of the Time class)delimiter(")> + operator(\)) + reserved(else) + ident(assert_kind_of)operator(() + constant(Date)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(last_read)operator(,) + string<delimiter(")content(The last_read attribute should be of the Date class)delimiter(")> + operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_preserving_time_objects) + ident(assert_kind_of)operator(() + constant(Time)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(bonus_time)operator(,) + string<delimiter(")content(The bonus_time attribute should be of the Time class)delimiter(")> + operator(\)) + + ident(assert_kind_of)operator(() + constant(Time)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(written_on)operator(,) + string<delimiter(")content(The written_on attribute should be of the Time class)delimiter(")> + operator(\)) + reserved(end) + + reserved(def) method(test_destroy) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(Yet Another New Topic)delimiter(")> + ident(topic)operator(.)ident(written_on) operator(=) string<delimiter(")content(2003-12-12 23:23:00)delimiter(")> + ident(topic)operator(.)ident(save) + ident(topic)operator(.)ident(destroy) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_destroy_returns_self) + ident(topic) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(Yet Another Title)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(save) + ident(assert_equal) ident(topic)operator(,) ident(topic)operator(.)ident(destroy)operator(,) string<delimiter(")content(destroy did not return destroyed object)delimiter(")> + reserved(end) + + reserved(def) method(test_record_not_found_exception) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(topicReloaded) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(99999)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_initialize_with_attributes) + ident(topic) operator(=) constant(Topic)operator(.)ident(new)operator(()operator({) + string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(initialized from attributes)delimiter(")>operator(,) string<delimiter(")content(written_on)delimiter(")> operator(=)operator(>) string<delimiter(")content(2003-12-12 23:23)delimiter(")> + operator(})operator(\)) + + ident(assert_equal)operator(()string<delimiter(")content(initialized from attributes)delimiter(")>operator(,) ident(topic)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_initialize_with_invalid_attribute) + reserved(begin) + ident(topic) operator(=) constant(Topic)operator(.)ident(new)operator(()operator({) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(test)delimiter(")>operator(,) + string<delimiter(")content(last_read(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2005)delimiter(")>operator(,) string<delimiter(")content(last_read(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2)delimiter(")>operator(,) string<delimiter(")content(last_read(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(31)delimiter(")>operator(})operator(\)) + reserved(rescue) constant(ActiveRecord)operator(::)constant(MultiparameterAssignmentErrors) operator(=)operator(>) ident(ex) + ident(assert_equal)operator(()integer(1)operator(,) ident(ex)operator(.)ident(errors)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(last_read)delimiter(")>operator(,) ident(ex)operator(.)ident(errors)operator([)integer(0)operator(])operator(.)ident(attribute)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_load) + ident(topics) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\)) + ident(assert_equal)operator(()integer(2)operator(,) ident(topics)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(title)operator(,) ident(topics)operator(.)ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_load_with_condition) + ident(topics) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(author_name = 'Mary')delimiter(")>operator(\)) + + ident(assert_equal)operator(()integer(1)operator(,) ident(topics)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:second)operator(\))operator(.)ident(title)operator(,) ident(topics)operator(.)ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_table_name_guesses) + ident(assert_equal) string<delimiter(")content(topics)delimiter(")>operator(,) constant(Topic)operator(.)ident(table_name) + + ident(assert_equal) string<delimiter(")content(categories)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + ident(assert_equal) string<delimiter(")content(smarts)delimiter(")>operator(,) constant(Smarts)operator(.)ident(table_name) + ident(assert_equal) string<delimiter(")content(credit_cards)delimiter(")>operator(,) constant(CreditCard)operator(.)ident(table_name) + ident(assert_equal) string<delimiter(")content(master_credit_cards)delimiter(")>operator(,) constant(MasterCreditCard)operator(.)ident(table_name) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(=) pre_constant(false) + operator([)constant(Category)operator(,) constant(Smarts)operator(,) constant(CreditCard)operator(,) constant(MasterCreditCard)operator(])operator(.)ident(each)operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(reset_table_name)operator(}) + ident(assert_equal) string<delimiter(")content(category)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + ident(assert_equal) string<delimiter(")content(smarts)delimiter(")>operator(,) constant(Smarts)operator(.)ident(table_name) + ident(assert_equal) string<delimiter(")content(credit_card)delimiter(")>operator(,) constant(CreditCard)operator(.)ident(table_name) + ident(assert_equal) string<delimiter(")content(master_credit_card)delimiter(")>operator(,) constant(MasterCreditCard)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(=) pre_constant(true) + operator([)constant(Category)operator(,) constant(Smarts)operator(,) constant(CreditCard)operator(,) constant(MasterCreditCard)operator(])operator(.)ident(each)operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(reset_table_name)operator(}) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")content(test_)delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(test_categories)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")content(_test)delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(test_categories_test)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(categories_test)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(categories)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(=) pre_constant(false) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")content(test_)delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(test_category)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")content(_test)delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(test_category_test)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(category_test)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")delimiter(")> + constant(Category)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(category)delimiter(")>operator(,) constant(Category)operator(.)ident(table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(=) pre_constant(true) + operator([)constant(Category)operator(,) constant(Smarts)operator(,) constant(CreditCard)operator(,) constant(MasterCreditCard)operator(])operator(.)ident(each)operator({)operator(|)ident(c)operator(|) ident(c)operator(.)ident(reset_table_name)operator(}) + reserved(end) + + reserved(def) method(test_destroy_all) + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(count) + + constant(Topic)operator(.)ident(destroy_all) string<delimiter(")content(author_name = 'Mary')delimiter(")> + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_destroy_many) + ident(assert_equal) integer(3)operator(,) constant(Client)operator(.)ident(count) + constant(Client)operator(.)ident(destroy)operator(()operator([)integer(2)operator(,) integer(3)operator(])operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Client)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_delete_many) + constant(Topic)operator(.)ident(delete)operator(()operator([)integer(1)operator(,) integer(2)operator(])operator(\)) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_boolean_attributes) + ident(assert) operator(!) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?) + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(approved?) + reserved(end) + + reserved(def) method(test_increment_counter) + constant(Topic)operator(.)ident(increment_counter)operator(()string<delimiter(")content(replies_count)delimiter(")>operator(,) integer(1)operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(replies_count) + + constant(Topic)operator(.)ident(increment_counter)operator(()string<delimiter(")content(replies_count)delimiter(")>operator(,) integer(1)operator(\)) + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(replies_count) + reserved(end) + + reserved(def) method(test_decrement_counter) + constant(Topic)operator(.)ident(decrement_counter)operator(()string<delimiter(")content(replies_count)delimiter(")>operator(,) integer(2)operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(replies_count) + + constant(Topic)operator(.)ident(decrement_counter)operator(()string<delimiter(")content(replies_count)delimiter(")>operator(,) integer(2)operator(\)) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(replies_count) + reserved(end) + + reserved(def) method(test_update_all) + comment(# The ADO library doesn't support the number of affected rows) + reserved(return) pre_constant(true) reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) + + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(update_all)operator(()string<delimiter(")content(content = 'bulk updated!')delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(bulk updated!)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(content) + ident(assert_equal) string<delimiter(")content(bulk updated!)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(content) + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(update_all)operator(()operator([)string<delimiter(')content(content = ?)delimiter(')>operator(,) string<delimiter(')content(bulk updated again!)delimiter(')>operator(])operator(\)) + ident(assert_equal) string<delimiter(")content(bulk updated again!)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(content) + ident(assert_equal) string<delimiter(")content(bulk updated again!)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(content) + reserved(end) + + reserved(def) method(test_update_many) + ident(topic_data) operator(=) operator({) integer(1) operator(=)operator(>) operator({) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(1 updated)delimiter(")> operator(})operator(,) integer(2) operator(=)operator(>) operator({) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(2 updated)delimiter(")> operator(}) operator(}) + ident(updated) operator(=) constant(Topic)operator(.)ident(update)operator(()ident(topic_data)operator(.)ident(keys)operator(,) ident(topic_data)operator(.)ident(values)operator(\)) + + ident(assert_equal) integer(2)operator(,) ident(updated)operator(.)ident(size) + ident(assert_equal) string<delimiter(")content(1 updated)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(content) + ident(assert_equal) string<delimiter(")content(2 updated)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(content) + reserved(end) + + reserved(def) method(test_delete_all) + comment(# The ADO library doesn't support the number of affected rows) + reserved(return) pre_constant(true) reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) + + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(delete_all) + reserved(end) + + reserved(def) method(test_update_by_condition) + constant(Topic)operator(.)ident(update_all) string<delimiter(")content(content = 'bulk updated!')delimiter(")>operator(,) operator([)string<delimiter(")content(approved = ?)delimiter(")>operator(,) pre_constant(true)operator(]) + ident(assert_equal) string<delimiter(")content(Have a nice day)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(content) + ident(assert_equal) string<delimiter(")content(bulk updated!)delimiter(")>operator(,) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(content) + reserved(end) + + reserved(def) method(test_attribute_present) + ident(t) operator(=) constant(Topic)operator(.)ident(new) + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(hello there!)delimiter(")> + ident(t)operator(.)ident(written_on) operator(=) constant(Time)operator(.)ident(now) + ident(assert) ident(t)operator(.)ident(attribute_present?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(attribute_present?)operator(()string<delimiter(")content(written_on)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(attribute_present?)operator(()string<delimiter(")content(content)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_attribute_keys_on_new_instance) + ident(t) operator(=) constant(Topic)operator(.)ident(new) + ident(assert_equal) pre_constant(nil)operator(,) ident(t)operator(.)ident(title)operator(,) string<delimiter(")content(The topics table has a title column, so it should be nil)delimiter(")> + ident(assert_raise)operator(()constant(NoMethodError)operator(\)) operator({) ident(t)operator(.)ident(title2) operator(}) + reserved(end) + + reserved(def) method(test_class_name) + ident(assert_equal) string<delimiter(")content(Firm)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(()string<delimiter(")content(firms)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Category)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(()string<delimiter(")content(categories)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(AccountHolder)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(()string<delimiter(")content(account_holder)delimiter(")>operator(\)) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(=) pre_constant(false) + ident(assert_equal) string<delimiter(")content(Firms)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(() string<delimiter(")content(firms)delimiter(")> operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(pluralize_table_names) operator(=) pre_constant(true) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")content(test_)delimiter(")> + ident(assert_equal) string<delimiter(")content(Firm)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(() string<delimiter(")content(test_firms)delimiter(")> operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")content(_tests)delimiter(")> + ident(assert_equal) string<delimiter(")content(Firm)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(() string<delimiter(")content(test_firms_tests)delimiter(")> operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")delimiter(")> + ident(assert_equal) string<delimiter(")content(Firm)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(() string<delimiter(")content(firms_tests)delimiter(")> operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")delimiter(")> + ident(assert_equal) string<delimiter(")content(Firm)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(class_name)operator(() string<delimiter(")content(firms)delimiter(")> operator(\)) + reserved(end) + + reserved(def) method(test_null_fields) + ident(assert_nil) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(parent_id) + ident(assert_nil) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(Hey you)delimiter(")>operator(\))operator(.)ident(parent_id) + reserved(end) + + reserved(def) method(test_default_values) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(assert) ident(topic)operator(.)ident(approved?) + ident(assert_nil) ident(topic)operator(.)ident(written_on) + ident(assert_nil) ident(topic)operator(.)ident(bonus_time) + ident(assert_nil) ident(topic)operator(.)ident(last_read) + + ident(topic)operator(.)ident(save) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(assert) ident(topic)operator(.)ident(approved?) + ident(assert_nil) ident(topic)operator(.)ident(last_read) + + comment(# Oracle has some funky default handling, so it requires a bit of ) + comment(# extra testing. See ticket #2788.) + reserved(if) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + ident(test) operator(=) constant(TestOracleDefault)operator(.)ident(new) + ident(assert_equal) string<delimiter(")content(X)delimiter(")>operator(,) ident(test)operator(.)ident(test_char) + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) ident(test)operator(.)ident(test_string) + ident(assert_equal) integer(3)operator(,) ident(test)operator(.)ident(test_int) + reserved(end) + reserved(end) + + reserved(def) method(test_utc_as_time_zone) + comment(# Oracle and SQLServer do not have a TIME datatype.) + reserved(return) pre_constant(true) reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + + constant(Topic)operator(.)ident(default_timezone) operator(=) symbol(:utc) + ident(attributes) operator(=) operator({) string<delimiter(")content(bonus_time)delimiter(")> operator(=)operator(>) string<delimiter(")content(5:42:00AM)delimiter(")> operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_equal) constant(Time)operator(.)ident(utc)operator(()integer(2000)operator(,) integer(1)operator(,) integer(1)operator(,) integer(5)operator(,) integer(42)operator(,) integer(0)operator(\))operator(,) ident(topic)operator(.)ident(bonus_time) + constant(Topic)operator(.)ident(default_timezone) operator(=) symbol(:local) + reserved(end) + + reserved(def) method(test_default_values_on_empty_strings) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(approved) operator(=) pre_constant(nil) + ident(topic)operator(.)ident(last_read) operator(=) pre_constant(nil) + + ident(topic)operator(.)ident(save) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\)) + ident(assert_nil) ident(topic)operator(.)ident(last_read) + + comment(# Sybase adapter does not allow nulls in boolean columns) + reserved(if) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + ident(assert) ident(topic)operator(.)ident(approved) operator(==) pre_constant(false) + reserved(else) + ident(assert_nil) ident(topic)operator(.)ident(approved) + reserved(end) + reserved(end) + + reserved(def) method(test_equality) + ident(assert_equal) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(topic) + reserved(end) + + reserved(def) method(test_equality_of_new_records) + ident(assert_not_equal) constant(Topic)operator(.)ident(new)operator(,) constant(Topic)operator(.)ident(new) + reserved(end) + + reserved(def) method(test_hashing) + ident(assert_equal) operator([) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) operator(])operator(,) operator([) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(topic) operator(]) operator(&) operator([) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) operator(]) + reserved(end) + + reserved(def) method(test_destroy_new_record) + ident(client) operator(=) constant(Client)operator(.)ident(new) + ident(client)operator(.)ident(destroy) + ident(assert) ident(client)operator(.)ident(frozen?) + reserved(end) + + reserved(def) method(test_destroy_record_with_associations) + ident(client) operator(=) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\)) + ident(client)operator(.)ident(destroy) + ident(assert) ident(client)operator(.)ident(frozen?) + ident(assert_kind_of) constant(Firm)operator(,) ident(client)operator(.)ident(firm) + ident(assert_raises)operator(()constant(TypeError)operator(\)) operator({) ident(client)operator(.)ident(name) operator(=) string<delimiter(")content(something else)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_update_attribute) + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?) + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(update_attribute)operator(()string<delimiter(")content(approved)delimiter(")>operator(,) pre_constant(true)operator(\)) + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?) + + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(update_attribute)operator(()symbol(:approved)operator(,) pre_constant(false)operator(\)) + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?) + reserved(end) + + reserved(def) method(test_mass_assignment_protection) + ident(firm) operator(=) constant(Firm)operator(.)ident(new) + ident(firm)operator(.)ident(attributes) operator(=) operator({) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Next Angle)delimiter(")>operator(,) string<delimiter(")content(rating)delimiter(")> operator(=)operator(>) integer(5) operator(}) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(rating) + reserved(end) + + reserved(def) method(test_customized_primary_key_remains_protected) + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(new)operator(()symbol(:nick) operator(=)operator(>) string<delimiter(')content(webster123)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(nice try)delimiter(')>operator(\)) + ident(assert_nil) ident(subscriber)operator(.)ident(id) + + ident(keyboard) operator(=) constant(Keyboard)operator(.)ident(new)operator(()symbol(:key_number) operator(=)operator(>) integer(9)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(nice try)delimiter(')>operator(\)) + ident(assert_nil) ident(keyboard)operator(.)ident(id) + reserved(end) + + reserved(def) method(test_customized_primary_key_remains_protected_when_refered_to_as_id) + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) string<delimiter(')content(webster123)delimiter(')>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(nice try)delimiter(')>operator(\)) + ident(assert_nil) ident(subscriber)operator(.)ident(id) + + ident(keyboard) operator(=) constant(Keyboard)operator(.)ident(new)operator(()symbol(:id) operator(=)operator(>) integer(9)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(')content(nice try)delimiter(')>operator(\)) + ident(assert_nil) ident(keyboard)operator(.)ident(id) + reserved(end) + + reserved(def) method(test_mass_assignment_protection_on_defaults) + ident(firm) operator(=) constant(Firm)operator(.)ident(new) + ident(firm)operator(.)ident(attributes) operator(=) operator({) string<delimiter(")content(id)delimiter(")> operator(=)operator(>) integer(5)operator(,) string<delimiter(")content(type)delimiter(")> operator(=)operator(>) string<delimiter(")content(Client)delimiter(")> operator(}) + ident(assert_nil) ident(firm)operator(.)ident(id) + ident(assert_equal) string<delimiter(")content(Firm)delimiter(")>operator(,) ident(firm)operator([)symbol(:type)operator(]) + reserved(end) + + reserved(def) method(test_mass_assignment_accessible) + ident(reply) operator(=) constant(Reply)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(world)delimiter(")>operator(,) string<delimiter(")content(approved)delimiter(")> operator(=)operator(>) pre_constant(true)operator(\)) + ident(reply)operator(.)ident(save) + + ident(assert) ident(reply)operator(.)ident(approved?) + + ident(reply)operator(.)ident(approved) operator(=) pre_constant(false) + ident(reply)operator(.)ident(save) + + ident(assert) operator(!)ident(reply)operator(.)ident(approved?) + reserved(end) + + reserved(def) method(test_mass_assignment_protection_inheritance) + ident(assert_nil) constant(LoosePerson)operator(.)ident(accessible_attributes) + ident(assert_equal) operator([) symbol(:credit_rating)operator(,) symbol(:administrator) operator(])operator(,) constant(LoosePerson)operator(.)ident(protected_attributes) + + ident(assert_nil) constant(LooseDescendant)operator(.)ident(accessible_attributes) + ident(assert_equal) operator([) symbol(:credit_rating)operator(,) symbol(:administrator)operator(,) symbol(:phone_number) operator(])operator(,) constant(LooseDescendant)operator(.)ident(protected_attributes) + + ident(assert_nil) constant(TightPerson)operator(.)ident(protected_attributes) + ident(assert_equal) operator([) symbol(:name)operator(,) symbol(:address) operator(])operator(,) constant(TightPerson)operator(.)ident(accessible_attributes) + + ident(assert_nil) constant(TightDescendant)operator(.)ident(protected_attributes) + ident(assert_equal) operator([) symbol(:name)operator(,) symbol(:address)operator(,) symbol(:phone_number) operator(])operator(,) constant(TightDescendant)operator(.)ident(accessible_attributes) + reserved(end) + + reserved(def) method(test_multiparameter_attributes_on_date) + ident(attributes) operator(=) operator({) string<delimiter(")content(last_read(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2004)delimiter(")>operator(,) string<delimiter(")content(last_read(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(6)delimiter(")>operator(,) string<delimiter(")content(last_read(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(24)delimiter(")> operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + comment(# note that extra #to_date call allows test to pass for Oracle, which ) + comment(# treats dates/times the same) + ident(assert_date_from_db) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(6)operator(,) integer(24)operator(\))operator(,) ident(topic)operator(.)ident(last_read)operator(.)ident(to_date) + reserved(end) + + reserved(def) method(test_multiparameter_attributes_on_date_with_empty_date) + ident(attributes) operator(=) operator({) string<delimiter(")content(last_read(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2004)delimiter(")>operator(,) string<delimiter(")content(last_read(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(6)delimiter(")>operator(,) string<delimiter(")content(last_read(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")> operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + comment(# note that extra #to_date call allows test to pass for Oracle, which ) + comment(# treats dates/times the same) + ident(assert_date_from_db) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(6)operator(,) integer(1)operator(\))operator(,) ident(topic)operator(.)ident(last_read)operator(.)ident(to_date) + reserved(end) + + reserved(def) method(test_multiparameter_attributes_on_date_with_all_empty) + ident(attributes) operator(=) operator({) string<delimiter(")content(last_read(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(last_read(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(last_read(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")> operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_nil) ident(topic)operator(.)ident(last_read) + reserved(end) + + reserved(def) method(test_multiparameter_attributes_on_time) + ident(attributes) operator(=) operator({) + string<delimiter(")content(written_on(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2004)delimiter(")>operator(,) string<delimiter(")content(written_on(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(6)delimiter(")>operator(,) string<delimiter(")content(written_on(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(24)delimiter(")>operator(,) + string<delimiter(")content(written_on(4i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(16)delimiter(")>operator(,) string<delimiter(")content(written_on(5i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(24)delimiter(")>operator(,) string<delimiter(")content(written_on(6i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(00)delimiter(")> + operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_equal) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(6)operator(,) integer(24)operator(,) integer(16)operator(,) integer(24)operator(,) integer(0)operator(\))operator(,) ident(topic)operator(.)ident(written_on) + reserved(end) + + reserved(def) method(test_multiparameter_attributes_on_time_with_empty_seconds) + ident(attributes) operator(=) operator({) + string<delimiter(")content(written_on(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2004)delimiter(")>operator(,) string<delimiter(")content(written_on(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(6)delimiter(")>operator(,) string<delimiter(")content(written_on(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(24)delimiter(")>operator(,) + string<delimiter(")content(written_on(4i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(16)delimiter(")>operator(,) string<delimiter(")content(written_on(5i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(24)delimiter(")>operator(,) string<delimiter(")content(written_on(6i\))delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")> + operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_equal) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(6)operator(,) integer(24)operator(,) integer(16)operator(,) integer(24)operator(,) integer(0)operator(\))operator(,) ident(topic)operator(.)ident(written_on) + reserved(end) + + reserved(def) method(test_multiparameter_mass_assignment_protector) + ident(task) operator(=) constant(Task)operator(.)ident(new) + ident(time) operator(=) constant(Time)operator(.)ident(mktime)operator(()integer(2000)operator(,) integer(1)operator(,) integer(1)operator(,) integer(1)operator(\)) + ident(task)operator(.)ident(starting) operator(=) ident(time) + ident(attributes) operator(=) operator({) string<delimiter(")content(starting(1i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(2004)delimiter(")>operator(,) string<delimiter(")content(starting(2i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(6)delimiter(")>operator(,) string<delimiter(")content(starting(3i\))delimiter(")> operator(=)operator(>) string<delimiter(")content(24)delimiter(")> operator(}) + ident(task)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_equal) ident(time)operator(,) ident(task)operator(.)ident(starting) + reserved(end) + + reserved(def) method(test_multiparameter_assignment_of_aggregation) + ident(customer) operator(=) constant(Customer)operator(.)ident(new) + ident(address) operator(=) constant(Address)operator(.)ident(new)operator(()string<delimiter(")content(The Street)delimiter(")>operator(,) string<delimiter(")content(The City)delimiter(")>operator(,) string<delimiter(")content(The Country)delimiter(")>operator(\)) + ident(attributes) operator(=) operator({) string<delimiter(")content(address(1\))delimiter(")> operator(=)operator(>) ident(address)operator(.)ident(street)operator(,) string<delimiter(")content(address(2\))delimiter(")> operator(=)operator(>) ident(address)operator(.)ident(city)operator(,) string<delimiter(")content(address(3\))delimiter(")> operator(=)operator(>) ident(address)operator(.)ident(country) operator(}) + ident(customer)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_equal) ident(address)operator(,) ident(customer)operator(.)ident(address) + reserved(end) + + reserved(def) method(test_attributes_on_dummy_time) + comment(# Oracle and SQL Server do not have a TIME datatype.) + reserved(return) pre_constant(true) reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + + ident(attributes) operator(=) operator({) + string<delimiter(")content(bonus_time)delimiter(")> operator(=)operator(>) string<delimiter(")content(5:42:00AM)delimiter(")> + operator(}) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(attributes) operator(=) ident(attributes) + ident(assert_equal) constant(Time)operator(.)ident(local)operator(()integer(2000)operator(,) integer(1)operator(,) integer(1)operator(,) integer(5)operator(,) integer(42)operator(,) integer(0)operator(\))operator(,) ident(topic)operator(.)ident(bonus_time) + reserved(end) + + reserved(def) method(test_boolean) + ident(b_false) operator(=) constant(Booleantest)operator(.)ident(create)operator(()operator({) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) pre_constant(false) operator(})operator(\)) + ident(false_id) operator(=) ident(b_false)operator(.)ident(id) + ident(b_true) operator(=) constant(Booleantest)operator(.)ident(create)operator(()operator({) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) pre_constant(true) operator(})operator(\)) + ident(true_id) operator(=) ident(b_true)operator(.)ident(id) + + ident(b_false) operator(=) constant(Booleantest)operator(.)ident(find)operator(()ident(false_id)operator(\)) + ident(assert) operator(!)ident(b_false)operator(.)ident(value?) + ident(b_true) operator(=) constant(Booleantest)operator(.)ident(find)operator(()ident(true_id)operator(\)) + ident(assert) ident(b_true)operator(.)ident(value?) + reserved(end) + + reserved(def) method(test_boolean_cast_from_string) + ident(b_false) operator(=) constant(Booleantest)operator(.)ident(create)operator(()operator({) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(0)delimiter(")> operator(})operator(\)) + ident(false_id) operator(=) ident(b_false)operator(.)ident(id) + ident(b_true) operator(=) constant(Booleantest)operator(.)ident(create)operator(()operator({) string<delimiter(")content(value)delimiter(")> operator(=)operator(>) string<delimiter(")content(1)delimiter(")> operator(})operator(\)) + ident(true_id) operator(=) ident(b_true)operator(.)ident(id) + + ident(b_false) operator(=) constant(Booleantest)operator(.)ident(find)operator(()ident(false_id)operator(\)) + ident(assert) operator(!)ident(b_false)operator(.)ident(value?) + ident(b_true) operator(=) constant(Booleantest)operator(.)ident(find)operator(()ident(true_id)operator(\)) + ident(assert) ident(b_true)operator(.)ident(value?) + reserved(end) + + reserved(def) method(test_clone) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(cloned_topic) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(cloned_topic) operator(=) ident(topic)operator(.)ident(clone) operator(}) + ident(assert_equal) ident(topic)operator(.)ident(title)operator(,) ident(cloned_topic)operator(.)ident(title) + ident(assert) ident(cloned_topic)operator(.)ident(new_record?) + + comment(# test if the attributes have been cloned) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(a)delimiter(")> + ident(cloned_topic)operator(.)ident(title) operator(=) string<delimiter(")content(b)delimiter(")> + ident(assert_equal) string<delimiter(")content(a)delimiter(")>operator(,) ident(topic)operator(.)ident(title) + ident(assert_equal) string<delimiter(")content(b)delimiter(")>operator(,) ident(cloned_topic)operator(.)ident(title) + + comment(# test if the attribute values have been cloned) + ident(topic)operator(.)ident(title) operator(=) operator({)string<delimiter(")content(a)delimiter(")> operator(=)operator(>) string<delimiter(")content(b)delimiter(")>operator(}) + ident(cloned_topic) operator(=) ident(topic)operator(.)ident(clone) + ident(cloned_topic)operator(.)ident(title)operator([)string<delimiter(")content(a)delimiter(")>operator(]) operator(=) string<delimiter(")content(c)delimiter(")> + ident(assert_equal) string<delimiter(")content(b)delimiter(")>operator(,) ident(topic)operator(.)ident(title)operator([)string<delimiter(")content(a)delimiter(")>operator(]) + + ident(cloned_topic)operator(.)ident(save) + ident(assert) operator(!)ident(cloned_topic)operator(.)ident(new_record?) + ident(assert) ident(cloned_topic)operator(.)ident(id) operator(!=) ident(topic)operator(.)ident(id) + reserved(end) + + reserved(def) method(test_clone_with_aggregate_of_same_name_as_attribute) + ident(dev) operator(=) constant(DeveloperWithAggregate)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_kind_of) constant(DeveloperSalary)operator(,) ident(dev)operator(.)ident(salary) + + ident(clone) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(clone) operator(=) ident(dev)operator(.)ident(clone) operator(}) + ident(assert_kind_of) constant(DeveloperSalary)operator(,) ident(clone)operator(.)ident(salary) + ident(assert_equal) ident(dev)operator(.)ident(salary)operator(.)ident(amount)operator(,) ident(clone)operator(.)ident(salary)operator(.)ident(amount) + ident(assert) ident(clone)operator(.)ident(new_record?) + + comment(# test if the attributes have been cloned) + ident(original_amount) operator(=) ident(clone)operator(.)ident(salary)operator(.)ident(amount) + ident(dev)operator(.)ident(salary)operator(.)ident(amount) operator(=) integer(1) + ident(assert_equal) ident(original_amount)operator(,) ident(clone)operator(.)ident(salary)operator(.)ident(amount) + + ident(assert) ident(clone)operator(.)ident(save) + ident(assert) operator(!)ident(clone)operator(.)ident(new_record?) + ident(assert) ident(clone)operator(.)ident(id) operator(!=) ident(dev)operator(.)ident(id) + reserved(end) + + reserved(def) method(test_clone_preserves_subtype) + ident(clone) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(clone) operator(=) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(clone) operator(}) + ident(assert_kind_of) constant(Client)operator(,) ident(clone) + reserved(end) + + reserved(def) method(test_bignum) + ident(company) operator(=) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(company)operator(.)ident(rating) operator(=) integer(2147483647) + ident(company)operator(.)ident(save) + ident(company) operator(=) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) integer(2147483647)operator(,) ident(company)operator(.)ident(rating) + reserved(end) + + comment(# TODO: extend defaults tests to other databases!) + reserved(if) ident(current_adapter?)operator(()symbol(:PostgreSQLAdapter)operator(\)) + reserved(def) method(test_default) + ident(default) operator(=) constant(Default)operator(.)ident(new) + + comment(# fixed dates / times) + ident(assert_equal) constant(Date)operator(.)ident(new)operator(()integer(2004)operator(,) integer(1)operator(,) integer(1)operator(\))operator(,) ident(default)operator(.)ident(fixed_date) + ident(assert_equal) constant(Time)operator(.)ident(local)operator(()integer(2004)operator(,) integer(1)operator(,)integer(1)operator(,)integer(0)operator(,)integer(0)operator(,)integer(0)operator(,)integer(0)operator(\))operator(,) ident(default)operator(.)ident(fixed_time) + + comment(# char types) + ident(assert_equal) string<delimiter(')content(Y)delimiter(')>operator(,) ident(default)operator(.)ident(char1) + ident(assert_equal) string<delimiter(')content(a varchar field)delimiter(')>operator(,) ident(default)operator(.)ident(char2) + ident(assert_equal) string<delimiter(')content(a text field)delimiter(')>operator(,) ident(default)operator(.)ident(char3) + reserved(end) + + reserved(class) class(Geometric) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) + reserved(def) method(test_geometric_content) + + comment(# accepted format notes:) + comment(# (\)'s aren't required) + comment(# values can be a mix of float or integer) + + ident(g) operator(=) constant(Geometric)operator(.)ident(new)operator(() + symbol(:a_point) operator(=)operator(>) string<delimiter(')content((5.0, 6.1\))delimiter(')>operator(,) + comment(#:a_line => '((2.0, 3\), (5.5, 7.0\)\)' # line type is currently unsupported in postgresql) + symbol(:a_line_segment) operator(=)operator(>) string<delimiter(')content((2.0, 3\), (5.5, 7.0\))delimiter(')>operator(,) + symbol(:a_box) operator(=)operator(>) string<delimiter(')content(2.0, 3, 5.5, 7.0)delimiter(')>operator(,) + symbol(:a_path) operator(=)operator(>) string<delimiter(')content([(2.0, 3\), (5.5, 7.0\), (8.5, 11.0\)])delimiter(')>operator(,) comment(# [ ] is an open path) + symbol(:a_polygon) operator(=)operator(>) string<delimiter(')content(((2.0, 3\), (5.5, 7.0\), (8.5, 11.0\)\))delimiter(')>operator(,) + symbol(:a_circle) operator(=)operator(>) string<delimiter(')content(<(5.3, 10.4\), 2>)delimiter(')> + operator(\)) + + ident(assert) ident(g)operator(.)ident(save) + + comment(# Reload and check that we have all the geometric attributes.) + ident(h) operator(=) constant(Geometric)operator(.)ident(find)operator(()ident(g)operator(.)ident(id)operator(\)) + + ident(assert_equal) string<delimiter(')content((5,6.1\))delimiter(')>operator(,) ident(h)operator(.)ident(a_point) + ident(assert_equal) string<delimiter(')content([(2,3\),(5.5,7\)])delimiter(')>operator(,) ident(h)operator(.)ident(a_line_segment) + ident(assert_equal) string<delimiter(')content((5.5,7\),(2,3\))delimiter(')>operator(,) ident(h)operator(.)ident(a_box) comment(# reordered to store upper right corner then bottom left corner) + ident(assert_equal) string<delimiter(')content([(2,3\),(5.5,7\),(8.5,11\)])delimiter(')>operator(,) ident(h)operator(.)ident(a_path) + ident(assert_equal) string<delimiter(')content(((2,3\),(5.5,7\),(8.5,11\)\))delimiter(')>operator(,) ident(h)operator(.)ident(a_polygon) + ident(assert_equal) string<delimiter(')content(<(5.3,10.4\),2>)delimiter(')>operator(,) ident(h)operator(.)ident(a_circle) + + comment(# use a geometric function to test for an open path) + ident(objs) operator(=) constant(Geometric)operator(.)ident(find_by_sql) operator([)string<delimiter(")content(select isopen(a_path\) from geometrics where id = ?)delimiter(")>operator(,) ident(g)operator(.)ident(id)operator(]) + ident(assert_equal) ident(objs)operator([)integer(0)operator(])operator(.)ident(isopen)operator(,) string<delimiter(')content(t)delimiter(')> + + comment(# test alternate formats when defining the geometric types) + + ident(g) operator(=) constant(Geometric)operator(.)ident(new)operator(() + symbol(:a_point) operator(=)operator(>) string<delimiter(')content(5.0, 6.1)delimiter(')>operator(,) + comment(#:a_line => '((2.0, 3\), (5.5, 7.0\)\)' # line type is currently unsupported in postgresql) + symbol(:a_line_segment) operator(=)operator(>) string<delimiter(')content(((2.0, 3\), (5.5, 7.0\)\))delimiter(')>operator(,) + symbol(:a_box) operator(=)operator(>) string<delimiter(')content((2.0, 3\), (5.5, 7.0\))delimiter(')>operator(,) + symbol(:a_path) operator(=)operator(>) string<delimiter(')content(((2.0, 3\), (5.5, 7.0\), (8.5, 11.0\)\))delimiter(')>operator(,) comment(# ( \) is a closed path) + symbol(:a_polygon) operator(=)operator(>) string<delimiter(')content(2.0, 3, 5.5, 7.0, 8.5, 11.0)delimiter(')>operator(,) + symbol(:a_circle) operator(=)operator(>) string<delimiter(')content(((5.3, 10.4\), 2\))delimiter(')> + operator(\)) + + ident(assert) ident(g)operator(.)ident(save) + + comment(# Reload and check that we have all the geometric attributes.) + ident(h) operator(=) constant(Geometric)operator(.)ident(find)operator(()ident(g)operator(.)ident(id)operator(\)) + + ident(assert_equal) string<delimiter(')content((5,6.1\))delimiter(')>operator(,) ident(h)operator(.)ident(a_point) + ident(assert_equal) string<delimiter(')content([(2,3\),(5.5,7\)])delimiter(')>operator(,) ident(h)operator(.)ident(a_line_segment) + ident(assert_equal) string<delimiter(')content((5.5,7\),(2,3\))delimiter(')>operator(,) ident(h)operator(.)ident(a_box) comment(# reordered to store upper right corner then bottom left corner) + ident(assert_equal) string<delimiter(')content(((2,3\),(5.5,7\),(8.5,11\)\))delimiter(')>operator(,) ident(h)operator(.)ident(a_path) + ident(assert_equal) string<delimiter(')content(((2,3\),(5.5,7\),(8.5,11\)\))delimiter(')>operator(,) ident(h)operator(.)ident(a_polygon) + ident(assert_equal) string<delimiter(')content(<(5.3,10.4\),2>)delimiter(')>operator(,) ident(h)operator(.)ident(a_circle) + + comment(# use a geometric function to test for an closed path) + ident(objs) operator(=) constant(Geometric)operator(.)ident(find_by_sql) operator([)string<delimiter(")content(select isclosed(a_path\) from geometrics where id = ?)delimiter(")>operator(,) ident(g)operator(.)ident(id)operator(]) + ident(assert_equal) ident(objs)operator([)integer(0)operator(])operator(.)ident(isclosed)operator(,) string<delimiter(')content(t)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(test_auto_id) + ident(auto) operator(=) constant(AutoId)operator(.)ident(new) + ident(auto)operator(.)ident(save) + ident(assert) operator(()ident(auto)operator(.)ident(id) operator(>) integer(0)operator(\)) + reserved(end) + + reserved(def) method(quote_column_name)operator(()ident(name)operator(\)) + string<delimiter(")content(<)inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + reserved(def) method(test_quote_keys) + ident(ar) operator(=) constant(AutoId)operator(.)ident(new) + ident(source) operator(=) operator({)string<delimiter(")content(foo)delimiter(")> operator(=)operator(>) string<delimiter(")content(bar)delimiter(")>operator(,) string<delimiter(")content(baz)delimiter(")> operator(=)operator(>) string<delimiter(")content(quux)delimiter(")>operator(}) + ident(actual) operator(=) ident(ar)operator(.)ident(send)operator(()symbol(:quote_columns)operator(,) pre_constant(self)operator(,) ident(source)operator(\)) + ident(inverted) operator(=) ident(actual)operator(.)ident(invert) + ident(assert_equal)operator(()string<delimiter(")content(<foo>)delimiter(")>operator(,) ident(inverted)operator([)string<delimiter(")content(bar)delimiter(")>operator(])operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(<baz>)delimiter(")>operator(,) ident(inverted)operator([)string<delimiter(")content(quux)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_sql_injection_via_find) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) reserved(do) + constant(Topic)operator(.)ident(find)operator(()string<delimiter(")content(123456 OR id > 0)delimiter(")>operator(\)) + reserved(end) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) reserved(do) + constant(Topic)operator(.)ident(find)operator(()string<delimiter(")content(;;; this should raise an RecordNotFound error)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_column_name_properly_quoted) + ident(col_record) operator(=) constant(ColumnName)operator(.)ident(new) + ident(col_record)operator(.)ident(references) operator(=) integer(40) + ident(assert) ident(col_record)operator(.)ident(save) + ident(col_record)operator(.)ident(references) operator(=) integer(41) + ident(assert) ident(col_record)operator(.)ident(save) + ident(assert_not_nil) ident(c2) operator(=) constant(ColumnName)operator(.)ident(find)operator(()ident(col_record)operator(.)ident(id)operator(\)) + ident(assert_equal)operator(()integer(41)operator(,) ident(c2)operator(.)ident(references)operator(\)) + reserved(end) + + constant(MyObject) operator(=) constant(Struct)operator(.)ident(new) symbol(:attribute1)operator(,) symbol(:attribute2) + + reserved(def) method(test_serialized_attribute) + ident(myobj) operator(=) constant(MyObject)operator(.)ident(new)operator(()string<delimiter(')content(value1)delimiter(')>operator(,) string<delimiter(')content(value2)delimiter(')>operator(\)) + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) ident(myobj)operator(\)) + constant(Topic)operator(.)ident(serialize)operator(()string<delimiter(")content(content)delimiter(")>operator(,) constant(MyObject)operator(\)) + ident(assert_equal)operator(()ident(myobj)operator(,) ident(topic)operator(.)ident(content)operator(\)) + reserved(end) + + reserved(def) method(test_serialized_attribute_with_class_constraint) + ident(myobj) operator(=) constant(MyObject)operator(.)ident(new)operator(()string<delimiter(')content(value1)delimiter(')>operator(,) string<delimiter(')content(value2)delimiter(')>operator(\)) + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) ident(myobj)operator(\)) + constant(Topic)operator(.)ident(serialize)operator(()symbol(:content)operator(,) constant(Hash)operator(\)) + + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(SerializationTypeMismatch)operator(\)) operator({) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(content) operator(}) + + ident(settings) operator(=) operator({) string<delimiter(")content(color)delimiter(")> operator(=)operator(>) string<delimiter(")content(blue)delimiter(")> operator(}) + constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(update_attribute)operator(()string<delimiter(")content(content)delimiter(")>operator(,) ident(settings)operator(\)) + ident(assert_equal)operator(()ident(settings)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(content)operator(\)) + constant(Topic)operator(.)ident(serialize)operator(()symbol(:content)operator(\)) + reserved(end) + + reserved(def) method(test_quote) + ident(author_name) operator(=) string<delimiter(")char(\\\\)content( )char(\\001)content( ' )char(\\n)content( )char(\\\\)content(n )char(\\")delimiter(")> + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(')content(author_name)delimiter(')> operator(=)operator(>) ident(author_name)operator(\)) + ident(assert_equal) ident(author_name)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(author_name) + reserved(end) + + reserved(def) method(test_class_level_destroy) + ident(should_be_destroyed_reply) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(world)delimiter(")>operator(\)) + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(replies) operator(<<) ident(should_be_destroyed_reply) + + constant(Topic)operator(.)ident(destroy)operator(()integer(1)operator(\)) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Reply)operator(.)ident(find)operator(()ident(should_be_destroyed_reply)operator(.)ident(id)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_class_level_delete) + ident(should_be_destroyed_reply) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(world)delimiter(")>operator(\)) + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(replies) operator(<<) ident(should_be_destroyed_reply) + + constant(Topic)operator(.)ident(delete)operator(()integer(1)operator(\)) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Reply)operator(.)ident(find)operator(()ident(should_be_destroyed_reply)operator(.)ident(id)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_increment_attribute) + ident(assert_equal) integer(0)operator(,) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(replies_count) + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(increment!) symbol(:replies_count) + ident(assert_equal) integer(1)operator(,) ident(topics)operator(()symbol(:first)operator(,) symbol(:reload)operator(\))operator(.)ident(replies_count) + + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(increment)operator(()symbol(:replies_count)operator(\))operator(.)ident(increment!)operator(()symbol(:replies_count)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(topics)operator(()symbol(:first)operator(,) symbol(:reload)operator(\))operator(.)ident(replies_count) + reserved(end) + + reserved(def) method(test_increment_nil_attribute) + ident(assert_nil) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(parent_id) + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(increment!) symbol(:parent_id) + ident(assert_equal) integer(1)operator(,) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(parent_id) + reserved(end) + + reserved(def) method(test_decrement_attribute) + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(increment)operator(()symbol(:replies_count)operator(\))operator(.)ident(increment!)operator(()symbol(:replies_count)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(replies_count) + + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(decrement!)operator(()symbol(:replies_count)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(topics)operator(()symbol(:first)operator(,) symbol(:reload)operator(\))operator(.)ident(replies_count) + + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(decrement)operator(()symbol(:replies_count)operator(\))operator(.)ident(decrement!)operator(()symbol(:replies_count)operator(\)) + ident(assert_equal) integer(-1)operator(,) ident(topics)operator(()symbol(:first)operator(,) symbol(:reload)operator(\))operator(.)ident(replies_count) + reserved(end) + + reserved(def) method(test_toggle_attribute) + ident(assert) operator(!)ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(approved?) + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(toggle!)operator(()symbol(:approved)operator(\)) + ident(assert) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(approved?) + ident(topic) operator(=) ident(topics)operator(()symbol(:first)operator(\)) + ident(topic)operator(.)ident(toggle)operator(()symbol(:approved)operator(\)) + ident(assert) operator(!)ident(topic)operator(.)ident(approved?) + ident(topic)operator(.)ident(reload) + ident(assert) ident(topic)operator(.)ident(approved?) + reserved(end) + + reserved(def) method(test_reload) + ident(t1) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(t2) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(t1)operator(.)ident(title) operator(=) string<delimiter(")content(something else)delimiter(")> + ident(t1)operator(.)ident(save) + ident(t2)operator(.)ident(reload) + ident(assert_equal) ident(t1)operator(.)ident(title)operator(,) ident(t2)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_define_attr_method_with_value) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(send)operator(()symbol(:define_attr_method)operator(,) symbol(:table_name)operator(,) string<delimiter(")content(foo)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(foo)delimiter(")>operator(,) ident(k)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(test_define_attr_method_with_block) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(send)operator(()symbol(:define_attr_method)operator(,) symbol(:primary_key)operator(\)) operator({) string<delimiter(")content(sys_)delimiter(")> operator(+) ident(original_primary_key) operator(}) + ident(assert_equal) string<delimiter(")content(sys_id)delimiter(")>operator(,) ident(k)operator(.)ident(primary_key) + reserved(end) + + reserved(def) method(test_set_table_name_with_value) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(table_name) operator(=) string<delimiter(")content(foo)delimiter(")> + ident(assert_equal) string<delimiter(")content(foo)delimiter(")>operator(,) ident(k)operator(.)ident(table_name) + ident(k)operator(.)ident(set_table_name) string<delimiter(")content(bar)delimiter(")> + ident(assert_equal) string<delimiter(")content(bar)delimiter(")>operator(,) ident(k)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(test_set_table_name_with_block) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(set_table_name) operator({) string<delimiter(")content(ks)delimiter(")> operator(}) + ident(assert_equal) string<delimiter(")content(ks)delimiter(")>operator(,) ident(k)operator(.)ident(table_name) + reserved(end) + + reserved(def) method(test_set_primary_key_with_value) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(primary_key) operator(=) string<delimiter(")content(foo)delimiter(")> + ident(assert_equal) string<delimiter(")content(foo)delimiter(")>operator(,) ident(k)operator(.)ident(primary_key) + ident(k)operator(.)ident(set_primary_key) string<delimiter(")content(bar)delimiter(")> + ident(assert_equal) string<delimiter(")content(bar)delimiter(")>operator(,) ident(k)operator(.)ident(primary_key) + reserved(end) + + reserved(def) method(test_set_primary_key_with_block) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(set_primary_key) operator({) string<delimiter(")content(sys_)delimiter(")> operator(+) ident(original_primary_key) operator(}) + ident(assert_equal) string<delimiter(")content(sys_id)delimiter(")>operator(,) ident(k)operator(.)ident(primary_key) + reserved(end) + + reserved(def) method(test_set_inheritance_column_with_value) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(inheritance_column) operator(=) string<delimiter(")content(foo)delimiter(")> + ident(assert_equal) string<delimiter(")content(foo)delimiter(")>operator(,) ident(k)operator(.)ident(inheritance_column) + ident(k)operator(.)ident(set_inheritance_column) string<delimiter(")content(bar)delimiter(")> + ident(assert_equal) string<delimiter(")content(bar)delimiter(")>operator(,) ident(k)operator(.)ident(inheritance_column) + reserved(end) + + reserved(def) method(test_set_inheritance_column_with_block) + ident(k) operator(=) constant(Class)operator(.)ident(new)operator(() constant(ActiveRecord)operator(::)constant(Base) operator(\)) + ident(k)operator(.)ident(set_inheritance_column) operator({) ident(original_inheritance_column) operator(+) string<delimiter(")content(_id)delimiter(")> operator(}) + ident(assert_equal) string<delimiter(")content(type_id)delimiter(")>operator(,) ident(k)operator(.)ident(inheritance_column) + reserved(end) + + reserved(def) method(test_count_with_join) + ident(res) operator(=) constant(Post)operator(.)ident(count_by_sql) string<delimiter(")content(SELECT COUNT(*\) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post')delimiter(")> + ident(res2) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(res2) operator(=) constant(Post)operator(.)ident(count)operator(()string<delimiter(")content(posts.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post')delimiter(")>operator(,) + string<delimiter(")content(LEFT JOIN comments ON posts.id=comments.post_id)delimiter(")>operator(\)) + reserved(end) + ident(assert_equal) ident(res)operator(,) ident(res2) + + ident(res3) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(res3) operator(=) constant(Post)operator(.)ident(count)operator(()symbol(:conditions) operator(=)operator(>) string<delimiter(")content(posts.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post')delimiter(")>operator(,) + symbol(:joins) operator(=)operator(>) string<delimiter(")content(LEFT JOIN comments ON posts.id=comments.post_id)delimiter(")>operator(\)) + reserved(end) + ident(assert_equal) ident(res)operator(,) ident(res3) + + ident(res4) operator(=) constant(Post)operator(.)ident(count_by_sql) string<delimiter(")content(SELECT COUNT(p.id\) FROM posts p, comments c WHERE p.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post' AND p.id=c.post_id)delimiter(")> + ident(res5) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(res5) operator(=) constant(Post)operator(.)ident(count)operator(()symbol(:conditions) operator(=)operator(>) string<delimiter(")content(p.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post' AND p.id=c.post_id)delimiter(")>operator(,) + symbol(:joins) operator(=)operator(>) string<delimiter(")content(p, comments c)delimiter(")>operator(,) + symbol(:select) operator(=)operator(>) string<delimiter(")content(p.id)delimiter(")>operator(\)) + reserved(end) + + ident(assert_equal) ident(res4)operator(,) ident(res5) + + ident(res6) operator(=) constant(Post)operator(.)ident(count_by_sql) string<delimiter(")content(SELECT COUNT(DISTINCT p.id\) FROM posts p, comments c WHERE p.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post' AND p.id=c.post_id)delimiter(")> + ident(res7) operator(=) pre_constant(nil) + ident(assert_nothing_raised) reserved(do) + ident(res7) operator(=) constant(Post)operator(.)ident(count)operator(()symbol(:conditions) operator(=)operator(>) string<delimiter(")content(p.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post' AND p.id=c.post_id)delimiter(")>operator(,) + symbol(:joins) operator(=)operator(>) string<delimiter(")content(p, comments c)delimiter(")>operator(,) + symbol(:select) operator(=)operator(>) string<delimiter(")content(p.id)delimiter(")>operator(,) + symbol(:distinct) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + ident(assert_equal) ident(res6)operator(,) ident(res7) + reserved(end) + + reserved(def) method(test_clear_association_cache_stored) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_kind_of) constant(Firm)operator(,) ident(firm) + + ident(firm)operator(.)ident(clear_association_cache) + ident(assert_equal) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(clients)operator(.)ident(collect)operator({) operator(|)ident(x)operator(|) ident(x)operator(.)ident(name) operator(})operator(.)ident(sort)operator(,) ident(firm)operator(.)ident(clients)operator(.)ident(collect)operator({) operator(|)ident(x)operator(|) ident(x)operator(.)ident(name) operator(})operator(.)ident(sort) + reserved(end) + + reserved(def) method(test_clear_association_cache_new_record) + ident(firm) operator(=) constant(Firm)operator(.)ident(new) + ident(client_stored) operator(=) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\)) + ident(client_new) operator(=) constant(Client)operator(.)ident(new) + ident(client_new)operator(.)ident(name) operator(=) string<delimiter(")content(The Joneses)delimiter(")> + ident(clients) operator(=) operator([) ident(client_stored)operator(,) ident(client_new) operator(]) + + ident(firm)operator(.)ident(clients) operator(<<) ident(clients) + + ident(firm)operator(.)ident(clear_association_cache) + + ident(assert_equal) ident(firm)operator(.)ident(clients)operator(.)ident(collect)operator({) operator(|)ident(x)operator(|) ident(x)operator(.)ident(name) operator(})operator(.)ident(sort)operator(,) ident(clients)operator(.)ident(collect)operator({) operator(|)ident(x)operator(|) ident(x)operator(.)ident(name) operator(})operator(.)ident(sort) + reserved(end) + + reserved(def) method(test_interpolate_sql) + ident(assert_nothing_raised) operator({) constant(Category)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:interpolate_sql)operator(,) string<delimiter(')content(foo@bar)delimiter(')>operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Category)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:interpolate_sql)operator(,) string<delimiter(')content(foo bar\) baz)delimiter(')>operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Category)operator(.)ident(new)operator(.)ident(send)operator(()symbol(:interpolate_sql)operator(,) string<delimiter(')content(foo bar} baz)delimiter(')>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_scoped_find_conditions) + ident(scoped_developers) operator(=) constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(salary > 90000)delimiter(')> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(id < 5)delimiter(')>operator(\)) + reserved(end) + ident(assert) operator(!)ident(scoped_developers)operator(.)ident(include?)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(\)) comment(# David's salary is less than 90,000) + ident(assert_equal) integer(3)operator(,) ident(scoped_developers)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_scoped_find_limit_offset) + ident(scoped_developers) operator(=) constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(2) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\)) + reserved(end) + ident(assert) operator(!)ident(scoped_developers)operator(.)ident(include?)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(\)) + ident(assert) operator(!)ident(scoped_developers)operator(.)ident(include?)operator(()ident(developers)operator(()symbol(:jamis)operator(\))operator(\)) + ident(assert_equal) integer(3)operator(,) ident(scoped_developers)operator(.)ident(size) + + comment(# Test without scoped find conditions to ensure we get the whole thing) + ident(developers) operator(=) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\)) + ident(assert_equal) constant(Developer)operator(.)ident(count)operator(,) ident(developers)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_base_class) + ident(assert) constant(LoosePerson)operator(.)ident(abstract_class?) + ident(assert) operator(!)constant(LooseDescendant)operator(.)ident(abstract_class?) + ident(assert_equal) constant(LoosePerson)operator(,) constant(LoosePerson)operator(.)ident(base_class) + ident(assert_equal) constant(LooseDescendant)operator(,) constant(LooseDescendant)operator(.)ident(base_class) + ident(assert_equal) constant(TightPerson)operator(,) constant(TightPerson)operator(.)ident(base_class) + ident(assert_equal) constant(TightPerson)operator(,) constant(TightDescendant)operator(.)ident(base_class) + reserved(end) + + reserved(def) method(test_assert_queries) + ident(query) operator(=) ident(lambda) operator({) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(')content(select count(*\) from developers)delimiter(')> operator(}) + ident(assert_queries)operator(()integer(2)operator(\)) operator({) integer(2)operator(.)ident(times) operator({) ident(query)operator(.)ident(call) operator(}) operator(}) + ident(assert_queries) integer(1)operator(,) operator(&)ident(query) + ident(assert_no_queries) operator({) ident(assert) pre_constant(true) operator(}) + reserved(end) + + reserved(def) method(test_to_xml) + ident(xml) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(\)) + ident(bonus_time_in_current_timezone) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(bonus_time)operator(.)ident(xmlschema) + ident(written_on_in_current_timezone) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(written_on)operator(.)ident(xmlschema) + ident(last_read_in_current_timezone) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(last_read)operator(.)ident(xmlschema) + ident(assert_equal) string<delimiter(")content(<topic>)delimiter(")>operator(,) ident(xml)operator(.)ident(first)operator(()integer(7)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<title>The First Topic</title>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<author-name>David</author-name>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<id type="integer">1</id>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<replies-count type="integer">0</replies-count>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<written-on type="datetime">)inline<inline_delimiter(#{)ident(written_on_in_current_timezone)inline_delimiter(})>content(</written-on>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<content>Have a nice day</content>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<author-email-address>david@loudthinking.com</author-email-address>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<parent-id></parent-id>)delimiter(\))>operator(\)) + reserved(if) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) reserved(or) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<last-read type="datetime">)inline<inline_delimiter(#{)ident(last_read_in_current_timezone)inline_delimiter(})>content(</last-read>)delimiter(\))>operator(\)) + reserved(else) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<last-read type="date">2004-04-15</last-read>)delimiter(\))>operator(\)) + reserved(end) + comment(# Oracle and DB2 don't have true boolean or time-only fields) + reserved(unless) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:DB2Adapter)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<approved type="boolean">false</approved>)delimiter(\))>operator(\))operator(,) string<delimiter(")content(Approved should be a boolean)delimiter(")> + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<bonus-time type="datetime">)inline<inline_delimiter(#{)ident(bonus_time_in_current_timezone)inline_delimiter(})>content(</bonus-time>)delimiter(\))>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_to_xml_skipping_attributes) + ident(xml) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:except) operator(=)operator(>) symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(<topic>)delimiter(")>operator(,) ident(xml)operator(.)ident(first)operator(()integer(7)operator(\)) + ident(assert) operator(!)ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<title>The First Topic</title>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<author-name>David</author-name>)delimiter(\))>operator(\)) + + ident(xml) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:except) operator(=)operator(>) operator([) symbol(:title)operator(,) symbol(:author_name) operator(])operator(\)) + ident(assert) operator(!)ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<title>The First Topic</title>)delimiter(\))>operator(\)) + ident(assert) operator(!)ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<author-name>David</author-name>)delimiter(\))>operator(\)) + reserved(end) + + reserved(def) method(test_to_xml_including_has_many_association) + ident(xml) operator(=) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:include) operator(=)operator(>) symbol(:replies)operator(\)) + ident(assert_equal) string<delimiter(")content(<topic>)delimiter(")>operator(,) ident(xml)operator(.)ident(first)operator(()integer(7)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<replies><reply>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<title>The Second Topic's of the day</title>)delimiter(\))>operator(\)) + reserved(end) + + reserved(def) method(test_to_xml_including_belongs_to_association) + ident(xml) operator(=) ident(companies)operator(()symbol(:first_client)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:include) operator(=)operator(>) symbol(:firm)operator(\)) + ident(assert) operator(!)ident(xml)operator(.)ident(include?)operator(()string<delimiter(")content(<firm>)delimiter(")>operator(\)) + + ident(xml) operator(=) ident(companies)operator(()symbol(:second_client)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:include) operator(=)operator(>) symbol(:firm)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(")content(<firm>)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_to_xml_including_multiple_associations) + ident(xml) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(to_xml)operator(()symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:clients)operator(,) symbol(:account) operator(])operator(\)) + ident(assert_equal) string<delimiter(")content(<firm>)delimiter(")>operator(,) ident(xml)operator(.)ident(first)operator(()integer(6)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<account>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<clients><client>)delimiter(\))>operator(\)) + reserved(end) + + reserved(def) method(test_to_xml_including_multiple_associations_with_options) + ident(xml) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(to_xml)operator(() + symbol(:indent) operator(=)operator(>) integer(0)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) + symbol(:include) operator(=)operator(>) operator({) symbol(:clients) operator(=)operator(>) operator({) symbol(:only) operator(=)operator(>) symbol(:name) operator(}) operator(}) + operator(\)) + + ident(assert_equal) string<delimiter(")content(<firm>)delimiter(")>operator(,) ident(xml)operator(.)ident(first)operator(()integer(6)operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<client><name>Summit</name></client>)delimiter(\))>operator(\)) + ident(assert) ident(xml)operator(.)ident(include?)operator(()string<delimiter(%()content(<clients><client>)delimiter(\))>operator(\)) + reserved(end) + + reserved(def) method(test_except_attributes) + ident(assert_equal)operator(() + string<delimiter(%w()content( author_name type id approved replies_count bonus_time written_on content author_email_address parent_id last_read)delimiter(\))>operator(,) + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(attributes)operator(()symbol(:except) operator(=)operator(>) symbol(:title)operator(\))operator(.)ident(keys) + operator(\)) + + ident(assert_equal)operator(() + string<delimiter(%w()content( replies_count bonus_time written_on content author_email_address parent_id last_read)delimiter(\))>operator(,) + ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(attributes)operator(()symbol(:except) operator(=)operator(>) operator([) symbol(:title)operator(,) symbol(:id)operator(,) symbol(:type)operator(,) symbol(:approved)operator(,) symbol(:author_name) operator(])operator(\))operator(.)ident(keys) + operator(\)) + reserved(end) + + reserved(def) method(test_include_attributes) + ident(assert_equal)operator(()string<delimiter(%w()content( title )delimiter(\))>operator(,) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(attributes)operator(()symbol(:only) operator(=)operator(>) symbol(:title)operator(\))operator(.)ident(keys)operator(\)) + ident(assert_equal)operator(()string<delimiter(%w()content( title author_name type id approved )delimiter(\))>operator(,) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(attributes)operator(()symbol(:only) operator(=)operator(>) operator([) symbol(:title)operator(,) symbol(:id)operator(,) symbol(:type)operator(,) symbol(:approved)operator(,) symbol(:author_name) operator(])operator(\))operator(.)ident(keys)operator(\)) + reserved(end) + + reserved(def) method(test_type_name_with_module_should_handle_beginning) + ident(assert_equal) string<delimiter(')content(ActiveRecord::Person)delimiter(')>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:type_name_with_module)operator(,) string<delimiter(')content(Person)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(')content(::Person)delimiter(')>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:type_name_with_module)operator(,) string<delimiter(')content(::Person)delimiter(')>operator(\)) + reserved(end) + + comment(# FIXME: this test ought to run, but it needs to run sandboxed so that it) + comment(# doesn't b0rk the current test environment by undefing everything.) + comment(#) + comment(#def test_dev_mode_memory_leak) + comment(# counts = []) + comment(# 2.times do) + comment(# require_dependency 'fixtures/company') + comment(# Firm.find(:first\)) + comment(# Dependencies.clear) + comment(# ActiveRecord::Base.reset_subclasses) + comment(# Dependencies.remove_subclasses_for(ActiveRecord::Base\)) + comment(#) + comment(# GC.start) + comment(# ) + comment(# count = 0) + comment(# ObjectSpace.each_object(Proc\) { count += 1 }) + comment(# counts << count) + comment(# end) + comment(# assert counts.last <= counts.first,) + comment(# "expected last count (#{counts.last}\) to be <= first count (#{counts.first}\)") + comment(#end) + + ident(private) + reserved(def) method(assert_readers)operator(()ident(model)operator(,) ident(exceptions)operator(\)) + ident(expected_readers) operator(=) constant(Set)operator(.)ident(new)operator(()ident(model)operator(.)ident(column_names) operator(-) operator(()ident(model)operator(.)ident(serialized_attributes)operator(.)ident(keys) operator(+) operator([)string<delimiter(')content(id)delimiter(')>operator(])operator(\))operator(\)) + ident(expected_readers) operator(+=) ident(expected_readers)operator(.)ident(map) operator({) operator(|)ident(col)operator(|) string<delimiter(")inline<inline_delimiter(#{)ident(col)inline_delimiter(})>content(?)delimiter(")> operator(}) + ident(expected_readers) operator(-=) ident(exceptions) + ident(assert_equal) ident(expected_readers)operator(,) ident(model)operator(.)ident(read_methods) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/binary)delimiter(')> + +reserved(class) class(BinaryTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + constant(BINARY_FIXTURE_PATH) operator(=) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/flowers.jpg)delimiter(')> + + reserved(def) method(setup) + constant(Binary)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(')content(DELETE FROM binaries)delimiter(')> + instance_variable(@data) operator(=) constant(File)operator(.)ident(read)operator(()constant(BINARY_FIXTURE_PATH)operator(\))operator(.)ident(freeze) + reserved(end) + + reserved(def) method(test_truth) + ident(assert) pre_constant(true) + reserved(end) + + comment(# Without using prepared statements, it makes no sense to test) + comment(# BLOB data with SQL Server, because the length of a statement is) + comment(# limited to 8KB.) + comment(#) + comment(# Without using prepared statements, it makes no sense to test) + comment(# BLOB data with DB2 or Firebird, because the length of a statement) + comment(# is limited to 32KB.) + reserved(unless) string<delimiter(%w()content(SQLServer Sybase DB2 Oracle Firebird)delimiter(\))>operator(.)ident(include?) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(adapter_name) + reserved(def) method(test_load_save) + ident(bin) operator(=) constant(Binary)operator(.)ident(new) + ident(bin)operator(.)ident(data) operator(=) instance_variable(@data) + + ident(assert) instance_variable(@data) operator(==) ident(bin)operator(.)ident(data)operator(,) string<delimiter(')content(Newly assigned data differs from original)delimiter(')> + + ident(bin)operator(.)ident(save) + ident(assert) instance_variable(@data) operator(==) ident(bin)operator(.)ident(data)operator(,) string<delimiter(')content(Data differs from original after save)delimiter(')> + + ident(db_bin) operator(=) constant(Binary)operator(.)ident(find)operator(()ident(bin)operator(.)ident(id)operator(\)) + ident(assert) instance_variable(@data) operator(==) ident(db_bin)operator(.)ident(data)operator(,) string<delimiter(')content(Reloaded data differs from original)delimiter(')> + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> + +constant(Company)operator(.)ident(has_many) symbol(:accounts) + +reserved(class) class(CalculationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:companies)operator(,) symbol(:accounts)operator(,) symbol(:topics) + + reserved(def) method(test_should_sum_field) + ident(assert_equal) integer(265)operator(,) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(\)) + reserved(end) + + reserved(def) method(test_should_average_field) + ident(value) operator(=) constant(Account)operator(.)ident(average)operator(()symbol(:credit_limit)operator(\)) + ident(assert_equal) integer(53)operator(,) ident(value) + ident(assert_kind_of) constant(Float)operator(,) ident(value) + reserved(end) + + reserved(def) method(test_should_get_maximum_of_field) + ident(assert_equal) integer(60)operator(,) constant(Account)operator(.)ident(maximum)operator(()symbol(:credit_limit)operator(\)) + reserved(end) + + reserved(def) method(test_should_get_minimum_of_field) + ident(assert_equal) integer(50)operator(,) constant(Account)operator(.)ident(minimum)operator(()symbol(:credit_limit)operator(\)) + reserved(end) + + reserved(def) method(test_should_group_by_field) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(\)) + operator([)integer(1)operator(,)integer(6)operator(,)integer(2)operator(])operator(.)ident(each) operator({) operator(|)ident(firm_id)operator(|) ident(assert) ident(c)operator(.)ident(keys)operator(.)ident(include?)operator(()ident(firm_id)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_should_group_by_summed_field) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(\)) + ident(assert_equal) integer(50)operator(,) ident(c)operator([)integer(1)operator(]) + ident(assert_equal) integer(105)operator(,) ident(c)operator([)integer(6)operator(]) + ident(assert_equal) integer(60)operator(,) ident(c)operator([)integer(2)operator(]) + reserved(end) + + reserved(def) method(test_should_order_by_grouped_field) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(\)) + ident(assert_equal) operator([)integer(1)operator(,) integer(2)operator(,) integer(6)operator(])operator(,) ident(c)operator(.)ident(keys)operator(.)ident(compact) + reserved(end) + + reserved(def) method(test_should_order_by_calculation) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(sum_credit_limit desc, firm_id)delimiter(")>operator(\)) + ident(assert_equal) operator([)integer(105)operator(,) integer(60)operator(,) integer(50)operator(,) integer(50)operator(])operator(,) ident(c)operator(.)ident(keys)operator(.)ident(collect) operator({) operator(|)ident(k)operator(|) ident(c)operator([)ident(k)operator(]) operator(}) + ident(assert_equal) operator([)integer(6)operator(,) integer(2)operator(,) integer(1)operator(])operator(,) ident(c)operator(.)ident(keys)operator(.)ident(compact) + reserved(end) + + reserved(def) method(test_should_limit_calculation) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(firm_id IS NOT NULL)delimiter(")>operator(,) + symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(\)) + ident(assert_equal) operator([)integer(1)operator(,) integer(2)operator(])operator(,) ident(c)operator(.)ident(keys)operator(.)ident(compact) + reserved(end) + + reserved(def) method(test_should_limit_calculation_with_offset) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(firm_id IS NOT NULL)delimiter(")>operator(,) + symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:offset) operator(=)operator(>) integer(1)operator(\)) + ident(assert_equal) operator([)integer(2)operator(,) integer(6)operator(])operator(,) ident(c)operator(.)ident(keys)operator(.)ident(compact) + reserved(end) + + reserved(def) method(test_should_group_by_summed_field_having_condition) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(,) + symbol(:having) operator(=)operator(>) string<delimiter(')content(sum(credit_limit\) > 50)delimiter(')>operator(\)) + ident(assert_nil) ident(c)operator([)integer(1)operator(]) + ident(assert_equal) integer(105)operator(,) ident(c)operator([)integer(6)operator(]) + ident(assert_equal) integer(60)operator(,) ident(c)operator([)integer(2)operator(]) + reserved(end) + + reserved(def) method(test_should_group_by_summed_association) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm)operator(\)) + ident(assert_equal) integer(50)operator(,) ident(c)operator([)ident(companies)operator(()symbol(:first_firm)operator(\))operator(]) + ident(assert_equal) integer(105)operator(,) ident(c)operator([)ident(companies)operator(()symbol(:rails_core)operator(\))operator(]) + ident(assert_equal) integer(60)operator(,) ident(c)operator([)ident(companies)operator(()symbol(:first_client)operator(\))operator(]) + reserved(end) + + reserved(def) method(test_should_sum_field_with_conditions) + ident(assert_equal) integer(105)operator(,) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(firm_id = 6)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_should_group_by_summed_field_with_conditions) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(firm_id > 1)delimiter(')>operator(,) + symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(\)) + ident(assert_nil) ident(c)operator([)integer(1)operator(]) + ident(assert_equal) integer(105)operator(,) ident(c)operator([)integer(6)operator(]) + ident(assert_equal) integer(60)operator(,) ident(c)operator([)integer(2)operator(]) + reserved(end) + + reserved(def) method(test_should_group_by_summed_field_with_conditions_and_having) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(firm_id > 1)delimiter(')>operator(,) + symbol(:group) operator(=)operator(>) symbol(:firm_id)operator(,) + symbol(:having) operator(=)operator(>) string<delimiter(')content(sum(credit_limit\) > 60)delimiter(')>operator(\)) + ident(assert_nil) ident(c)operator([)integer(1)operator(]) + ident(assert_equal) integer(105)operator(,) ident(c)operator([)integer(6)operator(]) + ident(assert_nil) ident(c)operator([)integer(2)operator(]) + reserved(end) + + reserved(def) method(test_should_group_by_fields_with_table_alias) + ident(c) operator(=) constant(Account)operator(.)ident(sum)operator(()symbol(:credit_limit)operator(,) symbol(:group) operator(=)operator(>) string<delimiter(')content(accounts.firm_id)delimiter(')>operator(\)) + ident(assert_equal) integer(50)operator(,) ident(c)operator([)integer(1)operator(]) + ident(assert_equal) integer(105)operator(,) ident(c)operator([)integer(6)operator(]) + ident(assert_equal) integer(60)operator(,) ident(c)operator([)integer(2)operator(]) + reserved(end) + + reserved(def) method(test_should_calculate_with_invalid_field) + ident(assert_equal) integer(5)operator(,) constant(Account)operator(.)ident(calculate)operator(()symbol(:count)operator(,) string<delimiter(')content(*)delimiter(')>operator(\)) + ident(assert_equal) integer(5)operator(,) constant(Account)operator(.)ident(calculate)operator(()symbol(:count)operator(,) symbol(:all)operator(\)) + reserved(end) + + reserved(def) method(test_should_calculate_grouped_with_invalid_field) + ident(c) operator(=) constant(Account)operator(.)ident(count)operator(()symbol(:all)operator(,) symbol(:group) operator(=)operator(>) string<delimiter(')content(accounts.firm_id)delimiter(')>operator(\)) + ident(assert_equal) integer(1)operator(,) ident(c)operator([)integer(1)operator(]) + ident(assert_equal) integer(2)operator(,) ident(c)operator([)integer(6)operator(]) + ident(assert_equal) integer(1)operator(,) ident(c)operator([)integer(2)operator(]) + reserved(end) + + reserved(def) method(test_should_calculate_grouped_association_with_invalid_field) + ident(c) operator(=) constant(Account)operator(.)ident(count)operator(()symbol(:all)operator(,) symbol(:group) operator(=)operator(>) symbol(:firm)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(c)operator([)ident(companies)operator(()symbol(:first_firm)operator(\))operator(]) + ident(assert_equal) integer(2)operator(,) ident(c)operator([)ident(companies)operator(()symbol(:rails_core)operator(\))operator(]) + ident(assert_equal) integer(1)operator(,) ident(c)operator([)ident(companies)operator(()symbol(:first_client)operator(\))operator(]) + reserved(end) + + reserved(def) method(test_should_calculate_grouped_by_function) + ident(c) operator(=) constant(Company)operator(.)ident(count)operator(()symbol(:all)operator(,) symbol(:group) operator(=)operator(>) string<delimiter(')content(UPPER(type\))delimiter(')>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(c)operator([)pre_constant(nil)operator(]) + ident(assert_equal) integer(1)operator(,) ident(c)operator([)string<delimiter(')content(DEPENDENTFIRM)delimiter(')>operator(]) + ident(assert_equal) integer(3)operator(,) ident(c)operator([)string<delimiter(')content(CLIENT)delimiter(')>operator(]) + ident(assert_equal) integer(2)operator(,) ident(c)operator([)string<delimiter(')content(FIRM)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_should_calculate_grouped_by_function_with_table_alias) + ident(c) operator(=) constant(Company)operator(.)ident(count)operator(()symbol(:all)operator(,) symbol(:group) operator(=)operator(>) string<delimiter(')content(UPPER(companies.type\))delimiter(')>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(c)operator([)pre_constant(nil)operator(]) + ident(assert_equal) integer(1)operator(,) ident(c)operator([)string<delimiter(')content(DEPENDENTFIRM)delimiter(')>operator(]) + ident(assert_equal) integer(3)operator(,) ident(c)operator([)string<delimiter(')content(CLIENT)delimiter(')>operator(]) + ident(assert_equal) integer(2)operator(,) ident(c)operator([)string<delimiter(')content(FIRM)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_should_sum_scoped_field) + ident(assert_equal) integer(15)operator(,) ident(companies)operator(()symbol(:rails_core)operator(\))operator(.)ident(companies)operator(.)ident(sum)operator(()symbol(:id)operator(\)) + reserved(end) + + reserved(def) method(test_should_sum_scoped_field_with_conditions) + ident(assert_equal) integer(8)operator(,) ident(companies)operator(()symbol(:rails_core)operator(\))operator(.)ident(companies)operator(.)ident(sum)operator(()symbol(:id)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(id > 7)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_should_group_by_scoped_field) + ident(c) operator(=) ident(companies)operator(()symbol(:rails_core)operator(\))operator(.)ident(companies)operator(.)ident(sum)operator(()symbol(:id)operator(,) symbol(:group) operator(=)operator(>) symbol(:name)operator(\)) + ident(assert_equal) integer(7)operator(,) ident(c)operator([)string<delimiter(')content(Leetsoft)delimiter(')>operator(]) + ident(assert_equal) integer(8)operator(,) ident(c)operator([)string<delimiter(')content(Jadedpixel)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_should_group_by_summed_field_with_conditions_and_having) + ident(c) operator(=) ident(companies)operator(()symbol(:rails_core)operator(\))operator(.)ident(companies)operator(.)ident(sum)operator(()symbol(:id)operator(,) symbol(:group) operator(=)operator(>) symbol(:name)operator(,) + symbol(:having) operator(=)operator(>) string<delimiter(')content(sum(id\) > 7)delimiter(')>operator(\)) + ident(assert_nil) ident(c)operator([)string<delimiter(')content(Leetsoft)delimiter(')>operator(]) + ident(assert_equal) integer(8)operator(,) ident(c)operator([)string<delimiter(')content(Jadedpixel)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_should_reject_invalid_options) + ident(assert_nothing_raised) reserved(do) + operator([)symbol(:count)operator(,) symbol(:sum)operator(])operator(.)ident(each) reserved(do) operator(|)ident(func)operator(|) + comment(# empty options are valid) + constant(Company)operator(.)ident(send)operator(()symbol(:validate_calculation_options)operator(,) ident(func)operator(\)) + comment(# these options are valid for all calculations) + operator([)symbol(:select)operator(,) symbol(:conditions)operator(,) symbol(:joins)operator(,) symbol(:order)operator(,) symbol(:group)operator(,) symbol(:having)operator(,) symbol(:distinct)operator(])operator(.)ident(each) reserved(do) operator(|)ident(opt)operator(|) + constant(Company)operator(.)ident(send)operator(()symbol(:validate_calculation_options)operator(,) ident(func)operator(,) ident(opt) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + reserved(end) + + comment(# :include is only valid on :count) + constant(Company)operator(.)ident(send)operator(()symbol(:validate_calculation_options)operator(,) symbol(:count)operator(,) symbol(:include) operator(=)operator(>) pre_constant(true)operator(\)) + reserved(end) + + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) constant(Company)operator(.)ident(send)operator(()symbol(:validate_calculation_options)operator(,) symbol(:sum)operator(,) symbol(:include) operator(=)operator(>) symbol(:posts)operator(\)) operator(}) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) constant(Company)operator(.)ident(send)operator(()symbol(:validate_calculation_options)operator(,) symbol(:sum)operator(,) symbol(:foo) operator(=)operator(>) symbol(:bar)operator(\)) operator(}) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) constant(Company)operator(.)ident(send)operator(()symbol(:validate_calculation_options)operator(,) symbol(:count)operator(,) symbol(:foo) operator(=)operator(>) symbol(:bar)operator(\)) operator(}) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(CallbackDeveloper) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(developers)delimiter(')> + + reserved(class) operator(<<) class(self) + reserved(def) method(callback_string)operator(()ident(callback_method)operator(\)) + string<delimiter(")content(history << [)inline<inline_delimiter(#{)ident(callback_method)operator(.)ident(to_sym)operator(.)ident(inspect)inline_delimiter(})>content(, :string])delimiter(")> + reserved(end) + + reserved(def) method(callback_proc)operator(()ident(callback_method)operator(\)) + constant(Proc)operator(.)ident(new) operator({) operator(|)ident(model)operator(|) ident(model)operator(.)ident(history) operator(<<) operator([)ident(callback_method)operator(,) symbol(:proc)operator(]) operator(}) + reserved(end) + + reserved(def) method(define_callback_method)operator(()ident(callback_method)operator(\)) + ident(define_method)operator(()string<delimiter(")inline<inline_delimiter(#{)ident(callback_method)inline_delimiter(})>content(_method)delimiter(")>operator(\)) reserved(do) operator(|)ident(model)operator(|) + ident(model)operator(.)ident(history) operator(<<) operator([)ident(callback_method)operator(,) symbol(:method)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(callback_object)operator(()ident(callback_method)operator(\)) + ident(klass) operator(=) constant(Class)operator(.)ident(new) + ident(klass)operator(.)ident(send)operator(()symbol(:define_method)operator(,) ident(callback_method)operator(\)) reserved(do) operator(|)ident(model)operator(|) + ident(model)operator(.)ident(history) operator(<<) operator([)ident(callback_method)operator(,) symbol(:object)operator(]) + reserved(end) + ident(klass)operator(.)ident(new) + reserved(end) + reserved(end) + + constant(ActiveRecord)operator(::)constant(Callbacks)operator(::)constant(CALLBACKS)operator(.)ident(each) reserved(do) operator(|)ident(callback_method)operator(|) + ident(callback_method_sym) operator(=) ident(callback_method)operator(.)ident(to_sym) + ident(define_callback_method)operator(()ident(callback_method_sym)operator(\)) + ident(send)operator(()ident(callback_method)operator(,) ident(callback_method_sym)operator(\)) + ident(send)operator(()ident(callback_method)operator(,) ident(callback_string)operator(()ident(callback_method_sym)operator(\))operator(\)) + ident(send)operator(()ident(callback_method)operator(,) ident(callback_proc)operator(()ident(callback_method_sym)operator(\))operator(\)) + ident(send)operator(()ident(callback_method)operator(,) ident(callback_object)operator(()ident(callback_method_sym)operator(\))operator(\)) + ident(send)operator(()ident(callback_method)operator(\)) operator({) operator(|)ident(model)operator(|) ident(model)operator(.)ident(history) operator(<<) operator([)ident(callback_method_sym)operator(,) symbol(:block)operator(]) operator(}) + reserved(end) + + reserved(def) method(history) + instance_variable(@history) operator(||=) operator([)operator(]) + reserved(end) + + comment(# after_initialize and after_find are invoked only if instance methods have been defined.) + reserved(def) method(after_initialize) + reserved(end) + + reserved(def) method(after_find) + reserved(end) +reserved(end) + +reserved(class) class(RecursiveCallbackDeveloper) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(developers)delimiter(')> + + ident(before_save) symbol(:on_before_save) + ident(after_save) symbol(:on_after_save) + + ident(attr_reader) symbol(:on_before_save_called)operator(,) symbol(:on_after_save_called) + + reserved(def) method(on_before_save) + instance_variable(@on_before_save_called) operator(||=) integer(0) + instance_variable(@on_before_save_called) operator(+=) integer(1) + ident(save) reserved(unless) instance_variable(@on_before_save_called) operator(>) integer(1) + reserved(end) + + reserved(def) method(on_after_save) + instance_variable(@on_after_save_called) operator(||=) integer(0) + instance_variable(@on_after_save_called) operator(+=) integer(1) + ident(save) reserved(unless) instance_variable(@on_after_save_called) operator(>) integer(1) + reserved(end) +reserved(end) + +reserved(class) class(ImmutableDeveloper) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(developers)delimiter(')> + + ident(validates_inclusion_of) symbol(:salary)operator(,) symbol(:in) operator(=)operator(>) integer(50000)operator(..)integer(200000) + + ident(before_save) symbol(:cancel) + ident(before_destroy) symbol(:cancel) + + reserved(def) method(cancelled?) + instance_variable(@cancelled) operator(==) pre_constant(true) + reserved(end) + + ident(private) + reserved(def) method(cancel) + instance_variable(@cancelled) operator(=) pre_constant(true) + pre_constant(false) + reserved(end) +reserved(end) + +reserved(class) class(ImmutableMethodDeveloper) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(developers)delimiter(')> + + ident(validates_inclusion_of) symbol(:salary)operator(,) symbol(:in) operator(=)operator(>) integer(50000)operator(..)integer(200000) + + reserved(def) method(cancelled?) + instance_variable(@cancelled) operator(==) pre_constant(true) + reserved(end) + + reserved(def) method(before_save) + instance_variable(@cancelled) operator(=) pre_constant(true) + pre_constant(false) + reserved(end) + + reserved(def) method(before_destroy) + instance_variable(@cancelled) operator(=) pre_constant(true) + pre_constant(false) + reserved(end) +reserved(end) + +reserved(class) class(CallbacksTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:developers) + + reserved(def) method(test_initialize) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(new) + ident(assert_equal) operator([) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_find) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) operator([) + operator([) symbol(:after_find)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_new_valid?) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(new) + ident(david)operator(.)ident(valid?) + ident(assert_equal) operator([) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:block) operator(]) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_existing_valid?) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(valid?) + ident(assert_equal) operator([) + operator([) symbol(:after_find)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:block) operator(]) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_create) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(create)operator(()string<delimiter(')content(name)delimiter(')> operator(=)operator(>) string<delimiter(')content(David)delimiter(')>operator(,) string<delimiter(')content(salary)delimiter(')> operator(=)operator(>) integer(1000000)operator(\)) + ident(assert_equal) operator([) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation_on_create)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation_on_create)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_create)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_create)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_create)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_create)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_create)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_create)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_create)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_create)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:block) operator(]) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_save) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(save) + ident(assert_equal) operator([) + operator([) symbol(:after_find)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation_on_update)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_validation_on_update)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_save)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_update)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_update)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_update)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_update)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_update)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_update)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_update)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_update)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_save)operator(,) symbol(:block) operator(]) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_destroy) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(destroy) + ident(assert_equal) operator([) + operator([) symbol(:after_find)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_destroy)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_destroy)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_destroy)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_destroy)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_destroy)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_destroy)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_destroy)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_destroy)operator(,) symbol(:block) operator(]) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_delete) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + constant(CallbackDeveloper)operator(.)ident(delete)operator(()ident(david)operator(.)ident(id)operator(\)) + ident(assert_equal) operator([) + operator([) symbol(:after_find)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) + + reserved(def) method(test_before_save_returning_false) + ident(david) operator(=) constant(ImmutableDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(david)operator(.)ident(valid?) + ident(assert) operator(!)ident(david)operator(.)ident(save) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotSaved)operator(\)) operator({) ident(david)operator(.)ident(save!) operator(}) + + ident(david) operator(=) constant(ImmutableDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(salary) operator(=) integer(10_000_000) + ident(assert) operator(!)ident(david)operator(.)ident(valid?) + ident(assert) operator(!)ident(david)operator(.)ident(save) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordInvalid)operator(\)) operator({) ident(david)operator(.)ident(save!) operator(}) + reserved(end) + + reserved(def) method(test_before_destroy_returning_false) + ident(david) operator(=) constant(ImmutableDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(david)operator(.)ident(destroy) + ident(assert_not_nil) constant(ImmutableDeveloper)operator(.)ident(find_by_id)operator(()integer(1)operator(\)) + reserved(end) + + reserved(def) method(test_zzz_callback_returning_false) comment(# must be run last since we modify CallbackDeveloper) + ident(david) operator(=) constant(CallbackDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + constant(CallbackDeveloper)operator(.)ident(before_validation) ident(proc) operator({) operator(|)ident(model)operator(|) ident(model)operator(.)ident(history) operator(<<) operator([)symbol(:before_validation)operator(,) symbol(:returning_false)operator(])operator(;) reserved(return) pre_constant(false) operator(}) + constant(CallbackDeveloper)operator(.)ident(before_validation) ident(proc) operator({) operator(|)ident(model)operator(|) ident(model)operator(.)ident(history) operator(<<) operator([)symbol(:before_validation)operator(,) symbol(:should_never_get_here)operator(]) operator(}) + ident(david)operator(.)ident(save) + ident(assert_equal) operator([) + operator([) symbol(:after_find)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_find)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:after_initialize)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:string) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:proc) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:object) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:block) operator(])operator(,) + operator([) symbol(:before_validation)operator(,) symbol(:returning_false) operator(]) + operator(])operator(,) ident(david)operator(.)ident(history) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(test/unit)delimiter(')> +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(active_support/core_ext/class/inheritable_attributes)delimiter(')> + +reserved(class) class(A) + ident(include) constant(ClassInheritableAttributes) +reserved(end) + +reserved(class) class(B) operator(<) constant(A) + ident(write_inheritable_array) string<delimiter(")content(first)delimiter(")>operator(,) operator([) symbol(:one)operator(,) symbol(:two) operator(]) +reserved(end) + +reserved(class) class(C) operator(<) constant(A) + ident(write_inheritable_array) string<delimiter(")content(first)delimiter(")>operator(,) operator([) symbol(:three) operator(]) +reserved(end) + +reserved(class) class(D) operator(<) constant(B) + ident(write_inheritable_array) string<delimiter(")content(first)delimiter(")>operator(,) operator([) symbol(:four) operator(]) +reserved(end) + + +reserved(class) class(ClassInheritableAttributesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_first_level) + ident(assert_equal) operator([) symbol(:one)operator(,) symbol(:two) operator(])operator(,) constant(B)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(first)delimiter(")>operator(\)) + ident(assert_equal) operator([) symbol(:three) operator(])operator(,) constant(C)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(first)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_second_level) + ident(assert_equal) operator([) symbol(:one)operator(,) symbol(:two)operator(,) symbol(:four) operator(])operator(,) constant(D)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(first)delimiter(")>operator(\)) + ident(assert_equal) operator([) symbol(:one)operator(,) symbol(:two) operator(])operator(,) constant(B)operator(.)ident(read_inheritable_attribute)operator(()string<delimiter(")content(first)delimiter(")>operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> + +reserved(class) class(TestColumnAlias) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics) + + constant(QUERY) operator(=) reserved(if) string<delimiter(')content(Oracle)delimiter(')> operator(==) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(adapter_name) + string<delimiter(')content(SELECT id AS pk FROM topics WHERE ROWNUM < 2)delimiter(')> + reserved(else) + string<delimiter(')content(SELECT id AS pk FROM topics)delimiter(')> + reserved(end) + + reserved(def) method(test_column_alias) + ident(records) operator(=) constant(Topic)operator(.)ident(connection)operator(.)ident(select_all)operator(()constant(QUERY)operator(\)) + ident(assert_equal) string<delimiter(')content(pk)delimiter(')>operator(,) ident(records)operator([)integer(0)operator(])operator(.)ident(keys)operator([)integer(0)operator(]) + reserved(end) +reserved(end) +ident(print) string<delimiter(")content(Using native DB2)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(arunit)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(arunit2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(db2)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(arunit)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")content(arunit)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(db2)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(arunit2)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")content(arunit2)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2) +operator(\)) +ident(print) string<delimiter(")content(Using native Firebird)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(firebird)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(firebird)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2) +operator(\)) +ident(print) string<delimiter(")content(Using native MySQL)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(mysql)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:encoding) operator(=)operator(>) string<delimiter(")content(utf8)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(mysql)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(rails)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2) +operator(\)) +ident(print) string<delimiter(")content(Using native OpenBase)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(openbase)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(admin)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(openbase)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(admin)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2) +operator(\)) +ident(print) string<delimiter(")content(Using Oracle)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new) constant(STDOUT) +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger)operator(.)ident(level) operator(=) constant(Logger)operator(::)constant(WARN) + +comment(# Set these to your database connection strings) +ident(db) operator(=) constant(ENV)operator([)string<delimiter(')content(ARUNIT_DB)delimiter(')>operator(]) operator(||) string<delimiter(')content(activerecord_unittest)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(')content(oracle)delimiter(')>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(')content(arunit)delimiter(')>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(')content(arunit)delimiter(')>operator(,) + symbol(:database) operator(=)operator(>) ident(db) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(')content(oracle)delimiter(')>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(')content(arunit2)delimiter(')>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(')content(arunit2)delimiter(')>operator(,) + symbol(:database) operator(=)operator(>) ident(db) +operator(\)) +ident(print) string<delimiter(")content(Using native PostgreSQL)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(postgresql)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(postgres)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")content(postgres)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1)operator(,) + symbol(:min_messages) operator(=)operator(>) string<delimiter(")content(warning)delimiter(")> +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(postgresql)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(postgres)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")content(postgres)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2)operator(,) + symbol(:min_messages) operator(=)operator(>) string<delimiter(")content(warning)delimiter(")> +operator(\)) +ident(print) string<delimiter(")content(Using native SQlite)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +reserved(class) class(SqliteError) operator(<) constant(StandardError) +reserved(end) + +constant(BASE_DIR) operator(=) constant(File)operator(.)ident(expand_path)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../fixtures)delimiter(')>operator(\)) +ident(sqlite_test_db) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(BASE_DIR)inline_delimiter(})>content(/fixture_database.sqlite)delimiter(")> +ident(sqlite_test_db2) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(BASE_DIR)inline_delimiter(})>content(/fixture_database_2.sqlite)delimiter(")> + +reserved(def) method(make_connection)operator(()ident(clazz)operator(,) ident(db_file)operator(,) ident(db_definitions_file)operator(\)) + reserved(unless) constant(File)operator(.)ident(exist?)operator(()ident(db_file)operator(\)) + ident(puts) string<delimiter(")content(SQLite database not found at )inline<inline_delimiter(#{)ident(db_file)inline_delimiter(})>content(. Rebuilding it.)delimiter(")> + ident(sqlite_command) operator(=) string<delimiter(%Q{)content(sqlite )inline<inline_delimiter(#{)ident(db_file)inline_delimiter(})>content( "create table a (a integer\); drop table a;")delimiter(})> + ident(puts) string<delimiter(")content(Executing ')inline<inline_delimiter(#{)ident(sqlite_command)inline_delimiter(})>content(')delimiter(")> + ident(raise) constant(SqliteError)operator(.)ident(new)operator(()string<delimiter(")content(Seems that there is no sqlite executable available)delimiter(")>operator(\)) reserved(unless) ident(system)operator(()ident(sqlite_command)operator(\)) + ident(clazz)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlite)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db_file)operator(\)) + ident(script) operator(=) constant(File)operator(.)ident(read)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(BASE_DIR)inline_delimiter(})>content(/db_definitions/)inline<inline_delimiter(#{)ident(db_definitions_file)inline_delimiter(})>delimiter(")>operator(\)) + comment(# SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time) + ident(script)operator(.)ident(split)operator(()string<delimiter(')content(;)delimiter(')>operator(\))operator(.)ident(each) reserved(do) + operator(|)ident(command)operator(|) + ident(clazz)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(command)operator(\)) reserved(unless) ident(command)operator(.)ident(strip)operator(.)ident(empty?) + reserved(end) + reserved(else) + ident(clazz)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlite)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db_file)operator(\)) + reserved(end) +reserved(end) + +ident(make_connection)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(,) ident(sqlite_test_db)operator(,) string<delimiter(')content(sqlite.sql)delimiter(')>operator(\)) +ident(make_connection)operator(()constant(Course)operator(,) ident(sqlite_test_db2)operator(,) string<delimiter(')content(sqlite2.sql)delimiter(')>operator(\)) +ident(load)operator(()constant(File)operator(.)ident(join)operator(()constant(BASE_DIR)operator(,) string<delimiter(')content(db_definitions)delimiter(')>operator(,) string<delimiter(')content(schema.rb)delimiter(')>operator(\))operator(\)) +ident(print) string<delimiter(")content(Using native SQLite3)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +reserved(class) class(SqliteError) operator(<) constant(StandardError) +reserved(end) + +constant(BASE_DIR) operator(=) constant(File)operator(.)ident(expand_path)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../fixtures)delimiter(')>operator(\)) +ident(sqlite_test_db) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(BASE_DIR)inline_delimiter(})>content(/fixture_database.sqlite3)delimiter(")> +ident(sqlite_test_db2) operator(=) string<delimiter(")inline<inline_delimiter(#{)constant(BASE_DIR)inline_delimiter(})>content(/fixture_database_2.sqlite3)delimiter(")> + +reserved(def) method(make_connection)operator(()ident(clazz)operator(,) ident(db_file)operator(,) ident(db_definitions_file)operator(\)) + reserved(unless) constant(File)operator(.)ident(exist?)operator(()ident(db_file)operator(\)) + ident(puts) string<delimiter(")content(SQLite3 database not found at )inline<inline_delimiter(#{)ident(db_file)inline_delimiter(})>content(. Rebuilding it.)delimiter(")> + ident(sqlite_command) operator(=) string<delimiter(%Q{)content(sqlite3 )inline<inline_delimiter(#{)ident(db_file)inline_delimiter(})>content( "create table a (a integer\); drop table a;")delimiter(})> + ident(puts) string<delimiter(")content(Executing ')inline<inline_delimiter(#{)ident(sqlite_command)inline_delimiter(})>content(')delimiter(")> + ident(raise) constant(SqliteError)operator(.)ident(new)operator(()string<delimiter(")content(Seems that there is no sqlite3 executable available)delimiter(")>operator(\)) reserved(unless) ident(system)operator(()ident(sqlite_command)operator(\)) + ident(clazz)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlite3)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db_file)operator(\)) + ident(script) operator(=) constant(File)operator(.)ident(read)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(BASE_DIR)inline_delimiter(})>content(/db_definitions/)inline<inline_delimiter(#{)ident(db_definitions_file)inline_delimiter(})>delimiter(")>operator(\)) + comment(# SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time) + ident(script)operator(.)ident(split)operator(()string<delimiter(')content(;)delimiter(')>operator(\))operator(.)ident(each) reserved(do) + operator(|)ident(command)operator(|) + ident(clazz)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(command)operator(\)) reserved(unless) ident(command)operator(.)ident(strip)operator(.)ident(empty?) + reserved(end) + reserved(else) + ident(clazz)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlite3)delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db_file)operator(\)) + reserved(end) +reserved(end) + +ident(make_connection)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(,) ident(sqlite_test_db)operator(,) string<delimiter(')content(sqlite.sql)delimiter(')>operator(\)) +ident(make_connection)operator(()constant(Course)operator(,) ident(sqlite_test_db2)operator(,) string<delimiter(')content(sqlite2.sql)delimiter(')>operator(\)) +ident(load)operator(()constant(File)operator(.)ident(join)operator(()constant(BASE_DIR)operator(,) string<delimiter(')content(db_definitions)delimiter(')>operator(,) string<delimiter(')content(schema.rb)delimiter(')>operator(\))operator(\)) +ident(print) string<delimiter(")content(Using native SQLite3)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +reserved(class) class(SqliteError) operator(<) constant(StandardError) +reserved(end) + +reserved(def) method(make_connection)operator(()ident(clazz)operator(,) ident(db_definitions_file)operator(\)) + ident(clazz)operator(.)ident(establish_connection)operator(()symbol(:adapter) operator(=)operator(>) string<delimiter(')content(sqlite3)delimiter(')>operator(,) symbol(:database) operator(=)operator(>) string<delimiter(')content(:memory:)delimiter(')>operator(\)) + constant(File)operator(.)ident(read)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../../fixtures/db_definitions/)inline<inline_delimiter(#{)ident(db_definitions_file)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(split)operator(()string<delimiter(')content(;)delimiter(')>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(command)operator(|) + ident(clazz)operator(.)ident(connection)operator(.)ident(execute)operator(()ident(command)operator(\)) reserved(unless) ident(command)operator(.)ident(strip)operator(.)ident(empty?) + reserved(end) +reserved(end) + +ident(make_connection)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(,) string<delimiter(')content(sqlite.sql)delimiter(')>operator(\)) +ident(make_connection)operator(()constant(Course)operator(,) string<delimiter(')content(sqlite2.sql)delimiter(')>operator(\)) + ident(load)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../../fixtures/db_definitions/schema.rb)delimiter(")>operator(\))operator(\)) +ident(print) string<delimiter(")content(Using native SQLServer)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlserver)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(sa)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlserver)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(sa)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2) +operator(\)) +ident(print) string<delimiter(")content(Using native SQLServer via ODBC)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(dsn1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(dsn2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlserver)delimiter(")>operator(,) + symbol(:mode) operator(=)operator(>) string<delimiter(")content(ODBC)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(sa)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:dsn) operator(=)operator(>) ident(dsn1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sqlserver)delimiter(")>operator(,) + symbol(:mode) operator(=)operator(>) string<delimiter(")content(ODBC)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(localhost)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(sa)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:dsn) operator(=)operator(>) ident(dsn2) +operator(\)) +ident(print) string<delimiter(")content(Using native Sybase Open Client)char(\\n)delimiter(")> +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> +ident(require) string<delimiter(')content(logger)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger) operator(=) constant(Logger)operator(.)ident(new)operator(()string<delimiter(")content(debug.log)delimiter(")>operator(\)) + +ident(db1) operator(=) string<delimiter(')content(activerecord_unittest)delimiter(')> +ident(db2) operator(=) string<delimiter(')content(activerecord_unittest2)delimiter(')> + +constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sybase)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(database_ASE)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(sa)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db1) +operator(\)) + +constant(Course)operator(.)ident(establish_connection)operator(() + symbol(:adapter) operator(=)operator(>) string<delimiter(")content(sybase)delimiter(")>operator(,) + symbol(:host) operator(=)operator(>) string<delimiter(")content(database_ASE)delimiter(")>operator(,) + symbol(:username) operator(=)operator(>) string<delimiter(")content(sa)delimiter(")>operator(,) + symbol(:password) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) + symbol(:database) operator(=)operator(>) ident(db2) +operator(\)) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(CopyTableTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:companies)operator(,) symbol(:comments) + + reserved(def) method(setup) + instance_variable(@connection) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + reserved(class) operator(<<) instance_variable(@connection) + ident(public) symbol(:copy_table)operator(,) symbol(:table_structure)operator(,) symbol(:indexes) + reserved(end) + reserved(end) + + reserved(def) method(test_copy_table)operator(()ident(from) operator(=) string<delimiter(')content(companies)delimiter(')>operator(,) ident(to) operator(=) string<delimiter(')content(companies2)delimiter(')>operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(assert_nothing_raised) operator({)ident(copy_table)operator(()ident(from)operator(,) ident(to)operator(,) ident(options)operator(\))operator(}) + ident(assert_equal) ident(row_count)operator(()ident(from)operator(\))operator(,) ident(row_count)operator(()ident(to)operator(\)) + + reserved(if) ident(block_given?) + reserved(yield) ident(from)operator(,) ident(to)operator(,) ident(options) + reserved(else) + ident(assert_equal) ident(column_names)operator(()ident(from)operator(\))operator(,) ident(column_names)operator(()ident(to)operator(\)) + reserved(end) + + instance_variable(@connection)operator(.)ident(drop_table)operator(()ident(to)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_copy_table_renaming_column) + ident(test_copy_table)operator(()string<delimiter(')content(companies)delimiter(')>operator(,) string<delimiter(')content(companies2)delimiter(')>operator(,) + symbol(:rename) operator(=)operator(>) operator({)string<delimiter(')content(client_of)delimiter(')> operator(=)operator(>) string<delimiter(')content(fan_of)delimiter(')>operator(})operator(\)) reserved(do) operator(|)ident(from)operator(,) ident(to)operator(,) ident(options)operator(|) + ident(assert_equal) ident(column_values)operator(()ident(from)operator(,) string<delimiter(')content(client_of)delimiter(')>operator(\))operator(.)ident(compact)operator(.)ident(sort)operator(,) + ident(column_values)operator(()ident(to)operator(,) string<delimiter(')content(fan_of)delimiter(')>operator(\))operator(.)ident(compact)operator(.)ident(sort) + reserved(end) + reserved(end) + + reserved(def) method(test_copy_table_with_index) + ident(test_copy_table)operator(()string<delimiter(')content(comments)delimiter(')>operator(,) string<delimiter(')content(comments_with_index)delimiter(')>operator(\)) reserved(do) + instance_variable(@connection)operator(.)ident(add_index)operator(()string<delimiter(')content(comments_with_index)delimiter(')>operator(,) operator([)string<delimiter(')content(post_id)delimiter(')>operator(,) string<delimiter(')content(type)delimiter(')>operator(])operator(\)) + ident(test_copy_table)operator(()string<delimiter(')content(comments_with_index)delimiter(')>operator(,) string<delimiter(')content(comments_with_index2)delimiter(')>operator(\)) reserved(do) + ident(assert_equal) ident(table_indexes_without_name)operator(()string<delimiter(')content(comments_with_index)delimiter(')>operator(\))operator(,) + ident(table_indexes_without_name)operator(()string<delimiter(')content(comments_with_index2)delimiter(')>operator(\)) + reserved(end) + reserved(end) + reserved(end) + +ident(protected) + reserved(def) method(copy_table)operator(()ident(from)operator(,) ident(to)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + instance_variable(@connection)operator(.)ident(copy_table)operator(()ident(from)operator(,) ident(to)operator(,) operator({)symbol(:temporary) operator(=)operator(>) pre_constant(true)operator(})operator(.)ident(merge)operator(()ident(options)operator(\))operator(\)) + reserved(end) + + reserved(def) method(column_names)operator(()ident(table)operator(\)) + instance_variable(@connection)operator(.)ident(table_structure)operator(()ident(table)operator(\))operator(.)ident(map) operator({)operator(|)ident(column)operator(|) ident(column)operator([)string<delimiter(')content(name)delimiter(')>operator(])operator(}) + reserved(end) + + reserved(def) method(column_values)operator(()ident(table)operator(,) ident(column)operator(\)) + instance_variable(@connection)operator(.)ident(select_all)operator(()string<delimiter(")content(SELECT )inline<inline_delimiter(#{)ident(column)inline_delimiter(})>content( FROM )inline<inline_delimiter(#{)ident(table)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(map) operator({)operator(|)ident(row)operator(|) ident(row)operator([)ident(column)operator(])operator(}) + reserved(end) + + reserved(def) method(table_indexes_without_name)operator(()ident(table)operator(\)) + instance_variable(@connection)operator(.)ident(indexes)operator(()string<delimiter(')content(comments_with_index)delimiter(')>operator(\))operator(.)ident(delete)operator(()symbol(:name)operator(\)) + reserved(end) + + reserved(def) method(row_count)operator(()ident(table)operator(\)) + instance_variable(@connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT COUNT(*\) AS count FROM )inline<inline_delimiter(#{)ident(table)inline_delimiter(})>delimiter(")>operator(\))operator([)string<delimiter(')content(count)delimiter(')>operator(]) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/default)delimiter(')> + +reserved(class) class(DefaultTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_default_timestamp) + ident(default) operator(=) constant(Default)operator(.)ident(new) + ident(assert_instance_of)operator(()constant(Time)operator(,) ident(default)operator(.)ident(default_timestamp)operator(\)) + ident(assert_equal)operator(()symbol(:datetime)operator(,) ident(default)operator(.)ident(column_for_attribute)operator(()symbol(:default_timestamp)operator(\))operator(.)ident(type)operator(\)) + + comment(# Variance should be small; increase if required -- e.g., if test db is on) + comment(# remote host and clocks aren't synchronized.) + ident(t1) operator(=) constant(Time)operator(.)ident(new) + ident(accepted_variance) operator(=) float(1.0) + ident(assert_in_delta)operator(()ident(t1)operator(.)ident(to_f)operator(,) ident(default)operator(.)ident(default_timestamp)operator(.)ident(to_f)operator(,) ident(accepted_variance)operator(\)) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/default)delimiter(')> + +reserved(class) class(DefaultsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(if) string<delimiter(%w()content(PostgreSQL)delimiter(\))>operator(.)ident(include?) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(adapter_name) + reserved(def) method(test_default_integers) + ident(default) operator(=) constant(Default)operator(.)ident(new) + ident(assert_instance_of)operator(()constant(Fixnum)operator(,) ident(default)operator(.)ident(positive_integer)operator(\)) + ident(assert_equal)operator(()ident(default)operator(.)ident(positive_integer)operator(,) integer(1)operator(\)) + ident(assert_instance_of)operator(()constant(Fixnum)operator(,) ident(default)operator(.)ident(negative_integer)operator(\)) + ident(assert_equal)operator(()ident(default)operator(.)ident(negative_integer)operator(,) integer(-1)operator(\)) + reserved(end) + reserved(else) + reserved(def) method(test_dummy) + ident(assert) pre_constant(true) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> + +comment(# Can't declare new classes in test case methods, so tests before that) +ident(bad_collection_keys) operator(=) pre_constant(false) +reserved(begin) + reserved(class) class(Car) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) ident(has_many) symbol(:wheels)operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(wheels)delimiter(")>operator(;) reserved(end) +reserved(rescue) constant(ArgumentError) + ident(bad_collection_keys) operator(=) pre_constant(true) +reserved(end) +ident(raise) string<delimiter(")content(ActiveRecord should have barked on bad collection keys)delimiter(")> reserved(unless) ident(bad_collection_keys) + + +reserved(class) class(DeprecatedAssociationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:topics)operator(,) + symbol(:developers_projects) + + reserved(def) method(test_has_many_find) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_has_many_orders) + ident(assert_equal) string<delimiter(")content(Summit)delimiter(")>operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_has_many_class_name) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients_sorted_desc)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_has_many_foreign_key) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients_of_firm)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_has_many_conditions) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients_like_ms)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_has_many_sql) + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(assert_equal) string<delimiter(")content(Microsoft)delimiter(")>operator(,) ident(firm)operator(.)ident(clients_using_sql)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients_using_sql_count) + ident(assert_equal) integer(1)operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients_using_sql_count) + reserved(end) + + reserved(def) method(test_has_many_counter_sql) + ident(assert_equal) integer(1)operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(clients_using_counter_sql_count) + reserved(end) + + reserved(def) method(test_has_many_queries) + ident(assert) constant(Firm)operator(.)ident(find_first)operator(.)ident(has_clients?) + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients_count) comment(# tests using class count) + ident(firm)operator(.)ident(clients) + ident(assert) ident(firm)operator(.)ident(has_clients?) + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients_count) comment(# tests using collection length) + reserved(end) + + reserved(def) method(test_has_many_dependence) + ident(assert_equal) integer(3)operator(,) constant(Client)operator(.)ident(find_all)operator(.)ident(length) + constant(Firm)operator(.)ident(find_first)operator(.)ident(destroy) + ident(assert_equal) integer(1)operator(,) constant(Client)operator(.)ident(find_all)operator(.)ident(length) + reserved(end) + + ident(uses_transaction) symbol(:test_has_many_dependence_with_transaction_support_on_failure) + reserved(def) method(test_has_many_dependence_with_transaction_support_on_failure) + ident(assert_equal) integer(3)operator(,) constant(Client)operator(.)ident(find_all)operator(.)ident(length) + + ident(firm) operator(=) constant(Firm)operator(.)ident(find_first) + ident(clients) operator(=) ident(firm)operator(.)ident(clients) + ident(clients)operator(.)ident(last)operator(.)ident(instance_eval) operator({) reserved(def) method(before_destroy)operator(()operator(\)) ident(raise) string<delimiter(")content(Trigger rollback)delimiter(")> reserved(end) operator(}) + + ident(firm)operator(.)ident(destroy) reserved(rescue) string<delimiter(")content(do nothing)delimiter(")> + + ident(assert_equal) integer(3)operator(,) constant(Client)operator(.)ident(find_all)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_has_one_dependence) + ident(num_accounts) operator(=) constant(Account)operator(.)ident(count) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(firm)operator(.)ident(has_account?) + ident(firm)operator(.)ident(destroy) + ident(assert_equal) ident(num_accounts) operator(-) integer(1)operator(,) constant(Account)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_has_one_dependence_with_missing_association) + constant(Account)operator(.)ident(destroy_all) + ident(firm) operator(=) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(firm)operator(.)ident(has_account?) + ident(firm)operator(.)ident(destroy) + reserved(end) + + reserved(def) method(test_belongs_to) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(name)operator(,) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm)operator(.)ident(name) + ident(assert) constant(Client)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(has_firm?)operator(,) string<delimiter(")content(Microsoft should have a firm)delimiter(")> + comment(# assert !Company.find(1\).has_firm?, "37signals shouldn't have a firm") + reserved(end) + + reserved(def) method(test_belongs_to_with_different_class_name) + ident(assert_equal) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(name)operator(,) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm_with_other_name)operator(.)ident(name) + ident(assert) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(has_firm_with_other_name?)operator(,) string<delimiter(")content(Microsoft should have a firm)delimiter(")> + reserved(end) + + reserved(def) method(test_belongs_to_with_condition) + ident(assert_equal) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(name)operator(,) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm_with_condition)operator(.)ident(name) + ident(assert) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(has_firm_with_condition?)operator(,) string<delimiter(")content(Microsoft should have a firm)delimiter(")> + reserved(end) + + reserved(def) method(test_belongs_to_equality) + ident(assert) constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm?)operator(()constant(Company)operator(.)ident(find)operator(()integer(1)operator(\))operator(\))operator(,) string<delimiter(")content(Microsoft should have 37signals as firm)delimiter(")> + ident(assert_raises)operator(()constant(RuntimeError)operator(\)) operator({) operator(!)constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(.)ident(firm?)operator(()constant(Company)operator(.)ident(find)operator(()integer(3)operator(\))operator(\)) operator(}) comment(# "Summit shouldn't have itself as firm") + reserved(end) + + reserved(def) method(test_has_one) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account?)operator(()constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(\)) + ident(assert_equal) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(credit_limit)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account)operator(.)ident(credit_limit) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(has_account?)operator(,) string<delimiter(")content(37signals should have an account)delimiter(")> + ident(assert) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(firm?)operator(()ident(companies)operator(()symbol(:first_firm)operator(\))operator(\))operator(,) string<delimiter(")content(37signals account should be able to backtrack)delimiter(")> + ident(assert) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(has_firm?)operator(,) string<delimiter(")content(37signals account should be able to backtrack)delimiter(")> + + ident(assert) operator(!)constant(Account)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(has_firm?)operator(,) string<delimiter(")content(Unknown isn't linked)delimiter(")> + ident(assert) operator(!)constant(Account)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(firm?)operator(()ident(companies)operator(()symbol(:first_firm)operator(\))operator(\))operator(,) string<delimiter(")content(Unknown isn't linked)delimiter(")> + reserved(end) + + reserved(def) method(test_has_many_dependence_on_account) + ident(num_accounts) operator(=) constant(Account)operator(.)ident(count) + ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(destroy) + ident(assert_equal) ident(num_accounts) operator(-) integer(1)operator(,) constant(Account)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_find_in) + ident(assert_equal) constant(Client)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(name)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(find_in_clients)operator(()integer(2)operator(\))operator(.)ident(name) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(find_in_clients)operator(()integer(6)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_force_reload) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(A New Firm, Inc)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + ident(firm)operator(.)ident(clients)operator(.)ident(each) operator({)operator(|)ident(c)operator(|)operator(}) comment(# forcing to load all clients) + ident(assert) ident(firm)operator(.)ident(clients)operator(.)ident(empty?)operator(,) string<delimiter(")content(New firm shouldn't have client objects)delimiter(")> + ident(assert) operator(!)ident(firm)operator(.)ident(has_clients?)operator(,) string<delimiter(")content(New firm shouldn't have clients)delimiter(")> + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients_count)operator(,) string<delimiter(")content(New firm should have 0 clients)delimiter(")> + + ident(client) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(TheClient.com)delimiter(")>operator(,) string<delimiter(")content(firm_id)delimiter(")> operator(=)operator(>) ident(firm)operator(.)ident(id)operator(\)) + ident(client)operator(.)ident(save) + + ident(assert) ident(firm)operator(.)ident(clients)operator(.)ident(empty?)operator(,) string<delimiter(")content(New firm should have cached no client objects)delimiter(")> + ident(assert) operator(!)ident(firm)operator(.)ident(has_clients?)operator(,) string<delimiter(")content(New firm should have cached a no-clients response)delimiter(")> + ident(assert_equal) integer(0)operator(,) ident(firm)operator(.)ident(clients_count)operator(,) string<delimiter(")content(New firm should have cached 0 clients count)delimiter(")> + + ident(assert) operator(!)ident(firm)operator(.)ident(clients)operator(()pre_constant(true)operator(\))operator(.)ident(empty?)operator(,) string<delimiter(")content(New firm should have reloaded client objects)delimiter(")> + ident(assert) ident(firm)operator(.)ident(has_clients?)operator(()pre_constant(true)operator(\))operator(,) string<delimiter(")content(New firm should have reloaded with a have-clients response)delimiter(")> + ident(assert_equal) integer(1)operator(,) ident(firm)operator(.)ident(clients_count)operator(()pre_constant(true)operator(\))operator(,) string<delimiter(")content(New firm should have reloaded clients count)delimiter(")> + reserved(end) + + reserved(def) method(test_included_in_collection) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients)operator(.)ident(include?)operator(()constant(Client)operator(.)ident(find)operator(()integer(2)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_build_to_collection) + ident(assert_equal) integer(1)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm_count) + ident(new_client) operator(=) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(build_to_clients_of_firm)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content(Another Client)delimiter(")>operator(,) ident(new_client)operator(.)ident(name) + ident(assert) ident(new_client)operator(.)ident(save) + + ident(assert) ident(new_client)operator(.)ident(firm?)operator(()ident(companies)operator(()symbol(:first_firm)operator(\))operator(\)) + ident(assert_equal) integer(2)operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm_count)operator(()pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(test_create_in_collection) + ident(assert_equal) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(create_in_clients_of_firm)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another Client)delimiter(")>operator(\))operator(,) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(clients_of_firm)operator(()pre_constant(true)operator(\))operator(.)ident(last) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(david)operator(.)ident(has_projects?) + ident(assert_equal) integer(2)operator(,) ident(david)operator(.)ident(projects_count) + + ident(active_record) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(active_record)operator(.)ident(has_developers?) + ident(assert_equal) integer(3)operator(,) ident(active_record)operator(.)ident(developers_count) + ident(assert) ident(active_record)operator(.)ident(developers)operator(.)ident(include?)operator(()ident(david)operator(\)) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_removing) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(active_record) operator(=) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\)) + + ident(david)operator(.)ident(remove_projects)operator(()ident(active_record)operator(\)) + + ident(assert_equal) integer(1)operator(,) ident(david)operator(.)ident(projects_count) + ident(assert_equal) integer(2)operator(,) ident(active_record)operator(.)ident(developers_count) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_zero) + ident(david) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(david)operator(.)ident(remove_projects)operator(()constant(Project)operator(.)ident(find_all)operator(\)) + + ident(assert_equal) integer(0)operator(,) ident(david)operator(.)ident(projects_count) + ident(assert) operator(!)ident(david)operator(.)ident(has_projects?) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_adding) + ident(jamis) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(action_controller) operator(=) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\)) + + ident(jamis)operator(.)ident(add_projects)operator(()ident(action_controller)operator(\)) + + ident(assert_equal) integer(2)operator(,) ident(jamis)operator(.)ident(projects_count) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers_count) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_adding_from_the_project) + ident(jamis) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(action_controller) operator(=) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\)) + + ident(action_controller)operator(.)ident(add_developers)operator(()ident(jamis)operator(\)) + + ident(assert_equal) integer(2)operator(,) ident(jamis)operator(.)ident(projects_count) + ident(assert_equal) integer(2)operator(,) ident(action_controller)operator(.)ident(developers_count) + reserved(end) + + reserved(def) method(test_has_and_belongs_to_many_adding_a_collection) + ident(aredridel) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Aredridel)delimiter(")>operator(\)) + ident(aredridel)operator(.)ident(save) + + ident(aredridel)operator(.)ident(add_projects)operator(()operator([) constant(Project)operator(.)ident(find)operator(()integer(1)operator(\))operator(,) constant(Project)operator(.)ident(find)operator(()integer(2)operator(\)) operator(])operator(\)) + ident(assert_equal) integer(2)operator(,) ident(aredridel)operator(.)ident(projects_count) + reserved(end) + + reserved(def) method(test_belongs_to_counter) + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(\)) + ident(assert_equal) integer(0)operator(,) ident(topic)operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(replies_count)delimiter(")>operator(\))operator(,) string<delimiter(")content(No replies yet)delimiter(")> + + ident(reply) operator(=) ident(topic)operator(.)ident(create_in_replies)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(I'm saying no!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(over here)delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(replies_count)delimiter(")>operator(\))operator(,) string<delimiter(")content(First reply created)delimiter(")> + + ident(reply)operator(.)ident(destroy) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(find)operator(()ident(topic)operator(.)ident(id)operator(\))operator(.)ident(send)operator(()symbol(:read_attribute)operator(,) string<delimiter(")content(replies_count)delimiter(")>operator(\))operator(,) string<delimiter(")content(First reply deleted)delimiter(")> + reserved(end) + + reserved(def) method(test_natural_assignment_of_has_one) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(apple)operator(.)ident(account) operator(=) ident(citibank) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_natural_assignment_of_belongs_to) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(citibank) operator(=) constant(Account)operator(.)ident(create)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(10)operator(\)) + ident(citibank)operator(.)ident(firm) operator(=) ident(apple) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(citibank)operator(.)ident(firm_id) + reserved(end) + + reserved(def) method(test_natural_assignment_of_has_many) + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(natural) operator(=) constant(Client)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Natural Company)delimiter(")>operator(\)) + ident(apple)operator(.)ident(clients) operator(<<) ident(natural) + ident(assert_equal) ident(apple)operator(.)ident(id)operator(,) ident(natural)operator(.)ident(firm_id) + ident(assert_equal) constant(Client)operator(.)ident(find)operator(()ident(natural)operator(.)ident(id)operator(\))operator(,) constant(Firm)operator(.)ident(find)operator(()ident(apple)operator(.)ident(id)operator(\))operator(.)ident(clients)operator(.)ident(find)operator(()ident(natural)operator(.)ident(id)operator(\)) + ident(apple)operator(.)ident(clients)operator(.)ident(delete) ident(natural) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) + constant(Firm)operator(.)ident(find)operator(()ident(apple)operator(.)ident(id)operator(\))operator(.)ident(clients)operator(.)ident(find)operator(()ident(natural)operator(.)ident(id)operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_natural_adding_of_has_and_belongs_to_many) + ident(rails) operator(=) constant(Project)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Rails)delimiter(")>operator(\)) + ident(ap) operator(=) constant(Project)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Action Pack)delimiter(")>operator(\)) + ident(john) operator(=) constant(Developer)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(John)delimiter(")>operator(\)) + ident(mike) operator(=) constant(Developer)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Mike)delimiter(")>operator(\)) + ident(rails)operator(.)ident(developers) operator(<<) ident(john) + ident(rails)operator(.)ident(developers) operator(<<) ident(mike) + + ident(assert_equal) constant(Developer)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\))operator(,) constant(Project)operator(.)ident(find)operator(()ident(rails)operator(.)ident(id)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\)) + ident(assert_equal) constant(Developer)operator(.)ident(find)operator(()ident(mike)operator(.)ident(id)operator(\))operator(,) constant(Project)operator(.)ident(find)operator(()ident(rails)operator(.)ident(id)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()ident(mike)operator(.)ident(id)operator(\)) + ident(assert_equal) constant(Project)operator(.)ident(find)operator(()ident(rails)operator(.)ident(id)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()ident(mike)operator(.)ident(id)operator(\))operator(.)ident(projects)operator(.)ident(find)operator(()ident(rails)operator(.)ident(id)operator(\)) + ident(assert_equal) constant(Project)operator(.)ident(find)operator(()ident(rails)operator(.)ident(id)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\))operator(.)ident(projects)operator(.)ident(find)operator(()ident(rails)operator(.)ident(id)operator(\)) + ident(ap)operator(.)ident(developers) operator(<<) ident(john) + ident(assert_equal) constant(Developer)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\))operator(,) constant(Project)operator(.)ident(find)operator(()ident(ap)operator(.)ident(id)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\)) + ident(assert_equal) constant(Project)operator(.)ident(find)operator(()ident(ap)operator(.)ident(id)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\))operator(.)ident(projects)operator(.)ident(find)operator(()ident(ap)operator(.)ident(id)operator(\)) + + ident(ap)operator(.)ident(developers)operator(.)ident(delete) ident(john) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) + constant(Project)operator(.)ident(find)operator(()ident(ap)operator(.)ident(id)operator(\))operator(.)ident(developers)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\)) + operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) + constant(Developer)operator(.)ident(find)operator(()ident(john)operator(.)ident(id)operator(\))operator(.)ident(projects)operator(.)ident(find)operator(()ident(ap)operator(.)ident(id)operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_storing_in_pstore) + ident(require) string<delimiter(")content(pstore)delimiter(")> + ident(require) string<delimiter(")content(tmpdir)delimiter(")> + ident(apple) operator(=) constant(Firm)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Apple)delimiter(")>operator(\)) + ident(natural) operator(=) constant(Client)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(Natural Company)delimiter(")>operator(\)) + ident(apple)operator(.)ident(clients) operator(<<) ident(natural) + + ident(db) operator(=) constant(PStore)operator(.)ident(new)operator(()constant(File)operator(.)ident(join)operator(()constant(Dir)operator(.)ident(tmpdir)operator(,) string<delimiter(")content(ar-pstore-association-test)delimiter(")>operator(\))operator(\)) + ident(db)operator(.)ident(transaction) reserved(do) + ident(db)operator([)string<delimiter(")content(apple)delimiter(")>operator(]) operator(=) ident(apple) + reserved(end) + + ident(db) operator(=) constant(PStore)operator(.)ident(new)operator(()constant(File)operator(.)ident(join)operator(()constant(Dir)operator(.)ident(tmpdir)operator(,) string<delimiter(")content(ar-pstore-association-test)delimiter(")>operator(\))operator(\)) + ident(db)operator(.)ident(transaction) reserved(do) + ident(assert_equal) string<delimiter(")content(Natural Company)delimiter(")>operator(,) ident(db)operator([)string<delimiter(")content(apple)delimiter(")>operator(])operator(.)ident(clients)operator(.)ident(first)operator(.)ident(name) + reserved(end) + reserved(end) + + reserved(def) method(test_has_many_find_all) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(find_all_in_clients)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Client')delimiter(")>operator(\))operator(.)ident(length) + ident(assert_equal) integer(1)operator(,) constant(Firm)operator(.)ident(find_first)operator(.)ident(find_all_in_clients)operator(()string<delimiter(")content(name = 'Summit')delimiter(")>operator(\))operator(.)ident(length) + reserved(end) + + reserved(def) method(test_has_one) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(account?)operator(()constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(\)) + ident(assert) ident(companies)operator(()symbol(:first_firm)operator(\))operator(.)ident(has_account?)operator(,) string<delimiter(")content(37signals should have an account)delimiter(")> + ident(assert) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(firm?)operator(()ident(companies)operator(()symbol(:first_firm)operator(\))operator(\))operator(,) string<delimiter(")content(37signals account should be able to backtrack)delimiter(")> + ident(assert) constant(Account)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(has_firm?)operator(,) string<delimiter(")content(37signals account should be able to backtrack)delimiter(")> + + ident(assert) operator(!)constant(Account)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(has_firm?)operator(,) string<delimiter(")content(Unknown isn't linked)delimiter(")> + ident(assert) operator(!)constant(Account)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(firm?)operator(()ident(companies)operator(()symbol(:first_firm)operator(\))operator(\))operator(,) string<delimiter(")content(Unknown isn't linked)delimiter(")> + reserved(end) + + reserved(def) method(test_has_one_build) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(assert) ident(firm)operator(.)ident(save) + + ident(account) operator(=) ident(firm)operator(.)ident(build_account)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\)) + ident(assert) ident(account)operator(.)ident(save) + ident(assert_equal) ident(account)operator(,) ident(firm)operator(.)ident(account) + reserved(end) + + reserved(def) method(test_has_one_failing_build_association) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + + ident(account) operator(=) ident(firm)operator(.)ident(build_account) + ident(assert) operator(!)ident(account)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(can't be empty)delimiter(")>operator(,) ident(account)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(credit_limit)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_has_one_create) + ident(firm) operator(=) constant(Firm)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(GlobalMegaCorp)delimiter(")>operator(\)) + ident(firm)operator(.)ident(save) + ident(assert_equal) ident(firm)operator(.)ident(create_account)operator(()string<delimiter(")content(credit_limit)delimiter(")> operator(=)operator(>) integer(1000)operator(\))operator(,) ident(firm)operator(.)ident(account) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/entrant)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> + +reserved(class) class(DeprecatedFinderTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:companies)operator(,) symbol(:topics)operator(,) symbol(:entrants)operator(,) symbol(:developers) + + reserved(def) method(test_find_all_with_limit) + ident(entrants) operator(=) constant(Entrant)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(")content(id ASC)delimiter(")>operator(,) integer(2) + + ident(assert_equal)operator(()integer(2)operator(,) ident(entrants)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(entrants)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(,) ident(entrants)operator(.)ident(first)operator(.)ident(name)operator(\)) + reserved(end) + + reserved(def) method(test_find_all_with_prepared_limit_and_offset) + ident(entrants) operator(=) constant(Entrant)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(")content(id ASC)delimiter(")>operator(,) operator([)integer(2)operator(,) integer(1)operator(]) + + ident(assert_equal)operator(()integer(2)operator(,) ident(entrants)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(entrants)operator(()symbol(:second)operator(\))operator(.)ident(name)operator(,) ident(entrants)operator(.)ident(first)operator(.)ident(name)operator(\)) + reserved(end) + + reserved(def) method(test_find_first) + ident(first) operator(=) constant(Topic)operator(.)ident(find_first) string<delimiter(")content(title = 'The First Topic')delimiter(")> + ident(assert_equal)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(title)operator(,) ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_find_first_failing) + ident(first) operator(=) constant(Topic)operator(.)ident(find_first) string<delimiter(")content(title = 'The First Topic!')delimiter(")> + ident(assert_nil)operator(()ident(first)operator(\)) + reserved(end) + + reserved(def) method(test_deprecated_find_on_conditions) + ident(assert) constant(Topic)operator(.)ident(find_on_conditions)operator(()integer(1)operator(,) operator([)string<delimiter(")content(approved = ?)delimiter(")>operator(,) pre_constant(false)operator(])operator(\)) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Topic)operator(.)ident(find_on_conditions)operator(()integer(1)operator(,) operator([)string<delimiter(")content(approved = ?)delimiter(")>operator(,) pre_constant(true)operator(])operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_condition_interpolation) + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(37signals)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(37signals!)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(37signals!' OR 1=1)delimiter(")>operator(])operator(\)) + ident(assert_kind_of) constant(Time)operator(,) constant(Topic)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(id = %d)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(.)ident(written_on) + reserved(end) + + reserved(def) method(test_bind_variables) + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals!)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals!' OR 1=1)delimiter(")>operator(])operator(\)) + ident(assert_kind_of) constant(Time)operator(,) constant(Topic)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(id = ?)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(.)ident(written_on) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) + constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(id=? AND name = ?)delimiter(")>operator(,) integer(2)operator(])operator(\)) + operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) + constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(id=?)delimiter(")>operator(,) integer(2)operator(,) integer(3)operator(,) integer(4)operator(])operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_bind_variables_with_quotes) + constant(Company)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(\)) + ident(assert) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_named_bind_variables_with_quotes) + constant(Company)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(\)) + ident(assert) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({)symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(})operator(])operator(\)) + reserved(end) + + reserved(def) method(test_named_bind_variables) + ident(assert_equal) string<delimiter(')content(1)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(:a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) integer(1)operator(\)) comment(# ' ruby-mode) + ident(assert_equal) string<delimiter(')content(1 1)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(:a :a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) integer(1)operator(\)) comment(# ' ruby-mode) + + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals)delimiter(")> operator(})operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals!)delimiter(")> operator(})operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals!' OR 1=1)delimiter(")> operator(})operator(])operator(\)) + ident(assert_kind_of) constant(Time)operator(,) constant(Topic)operator(.)ident(find_first)operator(()operator([)string<delimiter(")content(id = :id)delimiter(")>operator(,) operator({) symbol(:id) operator(=)operator(>) integer(1) operator(})operator(])operator(\))operator(.)ident(written_on) + reserved(end) + + reserved(def) method(test_count) + ident(assert_equal)operator(()integer(0)operator(,) constant(Entrant)operator(.)ident(count)operator(()string<delimiter(")content(id > 3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) constant(Entrant)operator(.)ident(count)operator(()operator([)string<delimiter(")content(id > ?)delimiter(")>operator(,) integer(2)operator(])operator(\))operator(\)) + ident(assert_equal)operator(()integer(2)operator(,) constant(Entrant)operator(.)ident(count)operator(()operator([)string<delimiter(")content(id > ?)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_count_by_sql) + ident(assert_equal)operator(()integer(0)operator(,) constant(Entrant)operator(.)ident(count_by_sql)operator(()string<delimiter(")content(SELECT COUNT(*\) FROM entrants WHERE id > 3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) constant(Entrant)operator(.)ident(count_by_sql)operator(()operator([)string<delimiter(")content(SELECT COUNT(*\) FROM entrants WHERE id > ?)delimiter(")>operator(,) integer(2)operator(])operator(\))operator(\)) + ident(assert_equal)operator(()integer(2)operator(,) constant(Entrant)operator(.)ident(count_by_sql)operator(()operator([)string<delimiter(")content(SELECT COUNT(*\) FROM entrants WHERE id > ?)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_find_all_with_limit) + ident(first_five_developers) operator(=) constant(Developer)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) integer(5) + ident(assert_equal) integer(5)operator(,) ident(first_five_developers)operator(.)ident(length) + ident(assert_equal) string<delimiter(')content(David)delimiter(')>operator(,) ident(first_five_developers)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(')content(fixture_5)delimiter(')>operator(,) ident(first_five_developers)operator(.)ident(last)operator(.)ident(name) + + ident(no_developers) operator(=) constant(Developer)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) integer(0) + ident(assert_equal) integer(0)operator(,) ident(no_developers)operator(.)ident(length) + + ident(assert_equal) ident(first_five_developers)operator(,) constant(Developer)operator(.)ident(find_all)operator(()pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) operator([)integer(5)operator(])operator(\)) + ident(assert_equal) ident(no_developers)operator(,) constant(Developer)operator(.)ident(find_all)operator(()pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) operator([)integer(0)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_find_all_with_limit_and_offset) + ident(first_three_developers) operator(=) constant(Developer)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) operator([)integer(3)operator(,) integer(0)operator(]) + ident(second_three_developers) operator(=) constant(Developer)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) operator([)integer(3)operator(,) integer(3)operator(]) + ident(last_two_developers) operator(=) constant(Developer)operator(.)ident(find_all) pre_constant(nil)operator(,) string<delimiter(')content(id ASC)delimiter(')>operator(,) operator([)integer(2)operator(,) integer(8)operator(]) + + ident(assert_equal) integer(3)operator(,) ident(first_three_developers)operator(.)ident(length) + ident(assert_equal) integer(3)operator(,) ident(second_three_developers)operator(.)ident(length) + ident(assert_equal) integer(2)operator(,) ident(last_two_developers)operator(.)ident(length) + + ident(assert_equal) string<delimiter(')content(David)delimiter(')>operator(,) ident(first_three_developers)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(')content(fixture_4)delimiter(')>operator(,) ident(second_three_developers)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(')content(fixture_9)delimiter(')>operator(,) ident(last_two_developers)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_find_all_by_one_attribute_with_options) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_content)operator(()string<delimiter(")content(Have a nice day)delimiter(")>operator(,) string<delimiter(")content(id DESC)delimiter(")>operator(\)) + ident(assert) ident(topics)operator(()symbol(:first)operator(\))operator(,) ident(topics)operator(.)ident(last) + + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_content)operator(()string<delimiter(")content(Have a nice day)delimiter(")>operator(,) string<delimiter(")content(id DESC)delimiter(")>operator(\)) + ident(assert) ident(topics)operator(()symbol(:first)operator(\))operator(,) ident(topics)operator(.)ident(first) + reserved(end) + + ident(protected) + reserved(def) method(bind)operator(()ident(statement)operator(,) operator(*)ident(vars)operator(\)) + reserved(if) ident(vars)operator(.)ident(first)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:replace_named_bind_variables)operator(,) ident(statement)operator(,) ident(vars)operator(.)ident(first)operator(\)) + reserved(else) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:replace_bind_variables)operator(,) ident(statement)operator(,) ident(vars)operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> +ident(require) string<delimiter(')content(fixtures/entrant)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> + +reserved(class) class(FinderTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:companies)operator(,) symbol(:topics)operator(,) symbol(:entrants)operator(,) symbol(:developers)operator(,) symbol(:developers_projects)operator(,) symbol(:posts)operator(,) symbol(:accounts) + + reserved(def) method(test_find) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(title)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_exists) + ident(assert) operator(()constant(Topic)operator(.)ident(exists?)operator(()integer(1)operator(\))operator(\)) + ident(assert) operator(!)operator(()constant(Topic)operator(.)ident(exists?)operator(()integer(45)operator(\))operator(\)) + ident(assert) operator(!)operator(()constant(Topic)operator(.)ident(exists?)operator(()string<delimiter(")content(foo)delimiter(")>operator(\))operator(\)) + ident(assert) operator(!)operator(()constant(Topic)operator(.)ident(exists?)operator(()operator([)integer(1)operator(,)integer(2)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_find_by_array_of_one_id) + ident(assert_kind_of)operator(()constant(Array)operator(,) constant(Topic)operator(.)ident(find)operator(()operator([) integer(1) operator(])operator(\))operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) constant(Topic)operator(.)ident(find)operator(()operator([) integer(1) operator(])operator(\))operator(.)ident(length)operator(\)) + reserved(end) + + reserved(def) method(test_find_by_ids) + ident(assert_equal)operator(()integer(2)operator(,) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(,) integer(2)operator(\))operator(.)ident(length)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:second)operator(\))operator(.)ident(title)operator(,) constant(Topic)operator(.)ident(find)operator(()operator([) integer(2) operator(])operator(\))operator(.)ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_find_an_empty_array) + ident(assert_equal) operator([)operator(])operator(,) constant(Topic)operator(.)ident(find)operator(()operator([)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_find_by_ids_missing_one) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(,) integer(2)operator(,) integer(45)operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_find_all_with_limit) + ident(entrants) operator(=) constant(Entrant)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id ASC)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(\)) + + ident(assert_equal)operator(()integer(2)operator(,) ident(entrants)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(entrants)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(,) ident(entrants)operator(.)ident(first)operator(.)ident(name)operator(\)) + reserved(end) + + reserved(def) method(test_find_all_with_prepared_limit_and_offset) + ident(entrants) operator(=) constant(Entrant)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id ASC)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:offset) operator(=)operator(>) integer(1)operator(\)) + + ident(assert_equal)operator(()integer(2)operator(,) ident(entrants)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(entrants)operator(()symbol(:second)operator(\))operator(.)ident(name)operator(,) ident(entrants)operator(.)ident(first)operator(.)ident(name)operator(\)) + + ident(entrants) operator(=) constant(Entrant)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id ASC)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:offset) operator(=)operator(>) integer(2)operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) ident(entrants)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(entrants)operator(()symbol(:third)operator(\))operator(.)ident(name)operator(,) ident(entrants)operator(.)ident(first)operator(.)ident(name)operator(\)) + reserved(end) + + reserved(def) method(test_find_all_with_limit_and_offset_and_multiple_orderings) + ident(developers) operator(=) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(salary ASC, id DESC)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(1)operator(\)) + ident(assert_equal) operator([)string<delimiter(")content(David)delimiter(")>operator(,) string<delimiter(")content(fixture_10)delimiter(")>operator(,) string<delimiter(")content(fixture_9)delimiter(")>operator(])operator(,) ident(developers)operator(.)ident(collect) operator({)operator(|)ident(d)operator(|) ident(d)operator(.)ident(name)operator(}) + reserved(end) + + reserved(def) method(test_find_with_limit_and_condition) + ident(developers) operator(=) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary = 100000)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>)integer(7)operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) ident(developers)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(fixture_3)delimiter(")>operator(,) ident(developers)operator(.)ident(first)operator(.)ident(name)operator(\)) + reserved(end) + + reserved(def) method(test_find_with_entire_select_statement) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_by_sql) string<delimiter(")content(SELECT * FROM topics WHERE author_name = 'Mary')delimiter(")> + + ident(assert_equal)operator(()integer(1)operator(,) ident(topics)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:second)operator(\))operator(.)ident(title)operator(,) ident(topics)operator(.)ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_find_with_prepared_select_statement) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_by_sql) operator([)string<delimiter(")content(SELECT * FROM topics WHERE author_name = ?)delimiter(")>operator(,) string<delimiter(")content(Mary)delimiter(")>operator(]) + + ident(assert_equal)operator(()integer(1)operator(,) ident(topics)operator(.)ident(size)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:second)operator(\))operator(.)ident(title)operator(,) ident(topics)operator(.)ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_find_first) + ident(first) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(title = 'The First Topic')delimiter(")>operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(title)operator(,) ident(first)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_find_first_failing) + ident(first) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(title = 'The First Topic!')delimiter(")>operator(\)) + ident(assert_nil)operator(()ident(first)operator(\)) + reserved(end) + + reserved(def) method(test_unexisting_record_exception_handling) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(parent) + operator(}) + + constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(topic) + reserved(end) + + reserved(def) method(test_find_only_some_columns) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:select) operator(=)operator(>) string<delimiter(")content(author_name)delimiter(")>operator(\)) + ident(assert_raises)operator(()constant(NoMethodError)operator(\)) operator({) ident(topic)operator(.)ident(title) operator(}) + ident(assert_equal) string<delimiter(")content(David)delimiter(")>operator(,) ident(topic)operator(.)ident(author_name) + ident(assert) operator(!)ident(topic)operator(.)ident(attribute_present?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) + ident(assert) operator(!)ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(attribute_present?)operator(()string<delimiter(")content(author_name)delimiter(")>operator(\)) + ident(assert) ident(topic)operator(.)ident(respond_to?)operator(()string<delimiter(")content(author_name)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_on_conditions) + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(approved = ?)delimiter(")>operator(,) pre_constant(false)operator(])operator(\)) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(approved = ?)delimiter(")>operator(,) pre_constant(true)operator(])operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_condition_interpolation) + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(37signals)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(37signals!)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = '%s')delimiter(")>operator(,) string<delimiter(")content(37signals!' OR 1=1)delimiter(")>operator(])operator(\)) + ident(assert_kind_of) constant(Time)operator(,) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(id = %d)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(.)ident(written_on) + reserved(end) + + reserved(def) method(test_bind_variables) + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals!)delimiter(")>operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals!' OR 1=1)delimiter(")>operator(])operator(\)) + ident(assert_kind_of) constant(Time)operator(,) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(id = ?)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(.)ident(written_on) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) + constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(id=? AND name = ?)delimiter(")>operator(,) integer(2)operator(])operator(\)) + operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) + constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(id=?)delimiter(")>operator(,) integer(2)operator(,) integer(3)operator(,) integer(4)operator(])operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_bind_variables_with_quotes) + constant(Company)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(\)) + ident(assert) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_named_bind_variables_with_quotes) + constant(Company)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(\)) + ident(assert) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({)symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals' go'es agains)delimiter(")>operator(})operator(])operator(\)) + reserved(end) + + reserved(def) method(test_bind_arity) + ident(assert_nothing_raised) operator({) ident(bind) string<delimiter(')delimiter(')> operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) ident(bind) string<delimiter(')delimiter(')>operator(,) integer(1) operator(}) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) ident(bind) string<delimiter(')content(?)delimiter(')> operator(}) + ident(assert_nothing_raised) operator({) ident(bind) string<delimiter(')content(?)delimiter(')>operator(,) integer(1) operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(PreparedStatementInvalid)operator(\)) operator({) ident(bind) string<delimiter(')content(?)delimiter(')>operator(,) integer(1)operator(,) integer(1) operator(}) + reserved(end) + + reserved(def) method(test_named_bind_variables) + ident(assert_equal) string<delimiter(')content(1)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(:a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) integer(1)operator(\)) comment(# ' ruby-mode) + ident(assert_equal) string<delimiter(')content(1 1)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(:a :a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) integer(1)operator(\)) comment(# ' ruby-mode) + + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals)delimiter(")> operator(})operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals!)delimiter(")> operator(})operator(])operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = :name)delimiter(")>operator(,) operator({) symbol(:name) operator(=)operator(>) string<delimiter(")content(37signals!' OR 1=1)delimiter(")> operator(})operator(])operator(\)) + ident(assert_kind_of) constant(Time)operator(,) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(id = :id)delimiter(")>operator(,) operator({) symbol(:id) operator(=)operator(>) integer(1) operator(})operator(])operator(\))operator(.)ident(written_on) + reserved(end) + + reserved(def) method(test_bind_enumerable) + ident(assert_equal) string<delimiter(')content(1,2,3)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(?)delimiter(')>operator(,) operator([)integer(1)operator(,) integer(2)operator(,) integer(3)operator(])operator(\)) + ident(assert_equal) string<delimiter(%()content('a','b','c')delimiter(\))>operator(,) ident(bind)operator(()string<delimiter(')content(?)delimiter(')>operator(,) string<delimiter(%w()content(a b c)delimiter(\))>operator(\)) + + ident(assert_equal) string<delimiter(')content(1,2,3)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(:a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) operator([)integer(1)operator(,) integer(2)operator(,) integer(3)operator(])operator(\)) + ident(assert_equal) string<delimiter(%()content('a','b','c')delimiter(\))>operator(,) ident(bind)operator(()string<delimiter(')content(:a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) string<delimiter(%w()content(a b c)delimiter(\))>operator(\)) comment(# ') + + ident(require) string<delimiter(')content(set)delimiter(')> + ident(assert_equal) string<delimiter(')content(1,2,3)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(?)delimiter(')>operator(,) constant(Set)operator(.)ident(new)operator(()operator([)integer(1)operator(,) integer(2)operator(,) integer(3)operator(])operator(\))operator(\)) + ident(assert_equal) string<delimiter(%()content('a','b','c')delimiter(\))>operator(,) ident(bind)operator(()string<delimiter(')content(?)delimiter(')>operator(,) constant(Set)operator(.)ident(new)operator(()string<delimiter(%w()content(a b c)delimiter(\))>operator(\))operator(\)) + + ident(assert_equal) string<delimiter(')content(1,2,3)delimiter(')>operator(,) ident(bind)operator(()string<delimiter(')content(:a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) constant(Set)operator(.)ident(new)operator(()operator([)integer(1)operator(,) integer(2)operator(,) integer(3)operator(])operator(\))operator(\)) + ident(assert_equal) string<delimiter(%()content('a','b','c')delimiter(\))>operator(,) ident(bind)operator(()string<delimiter(')content(:a)delimiter(')>operator(,) symbol(:a) operator(=)operator(>) constant(Set)operator(.)ident(new)operator(()string<delimiter(%w()content(a b c)delimiter(\))>operator(\))operator(\)) comment(# ') + reserved(end) + + reserved(def) method(test_bind_string) + ident(assert_equal) string<delimiter(")content('')delimiter(")>operator(,) ident(bind)operator(()string<delimiter(')content(?)delimiter(')>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_string_sanitation) + ident(assert_not_equal) string<delimiter(")content('something ' 1=1')delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(sanitize)operator(()string<delimiter(")content(something ' 1=1)delimiter(")>operator(\)) + ident(assert_equal) string<delimiter(")content('something; select table')delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(sanitize)operator(()string<delimiter(")content(something; select table)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_count) + ident(assert_equal)operator(()integer(0)operator(,) constant(Entrant)operator(.)ident(count)operator(()string<delimiter(")content(id > 3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) constant(Entrant)operator(.)ident(count)operator(()operator([)string<delimiter(")content(id > ?)delimiter(")>operator(,) integer(2)operator(])operator(\))operator(\)) + ident(assert_equal)operator(()integer(2)operator(,) constant(Entrant)operator(.)ident(count)operator(()operator([)string<delimiter(")content(id > ?)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_count_by_sql) + ident(assert_equal)operator(()integer(0)operator(,) constant(Entrant)operator(.)ident(count_by_sql)operator(()string<delimiter(")content(SELECT COUNT(*\) FROM entrants WHERE id > 3)delimiter(")>operator(\))operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) constant(Entrant)operator(.)ident(count_by_sql)operator(()operator([)string<delimiter(")content(SELECT COUNT(*\) FROM entrants WHERE id > ?)delimiter(")>operator(,) integer(2)operator(])operator(\))operator(\)) + ident(assert_equal)operator(()integer(2)operator(,) constant(Entrant)operator(.)ident(count_by_sql)operator(()operator([)string<delimiter(")content(SELECT COUNT(*\) FROM entrants WHERE id > ?)delimiter(")>operator(,) integer(1)operator(])operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_find_by_one_attribute) + ident(assert_equal) ident(topics)operator(()symbol(:first)operator(\))operator(,) constant(Topic)operator(.)ident(find_by_title)operator(()string<delimiter(")content(The First Topic)delimiter(")>operator(\)) + ident(assert_nil) constant(Topic)operator(.)ident(find_by_title)operator(()string<delimiter(")content(The First Topic!)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_by_one_attribute_with_order_option) + ident(assert_equal) ident(accounts)operator(()symbol(:signals37)operator(\))operator(,) constant(Account)operator(.)ident(find_by_credit_limit)operator(()integer(50)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\)) + ident(assert_equal) ident(accounts)operator(()symbol(:rails_core_account)operator(\))operator(,) constant(Account)operator(.)ident(find_by_credit_limit)operator(()integer(50)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id DESC)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_find_by_one_attribute_with_conditions) + ident(assert_equal) ident(accounts)operator(()symbol(:rails_core_account)operator(\))operator(,) constant(Account)operator(.)ident(find_by_credit_limit)operator(()integer(50)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(firm_id = ?)delimiter(')>operator(,) integer(6)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_find_by_one_attribute_with_several_options) + ident(assert_equal) ident(accounts)operator(()symbol(:unknown)operator(\))operator(,) constant(Account)operator(.)ident(find_by_credit_limit)operator(()integer(50)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id DESC)delimiter(')>operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(id != ?)delimiter(')>operator(,) integer(3)operator(])operator(\)) + reserved(end) + + reserved(def) method(test_find_by_one_missing_attribute) + ident(assert_raises)operator(()constant(NoMethodError)operator(\)) operator({) constant(Topic)operator(.)ident(find_by_undertitle)operator(()string<delimiter(")content(The First Topic!)delimiter(")>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_find_by_two_attributes) + ident(assert_equal) ident(topics)operator(()symbol(:first)operator(\))operator(,) constant(Topic)operator(.)ident(find_by_title_and_author_name)operator(()string<delimiter(")content(The First Topic)delimiter(")>operator(,) string<delimiter(")content(David)delimiter(")>operator(\)) + ident(assert_nil) constant(Topic)operator(.)ident(find_by_title_and_author_name)operator(()string<delimiter(")content(The First Topic)delimiter(")>operator(,) string<delimiter(")content(Mary)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_all_by_one_attribute) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_content)operator(()string<delimiter(")content(Have a nice day)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(topics)operator(.)ident(size) + ident(assert) ident(topics)operator(.)ident(include?)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(\)) + + ident(assert_equal) operator([)operator(])operator(,) constant(Topic)operator(.)ident(find_all_by_title)operator(()string<delimiter(")content(The First Topic!!)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_all_by_one_attribute_with_options) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_content)operator(()string<delimiter(")content(Have a nice day)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")>operator(\)) + ident(assert) ident(topics)operator(()symbol(:first)operator(\))operator(,) ident(topics)operator(.)ident(last) + + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_content)operator(()string<delimiter(")content(Have a nice day)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(\)) + ident(assert) ident(topics)operator(()symbol(:first)operator(\))operator(,) ident(topics)operator(.)ident(first) + reserved(end) + + reserved(def) method(test_find_all_by_array_attribute) + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(find_all_by_title)operator(()operator([)string<delimiter(")content(The First Topic)delimiter(")>operator(,) string<delimiter(")content(The Second Topic's of the day)delimiter(")>operator(])operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_find_all_by_boolean_attribute) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_approved)operator(()pre_constant(false)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(topics)operator(.)ident(size) + ident(assert) ident(topics)operator(.)ident(include?)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(\)) + + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_approved)operator(()pre_constant(true)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(topics)operator(.)ident(size) + ident(assert) ident(topics)operator(.)ident(include?)operator(()ident(topics)operator(()symbol(:second)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_find_by_nil_attribute) + ident(topic) operator(=) constant(Topic)operator(.)ident(find_by_last_read) pre_constant(nil) + ident(assert_not_nil) ident(topic) + ident(assert_nil) ident(topic)operator(.)ident(last_read) + reserved(end) + + reserved(def) method(test_find_all_by_nil_attribute) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_last_read) pre_constant(nil) + ident(assert_equal) integer(1)operator(,) ident(topics)operator(.)ident(size) + ident(assert_nil) ident(topics)operator([)integer(0)operator(])operator(.)ident(last_read) + reserved(end) + + reserved(def) method(test_find_by_nil_and_not_nil_attributes) + ident(topic) operator(=) constant(Topic)operator(.)ident(find_by_last_read_and_author_name) pre_constant(nil)operator(,) string<delimiter(")content(Mary)delimiter(")> + ident(assert_equal) string<delimiter(")content(Mary)delimiter(")>operator(,) ident(topic)operator(.)ident(author_name) + reserved(end) + + reserved(def) method(test_find_all_by_nil_and_not_nil_attributes) + ident(topics) operator(=) constant(Topic)operator(.)ident(find_all_by_last_read_and_author_name) pre_constant(nil)operator(,) string<delimiter(")content(Mary)delimiter(")> + ident(assert_equal) integer(1)operator(,) ident(topics)operator(.)ident(size) + ident(assert_equal) string<delimiter(")content(Mary)delimiter(")>operator(,) ident(topics)operator([)integer(0)operator(])operator(.)ident(author_name) + reserved(end) + + reserved(def) method(test_find_or_create_from_one_attribute) + ident(number_of_companies) operator(=) constant(Company)operator(.)ident(count) + ident(sig38) operator(=) constant(Company)operator(.)ident(find_or_create_by_name)operator(()string<delimiter(")content(38signals)delimiter(")>operator(\)) + ident(assert_equal) ident(number_of_companies) operator(+) integer(1)operator(,) constant(Company)operator(.)ident(count) + ident(assert_equal) ident(sig38)operator(,) constant(Company)operator(.)ident(find_or_create_by_name)operator(()string<delimiter(")content(38signals)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_or_create_from_two_attributes) + ident(number_of_topics) operator(=) constant(Topic)operator(.)ident(count) + ident(another) operator(=) constant(Topic)operator(.)ident(find_or_create_by_title_and_author_name)operator(()string<delimiter(")content(Another topic)delimiter(")>operator(,)string<delimiter(")content(John)delimiter(")>operator(\)) + ident(assert_equal) ident(number_of_topics) operator(+) integer(1)operator(,) constant(Topic)operator(.)ident(count) + ident(assert_equal) ident(another)operator(,) constant(Topic)operator(.)ident(find_or_create_by_title_and_author_name)operator(()string<delimiter(")content(Another topic)delimiter(")>operator(,) string<delimiter(")content(John)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_find_with_bad_sql) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) operator({) constant(Topic)operator(.)ident(find_by_sql) string<delimiter(")content(select 1 from badtable)delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_find_with_invalid_params) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(find) symbol(:first)operator(,) symbol(:join) operator(=)operator(>) string<delimiter(")content(It should be `joins')delimiter(")> operator(}) + ident(assert_raises)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(find) symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(1 = 1)delimiter(')>operator(,) symbol(:join) operator(=)operator(>) string<delimiter(")content(It should be `joins')delimiter(")> operator(}) + reserved(end) + + reserved(def) method(test_find_all_with_limit) + ident(first_five_developers) operator(=) constant(Developer)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id ASC)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(5) + ident(assert_equal) integer(5)operator(,) ident(first_five_developers)operator(.)ident(length) + ident(assert_equal) string<delimiter(')content(David)delimiter(')>operator(,) ident(first_five_developers)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(')content(fixture_5)delimiter(')>operator(,) ident(first_five_developers)operator(.)ident(last)operator(.)ident(name) + + ident(no_developers) operator(=) constant(Developer)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id ASC)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(0) + ident(assert_equal) integer(0)operator(,) ident(no_developers)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_find_all_with_limit_and_offset) + ident(first_three_developers) operator(=) constant(Developer)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id ASC)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(0) + ident(second_three_developers) operator(=) constant(Developer)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id ASC)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(3) + ident(last_two_developers) operator(=) constant(Developer)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id ASC)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(2)operator(,) symbol(:offset) operator(=)operator(>) integer(8) + + ident(assert_equal) integer(3)operator(,) ident(first_three_developers)operator(.)ident(length) + ident(assert_equal) integer(3)operator(,) ident(second_three_developers)operator(.)ident(length) + ident(assert_equal) integer(2)operator(,) ident(last_two_developers)operator(.)ident(length) + + ident(assert_equal) string<delimiter(')content(David)delimiter(')>operator(,) ident(first_three_developers)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(')content(fixture_4)delimiter(')>operator(,) ident(second_three_developers)operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(')content(fixture_9)delimiter(')>operator(,) ident(last_two_developers)operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_find_all_with_limit_and_offset_and_multiple_order_clauses) + ident(first_three_posts) operator(=) constant(Post)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(author_id, id)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(0) + ident(second_three_posts) operator(=) constant(Post)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content( author_id,id )delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(3) + ident(last_posts) operator(=) constant(Post)operator(.)ident(find) symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content( author_id, id )delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(3)operator(,) symbol(:offset) operator(=)operator(>) integer(6) + + ident(assert_equal) operator([)operator([)integer(0)operator(,)integer(3)operator(])operator(,)operator([)integer(1)operator(,)integer(1)operator(])operator(,)operator([)integer(1)operator(,)integer(2)operator(])operator(])operator(,) ident(first_three_posts)operator(.)ident(map) operator({) operator(|)ident(p)operator(|) operator([)ident(p)operator(.)ident(author_id)operator(,) ident(p)operator(.)ident(id)operator(]) operator(}) + ident(assert_equal) operator([)operator([)integer(1)operator(,)integer(4)operator(])operator(,)operator([)integer(1)operator(,)integer(5)operator(])operator(,)operator([)integer(1)operator(,)integer(6)operator(])operator(])operator(,) ident(second_three_posts)operator(.)ident(map) operator({) operator(|)ident(p)operator(|) operator([)ident(p)operator(.)ident(author_id)operator(,) ident(p)operator(.)ident(id)operator(]) operator(}) + ident(assert_equal) operator([)operator([)integer(2)operator(,)integer(7)operator(])operator(])operator(,) ident(last_posts)operator(.)ident(map) operator({) operator(|)ident(p)operator(|) operator([)ident(p)operator(.)ident(author_id)operator(,) ident(p)operator(.)ident(id)operator(]) operator(}) + reserved(end) + + reserved(def) method(test_find_all_with_join) + ident(developers_on_project_one) operator(=) constant(Developer)operator(.)ident(find)operator(() + symbol(:all)operator(,) + symbol(:joins) operator(=)operator(>) string<delimiter(')content(LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id)delimiter(')>operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(')content(project_id=1)delimiter(')> + operator(\)) + ident(assert_equal) integer(3)operator(,) ident(developers_on_project_one)operator(.)ident(length) + ident(developer_names) operator(=) ident(developers_on_project_one)operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + ident(assert) ident(developer_names)operator(.)ident(include?)operator(()string<delimiter(')content(David)delimiter(')>operator(\)) + ident(assert) ident(developer_names)operator(.)ident(include?)operator(()string<delimiter(')content(Jamis)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_find_by_id_with_conditions_with_or) + ident(assert_nothing_raised) reserved(do) + constant(Post)operator(.)ident(find)operator(()operator([)integer(1)operator(,)integer(2)operator(,)integer(3)operator(])operator(,) + symbol(:conditions) operator(=)operator(>) string<delimiter(")content(posts.id <= 3 OR posts.)inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Post')delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_select_value) + ident(assert_equal) string<delimiter(")content(37signals)delimiter(")>operator(,) constant(Company)operator(.)ident(connection)operator(.)ident(select_value)operator(()string<delimiter(")content(SELECT name FROM companies WHERE id = 1)delimiter(")>operator(\)) + ident(assert_nil) constant(Company)operator(.)ident(connection)operator(.)ident(select_value)operator(()string<delimiter(")content(SELECT name FROM companies WHERE id = -1)delimiter(")>operator(\)) + comment(# make sure we didn't break count...) + ident(assert_equal) integer(0)operator(,) constant(Company)operator(.)ident(count_by_sql)operator(()string<delimiter(")content(SELECT COUNT(*\) FROM companies WHERE name = 'Halliburton')delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Company)operator(.)ident(count_by_sql)operator(()string<delimiter(")content(SELECT COUNT(*\) FROM companies WHERE name = '37signals')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_select_values) + ident(assert_equal) operator([)string<delimiter(")content(1)delimiter(")>operator(,)string<delimiter(")content(2)delimiter(")>operator(,)string<delimiter(")content(3)delimiter(")>operator(,)string<delimiter(")content(4)delimiter(")>operator(,)string<delimiter(")content(5)delimiter(")>operator(,)string<delimiter(")content(6)delimiter(")>operator(,)string<delimiter(")content(7)delimiter(")>operator(,)string<delimiter(")content(8)delimiter(")>operator(])operator(,) constant(Company)operator(.)ident(connection)operator(.)ident(select_values)operator(()string<delimiter(")content(SELECT id FROM companies ORDER BY id)delimiter(")>operator(\))operator(.)ident(map!) operator({) operator(|)ident(i)operator(|) ident(i)operator(.)ident(to_s) operator(}) + ident(assert_equal) operator([)string<delimiter(")content(37signals)delimiter(")>operator(,)string<delimiter(")content(Summit)delimiter(")>operator(,)string<delimiter(")content(Microsoft)delimiter(")>operator(,) string<delimiter(")content(Flamboyant Software)delimiter(")>operator(,) string<delimiter(")content(Ex Nihilo)delimiter(")>operator(,) string<delimiter(")content(RailsCore)delimiter(")>operator(,) string<delimiter(")content(Leetsoft)delimiter(")>operator(,) string<delimiter(")content(Jadedpixel)delimiter(")>operator(])operator(,) constant(Company)operator(.)ident(connection)operator(.)ident(select_values)operator(()string<delimiter(")content(SELECT name FROM companies ORDER BY id)delimiter(")>operator(\)) + reserved(end) + + ident(protected) + reserved(def) method(bind)operator(()ident(statement)operator(,) operator(*)ident(vars)operator(\)) + reserved(if) ident(vars)operator(.)ident(first)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:replace_named_bind_variables)operator(,) ident(statement)operator(,) ident(vars)operator(.)ident(first)operator(\)) + reserved(else) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:replace_bind_variables)operator(,) ident(statement)operator(,) ident(vars)operator(\)) + reserved(end) + reserved(end) +reserved(end) +reserved(class) class(Author) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_many) symbol(:posts) + ident(has_many) symbol(:posts_with_comments)operator(,) symbol(:include) operator(=)operator(>) symbol(:comments)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")> + ident(has_many) symbol(:posts_with_categories)operator(,) symbol(:include) operator(=)operator(>) symbol(:categories)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")> + ident(has_many) symbol(:posts_with_comments_and_categories)operator(,) symbol(:include) operator(=)operator(>) operator([) symbol(:comments)operator(,) symbol(:categories) operator(])operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(posts.id)delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")> + ident(has_many) symbol(:comments)operator(,) symbol(:through) operator(=)operator(>) symbol(:posts) + ident(has_many) symbol(:funky_comments)operator(,) symbol(:through) operator(=)operator(>) symbol(:posts)operator(,) symbol(:source) operator(=)operator(>) symbol(:comments) + + ident(has_many) symbol(:special_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")> + ident(has_many) symbol(:hello_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:conditions)operator(=)operator(>)string<delimiter(")char(\\#)content({aliased_table_name}.body = 'hello')delimiter(")> + ident(has_many) symbol(:nonexistent_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:conditions)operator(=)operator(>)string<delimiter(")char(\\#)content({aliased_table_name}.body = 'nonexistent')delimiter(")> + ident(has_many) symbol(:posts_with_callbacks)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:before_add) operator(=)operator(>) symbol(:log_before_adding)operator(,) + symbol(:after_add) operator(=)operator(>) symbol(:log_after_adding)operator(,) + symbol(:before_remove) operator(=)operator(>) symbol(:log_before_removing)operator(,) + symbol(:after_remove) operator(=)operator(>) symbol(:log_after_removing) + ident(has_many) symbol(:posts_with_proc_callbacks)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) + symbol(:before_add) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(post_log) operator(<<) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(,) + symbol(:after_add) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(post_log) operator(<<) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(,) + symbol(:before_remove) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(post_log) operator(<<) string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(,) + symbol(:after_remove) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(post_log) operator(<<) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(}) + ident(has_many) symbol(:posts_with_multiple_callbacks)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) + symbol(:before_add) operator(=)operator(>) operator([)symbol(:log_before_adding)operator(,) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(post_log) operator(<<) string<delimiter(")content(before_adding_proc)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(])operator(,) + symbol(:after_add) operator(=)operator(>) operator([)symbol(:log_after_adding)operator(,) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(post_log) operator(<<) string<delimiter(")content(after_adding_proc)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(]) + ident(has_many) symbol(:unchangable_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:before_add) operator(=)operator(>) symbol(:raise_exception)operator(,) symbol(:after_add) operator(=)operator(>) symbol(:log_after_adding) + + ident(has_many) symbol(:categorizations) + ident(has_many) symbol(:categories)operator(,) symbol(:through) operator(=)operator(>) symbol(:categorizations) + + ident(has_many) symbol(:nothings)operator(,) symbol(:through) operator(=)operator(>) symbol(:kateggorisatons)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Category)delimiter(')> + + ident(has_many) symbol(:author_favorites) + ident(has_many) symbol(:favorite_authors)operator(,) symbol(:through) operator(=)operator(>) symbol(:author_favorites)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(name)delimiter(')> + + ident(has_many) symbol(:tagging)operator(,) symbol(:through) operator(=)operator(>) symbol(:posts) comment(# through polymorphic has_one) + ident(has_many) symbol(:taggings)operator(,) symbol(:through) operator(=)operator(>) symbol(:posts)operator(,) symbol(:source) operator(=)operator(>) symbol(:taggings) comment(# through polymorphic has_many) + ident(has_many) symbol(:tags)operator(,) symbol(:through) operator(=)operator(>) symbol(:posts) comment(# through has_many :through) + ident(has_many) symbol(:post_categories)operator(,) symbol(:through) operator(=)operator(>) symbol(:posts)operator(,) symbol(:source) operator(=)operator(>) symbol(:categories) + + ident(belongs_to) symbol(:author_address) + + ident(attr_accessor) symbol(:post_log) + + reserved(def) method(after_initialize) + instance_variable(@post_log) operator(=) operator([)operator(]) + reserved(end) + + ident(private) + reserved(def) method(log_before_adding)operator(()ident(object)operator(\)) + instance_variable(@post_log) operator(<<) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(object)operator(.)ident(id)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(log_after_adding)operator(()ident(object)operator(\)) + instance_variable(@post_log) operator(<<) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(object)operator(.)ident(id)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(log_before_removing)operator(()ident(object)operator(\)) + instance_variable(@post_log) operator(<<) string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(object)operator(.)ident(id)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(log_after_removing)operator(()ident(object)operator(\)) + instance_variable(@post_log) operator(<<) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(object)operator(.)ident(id)inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(raise_exception)operator(()ident(object)operator(\)) + ident(raise) constant(Exception)operator(.)ident(new)operator(()string<delimiter(")content(You can't add a post)delimiter(")>operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(AuthorAddress) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_one) symbol(:author) +reserved(end) + +reserved(class) class(AuthorFavorite) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:author) + ident(belongs_to) symbol(:favorite_author)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Author)delimiter(")>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(favorite_author_id)delimiter(')> +ident(endclass) constant(AutoId) operator(<) constant(ActiveRecord)operator(::)constant(Base) + reserved(def) pre_constant(self)operator(.)ident(table_name) operator(()operator(\)) string<delimiter(")content(auto_id_tests)delimiter(")> reserved(end) + reserved(def) pre_constant(self)operator(.)ident(primary_key) operator(()operator(\)) string<delimiter(")content(auto_id)delimiter(")> reserved(end) +reserved(end) +reserved(class) class(Binary) operator(<) constant(ActiveRecord)operator(::)constant(Base) +ident(endclass) constant(Categorization) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:post) + ident(belongs_to) symbol(:category) + ident(belongs_to) symbol(:author) +ident(endclass) constant(Category) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:posts) + ident(has_and_belongs_to_many) symbol(:special_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")> + ident(has_and_belongs_to_many) symbol(:hello_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")char(\\#)content({aliased_table_name}.body = 'hello')delimiter(")> + ident(has_and_belongs_to_many) symbol(:nonexistent_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Post)delimiter(")>operator(,) symbol(:conditions)operator(=)operator(>)string<delimiter(")char(\\#)content({aliased_table_name}.body = 'nonexistent')delimiter(")> + + reserved(def) pre_constant(self)operator(.)ident(what_are_you) + string<delimiter(')content(a category...)delimiter(')> + reserved(end) + + ident(has_many) symbol(:categorizations) + ident(has_many) symbol(:authors)operator(,) symbol(:through) operator(=)operator(>) symbol(:categorizations)operator(,) symbol(:select) operator(=)operator(>) string<delimiter(')content(authors.*, categorizations.post_id)delimiter(')> +reserved(end) + +reserved(class) class(SpecialCategory) operator(<) constant(Category) + + reserved(def) pre_constant(self)operator(.)ident(what_are_you) + string<delimiter(')content(a special category...)delimiter(')> + reserved(end) + +reserved(end) +reserved(class) class(ColumnName) operator(<) constant(ActiveRecord)operator(::)constant(Base) + reserved(def) pre_constant(self)operator(.)ident(table_name) operator(()operator(\)) string<delimiter(")content(colnametests)delimiter(")> reserved(end) +ident(endclass) constant(Comment) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:post) + + reserved(def) pre_constant(self)operator(.)ident(what_are_you) + string<delimiter(')content(a comment...)delimiter(')> + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(search_by_type)operator(()ident(q)operator(\)) + pre_constant(self)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = ?)delimiter(")>operator(,) ident(q)operator(])operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(SpecialComment) operator(<) constant(Comment) + reserved(def) pre_constant(self)operator(.)ident(what_are_you) + string<delimiter(')content(a special comment...)delimiter(')> + reserved(end) +reserved(end) + +reserved(class) class(VerySpecialComment) operator(<) constant(Comment) + reserved(def) pre_constant(self)operator(.)ident(what_are_you) + string<delimiter(')content(a very special comment...)delimiter(')> + reserved(end) +ident(endclass) constant(Company) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(attr_protected) symbol(:rating) + ident(set_sequence_name) symbol(:companies_nonstd_seq) + + ident(validates_presence_of) symbol(:name) + + ident(has_one) symbol(:dummy_account)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Account)delimiter(")> +reserved(end) + + +reserved(class) class(Firm) operator(<) constant(Company) + ident(has_many) symbol(:clients)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy)operator(,) symbol(:counter_sql) operator(=)operator(>) + string<delimiter(")content(SELECT COUNT(*\) FROM companies WHERE firm_id = 1 )delimiter(")> operator(+) + string<delimiter(")content(AND ()inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'Client' OR )inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'SpecialClient' OR )inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content( = 'VerySpecialClient' \))delimiter(")> + ident(has_many) symbol(:clients_sorted_desc)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")> + ident(has_many) symbol(:clients_of_firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")> + ident(has_many) symbol(:dependent_clients_of_firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) + ident(has_many) symbol(:exclusively_dependent_clients_of_firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:delete_all) + ident(has_many) symbol(:limited_clients)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(1) + ident(has_many) symbol(:clients_like_ms)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Microsoft')delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")> + ident(has_many) symbol(:clients_using_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:finder_sql) operator(=)operator(>) string<delimiter(')content(SELECT * FROM companies WHERE client_of = #{id})delimiter(')> + ident(has_many) symbol(:clients_using_counter_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) + symbol(:finder_sql) operator(=)operator(>) string<delimiter(')content(SELECT * FROM companies WHERE client_of = #{id})delimiter(')>operator(,) + symbol(:counter_sql) operator(=)operator(>) string<delimiter(')content(SELECT COUNT(*\) FROM companies WHERE client_of = #{id})delimiter(')> + ident(has_many) symbol(:clients_using_zero_counter_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) + symbol(:finder_sql) operator(=)operator(>) string<delimiter(')content(SELECT * FROM companies WHERE client_of = #{id})delimiter(')>operator(,) + symbol(:counter_sql) operator(=)operator(>) string<delimiter(')content(SELECT 0 FROM companies WHERE client_of = #{id})delimiter(')> + ident(has_many) symbol(:no_clients_using_counter_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) + symbol(:finder_sql) operator(=)operator(>) string<delimiter(')content(SELECT * FROM companies WHERE client_of = 1000)delimiter(')>operator(,) + symbol(:counter_sql) operator(=)operator(>) string<delimiter(')content(SELECT COUNT(*\) FROM companies WHERE client_of = 1000)delimiter(')> + + ident(has_one) symbol(:account)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) +reserved(end) + +reserved(class) class(DependentFirm) operator(<) constant(Company) + ident(has_one) symbol(:account)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:nullify) + ident(has_many) symbol(:companies)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(client_of)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:nullify) +reserved(end) + + +reserved(class) class(Client) operator(<) constant(Company) + ident(belongs_to) symbol(:firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")> + ident(belongs_to) symbol(:firm_with_basic_id)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Firm)delimiter(")>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")> + ident(belongs_to) symbol(:firm_with_other_name)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Firm)delimiter(")>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")> + ident(belongs_to) symbol(:firm_with_condition)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Firm)delimiter(")>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")>operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(1 = ?)delimiter(")>operator(,) integer(1)operator(]) + + comment(# Record destruction so we can test whether firm.clients.clear has) + comment(# is calling client.destroy, deleting from the database, or setting) + comment(# foreign keys to NULL.) + reserved(def) pre_constant(self)operator(.)ident(destroyed_client_ids) + instance_variable(@destroyed_client_ids) operator(||=) constant(Hash)operator(.)ident(new) operator({) operator(|)ident(h)operator(,)ident(k)operator(|) ident(h)operator([)ident(k)operator(]) operator(=) operator([)operator(]) operator(}) + reserved(end) + + ident(before_destroy) reserved(do) operator(|)ident(client)operator(|) + reserved(if) ident(client)operator(.)ident(firm) + constant(Client)operator(.)ident(destroyed_client_ids)operator([)ident(client)operator(.)ident(firm)operator(.)ident(id)operator(]) operator(<<) ident(client)operator(.)ident(id) + reserved(end) + pre_constant(true) + reserved(end) + + comment(# Used to test that read and question methods are not generated for these attributes) + reserved(def) method(ruby_type) + ident(read_attribute) symbol(:ruby_type) + reserved(end) + + reserved(def) method(rating?) + ident(query_attribute) symbol(:rating) + reserved(end) +reserved(end) + + +reserved(class) class(SpecialClient) operator(<) constant(Client) +reserved(end) + +reserved(class) class(VerySpecialClient) operator(<) constant(SpecialClient) +reserved(end) + +reserved(class) class(Account) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:firm) + + ident(protected) + reserved(def) method(validate) + ident(errors)operator(.)ident(add_on_empty) string<delimiter(")content(credit_limit)delimiter(")> + reserved(end) +ident(endmodule) constant(MyApplication) + reserved(module) class(Business) + reserved(class) class(Company) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(attr_protected) symbol(:rating) + reserved(end) + + reserved(class) class(Firm) operator(<) constant(Company) + ident(has_many) symbol(:clients)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) + ident(has_many) symbol(:clients_sorted_desc)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")> + ident(has_many) symbol(:clients_of_firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")> + ident(has_many) symbol(:clients_like_ms)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Microsoft')delimiter(")>operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")> + ident(has_many) symbol(:clients_using_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Client)delimiter(")>operator(,) symbol(:finder_sql) operator(=)operator(>) string<delimiter(')content(SELECT * FROM companies WHERE client_of = #{id})delimiter(')> + + ident(has_one) symbol(:account)operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) + reserved(end) + + reserved(class) class(Client) operator(<) constant(Company) + ident(belongs_to) symbol(:firm)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")> + ident(belongs_to) symbol(:firm_with_other_name)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Firm)delimiter(")>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(client_of)delimiter(")> + reserved(end) + + reserved(class) class(Developer) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:projects) + + ident(protected) + reserved(def) method(validate) + ident(errors)operator(.)ident(add_on_boundary_breaking)operator(()string<delimiter(")content(name)delimiter(")>operator(,) integer(3)operator(..)integer(20)operator(\)) + reserved(end) + reserved(end) + + reserved(class) class(Project) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:developers) + reserved(end) + + reserved(end) + + reserved(module) class(Billing) + reserved(class) class(Firm) operator(<) constant(ActiveRecord)operator(::)constant(Base) + pre_constant(self)operator(.)ident(table_name) operator(=) string<delimiter(')content(companies)delimiter(')> + reserved(end) + + reserved(module) class(Nested) + reserved(class) class(Firm) operator(<) constant(ActiveRecord)operator(::)constant(Base) + pre_constant(self)operator(.)ident(table_name) operator(=) string<delimiter(')content(companies)delimiter(')> + reserved(end) + reserved(end) + + reserved(class) class(Account) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:firm)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(MyApplication::Business::Firm)delimiter(')> + ident(belongs_to) symbol(:qualified_billing_firm)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(MyApplication::Billing::Firm)delimiter(')> + ident(belongs_to) symbol(:unqualified_billing_firm)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Firm)delimiter(')> + ident(belongs_to) symbol(:nested_qualified_billing_firm)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(MyApplication::Billing::Nested::Firm)delimiter(')> + ident(belongs_to) symbol(:nested_unqualified_billing_firm)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Nested::Firm)delimiter(')> + + ident(protected) + reserved(def) method(validate) + ident(errors)operator(.)ident(add_on_empty) string<delimiter(")content(credit_limit)delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(class) class(Computer) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:developer)operator(,) symbol(:foreign_key)operator(=)operator(>)string<delimiter(')content(developer)delimiter(')> +reserved(end) +reserved(class) class(Course) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_many) symbol(:entrants) +reserved(end) +reserved(class) class(Customer) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(composed_of) symbol(:address)operator(,) symbol(:mapping) operator(=)operator(>) operator([) string<delimiter(%w()content(address_street street)delimiter(\))>operator(,) string<delimiter(%w()content(address_city city)delimiter(\))>operator(,) string<delimiter(%w()content(address_country country)delimiter(\))> operator(]) + ident(composed_of) symbol(:balance)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Money)delimiter(")>operator(,) symbol(:mapping) operator(=)operator(>) string<delimiter(%w()content(balance amount)delimiter(\))> + ident(composed_of) symbol(:gps_location) +reserved(end) + +reserved(class) class(Address) + ident(attr_reader) symbol(:street)operator(,) symbol(:city)operator(,) symbol(:country) + + reserved(def) method(initialize)operator(()ident(street)operator(,) ident(city)operator(,) ident(country)operator(\)) + instance_variable(@street)operator(,) instance_variable(@city)operator(,) instance_variable(@country) operator(=) ident(street)operator(,) ident(city)operator(,) ident(country) + reserved(end) + + reserved(def) method(close_to?)operator(()ident(other_address)operator(\)) + ident(city) operator(==) ident(other_address)operator(.)ident(city) operator(&&) ident(country) operator(==) ident(other_address)operator(.)ident(country) + reserved(end) + + reserved(def) method(==)operator(()ident(other)operator(\)) + ident(other)operator(.)ident(is_a?)operator(()pre_constant(self)operator(.)ident(class)operator(\)) operator(&&) ident(other)operator(.)ident(street) operator(==) ident(street) operator(&&) ident(other)operator(.)ident(city) operator(==) ident(city) operator(&&) ident(other)operator(.)ident(country) operator(==) ident(country) + reserved(end) +reserved(end) + +reserved(class) class(Money) + ident(attr_reader) symbol(:amount)operator(,) symbol(:currency) + + constant(EXCHANGE_RATES) operator(=) operator({) string<delimiter(")content(USD_TO_DKK)delimiter(")> operator(=)operator(>) integer(6)operator(,) string<delimiter(")content(DKK_TO_USD)delimiter(")> operator(=)operator(>) float(0.6) operator(}) + + reserved(def) method(initialize)operator(()ident(amount)operator(,) ident(currency) operator(=) string<delimiter(")content(USD)delimiter(")>operator(\)) + instance_variable(@amount)operator(,) instance_variable(@currency) operator(=) ident(amount)operator(,) ident(currency) + reserved(end) + + reserved(def) method(exchange_to)operator(()ident(other_currency)operator(\)) + constant(Money)operator(.)ident(new)operator(()operator(()ident(amount) operator(*) constant(EXCHANGE_RATES)operator([)string<delimiter(")inline<inline_delimiter(#{)ident(currency)inline_delimiter(})>content(_TO_)inline<inline_delimiter(#{)ident(other_currency)inline_delimiter(})>delimiter(")>operator(])operator(\))operator(.)ident(floor)operator(,) ident(other_currency)operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(GpsLocation) + ident(attr_reader) symbol(:gps_location) + + reserved(def) method(initialize)operator(()ident(gps_location)operator(\)) + instance_variable(@gps_location) operator(=) ident(gps_location) + reserved(end) + + reserved(def) method(latitude) + ident(gps_location)operator(.)ident(split)operator(()string<delimiter(")content(x)delimiter(")>operator(\))operator(.)ident(first) + reserved(end) + + reserved(def) method(longitude) + ident(gps_location)operator(.)ident(split)operator(()string<delimiter(")content(x)delimiter(")>operator(\))operator(.)ident(last) + reserved(end) + + reserved(def) method(==)operator(()ident(other)operator(\)) + pre_constant(self)operator(.)ident(latitude) operator(==) ident(other)operator(.)ident(latitude) operator(&&) pre_constant(self)operator(.)ident(longitude) operator(==) ident(other)operator(.)ident(longitude) + reserved(end) +ident(endActiveRecord)operator(::)constant(Schema)operator(.)ident(define) reserved(do) + + ident(create_table) symbol(:taggings)operator(,) symbol(:force) operator(=)operator(>) pre_constant(true) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:tag_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:super_tag_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:taggable_type)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:taggable_id)operator(,) symbol(:integer) + reserved(end) + + ident(create_table) symbol(:tags)operator(,) symbol(:force) operator(=)operator(>) pre_constant(true) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:name)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:taggings_count)operator(,) symbol(:integer)operator(,) symbol(:default) operator(=)operator(>) integer(0) + reserved(end) + + ident(create_table) symbol(:categorizations)operator(,) symbol(:force) operator(=)operator(>) pre_constant(true) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:category_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:post_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:author_id)operator(,) symbol(:integer) + reserved(end) + + ident(add_column) symbol(:posts)operator(,) symbol(:taggings_count)operator(,) symbol(:integer)operator(,) symbol(:default) operator(=)operator(>) integer(0) + ident(add_column) symbol(:authors)operator(,) symbol(:author_address_id)operator(,) symbol(:integer) + + ident(create_table) symbol(:author_addresses)operator(,) symbol(:force) operator(=)operator(>) pre_constant(true) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:author_address_id)operator(,) symbol(:integer) + reserved(end) + + ident(create_table) symbol(:author_favorites)operator(,) symbol(:force) operator(=)operator(>) pre_constant(true) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:author_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:favorite_author_id)operator(,) symbol(:integer) + reserved(end) +ident(endclass) constant(Default) operator(<) constant(ActiveRecord)operator(::)constant(Base) +reserved(end) +reserved(module) class(DeveloperProjectsAssociationExtension) + reserved(def) method(find_most_recent) + ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")>operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(Developer) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:projects) reserved(do) + reserved(def) method(find_most_recent) + ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(has_and_belongs_to_many) symbol(:projects_extended_by_name)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Project)delimiter(")>operator(,) + symbol(:join_table) operator(=)operator(>) string<delimiter(")content(developers_projects)delimiter(")>operator(,) + symbol(:association_foreign_key) operator(=)operator(>) string<delimiter(")content(project_id)delimiter(")>operator(,) + symbol(:extend) operator(=)operator(>) constant(DeveloperProjectsAssociationExtension) + + ident(has_and_belongs_to_many) symbol(:special_projects)operator(,) symbol(:join_table) operator(=)operator(>) string<delimiter(')content(developers_projects)delimiter(')>operator(,) symbol(:association_foreign_key) operator(=)operator(>) string<delimiter(')content(project_id)delimiter(')> + + ident(validates_inclusion_of) symbol(:salary)operator(,) symbol(:in) operator(=)operator(>) integer(50000)operator(..)integer(200000) + ident(validates_length_of) symbol(:name)operator(,) symbol(:within) operator(=)operator(>) integer(3)operator(..)integer(20) +reserved(end) + +constant(DeveloperSalary) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:amount)operator(\)) +reserved(class) class(DeveloperWithAggregate) operator(<) constant(ActiveRecord)operator(::)constant(Base) + pre_constant(self)operator(.)ident(table_name) operator(=) string<delimiter(')content(developers)delimiter(')> + ident(composed_of) symbol(:salary)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(DeveloperSalary)delimiter(')>operator(,) symbol(:mapping) operator(=)operator(>) operator([)string<delimiter(%w()content(salary amount)delimiter(\))>operator(]) +reserved(end) + +reserved(class) class(DeveloperWithBeforeDestroyRaise) operator(<) constant(ActiveRecord)operator(::)constant(Base) + pre_constant(self)operator(.)ident(table_name) operator(=) string<delimiter(')content(developers)delimiter(')> + ident(has_and_belongs_to_many) symbol(:projects)operator(,) symbol(:join_table) operator(=)operator(>) string<delimiter(')content(developers_projects)delimiter(')>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(developer_id)delimiter(')> + ident(before_destroy) symbol(:raise_if_projects_empty!) + + reserved(def) method(raise_if_projects_empty!) + ident(raise) reserved(if) ident(projects)operator(.)ident(empty?) + reserved(end) +reserved(end) +reserved(class) class(Entrant) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:course) +reserved(end) +reserved(class) class(Joke) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(funny_jokes)delimiter(')> +reserved(end) +reserved(class) class(Joke) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_table_name) string<delimiter(')content(funny_jokes)delimiter(')> +ident(endclass) constant(Keyboard) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_primary_key) string<delimiter(')content(key_number)delimiter(')> +reserved(end) +reserved(class) class(LegacyThing) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_locking_column) symbol(:version) +reserved(end) +reserved(class) class(PeopleHaveLastNames) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(,) symbol(:string) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + ident(remove_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")> + reserved(end) +ident(endclass) constant(WeNeedReminders) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + ident(create_table)operator(()string<delimiter(")content(reminders)delimiter(")>operator(\)) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:content)operator(,) symbol(:text) + ident(t)operator(.)ident(column) symbol(:remind_at)operator(,) symbol(:datetime) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + ident(drop_table) string<delimiter(")content(reminders)delimiter(")> + reserved(end) +ident(endclass) constant(InnocentJointable) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + ident(create_table)operator(()string<delimiter(")content(people_reminders)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) pre_constant(false)operator(\)) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:reminder_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:person_id)operator(,) symbol(:integer) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + ident(drop_table) string<delimiter(")content(people_reminders)delimiter(")> + reserved(end) +ident(endclass) constant(PeopleHaveLastNames) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(,) symbol(:string) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + ident(remove_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")> + reserved(end) +ident(endclass) constant(WeNeedReminders) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + ident(create_table)operator(()string<delimiter(")content(reminders)delimiter(")>operator(\)) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:content)operator(,) symbol(:text) + ident(t)operator(.)ident(column) symbol(:remind_at)operator(,) symbol(:datetime) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + ident(drop_table) string<delimiter(")content(reminders)delimiter(")> + reserved(end) +ident(endclass) constant(Foo) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + reserved(end) +ident(endclass) constant(InnocentJointable) operator(<) constant(ActiveRecord)operator(::)constant(Migration) + reserved(def) pre_constant(self)operator(.)ident(up) + ident(create_table)operator(()string<delimiter(")content(people_reminders)delimiter(")>operator(,) symbol(:id) operator(=)operator(>) pre_constant(false)operator(\)) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:reminder_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:person_id)operator(,) symbol(:integer) + reserved(end) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(down) + ident(drop_table) string<delimiter(")content(people_reminders)delimiter(")> + reserved(end) +ident(endclass) constant(Mixin) operator(<) constant(ActiveRecord)operator(::)constant(Base) + +reserved(end) + +reserved(class) class(TreeMixin) operator(<) constant(Mixin) + ident(acts_as_tree) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")> +reserved(end) + +reserved(class) class(TreeMixinWithoutOrder) operator(<) constant(Mixin) + ident(acts_as_tree) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")> +reserved(end) + +reserved(class) class(ListMixin) operator(<) constant(Mixin) + ident(acts_as_list) symbol(:column) operator(=)operator(>) string<delimiter(")content(pos)delimiter(")>operator(,) symbol(:scope) operator(=)operator(>) symbol(:parent) + + reserved(def) pre_constant(self)operator(.)ident(table_name)operator(()operator(\)) string<delimiter(")content(mixins)delimiter(")> reserved(end) +reserved(end) + +reserved(class) class(ListMixinSub1) operator(<) constant(ListMixin) +reserved(end) + +reserved(class) class(ListMixinSub2) operator(<) constant(ListMixin) +reserved(end) + + +reserved(class) class(ListWithStringScopeMixin) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(acts_as_list) symbol(:column) operator(=)operator(>) string<delimiter(")content(pos)delimiter(")>operator(,) symbol(:scope) operator(=)operator(>) string<delimiter(')content(parent_id = #{parent_id})delimiter(')> + + reserved(def) pre_constant(self)operator(.)ident(table_name)operator(()operator(\)) string<delimiter(")content(mixins)delimiter(")> reserved(end) +reserved(end) + +reserved(class) class(NestedSet) operator(<) constant(Mixin) + ident(acts_as_nested_set) symbol(:scope) operator(=)operator(>) string<delimiter(")content(root_id IS NULL)delimiter(")> + + reserved(def) pre_constant(self)operator(.)ident(table_name)operator(()operator(\)) string<delimiter(")content(mixins)delimiter(")> reserved(end) +reserved(end) + +reserved(class) class(NestedSetWithStringScope) operator(<) constant(Mixin) + ident(acts_as_nested_set) symbol(:scope) operator(=)operator(>) string<delimiter(')content(root_id = #{root_id})delimiter(')> + + reserved(def) pre_constant(self)operator(.)ident(table_name)operator(()operator(\)) string<delimiter(")content(mixins)delimiter(")> reserved(end) +reserved(end) + +reserved(class) class(NestedSetWithSymbolScope) operator(<) constant(Mixin) + ident(acts_as_nested_set) symbol(:scope) operator(=)operator(>) symbol(:root) + + reserved(def) pre_constant(self)operator(.)ident(table_name)operator(()operator(\)) string<delimiter(")content(mixins)delimiter(")> reserved(end) +reserved(end) +reserved(class) class(Movie) operator(<) constant(ActiveRecord)operator(::)constant(Base) + reserved(def) pre_constant(self)operator(.)ident(primary_key) + string<delimiter(")content(movieid)delimiter(")> + reserved(end) +reserved(end) +reserved(class) class(Order) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:billing)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Customer)delimiter(')>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(billing_customer_id)delimiter(')> + ident(belongs_to) symbol(:shipping)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Customer)delimiter(')>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(shipping_customer_id)delimiter(')> +reserved(end) +reserved(class) class(Person) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_many) symbol(:readers) + ident(has_many) symbol(:posts)operator(,) symbol(:through) operator(=)operator(>) symbol(:readers) +reserved(end) +reserved(class) class(Post) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:author) reserved(do) + reserved(def) method(greeting) + string<delimiter(")content(hello)delimiter(")> + reserved(end) + reserved(end) + + ident(belongs_to) symbol(:author_with_posts)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Author)delimiter(")>operator(,) symbol(:include) operator(=)operator(>) symbol(:posts) + + ident(has_many) symbol(:comments)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(body)delimiter(")> reserved(do) + reserved(def) method(find_most_recent) + ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(")content(id DESC)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + ident(has_one) symbol(:very_special_comment) + ident(has_one) symbol(:very_special_comment_with_post)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(VerySpecialComment)delimiter(")>operator(,) symbol(:include) operator(=)operator(>) symbol(:post) + ident(has_many) symbol(:special_comments) + + ident(has_and_belongs_to_many) symbol(:categories) + ident(has_and_belongs_to_many) symbol(:special_categories)operator(,) symbol(:join_table) operator(=)operator(>) string<delimiter(")content(categories_posts)delimiter(")>operator(,) symbol(:association_foreign_key) operator(=)operator(>) string<delimiter(')content(category_id)delimiter(')> + + ident(has_many) symbol(:taggings)operator(,) symbol(:as) operator(=)operator(>) symbol(:taggable) + ident(has_many) symbol(:tags)operator(,) symbol(:through) operator(=)operator(>) symbol(:taggings)operator(,) symbol(:include) operator(=)operator(>) symbol(:tagging) reserved(do) + reserved(def) method(add_joins_and_select) + ident(find) symbol(:all)operator(,) symbol(:select) operator(=)operator(>) string<delimiter(')content(tags.*, authors.id as author_id)delimiter(')>operator(,) symbol(:include) operator(=)operator(>) pre_constant(false)operator(,) + symbol(:joins) operator(=)operator(>) string<delimiter(')content(left outer join posts on taggings.taggable_id = posts.id left outer join authors on posts.author_id = authors.id)delimiter(')> + reserved(end) + reserved(end) + + ident(has_many) symbol(:funky_tags)operator(,) symbol(:through) operator(=)operator(>) symbol(:taggings)operator(,) symbol(:source) operator(=)operator(>) symbol(:tag) + ident(has_many) symbol(:super_tags)operator(,) symbol(:through) operator(=)operator(>) symbol(:taggings) + ident(has_one) symbol(:tagging)operator(,) symbol(:as) operator(=)operator(>) symbol(:taggable) + + ident(has_many) symbol(:invalid_taggings)operator(,) symbol(:as) operator(=)operator(>) symbol(:taggable)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Tagging)delimiter(")>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(taggings.id < 0)delimiter(')> + ident(has_many) symbol(:invalid_tags)operator(,) symbol(:through) operator(=)operator(>) symbol(:invalid_taggings)operator(,) symbol(:source) operator(=)operator(>) symbol(:tag) + + ident(has_many) symbol(:categorizations)operator(,) symbol(:foreign_key) operator(=)operator(>) symbol(:category_id) + ident(has_many) symbol(:authors)operator(,) symbol(:through) operator(=)operator(>) symbol(:categorizations) + + ident(has_many) symbol(:readers) + ident(has_many) symbol(:people)operator(,) symbol(:through) operator(=)operator(>) symbol(:readers) + + reserved(def) pre_constant(self)operator(.)ident(what_are_you) + string<delimiter(')content(a post...)delimiter(')> + reserved(end) +reserved(end) + +reserved(class) class(SpecialPost) operator(<) constant(Post)operator(;) reserved(end)operator(;) + +reserved(class) class(StiPost) operator(<) constant(Post) + pre_constant(self)operator(.)ident(abstract_class) operator(=) pre_constant(true) + ident(has_one) symbol(:special_comment)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(SpecialComment)delimiter(")> +reserved(end) + +reserved(class) class(SubStiPost) operator(<) constant(StiPost) +reserved(end) +reserved(class) class(Project) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_and_belongs_to_many) symbol(:developers)operator(,) symbol(:uniq) operator(=)operator(>) pre_constant(true) + ident(has_and_belongs_to_many) symbol(:limited_developers)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Developer)delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(1) + ident(has_and_belongs_to_many) symbol(:developers_named_david)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Developer)delimiter(")>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")>operator(,) symbol(:uniq) operator(=)operator(>) pre_constant(true) + ident(has_and_belongs_to_many) symbol(:salaried_developers)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Developer)delimiter(")>operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary > 0)delimiter(")> + ident(has_and_belongs_to_many) symbol(:developers_with_finder_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Developer)delimiter(")>operator(,) symbol(:finder_sql) operator(=)operator(>) string<delimiter(')content(SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id})delimiter(')> + ident(has_and_belongs_to_many) symbol(:developers_by_sql)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Developer)delimiter(")>operator(,) symbol(:delete_sql) operator(=)operator(>) string<delimiter(")content(DELETE FROM developers_projects WHERE project_id = )char(\\#)content({id} AND developer_id = )char(\\#)content({record.id})delimiter(")> + ident(has_and_belongs_to_many) symbol(:developers_with_callbacks)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Developer)delimiter(")>operator(,) symbol(:before_add) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(developers_log) operator(<<) string<delimiter(")content(before_adding)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(,) + symbol(:after_add) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(developers_log) operator(<<) string<delimiter(")content(after_adding)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(,) + symbol(:before_remove) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(developers_log) operator(<<) string<delimiter(")content(before_removing)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(})operator(,) + symbol(:after_remove) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({)operator(|)ident(o)operator(,) ident(r)operator(|) ident(o)operator(.)ident(developers_log) operator(<<) string<delimiter(")content(after_removing)inline<inline_delimiter(#{)ident(r)operator(.)ident(id)inline_delimiter(})>delimiter(")>operator(}) + + ident(attr_accessor) symbol(:developers_log) + + reserved(def) method(after_initialize) + instance_variable(@developers_log) operator(=) operator([)operator(]) + reserved(end) + +reserved(end) + +reserved(class) class(SpecialProject) operator(<) constant(Project) + reserved(def) method(hello_world) + string<delimiter(")content(hello there!)delimiter(")> + reserved(end) +reserved(end) +reserved(class) class(Reader) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:post) + ident(belongs_to) symbol(:person) +reserved(end) +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> + +reserved(class) class(Reply) operator(<) constant(Topic) + ident(belongs_to) symbol(:topic)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")>operator(,) symbol(:counter_cache) operator(=)operator(>) pre_constant(true) + ident(has_many) symbol(:replies)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(SillyReply)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")> + + ident(validate) symbol(:errors_on_empty_content) + ident(validate_on_create) symbol(:title_is_wrong_create) + + ident(attr_accessible) symbol(:title)operator(,) symbol(:author_name)operator(,) symbol(:author_email_address)operator(,) symbol(:written_on)operator(,) symbol(:content)operator(,) symbol(:last_read) + + reserved(def) method(validate) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Empty)delimiter(")>operator(\)) reserved(unless) ident(attribute_present?) string<delimiter(")content(title)delimiter(")> + reserved(end) + + reserved(def) method(errors_on_empty_content) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(content)delimiter(")>operator(,) string<delimiter(")content(Empty)delimiter(")>operator(\)) reserved(unless) ident(attribute_present?) string<delimiter(")content(content)delimiter(")> + reserved(end) + + reserved(def) method(validate_on_create) + reserved(if) ident(attribute_present?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) operator(&&) ident(attribute_present?)operator(()string<delimiter(")content(content)delimiter(")>operator(\)) operator(&&) ident(content) operator(==) string<delimiter(")content(Mismatch)delimiter(")> + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(is Content Mismatch)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(title_is_wrong_create) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(is Wrong Create)delimiter(")>operator(\)) reserved(if) ident(attribute_present?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) operator(&&) ident(title) operator(==) string<delimiter(")content(Wrong Create)delimiter(")> + reserved(end) + + reserved(def) method(validate_on_update) + ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(is Wrong Update)delimiter(")>operator(\)) reserved(if) ident(attribute_present?)operator(()string<delimiter(")content(title)delimiter(")>operator(\)) operator(&&) ident(title) operator(==) string<delimiter(")content(Wrong Update)delimiter(")> + reserved(end) +reserved(end) + +reserved(class) class(SillyReply) operator(<) constant(Reply) + ident(belongs_to) symbol(:reply)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")>operator(,) symbol(:counter_cache) operator(=)operator(>) symbol(:replies_count) +reserved(end) +comment(# used for OracleSynonymTest, see test/synonym_test_oci.rb) +comment(#) +reserved(class) class(Subject) operator(<) constant(ActiveRecord)operator(::)constant(Base) +reserved(end) +reserved(class) class(Subscriber) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(set_primary_key) string<delimiter(')content(nick)delimiter(')> +reserved(end) + +reserved(class) class(SpecialSubscriber) operator(<) constant(Subscriber) +reserved(end) +reserved(class) class(Tag) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_many) symbol(:taggings) + ident(has_many) symbol(:taggables)operator(,) symbol(:through) operator(=)operator(>) symbol(:taggings) + ident(has_one) symbol(:tagging) +ident(endclass) constant(Tagging) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(belongs_to) symbol(:tag)operator(,) symbol(:include) operator(=)operator(>) symbol(:tagging) + ident(belongs_to) symbol(:super_tag)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Tag)delimiter(')>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(super_tag_id)delimiter(')> + ident(belongs_to) symbol(:invalid_tag)operator(,) symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Tag)delimiter(')>operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(')content(tag_id)delimiter(')> + ident(belongs_to) symbol(:taggable)operator(,) symbol(:polymorphic) operator(=)operator(>) pre_constant(true)operator(,) symbol(:counter_cache) operator(=)operator(>) pre_constant(true) +ident(endclass) constant(Task) operator(<) constant(ActiveRecord)operator(::)constant(Base) + +reserved(end) +reserved(class) class(Topic) operator(<) constant(ActiveRecord)operator(::)constant(Base) + ident(has_many) symbol(:replies)operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy)operator(,) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")> + ident(serialize) symbol(:content) + + ident(before_create) symbol(:default_written_on) + ident(before_destroy) symbol(:destroy_children) + + reserved(def) method(parent) + constant(Topic)operator(.)ident(find)operator(()ident(parent_id)operator(\)) + reserved(end) + + ident(protected) + reserved(def) method(default_written_on) + pre_constant(self)operator(.)ident(written_on) operator(=) constant(Time)operator(.)ident(now) reserved(unless) ident(attribute_present?)operator(()string<delimiter(")content(written_on)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(destroy_children) + pre_constant(self)operator(.)ident(class)operator(.)ident(delete_all) string<delimiter(")content(parent_id = )inline<inline_delimiter(#{)ident(id)inline_delimiter(})>delimiter(")> + reserved(end) +ident(endrequire) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/task)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> +ident(require) string<delimiter(')content(fixtures/joke)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> + +reserved(class) class(FixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) pre_constant(true) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + ident(fixtures) symbol(:topics)operator(,) symbol(:developers)operator(,) symbol(:accounts)operator(,) symbol(:tasks)operator(,) symbol(:categories)operator(,) symbol(:funny_jokes) + + constant(FIXTURES) operator(=) string<delimiter(%w()content( accounts companies customers + developers developers_projects entrants + movies projects subscribers topics tasks )delimiter(\))> + constant(MATCH_ATTRIBUTE_NAME) operator(=) regexp<delimiter(/)content([a-zA-Z][-_)char(\\w)content(]*)delimiter(/)> + + reserved(def) method(test_clean_fixtures) + constant(FIXTURES)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(|) + ident(fixtures) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(fixtures) operator(=) ident(create_fixtures)operator(()ident(name)operator(\)) operator(}) + ident(assert_kind_of)operator(()constant(Fixtures)operator(,) ident(fixtures)operator(\)) + ident(fixtures)operator(.)ident(each) operator({) operator(|)ident(name)operator(,) ident(fixture)operator(|) + ident(fixture)operator(.)ident(each) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) + ident(assert_match)operator(()constant(MATCH_ATTRIBUTE_NAME)operator(,) ident(key)operator(\)) + operator(}) + operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_multiple_clean_fixtures) + ident(fixtures_array) operator(=) pre_constant(nil) + ident(assert_nothing_raised) operator({) ident(fixtures_array) operator(=) ident(create_fixtures)operator(()operator(*)constant(FIXTURES)operator(\)) operator(}) + ident(assert_kind_of)operator(()constant(Array)operator(,) ident(fixtures_array)operator(\)) + ident(fixtures_array)operator(.)ident(each) operator({) operator(|)ident(fixtures)operator(|) ident(assert_kind_of)operator(()constant(Fixtures)operator(,) ident(fixtures)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_attributes) + ident(topics) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(topics)delimiter(")>operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(The First Topic)delimiter(")>operator(,) ident(topics)operator([)string<delimiter(")content(first)delimiter(")>operator(])operator([)string<delimiter(")content(title)delimiter(")>operator(])operator(\)) + ident(assert_nil)operator(()ident(topics)operator([)string<delimiter(")content(second)delimiter(")>operator(])operator([)string<delimiter(")content(author_email_address)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_inserts) + ident(topics) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(topics)delimiter(")>operator(\)) + ident(firstRow) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT * FROM topics WHERE author_name = 'David')delimiter(")>operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(The First Topic)delimiter(")>operator(,) ident(firstRow)operator([)string<delimiter(")content(title)delimiter(")>operator(])operator(\)) + + ident(secondRow) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT * FROM topics WHERE author_name = 'Mary')delimiter(")>operator(\)) + ident(assert_nil)operator(()ident(secondRow)operator([)string<delimiter(")content(author_email_address)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(supports_migrations?) + reserved(def) method(test_inserts_with_pre_and_suffix) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(create_table) symbol(:prefix_topics_suffix) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:title)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:author_name)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:author_email_address)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:written_on)operator(,) symbol(:datetime) + ident(t)operator(.)ident(column) symbol(:bonus_time)operator(,) symbol(:time) + ident(t)operator(.)ident(column) symbol(:last_read)operator(,) symbol(:date) + ident(t)operator(.)ident(column) symbol(:content)operator(,) symbol(:string) + ident(t)operator(.)ident(column) symbol(:approved)operator(,) symbol(:boolean)operator(,) symbol(:default) operator(=)operator(>) pre_constant(true) + ident(t)operator(.)ident(column) symbol(:replies_count)operator(,) symbol(:integer)operator(,) symbol(:default) operator(=)operator(>) integer(0) + ident(t)operator(.)ident(column) symbol(:parent_id)operator(,) symbol(:integer) + ident(t)operator(.)ident(column) symbol(:type)operator(,) symbol(:string)operator(,) symbol(:limit) operator(=)operator(>) integer(50) + reserved(end) + + comment(# Store existing prefix/suffix) + ident(old_prefix) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) + ident(old_suffix) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) + + comment(# Set a prefix/suffix we can test against) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(')content(prefix_)delimiter(')> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(')content(_suffix)delimiter(')> + + ident(topics) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(topics)delimiter(")>operator(\)) + + ident(firstRow) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT * FROM prefix_topics_suffix WHERE author_name = 'David')delimiter(")>operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(The First Topic)delimiter(")>operator(,) ident(firstRow)operator([)string<delimiter(")content(title)delimiter(")>operator(])operator(\)) + + ident(secondRow) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(select_one)operator(()string<delimiter(")content(SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary')delimiter(")>operator(\)) + ident(assert_nil)operator(()ident(secondRow)operator([)string<delimiter(")content(author_email_address)delimiter(")>operator(])operator(\)) + reserved(ensure) + comment(# Restore prefix/suffix to its previous values) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) ident(old_prefix) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) ident(old_suffix) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:prefix_topics_suffix) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(test_insert_with_datetime) + ident(topics) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(tasks)delimiter(")>operator(\)) + ident(first) operator(=) constant(Task)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) ident(first) + reserved(end) + + + reserved(def) method(test_bad_format) + ident(path) operator(=) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(')content(fixtures)delimiter(')>operator(,) string<delimiter(')content(bad_fixtures)delimiter(')>operator(\)) + constant(Dir)operator(.)ident(entries)operator(()ident(path)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(file)operator(|) + reserved(next) reserved(unless) constant(File)operator(.)ident(file?)operator(()ident(file)operator(\)) reserved(and) ident(file) operator(!)operator(~) constant(Fixtures)operator(::)constant(DEFAULT_FILTER_RE) + ident(assert_raise)operator(()constant(Fixture)operator(::)constant(FormatError)operator(\)) operator({) + constant(Fixture)operator(.)ident(new)operator(()ident(bad_fixtures_path)operator(,) ident(file)operator(\)) + operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_deprecated_yaml_extension) + ident(assert_raise)operator(()constant(Fixture)operator(::)constant(FormatError)operator(\)) operator({) + constant(Fixtures)operator(.)ident(new)operator(()pre_constant(nil)operator(,) string<delimiter(')content(bad_extension)delimiter(')>operator(,) string<delimiter(')content(BadExtension)delimiter(')>operator(,) constant(File)operator(.)ident(join)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(,) string<delimiter(')content(fixtures)delimiter(')>operator(\))operator(\)) + operator(}) + reserved(end) + + reserved(def) method(test_logger_level_invariant) + ident(level) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger)operator(.)ident(level) + ident(create_fixtures)operator(()string<delimiter(')content(topics)delimiter(')>operator(\)) + ident(assert_equal) ident(level)operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(logger)operator(.)ident(level) + reserved(end) + + reserved(def) method(test_instantiation) + ident(topics) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(topics)delimiter(")>operator(\)) + ident(assert_kind_of) constant(Topic)operator(,) ident(topics)operator([)string<delimiter(")content(first)delimiter(")>operator(])operator(.)ident(find) + reserved(end) + + reserved(def) method(test_complete_instantiation) + ident(assert_equal) integer(2)operator(,) instance_variable(@topics)operator(.)ident(size) + ident(assert_equal) string<delimiter(")content(The First Topic)delimiter(")>operator(,) instance_variable(@first)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_fixtures_from_root_yml_with_instantiation) + comment(# assert_equal 2, @accounts.size) + ident(assert_equal) integer(50)operator(,) instance_variable(@unknown)operator(.)ident(credit_limit) + reserved(end) + + reserved(def) method(test_erb_in_fixtures) + ident(assert_equal) integer(11)operator(,) instance_variable(@developers)operator(.)ident(size) + ident(assert_equal) string<delimiter(")content(fixture_5)delimiter(")>operator(,) instance_variable(@dev_5)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_empty_yaml_fixture) + ident(assert_not_nil) constant(Fixtures)operator(.)ident(new)operator(() constant(Account)operator(.)ident(connection)operator(,) string<delimiter(")content(accounts)delimiter(")>operator(,) string<delimiter(')content(Account)delimiter(')>operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/naked/yml/accounts)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_empty_yaml_fixture_with_a_comment_in_it) + ident(assert_not_nil) constant(Fixtures)operator(.)ident(new)operator(() constant(Account)operator(.)ident(connection)operator(,) string<delimiter(")content(companies)delimiter(")>operator(,) string<delimiter(')content(Company)delimiter(')>operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/naked/yml/companies)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_dirty_dirty_yaml_file) + ident(assert_raises)operator(()constant(Fixture)operator(::)constant(FormatError)operator(\)) reserved(do) + constant(Fixtures)operator(.)ident(new)operator(() constant(Account)operator(.)ident(connection)operator(,) string<delimiter(")content(courses)delimiter(")>operator(,) string<delimiter(')content(Course)delimiter(')>operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/naked/yml/courses)delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_empty_csv_fixtures) + ident(assert_not_nil) constant(Fixtures)operator(.)ident(new)operator(() constant(Account)operator(.)ident(connection)operator(,) string<delimiter(")content(accounts)delimiter(")>operator(,) string<delimiter(')content(Account)delimiter(')>operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/fixtures/naked/csv/accounts)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_omap_fixtures) + ident(assert_nothing_raised) reserved(do) + ident(fixtures) operator(=) constant(Fixtures)operator(.)ident(new)operator(()constant(Account)operator(.)ident(connection)operator(,) string<delimiter(')content(categories)delimiter(')>operator(,) string<delimiter(')content(Category)delimiter(')>operator(,) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/categories_ordered)delimiter(')>operator(\)) + + ident(i) operator(=) integer(0) + ident(fixtures)operator(.)ident(each) reserved(do) operator(|)ident(name)operator(,) ident(fixture)operator(|) + ident(assert_equal) string<delimiter(")content(fixture_no_)inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")>operator(,) ident(name) + ident(assert_equal) string<delimiter(")content(Category )inline<inline_delimiter(#{)ident(i)inline_delimiter(})>delimiter(")>operator(,) ident(fixture)operator([)string<delimiter(')content(name)delimiter(')>operator(]) + ident(i) operator(+=) integer(1) + reserved(end) + reserved(end) + reserved(end) + + + reserved(def) method(test_yml_file_in_subdirectory) + ident(assert_equal)operator(()ident(categories)operator(()symbol(:sub_special_1)operator(\))operator(.)ident(name)operator(,) string<delimiter(")content(A special category in a subdir file)delimiter(")>operator(\)) + ident(assert_equal)operator(()ident(categories)operator(()symbol(:sub_special_1)operator(\))operator(.)ident(class)operator(,) constant(SpecialCategory)operator(\)) + reserved(end) + + reserved(def) method(test_subsubdir_file_with_arbitrary_name) + ident(assert_equal)operator(()ident(categories)operator(()symbol(:sub_special_3)operator(\))operator(.)ident(name)operator(,) string<delimiter(")content(A special category in an arbitrarily named subsubdir file)delimiter(")>operator(\)) + ident(assert_equal)operator(()ident(categories)operator(()symbol(:sub_special_3)operator(\))operator(.)ident(class)operator(,) constant(SpecialCategory)operator(\)) + reserved(end) + + +reserved(end) + +reserved(if) constant(Account)operator(.)ident(connection)operator(.)ident(respond_to?)operator(()symbol(:reset_pk_sequence!)operator(\)) + reserved(class) class(FixturesResetPkSequenceTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts) + ident(fixtures) symbol(:companies) + + reserved(def) method(setup) + instance_variable(@instances) operator(=) operator([)constant(Account)operator(.)ident(new)operator(()symbol(:credit_limit) operator(=)operator(>) integer(50)operator(\))operator(,) constant(Company)operator(.)ident(new)operator(()symbol(:name) operator(=)operator(>) string<delimiter(')content(RoR Consulting)delimiter(')>operator(\))operator(]) + reserved(end) + + reserved(def) method(test_resets_to_min_pk_with_specified_pk_and_sequence) + instance_variable(@instances)operator(.)ident(each) reserved(do) operator(|)ident(instance)operator(|) + ident(model) operator(=) ident(instance)operator(.)ident(class) + ident(model)operator(.)ident(delete_all) + ident(model)operator(.)ident(connection)operator(.)ident(reset_pk_sequence!)operator(()ident(model)operator(.)ident(table_name)operator(,) ident(model)operator(.)ident(primary_key)operator(,) ident(model)operator(.)ident(sequence_name)operator(\)) + + ident(instance)operator(.)ident(save!) + ident(assert_equal) integer(1)operator(,) ident(instance)operator(.)ident(id)operator(,) string<delimiter(")content(Sequence reset for )inline<inline_delimiter(#{)ident(model)operator(.)ident(table_name)inline_delimiter(})>content( failed.)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_resets_to_min_pk_with_default_pk_and_sequence) + instance_variable(@instances)operator(.)ident(each) reserved(do) operator(|)ident(instance)operator(|) + ident(model) operator(=) ident(instance)operator(.)ident(class) + ident(model)operator(.)ident(delete_all) + ident(model)operator(.)ident(connection)operator(.)ident(reset_pk_sequence!)operator(()ident(model)operator(.)ident(table_name)operator(\)) + + ident(instance)operator(.)ident(save!) + ident(assert_equal) integer(1)operator(,) ident(instance)operator(.)ident(id)operator(,) string<delimiter(")content(Sequence reset for )inline<inline_delimiter(#{)ident(model)operator(.)ident(table_name)inline_delimiter(})>content( failed.)delimiter(")> + reserved(end) + reserved(end) + + reserved(def) method(test_create_fixtures_resets_sequences) + instance_variable(@instances)operator(.)ident(each) reserved(do) operator(|)ident(instance)operator(|) + ident(max_id) operator(=) ident(create_fixtures)operator(()ident(instance)operator(.)ident(class)operator(.)ident(table_name)operator(\))operator(.)ident(inject)operator(()integer(0)operator(\)) reserved(do) operator(|)ident(max_id)operator(,) operator(()ident(name)operator(,) ident(fixture)operator(\))operator(|) + ident(fixture_id) operator(=) ident(fixture)operator([)string<delimiter(')content(id)delimiter(')>operator(])operator(.)ident(to_i) + ident(fixture_id) operator(>) ident(max_id) operator(?) ident(fixture_id) operator(:) ident(max_id) + reserved(end) + + comment(# Clone the last fixture to check that it gets the next greatest id.) + ident(instance)operator(.)ident(save!) + ident(assert_equal) ident(max_id) operator(+) integer(1)operator(,) ident(instance)operator(.)ident(id)operator(,) string<delimiter(")content(Sequence reset for )inline<inline_delimiter(#{)ident(instance)operator(.)ident(class)operator(.)ident(table_name)inline_delimiter(})>content( failed.)delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) + + +reserved(class) class(FixturesWithoutInstantiationTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) pre_constant(false) + ident(fixtures) symbol(:topics)operator(,) symbol(:developers)operator(,) symbol(:accounts) + + reserved(def) method(test_without_complete_instantiation) + ident(assert_nil) instance_variable(@first) + ident(assert_nil) instance_variable(@topics) + ident(assert_nil) instance_variable(@developers) + ident(assert_nil) instance_variable(@accounts) + reserved(end) + + reserved(def) method(test_fixtures_from_root_yml_without_instantiation) + ident(assert_nil) instance_variable(@unknown) + reserved(end) + + reserved(def) method(test_accessor_methods) + ident(assert_equal) string<delimiter(")content(The First Topic)delimiter(")>operator(,) ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(title) + ident(assert_equal) string<delimiter(")content(Jamis)delimiter(")>operator(,) ident(developers)operator(()symbol(:jamis)operator(\))operator(.)ident(name) + ident(assert_equal) integer(50)operator(,) ident(accounts)operator(()symbol(:signals37)operator(\))operator(.)ident(credit_limit) + reserved(end) +reserved(end) + + +reserved(class) class(FixturesWithoutInstanceInstantiationTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) pre_constant(true) + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) symbol(:no_instances) + + ident(fixtures) symbol(:topics)operator(,) symbol(:developers)operator(,) symbol(:accounts) + + reserved(def) method(test_without_instance_instantiation) + ident(assert_nil) instance_variable(@first) + ident(assert_not_nil) instance_variable(@topics) + ident(assert_not_nil) instance_variable(@developers) + ident(assert_not_nil) instance_variable(@accounts) + reserved(end) +reserved(end) + + +reserved(class) class(TransactionalFixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_instantiated_fixtures) operator(=) pre_constant(true) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(true) + + ident(fixtures) symbol(:topics) + + reserved(def) method(test_destroy) + ident(assert_not_nil) instance_variable(@first) + instance_variable(@first)operator(.)ident(destroy) + reserved(end) + + reserved(def) method(test_destroy_just_kidding) + ident(assert_not_nil) instance_variable(@first) + reserved(end) +reserved(end) + + +reserved(class) class(MultipleFixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics) + ident(fixtures) symbol(:developers)operator(,) symbol(:accounts) + + reserved(def) method(test_fixture_table_names) + ident(assert_equal) string<delimiter(%w()content(topics developers accounts)delimiter(\))>operator(,) ident(fixture_table_names) + reserved(end) +reserved(end) + + +reserved(class) class(OverlappingFixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:developers) + ident(fixtures) symbol(:developers)operator(,) symbol(:accounts) + + reserved(def) method(test_fixture_table_names) + ident(assert_equal) string<delimiter(%w()content(topics developers accounts)delimiter(\))>operator(,) ident(fixture_table_names) + reserved(end) +reserved(end) + + +reserved(class) class(ForeignKeyFixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:fk_test_has_pk)operator(,) symbol(:fk_test_has_fk) + + comment(# if foreign keys are implemented and fixtures) + comment(# are not deleted in reverse order then this test) + comment(# case will raise StatementInvalid) + + reserved(def) method(test_number1) + ident(assert) pre_constant(true) + reserved(end) + + reserved(def) method(test_number2) + ident(assert) pre_constant(true) + reserved(end) +reserved(end) + +reserved(class) class(SetTableNameFixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(set_fixture_class) symbol(:funny_jokes) operator(=)operator(>) string<delimiter(')content(Joke)delimiter(')> + ident(fixtures) symbol(:funny_jokes) + + reserved(def) method(test_table_method) + ident(assert_kind_of) constant(Joke)operator(,) ident(funny_jokes)operator(()symbol(:a_joke)operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(InvalidTableNameFixturesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:funny_jokes) + + reserved(def) method(test_raises_error) + ident(assert_raises) constant(FixtureClassNotFound) reserved(do) + ident(funny_jokes)operator(()symbol(:a_joke)operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/subscriber)delimiter(')> + +reserved(class) class(InheritanceTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:companies)operator(,) symbol(:projects)operator(,) symbol(:subscribers) + + reserved(def) method(test_a_bad_type_column) + comment(#SQLServer need to turn Identity Insert On before manually inserting into the Identity column) + reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + constant(Company)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(SET IDENTITY_INSERT companies ON)delimiter(")> + reserved(end) + constant(Company)operator(.)ident(connection)operator(.)ident(insert) string<delimiter(")content(INSERT INTO companies (id, )inline<inline_delimiter(#{)constant(QUOTED_TYPE)inline_delimiter(})>content(, name\) VALUES(100, 'bad_class!', 'Not happening'\))delimiter(")> + + comment(#We then need to turn it back Off before continuing.) + reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + constant(Company)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(SET IDENTITY_INSERT companies OFF)delimiter(")> + reserved(end) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(SubclassNotFound)operator(\)) operator({) constant(Company)operator(.)ident(find)operator(()integer(100)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_inheritance_find) + ident(assert) constant(Company)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(kind_of?)operator(()constant(Firm)operator(\))operator(,) string<delimiter(")content(37signals should be a firm)delimiter(")> + ident(assert) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(kind_of?)operator(()constant(Firm)operator(\))operator(,) string<delimiter(")content(37signals should be a firm)delimiter(")> + ident(assert) constant(Company)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(kind_of?)operator(()constant(Client)operator(\))operator(,) string<delimiter(")content(Summit should be a client)delimiter(")> + ident(assert) constant(Client)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(kind_of?)operator(()constant(Client)operator(\))operator(,) string<delimiter(")content(Summit should be a client)delimiter(")> + reserved(end) + + reserved(def) method(test_alt_inheritance_find) + ident(switch_to_alt_inheritance_column) + ident(test_inheritance_find) + reserved(end) + + reserved(def) method(test_inheritance_find_all) + ident(companies) operator(=) constant(Company)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\)) + ident(assert) ident(companies)operator([)integer(0)operator(])operator(.)ident(kind_of?)operator(()constant(Firm)operator(\))operator(,) string<delimiter(")content(37signals should be a firm)delimiter(")> + ident(assert) ident(companies)operator([)integer(1)operator(])operator(.)ident(kind_of?)operator(()constant(Client)operator(\))operator(,) string<delimiter(")content(Summit should be a client)delimiter(")> + reserved(end) + + reserved(def) method(test_alt_inheritance_find_all) + ident(switch_to_alt_inheritance_column) + ident(test_inheritance_find_all) + reserved(end) + + reserved(def) method(test_inheritance_save) + ident(firm) operator(=) constant(Firm)operator(.)ident(new) + ident(firm)operator(.)ident(name) operator(=) string<delimiter(")content(Next Angle)delimiter(")> + ident(firm)operator(.)ident(save) + + ident(next_angle) operator(=) constant(Company)operator(.)ident(find)operator(()ident(firm)operator(.)ident(id)operator(\)) + ident(assert) ident(next_angle)operator(.)ident(kind_of?)operator(()constant(Firm)operator(\))operator(,) string<delimiter(")content(Next Angle should be a firm)delimiter(")> + reserved(end) + + reserved(def) method(test_alt_inheritance_save) + ident(switch_to_alt_inheritance_column) + ident(test_inheritance_save) + reserved(end) + + reserved(def) method(test_inheritance_condition) + ident(assert_equal) integer(8)operator(,) constant(Company)operator(.)ident(count) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(count) + ident(assert_equal) integer(3)operator(,) constant(Client)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_alt_inheritance_condition) + ident(switch_to_alt_inheritance_column) + ident(test_inheritance_condition) + reserved(end) + + reserved(def) method(test_finding_incorrect_type_data) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) constant(Firm)operator(.)ident(find)operator(()integer(2)operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Firm)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_alt_finding_incorrect_type_data) + ident(switch_to_alt_inheritance_column) + ident(test_finding_incorrect_type_data) + reserved(end) + + reserved(def) method(test_update_all_within_inheritance) + constant(Client)operator(.)ident(update_all) string<delimiter(")content(name = 'I am a client')delimiter(")> + ident(assert_equal) string<delimiter(")content(I am a client)delimiter(")>operator(,) constant(Client)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(first)operator(.)ident(name) + ident(assert_equal) string<delimiter(")content(37signals)delimiter(")>operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(first)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_alt_update_all_within_inheritance) + ident(switch_to_alt_inheritance_column) + ident(test_update_all_within_inheritance) + reserved(end) + + reserved(def) method(test_destroy_all_within_inheritance) + constant(Client)operator(.)ident(destroy_all) + ident(assert_equal) integer(0)operator(,) constant(Client)operator(.)ident(count) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_alt_destroy_all_within_inheritance) + ident(switch_to_alt_inheritance_column) + ident(test_destroy_all_within_inheritance) + reserved(end) + + reserved(def) method(test_find_first_within_inheritance) + ident(assert_kind_of) constant(Firm)operator(,) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = '37signals')delimiter(")>operator(\)) + ident(assert_kind_of) constant(Firm)operator(,) constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = '37signals')delimiter(")>operator(\)) + ident(assert_nil) constant(Client)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = '37signals')delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_alt_find_first_within_inheritance) + ident(switch_to_alt_inheritance_column) + ident(test_find_first_within_inheritance) + reserved(end) + + reserved(def) method(test_complex_inheritance) + ident(very_special_client) operator(=) constant(VerySpecialClient)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(veryspecial)delimiter(")>operator(\)) + ident(assert_equal) ident(very_special_client)operator(,) constant(VerySpecialClient)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'veryspecial')delimiter(")>operator(\)) + ident(assert_equal) ident(very_special_client)operator(,) constant(SpecialClient)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'veryspecial')delimiter(")>operator(\)) + ident(assert_equal) ident(very_special_client)operator(,) constant(Company)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'veryspecial')delimiter(")>operator(\)) + ident(assert_equal) ident(very_special_client)operator(,) constant(Client)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'veryspecial')delimiter(")>operator(\)) + ident(assert_equal) integer(1)operator(,) constant(Client)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Summit')delimiter(")>operator(\))operator(.)ident(size) + ident(assert_equal) ident(very_special_client)operator(,) constant(Client)operator(.)ident(find)operator(()ident(very_special_client)operator(.)ident(id)operator(\)) + reserved(end) + + reserved(def) method(test_alt_complex_inheritance) + ident(switch_to_alt_inheritance_column) + ident(test_complex_inheritance) + reserved(end) + + reserved(def) method(test_inheritance_without_mapping) + ident(assert_kind_of) constant(SpecialSubscriber)operator(,) constant(SpecialSubscriber)operator(.)ident(find)operator(()string<delimiter(")content(webster132)delimiter(")>operator(\)) + ident(assert_nothing_raised) operator({) ident(s) operator(=) constant(SpecialSubscriber)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(And breaaaaathe!)delimiter(")>operator(\))operator(;) ident(s)operator(.)ident(id) operator(=) string<delimiter(')content(roger)delimiter(')>operator(;) ident(s)operator(.)ident(save) operator(}) + reserved(end) + + ident(private) + reserved(def) method(switch_to_alt_inheritance_column) + comment(# we don't want misleading test results, so get rid of the values in the type column) + constant(Company)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\))operator(.)ident(each) reserved(do) operator(|)ident(c)operator(|) + ident(c)operator([)string<delimiter(')content(type)delimiter(')>operator(]) operator(=) pre_constant(nil) + ident(c)operator(.)ident(save) + reserved(end) + + reserved(def) constant(Company)operator(.)ident(inheritance_column)operator(()operator(\)) string<delimiter(")content(ruby_type)delimiter(")> reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> + +reserved(class) class(Topic)operator(;) reserved(def) method(after_find)operator(()operator(\)) reserved(end) reserved(end) +reserved(class) class(Developer)operator(;) reserved(def) method(after_find)operator(()operator(\)) reserved(end) reserved(end) +reserved(class) class(SpecialDeveloper) operator(<) constant(Developer)operator(;) reserved(end) + +reserved(class) class(TopicManualObserver) + ident(include) constant(Singleton) + + ident(attr_reader) symbol(:action)operator(,) symbol(:object)operator(,) symbol(:callbacks) + + reserved(def) method(initialize) + constant(Topic)operator(.)ident(add_observer)operator(()pre_constant(self)operator(\)) + instance_variable(@callbacks) operator(=) operator([)operator(]) + reserved(end) + + reserved(def) method(update)operator(()ident(callback_method)operator(,) ident(object)operator(\)) + instance_variable(@callbacks) operator(<<) operator({) string<delimiter(")content(callback_method)delimiter(")> operator(=)operator(>) ident(callback_method)operator(,) string<delimiter(")content(object)delimiter(")> operator(=)operator(>) ident(object) operator(}) + reserved(end) + + reserved(def) method(has_been_notified?) + operator(!)instance_variable(@callbacks)operator(.)ident(empty?) + reserved(end) +reserved(end) + +reserved(class) class(TopicaObserver) operator(<) constant(ActiveRecord)operator(::)constant(Observer) + reserved(def) pre_constant(self)operator(.)ident(observed_class)operator(()operator(\)) constant(Topic) reserved(end) + + ident(attr_reader) symbol(:topic) + + reserved(def) method(after_find)operator(()ident(topic)operator(\)) + instance_variable(@topic) operator(=) ident(topic) + reserved(end) +reserved(end) + +reserved(class) class(TopicObserver) operator(<) constant(ActiveRecord)operator(::)constant(Observer) + ident(attr_reader) symbol(:topic) + + reserved(def) method(after_find)operator(()ident(topic)operator(\)) + instance_variable(@topic) operator(=) ident(topic) + reserved(end) +reserved(end) + +reserved(class) class(MultiObserver) operator(<) constant(ActiveRecord)operator(::)constant(Observer) + ident(attr_reader) symbol(:record) + + reserved(def) pre_constant(self)operator(.)ident(observed_class)operator(()operator(\)) operator([) constant(Topic)operator(,) constant(Developer) operator(]) reserved(end) + + reserved(def) method(after_find)operator(()ident(record)operator(\)) + instance_variable(@record) operator(=) ident(record) + reserved(end) + +reserved(end) + +reserved(class) class(LifecycleTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:developers) + + reserved(def) method(test_before_destroy) + ident(assert_equal) integer(2)operator(,) constant(Topic)operator(.)ident(count) + constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(destroy) + ident(assert_equal) integer(0)operator(,) constant(Topic)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_after_save) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(observers) operator(=) symbol(:topic_manual_observer) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(hello)delimiter(")> + ident(topic)operator(.)ident(save) + + ident(assert) constant(TopicManualObserver)operator(.)ident(instance)operator(.)ident(has_been_notified?) + ident(assert_equal) symbol(:after_save)operator(,) constant(TopicManualObserver)operator(.)ident(instance)operator(.)ident(callbacks)operator(.)ident(last)operator([)string<delimiter(")content(callback_method)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_observer_update_on_save) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(observers) operator(=) constant(TopicManualObserver) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) constant(TopicManualObserver)operator(.)ident(instance)operator(.)ident(has_been_notified?) + ident(assert_equal) symbol(:after_find)operator(,) constant(TopicManualObserver)operator(.)ident(instance)operator(.)ident(callbacks)operator(.)ident(first)operator([)string<delimiter(")content(callback_method)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_auto_observer) + ident(topic_observer) operator(=) constant(TopicaObserver)operator(.)ident(instance) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(topic_observer)operator(.)ident(topic)operator(.)ident(title)operator(,) ident(topic)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_infered_auto_observer) + ident(topic_observer) operator(=) constant(TopicObserver)operator(.)ident(instance) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(topic_observer)operator(.)ident(topic)operator(.)ident(title)operator(,) ident(topic)operator(.)ident(title) + reserved(end) + + reserved(def) method(test_observing_two_classes) + ident(multi_observer) operator(=) constant(MultiObserver)operator(.)ident(instance) + + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(multi_observer)operator(.)ident(record)operator(.)ident(title)operator(,) ident(topic)operator(.)ident(title) + + ident(developer) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(multi_observer)operator(.)ident(record)operator(.)ident(name)operator(,) ident(developer)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_observing_subclasses) + ident(multi_observer) operator(=) constant(MultiObserver)operator(.)ident(instance) + + ident(developer) operator(=) constant(SpecialDeveloper)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(multi_observer)operator(.)ident(record)operator(.)ident(name)operator(,) ident(developer)operator(.)ident(name) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/person)delimiter(')> +ident(require) string<delimiter(')content(fixtures/legacy_thing)delimiter(')> + +reserved(class) class(LockingTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:people)operator(,) symbol(:legacy_things) + + reserved(def) method(test_lock_existing) + ident(p1) operator(=) constant(Person)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(p2) operator(=) constant(Person)operator(.)ident(find)operator(()integer(1)operator(\)) + + ident(p1)operator(.)ident(first_name) operator(=) string<delimiter(")content(Michael)delimiter(")> + ident(p1)operator(.)ident(save) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StaleObjectError)operator(\)) operator({) + ident(p2)operator(.)ident(first_name) operator(=) string<delimiter(")content(should fail)delimiter(")> + ident(p2)operator(.)ident(save) + operator(}) + reserved(end) + + reserved(def) method(test_lock_new) + ident(p1) operator(=) constant(Person)operator(.)ident(create)operator(()operator({) string<delimiter(")content(first_name)delimiter(")>operator(=)operator(>)string<delimiter(")content(anika)delimiter(")>operator(})operator(\)) + ident(p2) operator(=) constant(Person)operator(.)ident(find)operator(()ident(p1)operator(.)ident(id)operator(\)) + ident(assert_equal) ident(p1)operator(.)ident(id)operator(,) ident(p2)operator(.)ident(id) + ident(p1)operator(.)ident(first_name) operator(=) string<delimiter(")content(Anika)delimiter(")> + ident(p1)operator(.)ident(save) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StaleObjectError)operator(\)) operator({) + ident(p2)operator(.)ident(first_name) operator(=) string<delimiter(")content(should fail)delimiter(")> + ident(p2)operator(.)ident(save) + operator(}) + reserved(end) + + reserved(def) method(test_lock_column_name_existing) + ident(t1) operator(=) constant(LegacyThing)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(t2) operator(=) constant(LegacyThing)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(t1)operator(.)ident(tps_report_number) operator(=) integer(400) + ident(t1)operator(.)ident(save) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StaleObjectError)operator(\)) operator({) + ident(t2)operator(.)ident(tps_report_number) operator(=) integer(300) + ident(t2)operator(.)ident(save) + operator(}) + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/category)delimiter(')> + +reserved(class) class(MethodScopingTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:comments)operator(,) symbol(:posts) + + reserved(def) method(test_set_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(just a test...)delimiter(')> operator(})operator(\)) reserved(do) + ident(assert_equal) string<delimiter(')content(just a test...)delimiter(')>operator(,) constant(Developer)operator(.)ident(send)operator(()symbol(:current_scoped_methods)operator(\))operator([)symbol(:find)operator(])operator([)symbol(:conditions)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_nothing_raised) operator({) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find_first) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary = 100000)delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal) constant(Developer)operator(.)ident(find)operator(()integer(10)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(name)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find_combines_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary = 9000)delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal) ident(developers)operator(()symbol(:poor_jamis)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find_sanitizes_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(salary = ?)delimiter(')>operator(,) integer(9000)operator(]) operator(})operator(\)) reserved(do) + ident(assert_equal) ident(developers)operator(()symbol(:poor_jamis)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find_combines_and_sanitizes_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(salary = ?)delimiter(')>operator(,) integer(9000)operator(]) operator(})operator(\)) reserved(do) + ident(assert_equal) ident(developers)operator(()symbol(:poor_jamis)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(name = ?)delimiter(')>operator(,) string<delimiter(')content(Jamis)delimiter(')>operator(])operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find_all) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal) operator([)ident(developers)operator(()symbol(:david)operator(\))operator(])operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_count) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(count) + reserved(end) + + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(salary = 100000)delimiter(')> operator(})operator(\)) reserved(do) + ident(assert_equal) integer(8)operator(,) constant(Developer)operator(.)ident(count) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(count)operator(()string<delimiter(")content(name LIKE 'fixture_1%')delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_find_include) + comment(# with the include, will retrieve only developers for the given project) + ident(scoped_developers) operator(=) constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(projects.id = 2)delimiter(')>operator(\)) + reserved(end) + ident(assert) ident(scoped_developers)operator(.)ident(include?)operator(()ident(developers)operator(()symbol(:david)operator(\))operator(\)) + ident(assert) operator(!)ident(scoped_developers)operator(.)ident(include?)operator(()ident(developers)operator(()symbol(:jamis)operator(\))operator(\)) + ident(assert_equal) integer(1)operator(,) ident(scoped_developers)operator(.)ident(size) + reserved(end) + + reserved(def) method(test_scoped_count_include) + comment(# with the include, will retrieve only developers for the given project) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects) operator(})operator(\)) reserved(do) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(count)operator(()string<delimiter(')content(projects.id = 2)delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_create) + ident(new_comment) operator(=) pre_constant(nil) + + constant(VerySpecialComment)operator(.)ident(with_scope)operator(()symbol(:create) operator(=)operator(>) operator({) symbol(:post_id) operator(=)operator(>) integer(1) operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()operator({) symbol(:post_id) operator(=)operator(>) integer(1) operator(})operator(,) constant(VerySpecialComment)operator(.)ident(send)operator(()symbol(:current_scoped_methods)operator(\))operator([)symbol(:create)operator(])operator(\)) + ident(new_comment) operator(=) constant(VerySpecialComment)operator(.)ident(create) symbol(:body) operator(=)operator(>) string<delimiter(")content(Wonderful world)delimiter(")> + reserved(end) + + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(comments)operator(.)ident(include?)operator(()ident(new_comment)operator(\)) + reserved(end) + + reserved(def) method(test_immutable_scope) + ident(options) operator(=) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(}) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) ident(options)operator(\)) reserved(do) + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + ident(options)operator([)symbol(:conditions)operator(]) operator(=) string<delimiter(")content(name != 'David')delimiter(")> + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + reserved(end) + + ident(scope) operator(=) operator({) symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(}) + constant(Developer)operator(.)ident(with_scope)operator(()ident(scope)operator(\)) reserved(do) + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + ident(scope)operator([)symbol(:find)operator(])operator([)symbol(:conditions)operator(]) operator(=) string<delimiter(")content(name != 'David')delimiter(")> + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_scoped_with_duck_typing) + ident(scoping) operator(=) constant(Struct)operator(.)ident(new)operator(()symbol(:method_scoping)operator(\))operator(.)ident(new)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')>operator(]) operator(})operator(\)) + constant(Developer)operator(.)ident(with_scope)operator(()ident(scoping)operator(\)) reserved(do) + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_ensure_that_method_scoping_is_correctly_restored) + ident(scoped_methods) operator(=) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\)) + + reserved(begin) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(})operator(\)) reserved(do) + ident(raise) string<delimiter(")content(an exception)delimiter(")> + reserved(end) + reserved(rescue) + reserved(end) + ident(assert_equal) ident(scoped_methods)operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\)) + reserved(end) +reserved(end) + +reserved(class) class(NestedScopingTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:comments)operator(,) symbol(:posts) + + reserved(def) method(test_merge_options) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(salary = 80000)delimiter(')> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:limit) operator(=)operator(>) integer(10) operator(})operator(\)) reserved(do) + ident(merged_option) operator(=) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(]) + ident(assert_equal)operator(()operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(salary = 80000)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(10) operator(})operator(,) ident(merged_option)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_replace_options) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()operator({)symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(})operator(})operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator(\)) + ident(assert_equal)operator(()operator({)symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(})operator(})operator(,) constant(Developer)operator(.)ident(send)operator(()symbol(:scoped_methods)operator(\))operator([)integer(-1)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_append_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(salary = 80000)delimiter(')> operator(})operator(\)) reserved(do) + ident(appended_condition) operator(=) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(])operator([)symbol(:conditions)operator(]) + ident(assert_equal)operator(()string<delimiter(")content(( name = 'David' \) AND ( salary = 80000 \))delimiter(")>operator(,) ident(appended_condition)operator(\)) + ident(assert_equal)operator(()integer(1)operator(,) constant(Developer)operator(.)ident(count)operator(\)) + reserved(end) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Maiha')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()integer(0)operator(,) constant(Developer)operator(.)ident(count)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_merge_and_append_options) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(salary = 80000)delimiter(')>operator(,) symbol(:limit) operator(=)operator(>) integer(10) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(merged_option) operator(=) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(]) + ident(assert_equal)operator(()operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(( salary = 80000 \) AND ( name = 'David' \))delimiter(")>operator(,) symbol(:limit) operator(=)operator(>) integer(10) operator(})operator(,) ident(merged_option)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_nested_scoped_find) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_nothing_raised) operator({) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + ident(assert_equal)operator(()string<delimiter(')content(Jamis)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_nested_scoped_find_include) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(projects.id = 2)delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_nothing_raised) operator({) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) operator(}) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_nested_scoped_find_merged_include) + comment(# :include's remain unique and don't "double up" when merging) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(projects.id = 2)delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects) operator(})operator(\)) reserved(do) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(])operator([)symbol(:include)operator(])operator(.)ident(length) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + + comment(# the nested scope doesn't remove the first :include) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(projects.id = 2)delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) operator([)operator(]) operator(})operator(\)) reserved(do) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(])operator([)symbol(:include)operator(])operator(.)ident(length) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + + comment(# mixing array and symbol include's will merge correctly) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) operator([)symbol(:projects)operator(])operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(projects.id = 2)delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects) operator(})operator(\)) reserved(do) + ident(assert_equal) integer(1)operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(])operator([)symbol(:include)operator(])operator(.)ident(length) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_nested_scoped_find_replace_include) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) symbol(:projects) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:include) operator(=)operator(>) operator([)operator(]) operator(})operator(\)) reserved(do) + ident(assert_equal) integer(0)operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\))operator([)symbol(:find)operator(])operator([)symbol(:include)operator(])operator(.)ident(length) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_three_level_nested_exclusive_scoped_find) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()string<delimiter(')content(Jamis)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Maiha')delimiter(")> operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()pre_constant(nil)operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(\)) + reserved(end) + + comment(# ensure that scoping is restored) + ident(assert_equal)operator(()string<delimiter(')content(David)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + + comment(# ensure that scoping is restored) + ident(assert_equal)operator(()string<delimiter(')content(Jamis)delimiter(')>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_merged_scoped_find) + ident(poor_jamis) operator(=) ident(developers)operator(()symbol(:poor_jamis)operator(\)) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary < 100000)delimiter(")> operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:offset) operator(=)operator(>) integer(1) operator(})operator(\)) reserved(do) + ident(assert_equal)operator(()ident(poor_jamis)operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id asc)delimiter(')>operator(\))operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_merged_scoped_find_sanitizes_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')>operator(]) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(salary = ?)delimiter(')>operator(,) integer(9000)operator(]) operator(})operator(\)) reserved(do) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(RecordNotFound)operator(\)) operator({) ident(developers)operator(()symbol(:poor_jamis)operator(\)) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_nested_scoped_find_combines_and_sanitizes_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')>operator(]) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(salary = ?)delimiter(')>operator(,) integer(9000)operator(]) operator(})operator(\)) reserved(do) + ident(assert_equal) ident(developers)operator(()symbol(:poor_jamis)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(assert_equal) ident(developers)operator(()symbol(:poor_jamis)operator(\))operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(name = ?)delimiter(')>operator(,) string<delimiter(')content(Jamis)delimiter(')>operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_merged_scoped_find_combines_and_sanitizes_conditions) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(")content(name = ?)delimiter(")>operator(,) string<delimiter(')content(David)delimiter(')>operator(]) operator(})operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) operator([)string<delimiter(')content(salary > ?)delimiter(')>operator(,) integer(9000)operator(]) operator(})operator(\)) reserved(do) + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_immutable_nested_scope) + ident(options1) operator(=) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(}) + ident(options2) operator(=) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(}) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) ident(options1)operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_exclusive_scope)operator(()symbol(:find) operator(=)operator(>) ident(options2)operator(\)) reserved(do) + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + ident(options1)operator([)symbol(:conditions)operator(]) operator(=) ident(options2)operator([)symbol(:conditions)operator(]) operator(=) pre_constant(nil) + ident(assert_equal) string<delimiter(%w()content(David)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_immutable_merged_scope) + ident(options1) operator(=) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Jamis')delimiter(")> operator(}) + ident(options2) operator(=) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(salary > 10000)delimiter(")> operator(}) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) ident(options1)operator(\)) reserved(do) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) ident(options2)operator(\)) reserved(do) + ident(assert_equal) string<delimiter(%w()content(Jamis)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + ident(options1)operator([)symbol(:conditions)operator(]) operator(=) ident(options2)operator([)symbol(:conditions)operator(]) operator(=) pre_constant(nil) + ident(assert_equal) string<delimiter(%w()content(Jamis)delimiter(\))>operator(,) constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(map) operator({) operator(|)ident(d)operator(|) ident(d)operator(.)ident(name) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_ensure_that_method_scoping_is_correctly_restored) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'David')delimiter(")> operator(})operator(\)) reserved(do) + ident(scoped_methods) operator(=) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\)) + reserved(begin) + constant(Developer)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(")content(name = 'Maiha')delimiter(")> operator(})operator(\)) reserved(do) + ident(raise) string<delimiter(")content(an exception)delimiter(")> + reserved(end) + reserved(rescue) + reserved(end) + ident(assert_equal) ident(scoped_methods)operator(,) constant(Developer)operator(.)ident(instance_eval)operator(()string<delimiter(')content(current_scoped_methods)delimiter(')>operator(\)) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(HasManyScopingTest)operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:comments)operator(,) symbol(:posts) + + reserved(def) method(setup) + instance_variable(@welcome) operator(=) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\)) + reserved(end) + + reserved(def) method(test_forwarding_of_static_methods) + ident(assert_equal) string<delimiter(')content(a comment...)delimiter(')>operator(,) constant(Comment)operator(.)ident(what_are_you) + ident(assert_equal) string<delimiter(')content(a comment...)delimiter(')>operator(,) instance_variable(@welcome)operator(.)ident(comments)operator(.)ident(what_are_you) + reserved(end) + + reserved(def) method(test_forwarding_to_scoped) + ident(assert_equal) integer(4)operator(,) constant(Comment)operator(.)ident(search_by_type)operator(()string<delimiter(')content(Comment)delimiter(')>operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) instance_variable(@welcome)operator(.)ident(comments)operator(.)ident(search_by_type)operator(()string<delimiter(')content(Comment)delimiter(')>operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_forwarding_to_dynamic_finders) + ident(assert_equal) integer(4)operator(,) constant(Comment)operator(.)ident(find_all_by_type)operator(()string<delimiter(')content(Comment)delimiter(')>operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) instance_variable(@welcome)operator(.)ident(comments)operator(.)ident(find_all_by_type)operator(()string<delimiter(')content(Comment)delimiter(')>operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_nested_scope) + constant(Comment)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(1=1)delimiter(')> operator(})operator(\)) reserved(do) + ident(assert_equal) string<delimiter(')content(a comment...)delimiter(')>operator(,) instance_variable(@welcome)operator(.)ident(comments)operator(.)ident(what_are_you) + reserved(end) + reserved(end) +reserved(end) + + +reserved(class) class(HasAndBelongsToManyScopingTest)operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:posts)operator(,) symbol(:categories)operator(,) symbol(:categories_posts) + + reserved(def) method(setup) + instance_variable(@welcome) operator(=) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\)) + reserved(end) + + reserved(def) method(test_forwarding_of_static_methods) + ident(assert_equal) string<delimiter(')content(a category...)delimiter(')>operator(,) constant(Category)operator(.)ident(what_are_you) + ident(assert_equal) string<delimiter(')content(a category...)delimiter(')>operator(,) instance_variable(@welcome)operator(.)ident(categories)operator(.)ident(what_are_you) + reserved(end) + + reserved(def) method(test_forwarding_to_dynamic_finders) + ident(assert_equal) integer(4)operator(,) constant(Category)operator(.)ident(find_all_by_type)operator(()string<delimiter(')content(SpecialCategory)delimiter(')>operator(\))operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) instance_variable(@welcome)operator(.)ident(categories)operator(.)ident(find_all_by_type)operator(()string<delimiter(')content(SpecialCategory)delimiter(')>operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) instance_variable(@welcome)operator(.)ident(categories)operator(.)ident(find_all_by_type)operator(()string<delimiter(')content(Category)delimiter(')>operator(\))operator(.)ident(size) + reserved(end) + + reserved(def) method(test_nested_scope) + constant(Category)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(1=1)delimiter(')> operator(})operator(\)) reserved(do) + ident(assert_equal) string<delimiter(')content(a comment...)delimiter(')>operator(,) instance_variable(@welcome)operator(.)ident(comments)operator(.)ident(what_are_you) + reserved(end) + reserved(end) +reserved(end) + + +comment(=begin +# We disabled the scoping for has_one and belongs_to as we can't think of a proper use case + + +class BelongsToScopingTest< Test::Unit::TestCase + fixtures :comments, :posts + + def setup + @greetings = Comment.find(1\) + end + + def test_forwarding_of_static_method + assert_equal 'a post...', Post.what_are_you + assert_equal 'a post...', @greetings.post.what_are_you + end + + def test_forwarding_to_dynamic_finders + assert_equal 4, Post.find_all_by_type('Post'\).size + assert_equal 1, @greetings.post.find_all_by_type('Post'\).size + end + +end + + +class HasOneScopingTest< Test::Unit::TestCase + fixtures :comments, :posts + + def setup + @sti_comments = Post.find(4\) + end + + def test_forwarding_of_static_methods + assert_equal 'a comment...', Comment.what_are_you + assert_equal 'a very special comment...', @sti_comments.very_special_comment.what_are_you + end + + def test_forwarding_to_dynamic_finders + assert_equal 1, Comment.find_all_by_type('VerySpecialComment'\).size + assert_equal 1, @sti_comments.very_special_comment.find_all_by_type('VerySpecialComment'\).size + assert_equal 0, @sti_comments.very_special_comment.find_all_by_type('Comment'\).size + end + +end + +=end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/person)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/1_people_have_last_names)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/2_we_need_reminders)delimiter(')> + +reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(supports_migrations?) + reserved(class) class(Reminder) operator(<) constant(ActiveRecord)operator(::)constant(Base)operator(;) reserved(end) + + reserved(class) class(ActiveRecord::Migration) + reserved(class) operator(<<)class(self) + ident(attr_accessor) symbol(:message_count) + reserved(def) method(puts)operator(()ident(text)operator(=)string<delimiter(")delimiter(")>operator(\)) + pre_constant(self)operator(.)ident(message_count) operator(||=) integer(0) + pre_constant(self)operator(.)ident(message_count) operator(+=) integer(1) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(MigrationTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + reserved(def) method(setup) + constant(ActiveRecord)operator(::)constant(Migration)operator(.)ident(verbose) operator(=) pre_constant(true) + constant(PeopleHaveLastNames)operator(.)ident(message_count) operator(=) integer(0) + reserved(end) + + reserved(def) method(teardown) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(initialize_schema_information) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(update) string<delimiter(")content(UPDATE )inline<inline_delimiter(#{)constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(schema_info_table_name)inline_delimiter(})>content( SET version = 0)delimiter(")> + + constant(Reminder)operator(.)ident(connection)operator(.)ident(drop_table)operator(()string<delimiter(")content(reminders)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Reminder)operator(.)ident(connection)operator(.)ident(drop_table)operator(()string<delimiter(")content(people_reminders)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Reminder)operator(.)ident(connection)operator(.)ident(drop_table)operator(()string<delimiter(")content(prefix_reminders_suffix)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Reminder)operator(.)ident(reset_column_information) + + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(key)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(bio)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(age)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(height)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(birthday)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(favorite_day)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(male)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(administrator)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(reset_column_information) + reserved(end) + + reserved(def) method(test_add_index) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(,) symbol(:string) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(administrator)delimiter(")>operator(,) symbol(:boolean) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(key)delimiter(")>operator(,) symbol(:string) + + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(add_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(remove_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(\)) operator(}) + + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(add_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) operator([)string<delimiter(")content(last_name)delimiter(")>operator(,) string<delimiter(")content(first_name)delimiter(")>operator(])operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(remove_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(\)) operator(}) + + comment(# quoting) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(add_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) operator([)string<delimiter(")content(key)delimiter(")>operator(])operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(key)delimiter(")>operator(,) symbol(:unique) operator(=)operator(>) pre_constant(true)operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(remove_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(key)delimiter(")>operator(\)) operator(}) + + comment(# Sybase adapter does not support indexes on :boolean columns) + reserved(unless) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(add_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(%w()content(last_name first_name administrator)delimiter(\))>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(named_admin)delimiter(")>operator(\)) operator(}) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(remove_index)operator(()string<delimiter(")content(people)delimiter(")>operator(,) symbol(:name) operator(=)operator(>) string<delimiter(")content(named_admin)delimiter(")>operator(\)) operator(}) + reserved(end) + reserved(end) + + reserved(def) method(test_create_table_adds_id) + constant(Person)operator(.)ident(connection)operator(.)ident(create_table) symbol(:testings) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:foo)operator(,) symbol(:string) + reserved(end) + + ident(assert_equal) string<delimiter(%w()content(foo id)delimiter(\))>operator(,) + constant(Person)operator(.)ident(connection)operator(.)ident(columns)operator(()symbol(:testings)operator(\))operator(.)ident(map) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(})operator(.)ident(sort) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:testings) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_create_table_with_not_null_column) + constant(Person)operator(.)ident(connection)operator(.)ident(create_table) symbol(:testings) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:foo)operator(,) symbol(:string)operator(,) symbol(:null) operator(=)operator(>) pre_constant(false) + reserved(end) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) reserved(do) + constant(Person)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(insert into testings (foo\) values (NULL\))delimiter(")> + reserved(end) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:testings) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_create_table_with_defaults) + constant(Person)operator(.)ident(connection)operator(.)ident(create_table) symbol(:testings) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:one)operator(,) symbol(:string)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(")content(hello)delimiter(")> + ident(t)operator(.)ident(column) symbol(:two)operator(,) symbol(:boolean)operator(,) symbol(:default) operator(=)operator(>) pre_constant(true) + ident(t)operator(.)ident(column) symbol(:three)operator(,) symbol(:boolean)operator(,) symbol(:default) operator(=)operator(>) pre_constant(false) + ident(t)operator(.)ident(column) symbol(:four)operator(,) symbol(:integer)operator(,) symbol(:default) operator(=)operator(>) integer(1) + reserved(end) + + ident(columns) operator(=) constant(Person)operator(.)ident(connection)operator(.)ident(columns)operator(()symbol(:testings)operator(\)) + ident(one) operator(=) ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(")content(one)delimiter(")> operator(}) + ident(two) operator(=) ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(")content(two)delimiter(")> operator(}) + ident(three) operator(=) ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(")content(three)delimiter(")> operator(}) + ident(four) operator(=) ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(")content(four)delimiter(")> operator(}) + + ident(assert_equal) string<delimiter(")content(hello)delimiter(")>operator(,) ident(one)operator(.)ident(default) + reserved(if) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + comment(# Oracle doesn't support native booleans) + ident(assert_equal) pre_constant(true)operator(,) ident(two)operator(.)ident(default) operator(==) integer(1) + ident(assert_equal) pre_constant(false)operator(,) ident(three)operator(.)ident(default) operator(!=) integer(0) + reserved(else) + ident(assert_equal) pre_constant(true)operator(,) ident(two)operator(.)ident(default) + ident(assert_equal) pre_constant(false)operator(,) ident(three)operator(.)ident(default) + reserved(end) + ident(assert_equal) integer(1)operator(,) ident(four)operator(.)ident(default) + + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:testings) reserved(rescue) pre_constant(nil) + reserved(end) + + comment(# SQL Server and Sybase will not allow you to add a NOT NULL column) + comment(# to a table without specifying a default value, so the) + comment(# following test must be skipped ) + reserved(unless) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + reserved(def) method(test_add_column_not_null_without_default) + constant(Person)operator(.)ident(connection)operator(.)ident(create_table) symbol(:testings) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:foo)operator(,) symbol(:string) + reserved(end) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) symbol(:testings)operator(,) symbol(:bar)operator(,) symbol(:string)operator(,) symbol(:null) operator(=)operator(>) pre_constant(false) + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) reserved(do) + constant(Person)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(insert into testings (foo, bar\) values ('hello', NULL\))delimiter(")> + reserved(end) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:testings) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(test_add_column_not_null_with_default) + constant(Person)operator(.)ident(connection)operator(.)ident(create_table) symbol(:testings) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:foo)operator(,) symbol(:string) + reserved(end) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) symbol(:testings)operator(,) symbol(:bar)operator(,) symbol(:string)operator(,) symbol(:null) operator(=)operator(>) pre_constant(false)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(")content(default)delimiter(")> + + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) reserved(do) + constant(Person)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(insert into testings (foo, bar\) values ('hello', NULL\))delimiter(")> + reserved(end) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:testings) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_native_types) + constant(Person)operator(.)ident(delete_all) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(last_name)delimiter(")>operator(,) symbol(:string) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(bio)delimiter(")>operator(,) symbol(:text) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(age)delimiter(")>operator(,) symbol(:integer) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(height)delimiter(")>operator(,) symbol(:float) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(birthday)delimiter(")>operator(,) symbol(:datetime) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(favorite_day)delimiter(")>operator(,) symbol(:date) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(male)delimiter(")>operator(,) symbol(:boolean) + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(create) symbol(:first_name) operator(=)operator(>) string<delimiter(')content(bob)delimiter(')>operator(,) symbol(:last_name) operator(=)operator(>) string<delimiter(')content(bobsen)delimiter(')>operator(,) symbol(:bio) operator(=)operator(>) string<delimiter(")content(I was born ....)delimiter(")>operator(,) symbol(:age) operator(=)operator(>) integer(18)operator(,) symbol(:height) operator(=)operator(>) float(1.78)operator(,) symbol(:birthday) operator(=)operator(>) integer(18)operator(.)ident(years)operator(.)ident(ago)operator(,) symbol(:favorite_day) operator(=)operator(>) integer(10)operator(.)ident(days)operator(.)ident(ago)operator(,) symbol(:male) operator(=)operator(>) pre_constant(true) operator(}) + ident(bob) operator(=) constant(Person)operator(.)ident(find)operator(()symbol(:first)operator(\)) + + ident(assert_equal) ident(bob)operator(.)ident(first_name)operator(,) string<delimiter(')content(bob)delimiter(')> + ident(assert_equal) ident(bob)operator(.)ident(last_name)operator(,) string<delimiter(')content(bobsen)delimiter(')> + ident(assert_equal) ident(bob)operator(.)ident(bio)operator(,) string<delimiter(")content(I was born ....)delimiter(")> + ident(assert_equal) ident(bob)operator(.)ident(age)operator(,) integer(18) + ident(assert_equal) ident(bob)operator(.)ident(male?)operator(,) pre_constant(true) + + ident(assert_equal) constant(String)operator(,) ident(bob)operator(.)ident(first_name)operator(.)ident(class) + ident(assert_equal) constant(String)operator(,) ident(bob)operator(.)ident(last_name)operator(.)ident(class) + ident(assert_equal) constant(String)operator(,) ident(bob)operator(.)ident(bio)operator(.)ident(class) + ident(assert_equal) constant(Fixnum)operator(,) ident(bob)operator(.)ident(age)operator(.)ident(class) + ident(assert_equal) constant(Time)operator(,) ident(bob)operator(.)ident(birthday)operator(.)ident(class) + + reserved(if) ident(current_adapter?)operator(()symbol(:SQLServerAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) operator(||) ident(current_adapter?)operator(()symbol(:SybaseAdapter)operator(\)) + comment(# SQL Server, Sybase, and Oracle don't differentiate between date/time) + ident(assert_equal) constant(Time)operator(,) ident(bob)operator(.)ident(favorite_day)operator(.)ident(class) + reserved(else) + ident(assert_equal) constant(Date)operator(,) ident(bob)operator(.)ident(favorite_day)operator(.)ident(class) + reserved(end) + + ident(assert_equal) constant(TrueClass)operator(,) ident(bob)operator(.)ident(male?)operator(.)ident(class) + reserved(end) + + reserved(def) method(test_add_remove_single_field_using_string_arguments) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + + constant(ActiveRecord)operator(::)constant(Migration)operator(.)ident(add_column) string<delimiter(')content(people)delimiter(')>operator(,) string<delimiter(')content(last_name)delimiter(')>operator(,) symbol(:string) + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + + constant(ActiveRecord)operator(::)constant(Migration)operator(.)ident(remove_column) string<delimiter(')content(people)delimiter(')>operator(,) string<delimiter(')content(last_name)delimiter(')> + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + reserved(end) + + reserved(def) method(test_add_remove_single_field_using_symbol_arguments) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + + constant(ActiveRecord)operator(::)constant(Migration)operator(.)ident(add_column) symbol(:people)operator(,) symbol(:last_name)operator(,) symbol(:string) + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + + constant(ActiveRecord)operator(::)constant(Migration)operator(.)ident(remove_column) symbol(:people)operator(,) symbol(:last_name) + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + reserved(end) + + reserved(def) method(test_add_rename) + constant(Person)operator(.)ident(delete_all) + + reserved(begin) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(girlfriend)delimiter(")>operator(,) symbol(:string) + constant(Person)operator(.)ident(create) symbol(:girlfriend) operator(=)operator(>) string<delimiter(')content(bobette)delimiter(')> + + constant(Person)operator(.)ident(connection)operator(.)ident(rename_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(girlfriend)delimiter(")>operator(,) string<delimiter(")content(exgirlfriend)delimiter(")> + + constant(Person)operator(.)ident(reset_column_information) + ident(bob) operator(=) constant(Person)operator(.)ident(find)operator(()symbol(:first)operator(\)) + + ident(assert_equal) string<delimiter(")content(bobette)delimiter(")>operator(,) ident(bob)operator(.)ident(exgirlfriend) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(girlfriend)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(exgirlfriend)delimiter(")>operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(end) + + reserved(def) method(test_rename_column_using_symbol_arguments) + reserved(begin) + constant(Person)operator(.)ident(connection)operator(.)ident(rename_column) symbol(:people)operator(,) symbol(:first_name)operator(,) symbol(:nick_name) + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_names)operator(.)ident(include?)operator(()string<delimiter(")content(nick_name)delimiter(")>operator(\)) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,)string<delimiter(")content(nick_name)delimiter(")>operator(\)) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,)string<delimiter(")content(first_name)delimiter(")>operator(,) symbol(:string)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_rename_column) + reserved(begin) + constant(Person)operator(.)ident(connection)operator(.)ident(rename_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(first_name)delimiter(")>operator(,) string<delimiter(")content(nick_name)delimiter(")> + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_names)operator(.)ident(include?)operator(()string<delimiter(")content(nick_name)delimiter(")>operator(\)) + reserved(ensure) + constant(Person)operator(.)ident(connection)operator(.)ident(remove_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,)string<delimiter(")content(nick_name)delimiter(")>operator(\)) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column)operator(()string<delimiter(")content(people)delimiter(")>operator(,)string<delimiter(")content(first_name)delimiter(")>operator(,) symbol(:string)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_rename_table) + reserved(begin) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(create_table) symbol(:octopuses) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) symbol(:url)operator(,) symbol(:string) + reserved(end) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(rename_table) symbol(:octopuses)operator(,) symbol(:octopi) + + ident(assert_nothing_raised) reserved(do) + reserved(if) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + comment(# Oracle requires the explicit sequence value for the pk) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(INSERT INTO octopi (id, url\) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg'\))delimiter(")> + reserved(else) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(execute) string<delimiter(")content(INSERT INTO octopi (url\) VALUES ('http://www.foreverflying.com/octopus-black7.jpg'\))delimiter(")> + reserved(end) + reserved(end) + + ident(assert_equal) string<delimiter(')content(http://www.foreverflying.com/octopus-black7.jpg)delimiter(')>operator(,) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(select_value)operator(()string<delimiter(")content(SELECT url FROM octopi WHERE id=1)delimiter(")>operator(\)) + + reserved(ensure) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:octopuses) reserved(rescue) pre_constant(nil) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:octopi) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(test_change_column) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(')content(people)delimiter(')>operator(,) string<delimiter(')content(age)delimiter(')>operator(,) symbol(:integer) + ident(old_columns) operator(=) constant(Person)operator(.)ident(connection)operator(.)ident(columns)operator(()constant(Person)operator(.)ident(table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Columns)delimiter(")>operator(\)) + ident(assert) ident(old_columns)operator(.)ident(find) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(')content(age)delimiter(')> reserved(and) ident(c)operator(.)ident(type) operator(==) symbol(:integer) operator(}) + + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(change_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(age)delimiter(")>operator(,) symbol(:string) operator(}) + + ident(new_columns) operator(=) constant(Person)operator(.)ident(connection)operator(.)ident(columns)operator(()constant(Person)operator(.)ident(table_name)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( Columns)delimiter(")>operator(\)) + ident(assert_nil) ident(new_columns)operator(.)ident(find) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(')content(age)delimiter(')> reserved(and) ident(c)operator(.)ident(type) operator(==) symbol(:integer) operator(}) + ident(assert) ident(new_columns)operator(.)ident(find) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(')content(age)delimiter(')> reserved(and) ident(c)operator(.)ident(type) operator(==) symbol(:string) operator(}) + reserved(end) + + reserved(def) method(test_change_column_with_new_default) + constant(Person)operator(.)ident(connection)operator(.)ident(add_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(administrator)delimiter(")>operator(,) symbol(:boolean)operator(,) symbol(:default) operator(=)operator(>) integer(1) + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(new)operator(.)ident(administrator?) + + ident(assert_nothing_raised) operator({) constant(Person)operator(.)ident(connection)operator(.)ident(change_column) string<delimiter(")content(people)delimiter(")>operator(,) string<delimiter(")content(administrator)delimiter(")>operator(,) symbol(:boolean)operator(,) symbol(:default) operator(=)operator(>) integer(0) operator(}) + constant(Person)operator(.)ident(reset_column_information) + ident(assert) operator(!)constant(Person)operator(.)ident(new)operator(.)ident(administrator?) + reserved(end) + + reserved(def) method(test_add_table) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + + constant(WeNeedReminders)operator(.)ident(up) + + ident(assert) constant(Reminder)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(remind_at)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(now)operator(\)) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(content) + + constant(WeNeedReminders)operator(.)ident(down) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) operator({) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_migrator) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(\)) + + ident(assert_equal) integer(3)operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(current_version) + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) constant(Reminder)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(remind_at)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(now)operator(\)) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(content) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(down)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(\)) + + ident(assert_equal) integer(0)operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(current_version) + constant(Person)operator(.)ident(reset_column_information) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) operator({) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_migrator_one_up) + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(1)operator(\)) + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(2)operator(\)) + + ident(assert) constant(Reminder)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(remind_at)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(now)operator(\)) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(content) + reserved(end) + + reserved(def) method(test_migrator_one_down) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(\)) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(down)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(1)operator(\)) + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + reserved(end) + + reserved(def) method(test_migrator_one_up_one_down) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(1)operator(\)) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(down)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(0)operator(\)) + + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + reserved(end) + + reserved(def) method(test_migrator_verbosity) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(1)operator(\)) + ident(assert) constant(PeopleHaveLastNames)operator(.)ident(message_count) operator(>) integer(0) + constant(PeopleHaveLastNames)operator(.)ident(message_count) operator(=) integer(0) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(down)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(0)operator(\)) + ident(assert) constant(PeopleHaveLastNames)operator(.)ident(message_count) operator(>) integer(0) + constant(PeopleHaveLastNames)operator(.)ident(message_count) operator(=) integer(0) + reserved(end) + + reserved(def) method(test_migrator_verbosity_off) + constant(PeopleHaveLastNames)operator(.)ident(verbose) operator(=) pre_constant(false) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(1)operator(\)) + ident(assert) constant(PeopleHaveLastNames)operator(.)ident(message_count)operator(.)ident(zero?) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(down)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(0)operator(\)) + ident(assert) constant(PeopleHaveLastNames)operator(.)ident(message_count)operator(.)ident(zero?) + reserved(end) + + reserved(def) method(test_migrator_going_down_due_to_version_target) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(up)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(1)operator(\)) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(migrate)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(,) integer(0)operator(\)) + + ident(assert) operator(!)constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(migrate)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations/)delimiter(')>operator(\)) + + constant(Person)operator(.)ident(reset_column_information) + ident(assert) constant(Person)operator(.)ident(column_methods_hash)operator(.)ident(include?)operator(()symbol(:last_name)operator(\)) + ident(assert) constant(Reminder)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(remind_at)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(now)operator(\)) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(content) + reserved(end) + + reserved(def) method(test_schema_info_table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")content(prefix_)delimiter(")> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")content(_suffix)delimiter(")> + constant(Reminder)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(prefix_schema_info_suffix)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(schema_info_table_name) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")delimiter(")> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")delimiter(")> + constant(Reminder)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(schema_info)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(schema_info_table_name) + reserved(ensure) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")delimiter(")> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")delimiter(")> + reserved(end) + + reserved(def) method(test_proper_table_name) + ident(assert_equal) string<delimiter(")content(table)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()string<delimiter(')content(table)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content(table)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()symbol(:table)operator(\)) + ident(assert_equal) string<delimiter(")content(reminders)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()constant(Reminder)operator(\)) + constant(Reminder)operator(.)ident(reset_table_name) + ident(assert_equal) constant(Reminder)operator(.)ident(table_name)operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()constant(Reminder)operator(\)) + + comment(# Use the model's own prefix/suffix if a model is given) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")content(ARprefix_)delimiter(")> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")content(_ARsuffix)delimiter(")> + constant(Reminder)operator(.)ident(table_name_prefix) operator(=) string<delimiter(')content(prefix_)delimiter(')> + constant(Reminder)operator(.)ident(table_name_suffix) operator(=) string<delimiter(')content(_suffix)delimiter(')> + constant(Reminder)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(prefix_reminders_suffix)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()constant(Reminder)operator(\)) + constant(Reminder)operator(.)ident(table_name_prefix) operator(=) string<delimiter(')delimiter(')> + constant(Reminder)operator(.)ident(table_name_suffix) operator(=) string<delimiter(')delimiter(')> + constant(Reminder)operator(.)ident(reset_table_name) + + comment(# Use AR::Base's prefix/suffix if string or symbol is given ) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")content(prefix_)delimiter(")> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")content(_suffix)delimiter(")> + constant(Reminder)operator(.)ident(reset_table_name) + ident(assert_equal) string<delimiter(")content(prefix_table_suffix)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()string<delimiter(')content(table)delimiter(')>operator(\)) + ident(assert_equal) string<delimiter(")content(prefix_table_suffix)delimiter(")>operator(,) constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(proper_table_name)operator(()symbol(:table)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(")delimiter(")> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(")delimiter(")> + constant(Reminder)operator(.)ident(reset_table_name) + reserved(end) + + reserved(def) method(test_add_drop_table_with_prefix_and_suffix) + ident(assert) operator(!)constant(Reminder)operator(.)ident(table_exists?) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(')content(prefix_)delimiter(')> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(')content(_suffix)delimiter(')> + constant(Reminder)operator(.)ident(reset_table_name) + constant(Reminder)operator(.)ident(reset_sequence_name) + constant(WeNeedReminders)operator(.)ident(up) + ident(assert) constant(Reminder)operator(.)ident(create)operator(()string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")>operator(,) string<delimiter(")content(remind_at)delimiter(")> operator(=)operator(>) constant(Time)operator(.)ident(now)operator(\)) + ident(assert_equal) string<delimiter(")content(hello world)delimiter(")>operator(,) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(content) + + constant(WeNeedReminders)operator(.)ident(down) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) operator({) constant(Reminder)operator(.)ident(find)operator(()symbol(:first)operator(\)) operator(}) + reserved(ensure) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_prefix) operator(=) string<delimiter(')delimiter(')> + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(table_name_suffix) operator(=) string<delimiter(')delimiter(')> + constant(Reminder)operator(.)ident(reset_table_name) + constant(Reminder)operator(.)ident(reset_sequence_name) + reserved(end) + + reserved(def) method(test_create_table_with_binary_column) + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:binary_testings) reserved(rescue) pre_constant(nil) + + ident(assert_nothing_raised) operator({) + constant(Person)operator(.)ident(connection)operator(.)ident(create_table) symbol(:binary_testings) reserved(do) operator(|)ident(t)operator(|) + ident(t)operator(.)ident(column) string<delimiter(")content(data)delimiter(")>operator(,) symbol(:binary)operator(,) symbol(:default) operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) symbol(:null) operator(=)operator(>) pre_constant(false) + reserved(end) + operator(}) + + ident(columns) operator(=) constant(Person)operator(.)ident(connection)operator(.)ident(columns)operator(()symbol(:binary_testings)operator(\)) + ident(data_column) operator(=) ident(columns)operator(.)ident(detect) operator({) operator(|)ident(c)operator(|) ident(c)operator(.)ident(name) operator(==) string<delimiter(")content(data)delimiter(")> operator(}) + + reserved(if) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + ident(assert_equal) string<delimiter(")content(empty_blob(\))delimiter(")>operator(,) ident(data_column)operator(.)ident(default) + reserved(else) + ident(assert_equal) string<delimiter(")delimiter(")>operator(,) ident(data_column)operator(.)ident(default) + reserved(end) + + constant(Person)operator(.)ident(connection)operator(.)ident(drop_table) symbol(:binary_testings) reserved(rescue) pre_constant(nil) + reserved(end) + + reserved(def) method(test_migrator_with_duplicates) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(DuplicateMigrationVersionError)operator(\)) reserved(do) + constant(ActiveRecord)operator(::)constant(Migrator)operator(.)ident(migrate)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/fixtures/migrations_with_duplicate/)delimiter(')>operator(,) pre_constant(nil)operator(\)) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/nested_set)delimiter(')> +ident(require) string<delimiter(')content(fixtures/mixin)delimiter(')> +ident(require) string<delimiter(')content(pp)delimiter(')> + +reserved(class) class(MixinNestedSetTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:mixins) + + reserved(def) method(test_mixing_in_methods) + ident(ns) operator(=) constant(NestedSet)operator(.)ident(new) + ident(assert)operator(() ident(ns)operator(.)ident(respond_to?)operator(() symbol(:all_children) operator(\)) operator(\)) + ident(assert_equal)operator(() ident(ns)operator(.)ident(scope_condition)operator(,) string<delimiter(")content(root_id IS NULL)delimiter(")> operator(\)) + + ident(check_method_mixins) ident(ns) + reserved(end) + + reserved(def) method(test_string_scope) + ident(ns) operator(=) constant(NestedSetWithStringScope)operator(.)ident(new) + + ident(ns)operator(.)ident(root_id) operator(=) integer(1) + ident(assert_equal)operator(() ident(ns)operator(.)ident(scope_condition)operator(,) string<delimiter(")content(root_id = 1)delimiter(")> operator(\)) + ident(ns)operator(.)ident(root_id) operator(=) integer(42) + ident(assert_equal)operator(() ident(ns)operator(.)ident(scope_condition)operator(,) string<delimiter(")content(root_id = 42)delimiter(")> operator(\)) + ident(check_method_mixins) ident(ns) + reserved(end) + + reserved(def) method(test_symbol_scope) + ident(ns) operator(=) constant(NestedSetWithSymbolScope)operator(.)ident(new) + ident(ns)operator(.)ident(root_id) operator(=) integer(1) + ident(assert_equal)operator(() ident(ns)operator(.)ident(scope_condition)operator(,) string<delimiter(")content(root_id = 1)delimiter(")> operator(\)) + ident(ns)operator(.)ident(root_id) operator(=) integer(42) + ident(assert_equal)operator(() ident(ns)operator(.)ident(scope_condition)operator(,) string<delimiter(")content(root_id = 42)delimiter(")> operator(\)) + ident(check_method_mixins) ident(ns) + reserved(end) + + reserved(def) method(check_method_mixins)operator(() ident(obj) operator(\)) + operator([)symbol(:scope_condition)operator(,) symbol(:left_col_name)operator(,) symbol(:right_col_name)operator(,) symbol(:parent_column)operator(,) symbol(:root?)operator(,) symbol(:add_child)operator(,) + symbol(:children_count)operator(,) symbol(:full_set)operator(,) symbol(:all_children)operator(,) symbol(:direct_children)operator(])operator(.)ident(each) operator({) operator(|)ident(symbol)operator(|) ident(assert)operator(() ident(obj)operator(.)ident(respond_to?)operator(()ident(symbol)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(set)operator(() ident(id) operator(\)) + constant(NestedSet)operator(.)ident(find)operator(() integer(3000) operator(+) ident(id) operator(\)) + reserved(end) + + reserved(def) method(test_adding_children) + ident(assert)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(unknown?) operator(\)) + ident(assert)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(unknown?) operator(\)) + ident(set)operator(()integer(1)operator(\))operator(.)ident(add_child) ident(set)operator(()integer(2)operator(\)) + + comment(# Did we maintain adding the parent_ids?) + ident(assert)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(root?) operator(\)) + ident(assert)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(child?) operator(\)) + ident(assert)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(parent_id) operator(==) ident(set)operator(()integer(1)operator(\))operator(.)ident(id) operator(\)) + + comment(# Check boundies) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(lft)operator(,) integer(1) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(lft)operator(,) integer(2) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(rgt)operator(,) integer(3) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(rgt)operator(,) integer(4) operator(\)) + + comment(# Check children cound) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(children_count)operator(,) integer(1) operator(\)) + + ident(set)operator(()integer(1)operator(\))operator(.)ident(add_child) ident(set)operator(()integer(3)operator(\)) + + comment(#check boundries) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(lft)operator(,) integer(1) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(lft)operator(,) integer(2) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(rgt)operator(,) integer(3) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(3)operator(\))operator(.)ident(lft)operator(,) integer(4) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(3)operator(\))operator(.)ident(rgt)operator(,) integer(5) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(rgt)operator(,) integer(6) operator(\)) + + comment(# How is the count looking?) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(children_count)operator(,) integer(2) operator(\)) + + ident(set)operator(()integer(2)operator(\))operator(.)ident(add_child) ident(set)operator(()integer(4)operator(\)) + + comment(# boundries) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(lft)operator(,) integer(1) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(lft)operator(,) integer(2) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(4)operator(\))operator(.)ident(lft)operator(,) integer(3) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(4)operator(\))operator(.)ident(rgt)operator(,) integer(4) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(rgt)operator(,) integer(5) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(3)operator(\))operator(.)ident(lft)operator(,) integer(6) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(3)operator(\))operator(.)ident(rgt)operator(,) integer(7) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(rgt)operator(,) integer(8) operator(\)) + + comment(# Children count) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(children_count)operator(,) integer(3) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(children_count)operator(,) integer(1) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(3)operator(\))operator(.)ident(children_count)operator(,) integer(0) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(4)operator(\))operator(.)ident(children_count)operator(,) integer(0) operator(\)) + + ident(set)operator(()integer(2)operator(\))operator(.)ident(add_child) ident(set)operator(()integer(5)operator(\)) + ident(set)operator(()integer(4)operator(\))operator(.)ident(add_child) ident(set)operator(()integer(6)operator(\)) + + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(children_count)operator(,) integer(3) operator(\)) + + + comment(# Children accessors) + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(full_set)operator(.)ident(length)operator(,) integer(6) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(2)operator(\))operator(.)ident(full_set)operator(.)ident(length)operator(,) integer(4) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(4)operator(\))operator(.)ident(full_set)operator(.)ident(length)operator(,) integer(2) operator(\)) + + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(all_children)operator(.)ident(length)operator(,) integer(5) operator(\)) + ident(assert_equal)operator(() ident(set)operator(()integer(6)operator(\))operator(.)ident(all_children)operator(.)ident(length)operator(,) integer(0) operator(\)) + + ident(assert_equal)operator(() ident(set)operator(()integer(1)operator(\))operator(.)ident(direct_children)operator(.)ident(length)operator(,) integer(2) operator(\)) + + reserved(end) + + reserved(def) method(test_snipping_tree) + ident(big_tree) operator(=) constant(NestedSetWithStringScope)operator(.)ident(find)operator(() integer(4001) operator(\)) + + comment(# Make sure we have the right one) + ident(assert_equal)operator(() integer(3)operator(,) ident(big_tree)operator(.)ident(direct_children)operator(.)ident(length) operator(\)) + ident(assert_equal)operator(() integer(10)operator(,) ident(big_tree)operator(.)ident(full_set)operator(.)ident(length) operator(\)) + + constant(NestedSetWithStringScope)operator(.)ident(find)operator(() integer(4005) operator(\))operator(.)ident(destroy) + + ident(big_tree) operator(=) constant(NestedSetWithStringScope)operator(.)ident(find)operator(() integer(4001) operator(\)) + + ident(assert_equal)operator(() integer(7)operator(,) ident(big_tree)operator(.)ident(full_set)operator(.)ident(length) operator(\)) + ident(assert_equal)operator(() integer(2)operator(,) ident(big_tree)operator(.)ident(direct_children)operator(.)ident(length) operator(\)) + + ident(assert_equal)operator(() integer(1)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4001)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(2)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4002)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(3)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4003)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(4)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4003)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(() integer(5)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4004)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(6)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4004)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(() integer(7)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4002)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(() integer(8)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4008)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(9)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4009)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(()integer(10)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4009)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(()integer(11)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4010)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(()integer(12)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4010)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(()integer(13)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4008)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(()integer(14)operator(,) constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4001)operator(\))operator(.)ident(rgt) operator(\)) + reserved(end) + + reserved(def) method(test_deleting_root) + constant(NestedSetWithStringScope)operator(.)ident(find)operator(()integer(4001)operator(\))operator(.)ident(destroy) + + ident(assert)operator(() constant(NestedSetWithStringScope)operator(.)ident(count) operator(==) integer(0) operator(\)) + reserved(end) + + reserved(def) method(test_common_usage) + ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(add_child)operator(() ident(mixins)operator(()symbol(:set_2)operator(\)) operator(\)) + ident(assert_equal)operator(() integer(1)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(direct_children)operator(.)ident(length) operator(\)) + + ident(mixins)operator(()symbol(:set_2)operator(\))operator(.)ident(add_child)operator(() ident(mixins)operator(()symbol(:set_3)operator(\)) operator(\)) + ident(assert_equal)operator(() integer(1)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(direct_children)operator(.)ident(length) operator(\)) + + comment(# Local cache is now out of date!) + comment(# Problem: the update_alls update all objects up the tree) + ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(reload) + ident(assert_equal)operator(() integer(2)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(all_children)operator(.)ident(length) operator(\)) + + ident(assert_equal)operator(() integer(1)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(2)operator(,) ident(mixins)operator(()symbol(:set_2)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(3)operator(,) ident(mixins)operator(()symbol(:set_3)operator(\))operator(.)ident(lft) operator(\)) + ident(assert_equal)operator(() integer(4)operator(,) ident(mixins)operator(()symbol(:set_3)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(() integer(5)operator(,) ident(mixins)operator(()symbol(:set_2)operator(\))operator(.)ident(rgt) operator(\)) + ident(assert_equal)operator(() integer(6)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(rgt) operator(\)) + + ident(assert)operator(() ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(root?) operator(\)) + + reserved(begin) + ident(mixins)operator(()symbol(:set_4)operator(\))operator(.)ident(add_child)operator(() ident(mixins)operator(()symbol(:set_1)operator(\)) operator(\)) + ident(fail) + reserved(rescue) + reserved(end) + + ident(assert_equal)operator(() integer(2)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(all_children)operator(.)ident(length) operator(\)) + + ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(add_child) ident(mixins)operator(()symbol(:set_4)operator(\)) + + ident(assert_equal)operator(() integer(3)operator(,) ident(mixins)operator(()symbol(:set_1)operator(\))operator(.)ident(all_children)operator(.)ident(length) operator(\)) + + + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/tree)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/list)delimiter(')> +ident(require) string<delimiter(')content(active_record/acts/nested_set)delimiter(')> +ident(require) string<delimiter(')content(fixtures/mixin)delimiter(')> + +reserved(class) class(ListTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:mixins) + + reserved(def) method(test_reordering) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_2)operator(\))operator(.)ident(move_lower) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_2)operator(\))operator(.)ident(move_higher) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_1)operator(\))operator(.)ident(move_to_bottom) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_1)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_1)operator(\))operator(.)ident(move_to_top) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + + ident(mixins)operator(()symbol(:list_2)operator(\))operator(.)ident(move_to_bottom) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_4)operator(\))operator(.)ident(move_to_top) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + reserved(end) + + reserved(def) method(test_move_to_bottom_with_next_to_last_item) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_3)operator(\))operator(.)ident(move_to_bottom) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_next_prev) + ident(assert_equal) ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) ident(mixins)operator(()symbol(:list_1)operator(\))operator(.)ident(lower_item) + ident(assert_nil) ident(mixins)operator(()symbol(:list_1)operator(\))operator(.)ident(higher_item) + ident(assert_equal) ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) ident(mixins)operator(()symbol(:list_4)operator(\))operator(.)ident(higher_item) + ident(assert_nil) ident(mixins)operator(()symbol(:list_4)operator(\))operator(.)ident(lower_item) + reserved(end) + + + reserved(def) method(test_injection) + ident(item) operator(=) constant(ListMixin)operator(.)ident(new)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(1)operator(\)) + ident(assert_equal) string<delimiter(")content(parent_id = 1)delimiter(")>operator(,) ident(item)operator(.)ident(scope_condition) + ident(assert_equal) string<delimiter(")content(pos)delimiter(")>operator(,) ident(item)operator(.)ident(position_column) + reserved(end) + + reserved(def) method(test_insert) + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(20)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new)operator(.)ident(pos) + ident(assert) ident(new)operator(.)ident(first?) + ident(assert) ident(new)operator(.)ident(last?) + + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(20)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(new)operator(.)ident(pos) + ident(assert) operator(!)ident(new)operator(.)ident(first?) + ident(assert) ident(new)operator(.)ident(last?) + + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(20)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(new)operator(.)ident(pos) + ident(assert) operator(!)ident(new)operator(.)ident(first?) + ident(assert) ident(new)operator(.)ident(last?) + + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(0)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new)operator(.)ident(pos) + ident(assert) ident(new)operator(.)ident(first?) + ident(assert) ident(new)operator(.)ident(last?) + reserved(end) + + reserved(def) method(test_insert_at) + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new)operator(.)ident(pos) + + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(new)operator(.)ident(pos) + + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(new)operator(.)ident(pos) + + ident(new4) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(4)operator(,) ident(new4)operator(.)ident(pos) + + ident(new4)operator(.)ident(insert_at)operator(()integer(3)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(new4)operator(.)ident(pos) + + ident(new)operator(.)ident(reload) + ident(assert_equal) integer(4)operator(,) ident(new)operator(.)ident(pos) + + ident(new)operator(.)ident(insert_at)operator(()integer(2)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(new)operator(.)ident(pos) + + ident(new4)operator(.)ident(reload) + ident(assert_equal) integer(4)operator(,) ident(new4)operator(.)ident(pos) + + ident(new5) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(5)operator(,) ident(new5)operator(.)ident(pos) + + ident(new5)operator(.)ident(insert_at)operator(()integer(1)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new5)operator(.)ident(pos) + + ident(new4)operator(.)ident(reload) + ident(assert_equal) integer(5)operator(,) ident(new4)operator(.)ident(pos) + reserved(end) + + reserved(def) method(test_delete_middle) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_2)operator(\))operator(.)ident(destroy) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_1)operator(,) symbol(:reload)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_3)operator(,) symbol(:reload)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(,) symbol(:reload)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(assert_equal) integer(1)operator(,) ident(mixins)operator(()symbol(:list_1)operator(\))operator(.)ident(pos) + ident(assert_equal) integer(2)operator(,) ident(mixins)operator(()symbol(:list_3)operator(\))operator(.)ident(pos) + ident(assert_equal) integer(3)operator(,) ident(mixins)operator(()symbol(:list_4)operator(\))operator(.)ident(pos) + + ident(mixins)operator(()symbol(:list_1)operator(\))operator(.)ident(destroy) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_3)operator(,) symbol(:reload)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_4)operator(,) symbol(:reload)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(assert_equal) integer(1)operator(,) ident(mixins)operator(()symbol(:list_3)operator(\))operator(.)ident(pos) + ident(assert_equal) integer(2)operator(,) ident(mixins)operator(()symbol(:list_4)operator(\))operator(.)ident(pos) + + reserved(end) + + reserved(def) method(test_with_string_based_scope) + ident(new) operator(=) constant(ListWithStringScopeMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(500)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new)operator(.)ident(pos) + ident(assert) ident(new)operator(.)ident(first?) + ident(assert) ident(new)operator(.)ident(last?) + reserved(end) + + reserved(def) method(test_nil_scope) + ident(new1)operator(,) ident(new2)operator(,) ident(new3) operator(=) constant(ListMixin)operator(.)ident(create)operator(,) constant(ListMixin)operator(.)ident(create)operator(,) constant(ListMixin)operator(.)ident(create) + ident(new2)operator(.)ident(move_higher) + ident(assert_equal) operator([)ident(new2)operator(,) ident(new1)operator(,) ident(new3)operator(])operator(,) constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id IS NULL)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + reserved(end) + +reserved(end) + +reserved(class) class(TreeTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:mixins) + + reserved(def) method(test_has_child) + ident(assert_equal) pre_constant(true)operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(has_children?) + ident(assert_equal) pre_constant(true)operator(,) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(has_children?) + ident(assert_equal) pre_constant(false)operator(,) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(has_children?) + ident(assert_equal) pre_constant(false)operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(has_children?) + reserved(end) + + reserved(def) method(test_children) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(children)operator(,) operator([)ident(mixins)operator(()symbol(:tree_2)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(]) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(children)operator(,) operator([)ident(mixins)operator(()symbol(:tree_3)operator(\))operator(]) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(children)operator(,) operator([)operator(]) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(children)operator(,) operator([)operator(]) + reserved(end) + + reserved(def) method(test_has_parent) + ident(assert_equal) pre_constant(false)operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(has_parent?) + ident(assert_equal) pre_constant(true)operator(,) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(has_parent?) + ident(assert_equal) pre_constant(true)operator(,) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(has_parent?) + ident(assert_equal) pre_constant(true)operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(has_parent?) + reserved(end) + + reserved(def) method(test_parent) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(parent)operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\)) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(parent)operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(parent) + ident(assert_nil) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(parent) + reserved(end) + + reserved(def) method(test_delete) + ident(assert_equal) integer(6)operator(,) constant(TreeMixin)operator(.)ident(count) + ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(destroy) + ident(assert_equal) integer(2)operator(,) constant(TreeMixin)operator(.)ident(count) + ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(.)ident(destroy) + ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(.)ident(destroy) + ident(assert_equal) integer(0)operator(,) constant(TreeMixin)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_insert) + instance_variable(@extra) operator(=) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(children)operator(.)ident(create) + + ident(assert) instance_variable(@extra) + + ident(assert_equal) instance_variable(@extra)operator(.)ident(parent)operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\)) + + ident(assert_equal) integer(3)operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(children)operator(.)ident(size) + ident(assert) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(children)operator(.)ident(include?)operator(()instance_variable(@extra)operator(\)) + ident(assert) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(children)operator(.)ident(include?)operator(()ident(mixins)operator(()symbol(:tree_2)operator(\))operator(\)) + ident(assert) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(children)operator(.)ident(include?)operator(()ident(mixins)operator(()symbol(:tree_4)operator(\))operator(\)) + reserved(end) + + reserved(def) method(test_ancestors) + ident(assert_equal) operator([)operator(])operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(ancestors) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(ancestors) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_2)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(ancestors) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(ancestors) + ident(assert_equal) operator([)operator(])operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(.)ident(ancestors) + ident(assert_equal) operator([)operator(])operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(.)ident(ancestors) + reserved(end) + + reserved(def) method(test_root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) constant(TreeMixin)operator(.)ident(root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(.)ident(root) + ident(assert_equal) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(.)ident(root) + reserved(end) + + reserved(def) method(test_roots) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) constant(TreeMixin)operator(.)ident(roots) + reserved(end) + + reserved(def) method(test_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_4)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(siblings) + ident(assert_equal) operator([)operator(])operator(,) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_2)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(.)ident(siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(.)ident(siblings) + reserved(end) + + reserved(def) method(test_self_and_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(self_and_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_2)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_2)operator(\))operator(.)ident(self_and_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_3)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_3)operator(\))operator(.)ident(self_and_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_2)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree_4)operator(\))operator(.)ident(self_and_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(.)ident(self_and_siblings) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:tree_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree2_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(])operator(,) ident(mixins)operator(()symbol(:tree3_1)operator(\))operator(.)ident(self_and_siblings) + reserved(end) +reserved(end) + +reserved(class) class(TreeTestWithoutOrder) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:mixins) + + reserved(def) method(test_root) + ident(assert) operator([)ident(mixins)operator(()symbol(:tree_without_order_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_without_order_2)operator(\))operator(])operator(.)ident(include?)operator(()constant(TreeMixinWithoutOrder)operator(.)ident(root)operator(\)) + reserved(end) + + reserved(def) method(test_roots) + ident(assert_equal) operator([)operator(])operator(,) operator([)ident(mixins)operator(()symbol(:tree_without_order_1)operator(\))operator(,) ident(mixins)operator(()symbol(:tree_without_order_2)operator(\))operator(]) operator(-) constant(TreeMixinWithoutOrder)operator(.)ident(roots) + reserved(end) +reserved(end) + +reserved(class) class(TouchTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:mixins) + + reserved(def) method(test_update) + ident(stamped) operator(=) constant(Mixin)operator(.)ident(new) + + ident(assert_nil) ident(stamped)operator(.)ident(updated_at) + ident(assert_nil) ident(stamped)operator(.)ident(created_at) + ident(stamped)operator(.)ident(save) + ident(assert_not_nil) ident(stamped)operator(.)ident(updated_at) + ident(assert_not_nil) ident(stamped)operator(.)ident(created_at) + reserved(end) + + reserved(def) method(test_create) + instance_variable(@obj) operator(=) constant(Mixin)operator(.)ident(create) + ident(assert_not_nil) instance_variable(@obj)operator(.)ident(updated_at) + ident(assert_not_nil) instance_variable(@obj)operator(.)ident(created_at) + reserved(end) + + reserved(def) method(test_many_updates) + ident(stamped) operator(=) constant(Mixin)operator(.)ident(new) + + ident(assert_nil) ident(stamped)operator(.)ident(updated_at) + ident(assert_nil) ident(stamped)operator(.)ident(created_at) + ident(stamped)operator(.)ident(save) + ident(assert_not_nil) ident(stamped)operator(.)ident(created_at) + ident(assert_not_nil) ident(stamped)operator(.)ident(updated_at) + + ident(old_updated_at) operator(=) ident(stamped)operator(.)ident(updated_at) + + ident(sleep) integer(1) + ident(stamped)operator(.)ident(save) + ident(assert_not_equal) ident(stamped)operator(.)ident(created_at)operator(,) ident(stamped)operator(.)ident(updated_at) + ident(assert_not_equal) ident(old_updated_at)operator(,) ident(stamped)operator(.)ident(updated_at) + + reserved(end) + + reserved(def) method(test_create_turned_off) + constant(Mixin)operator(.)ident(record_timestamps) operator(=) pre_constant(false) + + ident(assert_nil) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(updated_at) + ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(save) + ident(assert_nil) ident(mixins)operator(()symbol(:tree_1)operator(\))operator(.)ident(updated_at) + + constant(Mixin)operator(.)ident(record_timestamps) operator(=) pre_constant(true) + reserved(end) + +reserved(end) + + +reserved(class) class(ListSubTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:mixins) + + reserved(def) method(test_reordering) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(.)ident(move_lower) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(.)ident(move_higher) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(.)ident(move_to_bottom) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(.)ident(move_to_top) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(.)ident(move_to_bottom) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(.)ident(move_to_top) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + reserved(end) + + reserved(def) method(test_move_to_bottom_with_next_to_last_item) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(.)ident(move_to_bottom) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(test_next_prev) + ident(assert_equal) ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(.)ident(lower_item) + ident(assert_nil) ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(.)ident(higher_item) + ident(assert_equal) ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(.)ident(higher_item) + ident(assert_nil) ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(.)ident(lower_item) + reserved(end) + + + reserved(def) method(test_injection) + ident(item) operator(=) constant(ListMixin)operator(.)ident(new)operator(()string<delimiter(")content(parent_id)delimiter(")>operator(=)operator(>)integer(1)operator(\)) + ident(assert_equal) string<delimiter(")content(parent_id = 1)delimiter(")>operator(,) ident(item)operator(.)ident(scope_condition) + ident(assert_equal) string<delimiter(")content(pos)delimiter(")>operator(,) ident(item)operator(.)ident(position_column) + reserved(end) + + + reserved(def) method(test_insert_at) + ident(new) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new)operator(.)ident(pos) + + ident(new) operator(=) constant(ListMixinSub1)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(new)operator(.)ident(pos) + + ident(new) operator(=) constant(ListMixinSub2)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(new)operator(.)ident(pos) + + ident(new4) operator(=) constant(ListMixin)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(4)operator(,) ident(new4)operator(.)ident(pos) + + ident(new4)operator(.)ident(insert_at)operator(()integer(3)operator(\)) + ident(assert_equal) integer(3)operator(,) ident(new4)operator(.)ident(pos) + + ident(new)operator(.)ident(reload) + ident(assert_equal) integer(4)operator(,) ident(new)operator(.)ident(pos) + + ident(new)operator(.)ident(insert_at)operator(()integer(2)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(new)operator(.)ident(pos) + + ident(new4)operator(.)ident(reload) + ident(assert_equal) integer(4)operator(,) ident(new4)operator(.)ident(pos) + + ident(new5) operator(=) constant(ListMixinSub1)operator(.)ident(create)operator(()string<delimiter(")content(parent_id)delimiter(")> operator(=)operator(>) integer(20)operator(\)) + ident(assert_equal) integer(5)operator(,) ident(new5)operator(.)ident(pos) + + ident(new5)operator(.)ident(insert_at)operator(()integer(1)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(new5)operator(.)ident(pos) + + ident(new4)operator(.)ident(reload) + ident(assert_equal) integer(5)operator(,) ident(new4)operator(.)ident(pos) + reserved(end) + + reserved(def) method(test_delete_middle) + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(mixins)operator(()symbol(:list_sub_2)operator(\))operator(.)ident(destroy) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_1)operator(,) symbol(:reload)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_3)operator(,) symbol(:reload)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(,) symbol(:reload)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(assert_equal) integer(1)operator(,) ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(.)ident(pos) + ident(assert_equal) integer(2)operator(,) ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(.)ident(pos) + ident(assert_equal) integer(3)operator(,) ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(.)ident(pos) + + ident(mixins)operator(()symbol(:list_sub_1)operator(\))operator(.)ident(destroy) + + ident(assert_equal) operator([)ident(mixins)operator(()symbol(:list_sub_3)operator(,) symbol(:reload)operator(\))operator(,) + ident(mixins)operator(()symbol(:list_sub_4)operator(,) symbol(:reload)operator(\))operator(])operator(,) + constant(ListMixin)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(parent_id = 5000)delimiter(')>operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(pos)delimiter(')>operator(\)) + + ident(assert_equal) integer(1)operator(,) ident(mixins)operator(()symbol(:list_sub_3)operator(\))operator(.)ident(pos) + ident(assert_equal) integer(2)operator(,) ident(mixins)operator(()symbol(:list_sub_4)operator(\))operator(.)ident(pos) + + reserved(end) + +reserved(end) + +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company_in_module)delimiter(')> + +reserved(class) class(ModulesTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:accounts)operator(,) symbol(:companies)operator(,) symbol(:projects)operator(,) symbol(:developers) + + reserved(def) method(test_module_spanning_associations) + ident(assert) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\))operator(.)ident(has_clients?)operator(,) string<delimiter(")content(Firm should have clients)delimiter(")> + ident(firm) operator(=) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Firm)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(assert_nil) ident(firm)operator(.)ident(class)operator(.)ident(table_name)operator(.)ident(match)operator(()string<delimiter(')content(::)delimiter(')>operator(\))operator(,) string<delimiter(")content(Firm shouldn't have the module appear in its table name)delimiter(")> + ident(assert_equal) integer(2)operator(,) ident(firm)operator(.)ident(clients_count)operator(,) string<delimiter(")content(Firm should have two clients)delimiter(")> + reserved(end) + + reserved(def) method(test_module_spanning_has_and_belongs_to_many_associations) + ident(project) operator(=) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Project)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(project)operator(.)ident(developers) operator(<<) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Developer)operator(.)ident(create)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(John)delimiter(")>operator(\)) + ident(assert) string<delimiter(")content(John)delimiter(")>operator(,) ident(project)operator(.)ident(developers)operator(.)ident(last)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_associations_spanning_cross_modules) + ident(account) operator(=) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Account)operator(.)ident(find)operator(()symbol(:first)operator(,) symbol(:order) operator(=)operator(>) string<delimiter(')content(id)delimiter(')>operator(\)) + ident(assert_kind_of) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Firm)operator(,) ident(account)operator(.)ident(firm) + ident(assert_kind_of) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Firm)operator(,) ident(account)operator(.)ident(qualified_billing_firm) + ident(assert_kind_of) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Firm)operator(,) ident(account)operator(.)ident(unqualified_billing_firm) + ident(assert_kind_of) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Nested)operator(::)constant(Firm)operator(,) ident(account)operator(.)ident(nested_qualified_billing_firm) + ident(assert_kind_of) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Nested)operator(::)constant(Firm)operator(,) ident(account)operator(.)ident(nested_unqualified_billing_firm) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/entrant)delimiter(')> + +comment(# So we can test whether Course.connection survives a reload.) +ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> + +reserved(class) class(MultipleDbTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + reserved(def) method(setup) + instance_variable(@courses) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(courses)delimiter(")>operator(\)) operator({) constant(Course)operator(.)ident(retrieve_connection) operator(}) + instance_variable(@entrants) operator(=) ident(create_fixtures)operator(()string<delimiter(")content(entrants)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(test_connected) + ident(assert_not_nil) constant(Entrant)operator(.)ident(connection) + ident(assert_not_nil) constant(Course)operator(.)ident(connection) + reserved(end) + + reserved(def) method(test_proper_connection) + ident(assert_not_equal)operator(()constant(Entrant)operator(.)ident(connection)operator(,) constant(Course)operator(.)ident(connection)operator(\)) + ident(assert_equal)operator(()constant(Entrant)operator(.)ident(connection)operator(,) constant(Entrant)operator(.)ident(retrieve_connection)operator(\)) + ident(assert_equal)operator(()constant(Course)operator(.)ident(connection)operator(,) constant(Course)operator(.)ident(retrieve_connection)operator(\)) + ident(assert_equal)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) constant(Entrant)operator(.)ident(connection)operator(\)) + reserved(end) + + reserved(def) method(test_find) + ident(c1) operator(=) constant(Course)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) string<delimiter(")content(Ruby Development)delimiter(")>operator(,) ident(c1)operator(.)ident(name) + ident(c2) operator(=) constant(Course)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal) string<delimiter(")content(Java Development)delimiter(")>operator(,) ident(c2)operator(.)ident(name) + ident(e1) operator(=) constant(Entrant)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) string<delimiter(")content(Ruby Developer)delimiter(")>operator(,) ident(e1)operator(.)ident(name) + ident(e2) operator(=) constant(Entrant)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal) string<delimiter(")content(Ruby Guru)delimiter(")>operator(,) ident(e2)operator(.)ident(name) + ident(e3) operator(=) constant(Entrant)operator(.)ident(find)operator(()integer(3)operator(\)) + ident(assert_equal) string<delimiter(")content(Java Lover)delimiter(")>operator(,) ident(e3)operator(.)ident(name) + reserved(end) + + reserved(def) method(test_associations) + ident(c1) operator(=) constant(Course)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) integer(2)operator(,) ident(c1)operator(.)ident(entrants_count) + ident(e1) operator(=) constant(Entrant)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(e1)operator(.)ident(course)operator(.)ident(id)operator(,) ident(c1)operator(.)ident(id) + ident(c2) operator(=) constant(Course)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(c2)operator(.)ident(entrants_count) + ident(e3) operator(=) constant(Entrant)operator(.)ident(find)operator(()integer(3)operator(\)) + ident(assert_equal) ident(e3)operator(.)ident(course)operator(.)ident(id)operator(,) ident(c2)operator(.)ident(id) + reserved(end) + + reserved(def) method(test_course_connection_should_survive_dependency_reload) + ident(assert) constant(Course)operator(.)ident(connection) + + constant(Dependencies)operator(.)ident(clear) + constant(Object)operator(.)ident(send)operator(()symbol(:remove_const)operator(,) symbol(:Course)operator(\)) + ident(require_dependency) string<delimiter(')content(fixtures/course)delimiter(')> + + ident(assert) constant(Course)operator(.)ident(connection) + reserved(end) +reserved(end) +ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/abstract_unit)delimiter(")> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/subscriber)delimiter(')> +ident(require) string<delimiter(')content(fixtures/movie)delimiter(')> +ident(require) string<delimiter(')content(fixtures/keyboard)delimiter(')> + +reserved(class) class(PrimaryKeysTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:subscribers)operator(,) symbol(:movies) + + reserved(def) method(test_integer_key) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:first)operator(\))operator(.)ident(author_name)operator(,) ident(topic)operator(.)ident(author_name)operator(\)) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\)) + ident(assert_equal)operator(()ident(topics)operator(()symbol(:second)operator(\))operator(.)ident(author_name)operator(,) ident(topic)operator(.)ident(author_name)operator(\)) + + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(topic)operator(.)ident(title) operator(=) string<delimiter(")content(New Topic)delimiter(")> + ident(assert_equal)operator(()pre_constant(nil)operator(,) ident(topic)operator(.)ident(id)operator(\)) + ident(assert_nothing_raised) operator({) ident(topic)operator(.)ident(save!) operator(}) + ident(id) operator(=) ident(topic)operator(.)ident(id) + + ident(topicReloaded) operator(=) constant(Topic)operator(.)ident(find)operator(()ident(id)operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(New Topic)delimiter(")>operator(,) ident(topicReloaded)operator(.)ident(title)operator(\)) + reserved(end) + + reserved(def) method(test_customized_primary_key_auto_assigns_on_save) + constant(Keyboard)operator(.)ident(delete_all) + ident(keyboard) operator(=) constant(Keyboard)operator(.)ident(new)operator(()symbol(:name) operator(=)operator(>) string<delimiter(')content(HHKB)delimiter(')>operator(\)) + ident(assert_nothing_raised) operator({) ident(keyboard)operator(.)ident(save!) operator(}) + ident(assert_equal) ident(keyboard)operator(.)ident(id)operator(,) constant(Keyboard)operator(.)ident(find_by_name)operator(()string<delimiter(')content(HHKB)delimiter(')>operator(\))operator(.)ident(id) + reserved(end) + + reserved(def) method(test_customized_primary_key_can_be_get_before_saving) + ident(keyboard) operator(=) constant(Keyboard)operator(.)ident(new) + ident(assert_nil) ident(keyboard)operator(.)ident(id) + ident(assert_nothing_raised) operator({) ident(assert_nil) ident(keyboard)operator(.)ident(key_number) operator(}) + reserved(end) + + reserved(def) method(test_customized_string_primary_key_settable_before_save) + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(new) + ident(assert_nothing_raised) operator({) ident(subscriber)operator(.)ident(id) operator(=) string<delimiter(')content(webster123)delimiter(')> operator(}) + ident(assert_equal) string<delimiter(')content(webster123)delimiter(')>operator(,) ident(subscriber)operator(.)ident(id) + ident(assert_equal) string<delimiter(')content(webster123)delimiter(')>operator(,) ident(subscriber)operator(.)ident(nick) + reserved(end) + + reserved(def) method(test_string_key) + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(find)operator(()ident(subscribers)operator(()symbol(:first)operator(\))operator(.)ident(nick)operator(\)) + ident(assert_equal)operator(()ident(subscribers)operator(()symbol(:first)operator(\))operator(.)ident(name)operator(,) ident(subscriber)operator(.)ident(name)operator(\)) + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(find)operator(()ident(subscribers)operator(()symbol(:second)operator(\))operator(.)ident(nick)operator(\)) + ident(assert_equal)operator(()ident(subscribers)operator(()symbol(:second)operator(\))operator(.)ident(name)operator(,) ident(subscriber)operator(.)ident(name)operator(\)) + + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(new) + ident(subscriber)operator(.)ident(id) operator(=) string<delimiter(")content(jdoe)delimiter(")> + ident(assert_equal)operator(()string<delimiter(")content(jdoe)delimiter(")>operator(,) ident(subscriber)operator(.)ident(id)operator(\)) + ident(subscriber)operator(.)ident(name) operator(=) string<delimiter(")content(John Doe)delimiter(")> + ident(assert_nothing_raised) operator({) ident(subscriber)operator(.)ident(save!) operator(}) + ident(assert_equal)operator(()string<delimiter(")content(jdoe)delimiter(")>operator(,) ident(subscriber)operator(.)ident(id)operator(\)) + + ident(subscriberReloaded) operator(=) constant(Subscriber)operator(.)ident(find)operator(()string<delimiter(")content(jdoe)delimiter(")>operator(\)) + ident(assert_equal)operator(()string<delimiter(")content(John Doe)delimiter(")>operator(,) ident(subscriberReloaded)operator(.)ident(name)operator(\)) + reserved(end) + + reserved(def) method(test_find_with_more_than_one_string_key) + ident(assert_equal) integer(2)operator(,) constant(Subscriber)operator(.)ident(find)operator(()ident(subscribers)operator(()symbol(:first)operator(\))operator(.)ident(nick)operator(,) ident(subscribers)operator(()symbol(:second)operator(\))operator(.)ident(nick)operator(\))operator(.)ident(length) + reserved(end) + + reserved(def) method(test_primary_key_prefix) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(primary_key_prefix_type) operator(=) symbol(:table_name) + constant(Topic)operator(.)ident(reset_primary_key) + ident(assert_equal) string<delimiter(")content(topicid)delimiter(")>operator(,) constant(Topic)operator(.)ident(primary_key) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(primary_key_prefix_type) operator(=) symbol(:table_name_with_underscore) + constant(Topic)operator(.)ident(reset_primary_key) + ident(assert_equal) string<delimiter(")content(topic_id)delimiter(")>operator(,) constant(Topic)operator(.)ident(primary_key) + + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(primary_key_prefix_type) operator(=) pre_constant(nil) + constant(Topic)operator(.)ident(reset_primary_key) + ident(assert_equal) string<delimiter(")content(id)delimiter(")>operator(,) constant(Topic)operator(.)ident(primary_key) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/post)delimiter(')> +ident(require) string<delimiter(')content(fixtures/comment)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/project)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reader)delimiter(')> +ident(require) string<delimiter(')content(fixtures/person)delimiter(')> + +comment(# Dummy class methods to test implicit association scoping.) +reserved(def) constant(Comment)operator(.)ident(foo)operator(()operator(\)) ident(find) symbol(:first) reserved(end) +reserved(def) constant(Project)operator(.)ident(foo)operator(()operator(\)) ident(find) symbol(:first) reserved(end) + + +reserved(class) class(ReadOnlyTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:posts)operator(,) symbol(:comments)operator(,) symbol(:developers)operator(,) symbol(:projects)operator(,) symbol(:developers_projects) + + reserved(def) method(test_cant_save_readonly_record) + ident(dev) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(dev)operator(.)ident(readonly?) + + ident(dev)operator(.)ident(readonly!) + ident(assert) ident(dev)operator(.)ident(readonly?) + + ident(assert_nothing_raised) reserved(do) + ident(dev)operator(.)ident(name) operator(=) string<delimiter(')content(Luscious forbidden fruit.)delimiter(')> + ident(assert) operator(!)ident(dev)operator(.)ident(save) + ident(dev)operator(.)ident(name) operator(=) string<delimiter(')content(Forbidden.)delimiter(')> + reserved(end) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(ReadOnlyRecord)operator(\)) operator({) ident(dev)operator(.)ident(save) operator(}) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(ReadOnlyRecord)operator(\)) operator({) ident(dev)operator(.)ident(save!) operator(}) + reserved(end) + + + reserved(def) method(test_find_with_readonly_option) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) operator(!)ident(d)operator(.)ident(readonly?) operator(}) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) operator(!)ident(d)operator(.)ident(readonly?) operator(}) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) ident(d)operator(.)ident(readonly?) operator(}) + reserved(end) + + + reserved(def) method(test_find_with_joins_option_implies_readonly) + comment(# Blank joins don't count.) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:joins) operator(=)operator(>) string<delimiter(')content( )delimiter(')>operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) operator(!)ident(d)operator(.)ident(readonly?) operator(}) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:joins) operator(=)operator(>) string<delimiter(')content( )delimiter(')>operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) operator(!)ident(d)operator(.)ident(readonly?) operator(}) + + comment(# Others do.) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:joins) operator(=)operator(>) string<delimiter(')content(, projects)delimiter(')>operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) ident(d)operator(.)ident(readonly?) operator(}) + constant(Developer)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:joins) operator(=)operator(>) string<delimiter(')content(, projects)delimiter(')>operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(each) operator({) operator(|)ident(d)operator(|) ident(assert) operator(!)ident(d)operator(.)ident(readonly?) operator(}) + reserved(end) + + + reserved(def) method(test_habtm_find_readonly) + ident(dev) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(dev)operator(.)ident(projects)operator(.)ident(empty?) + ident(assert) ident(dev)operator(.)ident(projects)operator(.)ident(all?)operator(()operator(&)symbol(:readonly?)operator(\)) + ident(assert) ident(dev)operator(.)ident(projects)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(all?)operator(()operator(&)symbol(:readonly?)operator(\)) + ident(assert) ident(dev)operator(.)ident(projects)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(all?)operator(()operator(&)symbol(:readonly?)operator(\)) + reserved(end) + + reserved(def) method(test_has_many_find_readonly) + ident(post) operator(=) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert) operator(!)ident(post)operator(.)ident(comments)operator(.)ident(empty?) + ident(assert) operator(!)ident(post)operator(.)ident(comments)operator(.)ident(any?)operator(()operator(&)symbol(:readonly?)operator(\)) + ident(assert) operator(!)ident(post)operator(.)ident(comments)operator(.)ident(find)operator(()symbol(:all)operator(\))operator(.)ident(any?)operator(()operator(&)symbol(:readonly?)operator(\)) + ident(assert) ident(post)operator(.)ident(comments)operator(.)ident(find)operator(()symbol(:all)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(all?)operator(()operator(&)symbol(:readonly?)operator(\)) + reserved(end) + + reserved(def) method(test_has_many_with_through_is_not_implicitly_marked_readonly) + ident(assert) ident(people) operator(=) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(people) + ident(assert) operator(!)ident(people)operator(.)ident(any?)operator(()operator(&)symbol(:readonly?)operator(\)) + reserved(end) + + reserved(def) method(test_readonly_scoping) + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:conditions) operator(=)operator(>) string<delimiter(')content(1=1)delimiter(')> operator(})operator(\)) reserved(do) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(readonly?) + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(readonly?) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(readonly?) + reserved(end) + + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:joins) operator(=)operator(>) string<delimiter(')content( )delimiter(')> operator(})operator(\)) reserved(do) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(readonly?) + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(readonly?) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(readonly?) + reserved(end) + + comment(# Oracle barfs on this because the join includes unqualified and) + comment(# conflicting column names) + reserved(unless) ident(current_adapter?)operator(()symbol(:OracleAdapter)operator(\)) + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:joins) operator(=)operator(>) string<delimiter(')content(, developers)delimiter(')> operator(})operator(\)) reserved(do) + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(readonly?) + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(readonly?) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(readonly?) + reserved(end) + reserved(end) + + constant(Post)operator(.)ident(with_scope)operator(()symbol(:find) operator(=)operator(>) operator({) symbol(:readonly) operator(=)operator(>) pre_constant(true) operator(})operator(\)) reserved(do) + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(readonly?) + ident(assert) constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(true)operator(\))operator(.)ident(readonly?) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(,) symbol(:readonly) operator(=)operator(>) pre_constant(false)operator(\))operator(.)ident(readonly?) + reserved(end) + reserved(end) + + reserved(def) method(test_association_collection_method_missing_scoping_not_readonly) + ident(assert) operator(!)constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(projects)operator(.)ident(foo)operator(.)ident(readonly?) + ident(assert) operator(!)constant(Post)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(comments)operator(.)ident(foo)operator(.)ident(readonly?) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/customer)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company)delimiter(')> +ident(require) string<delimiter(')content(fixtures/company_in_module)delimiter(')> +ident(require) string<delimiter(')content(fixtures/subscriber)delimiter(')> + +reserved(class) class(ReflectionTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:customers)operator(,) symbol(:companies)operator(,) symbol(:subscribers) + + reserved(def) method(setup) + instance_variable(@first) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\)) + reserved(end) + + reserved(def) method(test_column_null_not_null) + ident(subscriber) operator(=) constant(Subscriber)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(assert) ident(subscriber)operator(.)ident(column_for_attribute)operator(()string<delimiter(")content(name)delimiter(")>operator(\))operator(.)ident(null) + ident(assert) operator(!)ident(subscriber)operator(.)ident(column_for_attribute)operator(()string<delimiter(")content(nick)delimiter(")>operator(\))operator(.)ident(null) + reserved(end) + + reserved(def) method(test_read_attribute_names) + ident(assert_equal)operator(() + string<delimiter(%w()content( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id type )delimiter(\))>operator(.)ident(sort)operator(,) + instance_variable(@first)operator(.)ident(attribute_names) + operator(\)) + reserved(end) + + reserved(def) method(test_columns) + ident(assert_equal) integer(12)operator(,) constant(Topic)operator(.)ident(columns)operator(.)ident(length) + reserved(end) + + reserved(def) method(test_columns_are_returned_in_the_order_they_were_declared) + ident(column_names) operator(=) constant(Topic)operator(.)ident(columns)operator(.)ident(map) operator({) operator(|)ident(column)operator(|) ident(column)operator(.)ident(name) operator(}) + ident(assert_equal) string<delimiter(%w()content(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id type)delimiter(\))>operator(,) ident(column_names) + reserved(end) + + reserved(def) method(test_content_columns) + ident(content_columns) operator(=) constant(Topic)operator(.)ident(content_columns) + ident(content_column_names) operator(=) ident(content_columns)operator(.)ident(map) operator({)operator(|)ident(column)operator(|) ident(column)operator(.)ident(name)operator(}) + ident(assert_equal) integer(8)operator(,) ident(content_columns)operator(.)ident(length) + ident(assert_equal) string<delimiter(%w()content(title author_name author_email_address written_on bonus_time last_read content approved)delimiter(\))>operator(.)ident(sort)operator(,) ident(content_column_names)operator(.)ident(sort) + reserved(end) + + reserved(def) method(test_column_string_type_and_limit) + ident(assert_equal) symbol(:string)operator(,) instance_variable(@first)operator(.)ident(column_for_attribute)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(.)ident(type) + ident(assert_equal) integer(255)operator(,) instance_variable(@first)operator(.)ident(column_for_attribute)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(.)ident(limit) + reserved(end) + + reserved(def) method(test_human_name_for_column) + ident(assert_equal) string<delimiter(")content(Author name)delimiter(")>operator(,) instance_variable(@first)operator(.)ident(column_for_attribute)operator(()string<delimiter(")content(author_name)delimiter(")>operator(\))operator(.)ident(human_name) + reserved(end) + + reserved(def) method(test_integer_columns) + ident(assert_equal) symbol(:integer)operator(,) instance_variable(@first)operator(.)ident(column_for_attribute)operator(()string<delimiter(")content(id)delimiter(")>operator(\))operator(.)ident(type) + reserved(end) + + reserved(def) method(test_aggregation_reflection) + ident(reflection_for_address) operator(=) constant(ActiveRecord)operator(::)constant(Reflection)operator(::)constant(AggregateReflection)operator(.)ident(new)operator(() + symbol(:composed_of)operator(,) symbol(:address)operator(,) operator({) symbol(:mapping) operator(=)operator(>) operator([) string<delimiter(%w()content(address_street street)delimiter(\))>operator(,) string<delimiter(%w()content(address_city city)delimiter(\))>operator(,) string<delimiter(%w()content(address_country country)delimiter(\))> operator(]) operator(})operator(,) constant(Customer) + operator(\)) + + ident(reflection_for_balance) operator(=) constant(ActiveRecord)operator(::)constant(Reflection)operator(::)constant(AggregateReflection)operator(.)ident(new)operator(() + symbol(:composed_of)operator(,) symbol(:balance)operator(,) operator({) symbol(:class_name) operator(=)operator(>) string<delimiter(")content(Money)delimiter(")>operator(,) symbol(:mapping) operator(=)operator(>) string<delimiter(%w()content(balance amount)delimiter(\))> operator(})operator(,) constant(Customer) + operator(\)) + + ident(reflection_for_gps_location) operator(=) constant(ActiveRecord)operator(::)constant(Reflection)operator(::)constant(AggregateReflection)operator(.)ident(new)operator(() + symbol(:composed_of)operator(,) symbol(:gps_location)operator(,) operator({) operator(})operator(,) constant(Customer) + operator(\)) + + ident(assert) constant(Customer)operator(.)ident(reflect_on_all_aggregations)operator(.)ident(include?)operator(()ident(reflection_for_gps_location)operator(\)) + ident(assert) constant(Customer)operator(.)ident(reflect_on_all_aggregations)operator(.)ident(include?)operator(()ident(reflection_for_balance)operator(\)) + ident(assert) constant(Customer)operator(.)ident(reflect_on_all_aggregations)operator(.)ident(include?)operator(()ident(reflection_for_address)operator(\)) + + ident(assert_equal) ident(reflection_for_address)operator(,) constant(Customer)operator(.)ident(reflect_on_aggregation)operator(()symbol(:address)operator(\)) + + ident(assert_equal) constant(Address)operator(,) constant(Customer)operator(.)ident(reflect_on_aggregation)operator(()symbol(:address)operator(\))operator(.)ident(klass) + + ident(assert_equal) constant(Money)operator(,) constant(Customer)operator(.)ident(reflect_on_aggregation)operator(()symbol(:balance)operator(\))operator(.)ident(klass) + reserved(end) + + reserved(def) method(test_has_many_reflection) + ident(reflection_for_clients) operator(=) constant(ActiveRecord)operator(::)constant(Reflection)operator(::)constant(AssociationReflection)operator(.)ident(new)operator(()symbol(:has_many)operator(,) symbol(:clients)operator(,) operator({) symbol(:order) operator(=)operator(>) string<delimiter(")content(id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) operator(})operator(,) constant(Firm)operator(\)) + + ident(assert_equal) ident(reflection_for_clients)operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:clients)operator(\)) + + ident(assert_equal) constant(Client)operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:clients)operator(\))operator(.)ident(klass) + ident(assert_equal) string<delimiter(')content(companies)delimiter(')>operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:clients)operator(\))operator(.)ident(table_name) + + ident(assert_equal) constant(Client)operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:clients_of_firm)operator(\))operator(.)ident(klass) + ident(assert_equal) string<delimiter(')content(companies)delimiter(')>operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:clients_of_firm)operator(\))operator(.)ident(table_name) + reserved(end) + + reserved(def) method(test_has_one_reflection) + ident(reflection_for_account) operator(=) constant(ActiveRecord)operator(::)constant(Reflection)operator(::)constant(AssociationReflection)operator(.)ident(new)operator(()symbol(:has_one)operator(,) symbol(:account)operator(,) operator({) symbol(:foreign_key) operator(=)operator(>) string<delimiter(")content(firm_id)delimiter(")>operator(,) symbol(:dependent) operator(=)operator(>) symbol(:destroy) operator(})operator(,) constant(Firm)operator(\)) + ident(assert_equal) ident(reflection_for_account)operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:account)operator(\)) + + ident(assert_equal) constant(Account)operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:account)operator(\))operator(.)ident(klass) + ident(assert_equal) string<delimiter(')content(accounts)delimiter(')>operator(,) constant(Firm)operator(.)ident(reflect_on_association)operator(()symbol(:account)operator(\))operator(.)ident(table_name) + reserved(end) + + reserved(def) method(test_association_reflection_in_modules) + ident(assert_reflection) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Firm)operator(,) + symbol(:clients_of_firm)operator(,) + symbol(:klass) operator(=)operator(>) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Client)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Client)delimiter(')>operator(,) + symbol(:table_name) operator(=)operator(>) string<delimiter(')content(companies)delimiter(')> + + ident(assert_reflection) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Account)operator(,) + symbol(:firm)operator(,) + symbol(:klass) operator(=)operator(>) constant(MyApplication)operator(::)constant(Business)operator(::)constant(Firm)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(')content(MyApplication::Business::Firm)delimiter(')>operator(,) + symbol(:table_name) operator(=)operator(>) string<delimiter(')content(companies)delimiter(')> + + ident(assert_reflection) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Account)operator(,) + symbol(:qualified_billing_firm)operator(,) + symbol(:klass) operator(=)operator(>) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Firm)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(')content(MyApplication::Billing::Firm)delimiter(')>operator(,) + symbol(:table_name) operator(=)operator(>) string<delimiter(')content(companies)delimiter(')> + + ident(assert_reflection) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Account)operator(,) + symbol(:unqualified_billing_firm)operator(,) + symbol(:klass) operator(=)operator(>) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Firm)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Firm)delimiter(')>operator(,) + symbol(:table_name) operator(=)operator(>) string<delimiter(')content(companies)delimiter(')> + + ident(assert_reflection) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Account)operator(,) + symbol(:nested_qualified_billing_firm)operator(,) + symbol(:klass) operator(=)operator(>) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Nested)operator(::)constant(Firm)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(')content(MyApplication::Billing::Nested::Firm)delimiter(')>operator(,) + symbol(:table_name) operator(=)operator(>) string<delimiter(')content(companies)delimiter(')> + + ident(assert_reflection) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Account)operator(,) + symbol(:nested_unqualified_billing_firm)operator(,) + symbol(:klass) operator(=)operator(>) constant(MyApplication)operator(::)constant(Billing)operator(::)constant(Nested)operator(::)constant(Firm)operator(,) + symbol(:class_name) operator(=)operator(>) string<delimiter(')content(Nested::Firm)delimiter(')>operator(,) + symbol(:table_name) operator(=)operator(>) string<delimiter(')content(companies)delimiter(')> + reserved(end) + + reserved(def) method(test_reflection_of_all_associations) + ident(assert_equal) integer(13)operator(,) constant(Firm)operator(.)ident(reflect_on_all_associations)operator(.)ident(size) + ident(assert_equal) integer(11)operator(,) constant(Firm)operator(.)ident(reflect_on_all_associations)operator(()symbol(:has_many)operator(\))operator(.)ident(size) + ident(assert_equal) integer(2)operator(,) constant(Firm)operator(.)ident(reflect_on_all_associations)operator(()symbol(:has_one)operator(\))operator(.)ident(size) + ident(assert_equal) integer(0)operator(,) constant(Firm)operator(.)ident(reflect_on_all_associations)operator(()symbol(:belongs_to)operator(\))operator(.)ident(size) + reserved(end) + + ident(private) + reserved(def) method(assert_reflection)operator(()ident(klass)operator(,) ident(association)operator(,) ident(options)operator(\)) + ident(assert) ident(reflection) operator(=) ident(klass)operator(.)ident(reflect_on_association)operator(()ident(association)operator(\)) + ident(options)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(,) ident(value)operator(|) + ident(assert_equal)operator(()ident(value)operator(,) ident(reflection)operator(.)ident(send)operator(()ident(method)operator(\))operator(\)) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(")inline<inline_delimiter(#{)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))inline_delimiter(})>content(/../lib/active_record/schema_dumper)delimiter(")> +ident(require) string<delimiter(')content(stringio)delimiter(')> + +reserved(if) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(.)ident(respond_to?)operator(()symbol(:tables)operator(\)) + + reserved(class) class(SchemaDumperTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + reserved(def) method(test_schema_dump) + ident(stream) operator(=) constant(StringIO)operator(.)ident(new) + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(dump)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) ident(stream)operator(\)) + ident(output) operator(=) ident(stream)operator(.)ident(string) + + ident(assert_match) regexp<delimiter(%r{)content(create_table "accounts")delimiter(})>operator(,) ident(output) + ident(assert_match) regexp<delimiter(%r{)content(create_table "authors")delimiter(})>operator(,) ident(output) + ident(assert_no_match) regexp<delimiter(%r{)content(create_table "schema_info")delimiter(})>operator(,) ident(output) + reserved(end) + + reserved(def) method(test_schema_dump_includes_not_null_columns) + ident(stream) operator(=) constant(StringIO)operator(.)ident(new) + + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(ignore_tables) operator(=) operator([)regexp<delimiter(/)content(^[^s])delimiter(/)>operator(]) + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(dump)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) ident(stream)operator(\)) + ident(output) operator(=) ident(stream)operator(.)ident(string) + ident(assert_match) regexp<delimiter(%r{)content(:null => false)delimiter(})>operator(,) ident(output) + reserved(end) + + reserved(def) method(test_schema_dump_with_string_ignored_table) + ident(stream) operator(=) constant(StringIO)operator(.)ident(new) + + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(ignore_tables) operator(=) operator([)string<delimiter(')content(accounts)delimiter(')>operator(]) + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(dump)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) ident(stream)operator(\)) + ident(output) operator(=) ident(stream)operator(.)ident(string) + ident(assert_no_match) regexp<delimiter(%r{)content(create_table "accounts")delimiter(})>operator(,) ident(output) + ident(assert_match) regexp<delimiter(%r{)content(create_table "authors")delimiter(})>operator(,) ident(output) + ident(assert_no_match) regexp<delimiter(%r{)content(create_table "schema_info")delimiter(})>operator(,) ident(output) + reserved(end) + + + reserved(def) method(test_schema_dump_with_regexp_ignored_table) + ident(stream) operator(=) constant(StringIO)operator(.)ident(new) + + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(ignore_tables) operator(=) operator([)regexp<delimiter(/)content(^account)delimiter(/)>operator(]) + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(dump)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) ident(stream)operator(\)) + ident(output) operator(=) ident(stream)operator(.)ident(string) + ident(assert_no_match) regexp<delimiter(%r{)content(create_table "accounts")delimiter(})>operator(,) ident(output) + ident(assert_match) regexp<delimiter(%r{)content(create_table "authors")delimiter(})>operator(,) ident(output) + ident(assert_no_match) regexp<delimiter(%r{)content(create_table "schema_info")delimiter(})>operator(,) ident(output) + reserved(end) + + + reserved(def) method(test_schema_dump_illegal_ignored_table_value) + ident(stream) operator(=) constant(StringIO)operator(.)ident(new) + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(ignore_tables) operator(=) operator([)integer(5)operator(]) + ident(assert_raise)operator(()constant(StandardError)operator(\)) reserved(do) + constant(ActiveRecord)operator(::)constant(SchemaDumper)operator(.)ident(dump)operator(()constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection)operator(,) ident(stream)operator(\)) + reserved(end) + reserved(end) + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(SchemaTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + constant(SCHEMA_NAME) operator(=) string<delimiter(')content(test_schema)delimiter(')> + constant(TABLE_NAME) operator(=) string<delimiter(')content(things)delimiter(')> + constant(COLUMNS) operator(=) operator([) + string<delimiter(')content(id integer)delimiter(')>operator(,) + string<delimiter(')content(name character varying(50\))delimiter(')>operator(,) + string<delimiter(')content(moment timestamp without time zone default now(\))delimiter(')> + operator(]) + + reserved(def) method(setup) + instance_variable(@connection) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + instance_variable(@connection)operator(.)ident(execute) string<delimiter(")content(CREATE SCHEMA )inline<inline_delimiter(#{)constant(SCHEMA_NAME)inline_delimiter(})>content( CREATE TABLE )inline<inline_delimiter(#{)constant(TABLE_NAME)inline_delimiter(})>content( ()inline<inline_delimiter(#{)constant(COLUMNS)operator(.)ident(join)operator(()string<delimiter(')content(,)delimiter(')>operator(\))inline_delimiter(})>content(\))delimiter(")> + reserved(end) + + reserved(def) method(teardown) + instance_variable(@connection)operator(.)ident(execute) string<delimiter(")content(DROP SCHEMA )inline<inline_delimiter(#{)constant(SCHEMA_NAME)inline_delimiter(})>content( CASCADE)delimiter(")> + reserved(end) + + reserved(def) method(test_with_schema_prefixed_table_name) + ident(assert_nothing_raised) reserved(do) + ident(assert_equal) constant(COLUMNS)operator(,) ident(columns)operator(()string<delimiter(")inline<inline_delimiter(#{)constant(SCHEMA_NAME)inline_delimiter(})>content(.)inline<inline_delimiter(#{)constant(TABLE_NAME)inline_delimiter(})>delimiter(")>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(test_with_schema_search_path) + ident(assert_nothing_raised) reserved(do) + ident(with_schema_search_path)operator(()constant(SCHEMA_NAME)operator(\)) reserved(do) + ident(assert_equal) constant(COLUMNS)operator(,) ident(columns)operator(()constant(TABLE_NAME)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(test_raise_on_unquoted_schema_name) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) reserved(do) + ident(with_schema_search_path) string<delimiter(')content($user,public)delimiter(')> + reserved(end) + reserved(end) + + reserved(def) method(test_without_schema_search_path) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(StatementInvalid)operator(\)) operator({) ident(columns)operator(()constant(TABLE_NAME)operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_ignore_nil_schema_search_path) + ident(assert_nothing_raised) operator({) ident(with_schema_search_path) pre_constant(nil) operator(}) + reserved(end) + + ident(private) + reserved(def) method(columns)operator(()ident(table_name)operator(\)) + instance_variable(@connection)operator(.)ident(send)operator(()symbol(:column_definitions)operator(,) ident(table_name)operator(\))operator(.)ident(map) reserved(do) operator(|)ident(name)operator(,) ident(type)operator(,) ident(default)operator(|) + string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(type)inline_delimiter(})>delimiter(")> operator(+) operator(()ident(default) operator(?) string<delimiter(")content( default )inline<inline_delimiter(#{)ident(default)inline_delimiter(})>delimiter(")> operator(:) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(with_schema_search_path)operator(()ident(schema_search_path)operator(\)) + instance_variable(@connection)operator(.)ident(schema_search_path) operator(=) ident(schema_search_path) + reserved(yield) reserved(if) ident(block_given?) + reserved(ensure) + instance_variable(@connection)operator(.)ident(schema_search_path) operator(=) string<delimiter(")content('$user', public)delimiter(")> + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/subject)delimiter(')> + +comment(# confirm that synonyms work just like tables; in this case) +comment(# the "subjects" table in Oracle (defined in oci.sql\) is just) +comment(# a synonym to the "topics" table) + +reserved(class) class(TestOracleSynonym) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + + reserved(def) method(test_oracle_synonym) + ident(topic) operator(=) constant(Topic)operator(.)ident(new) + ident(subject) operator(=) constant(Subject)operator(.)ident(new) + ident(assert_equal)operator(()ident(topic)operator(.)ident(attributes)operator(,) ident(subject)operator(.)ident(attributes)operator(\)) + reserved(end) + +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> + +reserved(class) class(ThreadedConnectionsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + ident(fixtures) symbol(:topics) + + reserved(def) method(setup) + instance_variable(@connection) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(remove_connection) + instance_variable(@connections) operator(=) operator([)operator(]) + instance_variable(@allow_concurrency) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(allow_concurrency) + reserved(end) + + reserved(def) method(teardown) + comment(# clear the connection cache) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(send)operator(()symbol(:clear_all_cached_connections!)operator(\)) + comment(# set allow_concurrency to saved value) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(allow_concurrency) operator(=) instance_variable(@allow_concurrency) + comment(# reestablish old connection) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(()instance_variable(@connection)operator(\)) + reserved(end) + + reserved(def) method(gather_connections)operator(()ident(use_threaded_connections)operator(\)) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(allow_concurrency) operator(=) ident(use_threaded_connections) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(()instance_variable(@connection)operator(\)) + + integer(5)operator(.)ident(times) reserved(do) + constant(Thread)operator(.)ident(new) reserved(do) + constant(Topic)operator(.)ident(find) symbol(:first) + instance_variable(@connections) operator(<<) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(active_connections)operator(.)ident(values)operator(.)ident(first) + reserved(end)operator(.)ident(join) + reserved(end) + reserved(end) + + reserved(def) method(test_threaded_connections) + ident(gather_connections)operator(()pre_constant(true)operator(\)) + ident(assert_equal) instance_variable(@connections)operator(.)ident(uniq)operator(.)ident(length)operator(,) integer(5) + reserved(end) + + reserved(def) method(test_unthreaded_connections) + ident(gather_connections)operator(()pre_constant(false)operator(\)) + ident(assert_equal) instance_variable(@connections)operator(.)ident(uniq)operator(.)ident(length)operator(,) integer(1) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> + +reserved(class) class(TransactionTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + ident(fixtures) symbol(:topics)operator(,) symbol(:developers) + + reserved(def) method(setup) + comment(# sqlite does not seem to return these in the right order, so we sort them) + comment(# explicitly for sqlite's sake. sqlite3 does fine.) + instance_variable(@first)operator(,) instance_variable(@second) operator(=) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(,) integer(2)operator(\))operator(.)ident(sort_by) operator({) operator(|)ident(t)operator(|) ident(t)operator(.)ident(id) operator(}) + reserved(end) + + reserved(def) method(test_successful) + constant(Topic)operator(.)ident(transaction) reserved(do) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@second)operator(.)ident(approved) operator(=) pre_constant(false) + instance_variable(@first)operator(.)ident(save) + instance_variable(@second)operator(.)ident(save) + reserved(end) + + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(First should have been approved)delimiter(")> + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should have been unapproved)delimiter(")> + reserved(end) + + reserved(def) method(transaction_with_return) + constant(Topic)operator(.)ident(transaction) reserved(do) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@second)operator(.)ident(approved) operator(=) pre_constant(false) + instance_variable(@first)operator(.)ident(save) + instance_variable(@second)operator(.)ident(save) + reserved(return) + reserved(end) + reserved(end) + + reserved(def) method(test_successful_with_return) + reserved(class) operator(<<) class(Topic)operator(.)ident(connection) + reserved(alias) symbol(:real_commit_db_transaction) symbol(:commit_db_transaction) + reserved(def) method(commit_db_transaction) + global_variable($committed) operator(=) pre_constant(true) + ident(real_commit_db_transaction) + reserved(end) + reserved(end) + + global_variable($committed) operator(=) pre_constant(false) + ident(transaction_with_return) + ident(assert) global_variable($committed) + + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(First should have been approved)delimiter(")> + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should have been unapproved)delimiter(")> + reserved(ensure) + reserved(class) operator(<<) class(Topic)operator(.)ident(connection) + reserved(alias) symbol(:commit_db_transaction) symbol(:real_commit_db_transaction) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(end) + + reserved(def) method(test_successful_with_instance_method) + instance_variable(@first)operator(.)ident(transaction) reserved(do) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@second)operator(.)ident(approved) operator(=) pre_constant(false) + instance_variable(@first)operator(.)ident(save) + instance_variable(@second)operator(.)ident(save) + reserved(end) + + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(First should have been approved)delimiter(")> + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should have been unapproved)delimiter(")> + reserved(end) + + reserved(def) method(test_failing_on_exception) + reserved(begin) + constant(Topic)operator(.)ident(transaction) reserved(do) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@second)operator(.)ident(approved) operator(=) pre_constant(false) + instance_variable(@first)operator(.)ident(save) + instance_variable(@second)operator(.)ident(save) + ident(raise) string<delimiter(")content(Bad things!)delimiter(")> + reserved(end) + reserved(rescue) + comment(# caught it) + reserved(end) + + ident(assert) instance_variable(@first)operator(.)ident(approved?)operator(,) string<delimiter(")content(First should still be changed in the objects)delimiter(")> + ident(assert) operator(!)instance_variable(@second)operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should still be changed in the objects)delimiter(")> + + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(First shouldn't have been approved)delimiter(")> + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should still be approved)delimiter(")> + reserved(end) + + reserved(def) method(test_failing_with_object_rollback) + ident(assert) operator(!)instance_variable(@first)operator(.)ident(approved?)operator(,) string<delimiter(")content(First should be unapproved initially)delimiter(")> + + reserved(begin) + constant(Topic)operator(.)ident(transaction)operator(()instance_variable(@first)operator(,) instance_variable(@second)operator(\)) reserved(do) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@second)operator(.)ident(approved) operator(=) pre_constant(false) + instance_variable(@first)operator(.)ident(save) + instance_variable(@second)operator(.)ident(save) + ident(raise) string<delimiter(")content(Bad things!)delimiter(")> + reserved(end) + reserved(rescue) + comment(# caught it) + reserved(end) + + ident(assert) operator(!)instance_variable(@first)operator(.)ident(approved?)operator(,) string<delimiter(")content(First shouldn't have been approved)delimiter(")> + ident(assert) instance_variable(@second)operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should still be approved)delimiter(")> + reserved(end) + + reserved(def) method(test_callback_rollback_in_save) + ident(add_exception_raising_after_save_callback_to_topic) + + reserved(begin) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@first)operator(.)ident(save) + ident(flunk) + reserved(rescue) operator(=)operator(>) ident(e) + ident(assert_equal) string<delimiter(")content(Make the transaction rollback)delimiter(")>operator(,) ident(e)operator(.)ident(message) + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?) + reserved(ensure) + ident(remove_exception_raising_after_save_callback_to_topic) + reserved(end) + reserved(end) + + reserved(def) method(test_nested_explicit_transactions) + constant(Topic)operator(.)ident(transaction) reserved(do) + constant(Topic)operator(.)ident(transaction) reserved(do) + instance_variable(@first)operator(.)ident(approved) operator(=) pre_constant(true) + instance_variable(@second)operator(.)ident(approved) operator(=) pre_constant(false) + instance_variable(@first)operator(.)ident(save) + instance_variable(@second)operator(.)ident(save) + reserved(end) + reserved(end) + + ident(assert) constant(Topic)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(First should have been approved)delimiter(")> + ident(assert) operator(!)constant(Topic)operator(.)ident(find)operator(()integer(2)operator(\))operator(.)ident(approved?)operator(,) string<delimiter(")content(Second should have been unapproved)delimiter(")> + reserved(end) + + comment(# This will cause transactions to overlap and fail unless they are) + comment(# performed on separate database connections.) + reserved(def) method(test_transaction_per_thread) + ident(assert_nothing_raised) reserved(do) + ident(threads) operator(=) operator(()integer(1)operator(..)integer(20)operator(\))operator(.)ident(map) reserved(do) + constant(Thread)operator(.)ident(new) reserved(do) + constant(Topic)operator(.)ident(transaction) reserved(do) + ident(topic) operator(=) constant(Topic)operator(.)ident(find)operator(()symbol(:first)operator(\)) + ident(topic)operator(.)ident(approved) operator(=) operator(!)ident(topic)operator(.)ident(approved?) + ident(topic)operator(.)ident(save!) + ident(topic)operator(.)ident(approved) operator(=) operator(!)ident(topic)operator(.)ident(approved?) + ident(topic)operator(.)ident(save!) + reserved(end) + reserved(end) + reserved(end) + + ident(threads)operator(.)ident(each) operator({) operator(|)ident(t)operator(|) ident(t)operator(.)ident(join) operator(}) + reserved(end) + reserved(end) + + comment(# Test for dirty reads among simultaneous transactions.) + reserved(def) method(test_transaction_isolation__read_committed) + comment(# Should be invariant.) + ident(original_salary) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(salary) + ident(temporary_salary) operator(=) integer(200000) + + ident(assert_nothing_raised) reserved(do) + ident(threads) operator(=) operator(()integer(1)operator(..)integer(20)operator(\))operator(.)ident(map) reserved(do) + constant(Thread)operator(.)ident(new) reserved(do) + constant(Developer)operator(.)ident(transaction) reserved(do) + comment(# Expect original salary.) + ident(dev) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(original_salary)operator(,) ident(dev)operator(.)ident(salary) + + ident(dev)operator(.)ident(salary) operator(=) ident(temporary_salary) + ident(dev)operator(.)ident(save!) + + comment(# Expect temporary salary.) + ident(dev) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(temporary_salary)operator(,) ident(dev)operator(.)ident(salary) + + ident(dev)operator(.)ident(salary) operator(=) ident(original_salary) + ident(dev)operator(.)ident(save!) + + comment(# Expect original salary.) + ident(dev) operator(=) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\)) + ident(assert_equal) ident(original_salary)operator(,) ident(dev)operator(.)ident(salary) + reserved(end) + reserved(end) + reserved(end) + + comment(# Keep our eyes peeled.) + ident(threads) operator(<<) constant(Thread)operator(.)ident(new) reserved(do) + integer(10)operator(.)ident(times) reserved(do) + ident(sleep) float(0.05) + constant(Developer)operator(.)ident(transaction) reserved(do) + comment(# Always expect original salary.) + ident(assert_equal) ident(original_salary)operator(,) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(salary) + reserved(end) + reserved(end) + reserved(end) + + ident(threads)operator(.)ident(each) operator({) operator(|)ident(t)operator(|) ident(t)operator(.)ident(join) operator(}) + reserved(end) + + ident(assert_equal) ident(original_salary)operator(,) constant(Developer)operator(.)ident(find)operator(()integer(1)operator(\))operator(.)ident(salary) + reserved(end) + + + ident(private) + reserved(def) method(add_exception_raising_after_save_callback_to_topic) + constant(Topic)operator(.)ident(class_eval) operator({) reserved(def) method(after_save)operator(()operator(\)) ident(raise) string<delimiter(")content(Make the transaction rollback)delimiter(")> reserved(end) operator(}) + reserved(end) + + reserved(def) method(remove_exception_raising_after_save_callback_to_topic) + constant(Topic)operator(.)ident(class_eval) operator({) ident(remove_method) symbol(:after_save) operator(}) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> + +reserved(class) class(TestRecord) operator(<) constant(ActiveRecord)operator(::)constant(Base) +reserved(end) + +reserved(class) class(TestUnconnectedAdaptor) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + pre_constant(self)operator(.)ident(use_transactional_fixtures) operator(=) pre_constant(false) + + reserved(def) method(setup) + instance_variable(@underlying) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(connection) + instance_variable(@specification) operator(=) constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(remove_connection) + reserved(end) + + reserved(def) method(teardown) + instance_variable(@underlying) operator(=) pre_constant(nil) + constant(ActiveRecord)operator(::)constant(Base)operator(.)ident(establish_connection)operator(()instance_variable(@specification)operator(\)) + reserved(end) + + reserved(def) method(test_connection_no_longer_established) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(ConnectionNotEstablished)operator(\)) reserved(do) + constant(TestRecord)operator(.)ident(find)operator(()integer(1)operator(\)) + reserved(end) + + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(ConnectionNotEstablished)operator(\)) reserved(do) + constant(TestRecord)operator(.)ident(new)operator(.)ident(save) + reserved(end) + reserved(end) + + reserved(def) method(test_underlying_adapter_no_longer_active) + ident(assert) operator(!)instance_variable(@underlying)operator(.)ident(active?)operator(,) string<delimiter(")content(Removed adapter should no longer be active)delimiter(")> + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(abstract_unit)delimiter(')> +ident(require) string<delimiter(')content(fixtures/topic)delimiter(')> +ident(require) string<delimiter(')content(fixtures/reply)delimiter(')> +ident(require) string<delimiter(')content(fixtures/developer)delimiter(')> + +comment(# The following methods in Topic are used in test_conditional_validation_*) +reserved(class) class(Topic) + reserved(def) method(condition_is_true) + reserved(return) pre_constant(true) + reserved(end) + + reserved(def) method(condition_is_true_but_its_not) + reserved(return) pre_constant(false) + reserved(end) +reserved(end) + +reserved(class) class(ValidationsTest) operator(<) constant(Test)operator(::)constant(Unit)operator(::)constant(TestCase) + ident(fixtures) symbol(:topics)operator(,) symbol(:developers) + + reserved(def) method(setup) + constant(Topic)operator(.)ident(write_inheritable_attribute)operator(()symbol(:validate)operator(,) pre_constant(nil)operator(\)) + constant(Topic)operator(.)ident(write_inheritable_attribute)operator(()symbol(:validate_on_create)operator(,) pre_constant(nil)operator(\)) + constant(Topic)operator(.)ident(write_inheritable_attribute)operator(()symbol(:validate_on_update)operator(,) pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(test_single_field_validation) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(title) operator(=) string<delimiter(")content(There's no content!)delimiter(")> + ident(assert) operator(!)ident(r)operator(.)ident(save)operator(,) string<delimiter(")content(A reply without content shouldn't be saveable)delimiter(")> + + ident(r)operator(.)ident(content) operator(=) string<delimiter(")content(Messa content!)delimiter(")> + ident(assert) ident(r)operator(.)ident(save)operator(,) string<delimiter(")content(A reply with content should be saveable)delimiter(")> + reserved(end) + + reserved(def) method(test_single_attr_validation_and_error_msg) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(title) operator(=) string<delimiter(")content(There's no content!)delimiter(")> + ident(r)operator(.)ident(save) + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(invalid?)operator(()string<delimiter(")content(content)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply without content should mark that attribute as invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(Empty)delimiter(")>operator(,) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(content)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply without content should contain an error)delimiter(")> + ident(assert_equal) integer(1)operator(,) ident(r)operator(.)ident(errors)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_double_attr_validation_and_error_msg) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(assert) operator(!)ident(r)operator(.)ident(save) + + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(invalid?)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply without title should mark that attribute as invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(Empty)delimiter(")>operator(,) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply without title should contain an error)delimiter(")> + + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(invalid?)operator(()string<delimiter(")content(content)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply without content should mark that attribute as invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(Empty)delimiter(")>operator(,) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(content)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply without content should contain an error)delimiter(")> + + ident(assert_equal) integer(2)operator(,) ident(r)operator(.)ident(errors)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_error_on_create) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(title) operator(=) string<delimiter(")content(Wrong Create)delimiter(")> + ident(assert) operator(!)ident(r)operator(.)ident(save) + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(invalid?)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply with a bad title should mark that attribute as invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(is Wrong Create)delimiter(")>operator(,) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply with a bad content should contain an error)delimiter(")> + reserved(end) + + reserved(def) method(test_error_on_update) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(title) operator(=) string<delimiter(")content(Bad)delimiter(")> + ident(r)operator(.)ident(content) operator(=) string<delimiter(")content(Good)delimiter(")> + ident(assert) ident(r)operator(.)ident(save)operator(,) string<delimiter(")content(First save should be successful)delimiter(")> + + ident(r)operator(.)ident(title) operator(=) string<delimiter(")content(Wrong Update)delimiter(")> + ident(assert) operator(!)ident(r)operator(.)ident(save)operator(,) string<delimiter(")content(Second save should fail)delimiter(")> + + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(invalid?)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply with a bad title should mark that attribute as invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(is Wrong Update)delimiter(")>operator(,) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(title)delimiter(")>operator(\))operator(,) string<delimiter(")content(A reply with a bad content should contain an error)delimiter(")> + reserved(end) + + reserved(def) method(test_invalid_record_exception) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordInvalid)operator(\)) operator({) constant(Reply)operator(.)ident(create!) operator(}) + ident(assert_raises)operator(()constant(ActiveRecord)operator(::)constant(RecordInvalid)operator(\)) operator({) constant(Reply)operator(.)ident(new)operator(.)ident(save!) operator(}) + + reserved(begin) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(save!) + ident(flunk) + reserved(rescue) constant(ActiveRecord)operator(::)constant(RecordInvalid) operator(=)operator(>) ident(invalid) + ident(assert_equal) ident(r)operator(,) ident(invalid)operator(.)ident(record) + reserved(end) + reserved(end) + + reserved(def) method(test_single_error_per_attr_iteration) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(save) + + ident(errors) operator(=) operator([)operator(]) + ident(r)operator(.)ident(errors)operator(.)ident(each) operator({) operator(|)ident(attr)operator(,) ident(msg)operator(|) ident(errors) operator(<<) operator([)ident(attr)operator(,) ident(msg)operator(]) operator(}) + + ident(assert) ident(errors)operator(.)ident(include?)operator(()operator([)string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(Empty)delimiter(")>operator(])operator(\)) + ident(assert) ident(errors)operator(.)ident(include?)operator(()operator([)string<delimiter(")content(content)delimiter(")>operator(,) string<delimiter(")content(Empty)delimiter(")>operator(])operator(\)) + reserved(end) + + reserved(def) method(test_multiple_errors_per_attr_iteration_with_full_error_composition) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(title) operator(=) string<delimiter(")content(Wrong Create)delimiter(")> + ident(r)operator(.)ident(content) operator(=) string<delimiter(")content(Mismatch)delimiter(")> + ident(r)operator(.)ident(save) + + ident(errors) operator(=) operator([)operator(]) + ident(r)operator(.)ident(errors)operator(.)ident(each_full) operator({) operator(|)ident(error)operator(|) ident(errors) operator(<<) ident(error) operator(}) + + ident(assert_equal) string<delimiter(")content(Title is Wrong Create)delimiter(")>operator(,) ident(errors)operator([)integer(0)operator(]) + ident(assert_equal) string<delimiter(")content(Title is Content Mismatch)delimiter(")>operator(,) ident(errors)operator([)integer(1)operator(]) + ident(assert_equal) integer(2)operator(,) ident(r)operator(.)ident(errors)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_errors_on_base) + ident(r) operator(=) constant(Reply)operator(.)ident(new) + ident(r)operator(.)ident(content) operator(=) string<delimiter(")content(Mismatch)delimiter(")> + ident(r)operator(.)ident(save) + ident(r)operator(.)ident(errors)operator(.)ident(add_to_base) string<delimiter(")content(Reply is not dignifying)delimiter(")> + + ident(errors) operator(=) operator([)operator(]) + ident(r)operator(.)ident(errors)operator(.)ident(each_full) operator({) operator(|)ident(error)operator(|) ident(errors) operator(<<) ident(error) operator(}) + + ident(assert_equal) string<delimiter(")content(Reply is not dignifying)delimiter(")>operator(,) ident(r)operator(.)ident(errors)operator(.)ident(on_base) + + ident(assert) ident(errors)operator(.)ident(include?)operator(()string<delimiter(")content(Title Empty)delimiter(")>operator(\)) + ident(assert) ident(errors)operator(.)ident(include?)operator(()string<delimiter(")content(Reply is not dignifying)delimiter(")>operator(\)) + ident(assert_equal) integer(2)operator(,) ident(r)operator(.)ident(errors)operator(.)ident(count) + reserved(end) + + reserved(def) method(test_create_without_validation) + ident(reply) operator(=) constant(Reply)operator(.)ident(new) + ident(assert) operator(!)ident(reply)operator(.)ident(save) + ident(assert) ident(reply)operator(.)ident(save)operator(()pre_constant(false)operator(\)) + reserved(end) + + reserved(def) method(test_validates_each) + ident(perform) operator(=) pre_constant(true) + ident(hits) operator(=) integer(0) + constant(Topic)operator(.)ident(validates_each)operator(()symbol(:title)operator(,) symbol(:content)operator(,) operator([)symbol(:title)operator(,) symbol(:content)operator(])operator(\)) reserved(do) operator(|)ident(record)operator(,) ident(attr)operator(|) + reserved(if) ident(perform) + ident(record)operator(.)ident(errors)operator(.)ident(add) ident(attr)operator(,) string<delimiter(')content(gotcha)delimiter(')> + ident(hits) operator(+=) integer(1) + reserved(end) + reserved(end) + ident(t) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert_equal) integer(4)operator(,) ident(hits) + ident(assert_equal) string<delimiter(%w()content(gotcha gotcha)delimiter(\))>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(%w()content(gotcha gotcha)delimiter(\))>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + reserved(ensure) + ident(perform) operator(=) pre_constant(false) + reserved(end) + + reserved(def) method(test_errors_on_boundary_breaking) + ident(developer) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(xs)delimiter(")>operator(\)) + ident(assert) operator(!)ident(developer)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 3 characters\))delimiter(")>operator(,) ident(developer)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) + + ident(developer)operator(.)ident(name) operator(=) string<delimiter(")content(All too very long for this boundary, it really is)delimiter(")> + ident(assert) operator(!)ident(developer)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(is too long (maximum is 20 characters\))delimiter(")>operator(,) ident(developer)operator(.)ident(errors)operator(.)ident(on)operator(()string<delimiter(")content(name)delimiter(")>operator(\)) + + ident(developer)operator(.)ident(name) operator(=) string<delimiter(")content(Just right)delimiter(")> + ident(assert) ident(developer)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_title_confirmation_no_confirm) + constant(Topic)operator(.)ident(validates_confirmation_of)operator(()symbol(:title)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(We should not be confirmed)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_title_confirmation) + constant(Topic)operator(.)ident(validates_confirmation_of)operator(()symbol(:title)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(We should be confirmed)delimiter(")>operator(,)string<delimiter(")content(title_confirmation)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(title_confirmation) operator(=) string<delimiter(")content(We should be confirmed)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_terms_of_service_agreement_no_acceptance) + constant(Topic)operator(.)ident(validates_acceptance_of)operator(()symbol(:terms_of_service)operator(,) symbol(:on) operator(=)operator(>) symbol(:create)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(We should not be confirmed)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_terms_of_service_agreement) + constant(Topic)operator(.)ident(validates_acceptance_of)operator(()symbol(:terms_of_service)operator(,) symbol(:on) operator(=)operator(>) symbol(:create)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(We should be confirmed)delimiter(")>operator(,)string<delimiter(")content(terms_of_service)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(must be accepted)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:terms_of_service)operator(\)) + + ident(t)operator(.)ident(terms_of_service) operator(=) string<delimiter(")content(1)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + + reserved(def) method(test_eula) + constant(Topic)operator(.)ident(validates_acceptance_of)operator(()symbol(:eula)operator(,) symbol(:message) operator(=)operator(>) string<delimiter(")content(must be abided)delimiter(")>operator(,) symbol(:on) operator(=)operator(>) symbol(:create)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(We should be confirmed)delimiter(")>operator(,)string<delimiter(")content(eula)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(must be abided)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:eula)operator(\)) + + ident(t)operator(.)ident(eula) operator(=) string<delimiter(")content(1)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_terms_of_service_agreement_with_accept_value) + constant(Topic)operator(.)ident(validates_acceptance_of)operator(()symbol(:terms_of_service)operator(,) symbol(:on) operator(=)operator(>) symbol(:create)operator(,) symbol(:accept) operator(=)operator(>) string<delimiter(")content(I agree.)delimiter(")>operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(We should be confirmed)delimiter(")>operator(,) string<delimiter(")content(terms_of_service)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(must be accepted)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:terms_of_service)operator(\)) + + ident(t)operator(.)ident(terms_of_service) operator(=) string<delimiter(")content(I agree.)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_validate_presences) + constant(Topic)operator(.)ident(validates_presence_of)operator(()symbol(:title)operator(,) symbol(:content)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(can't be blank)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(can't be blank)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(something)delimiter(")> + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content( )delimiter(")> + + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert_equal) string<delimiter(")content(can't be blank)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(like stuff)delimiter(")> + + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_validate_uniqueness) + constant(Topic)operator(.)ident(validates_uniqueness_of)operator(()symbol(:title)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(I'm unique!)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(save)operator(,) string<delimiter(")content(Should save t as unique)delimiter(")> + + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(Remaining unique)delimiter(")> + ident(assert) ident(t)operator(.)ident(save)operator(,) string<delimiter(")content(Should still save t as unique)delimiter(")> + + ident(t2) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(I'm unique!)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t2)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + ident(assert) operator(!)ident(t2)operator(.)ident(save)operator(,) string<delimiter(")content(Shouldn't save t2 as unique)delimiter(")> + ident(assert_equal) string<delimiter(")content(has already been taken)delimiter(")>operator(,) ident(t2)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + + ident(t2)operator(.)ident(title) operator(=) string<delimiter(")content(Now Im really also unique)delimiter(")> + ident(assert) ident(t2)operator(.)ident(save)operator(,) string<delimiter(")content(Should now save t2 as unique)delimiter(")> + reserved(end) + + reserved(def) method(test_validate_uniqueness_with_scope) + constant(Reply)operator(.)ident(validates_uniqueness_of)operator(()symbol(:content)operator(,) symbol(:scope) operator(=)operator(>) string<delimiter(")content(parent_id)delimiter(")>operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(I'm unique!)delimiter(")>operator(\)) + + ident(r1) operator(=) ident(t)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(r1)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")> + ident(assert) ident(r1)operator(.)ident(valid?)operator(,) string<delimiter(")content(Saving r1)delimiter(")> + + ident(r2) operator(=) ident(t)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(r2)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")> + ident(assert) operator(!)ident(r2)operator(.)ident(valid?)operator(,) string<delimiter(")content(Saving r2 first time)delimiter(")> + + ident(r2)operator(.)ident(content) operator(=) string<delimiter(")content(something else)delimiter(")> + ident(assert) ident(r2)operator(.)ident(save)operator(,) string<delimiter(")content(Saving r2 second time)delimiter(")> + + ident(t2) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(I'm unique too!)delimiter(")>operator(\)) + ident(r3) operator(=) ident(t2)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(r3)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(hello world)delimiter(")> + ident(assert) ident(r3)operator(.)ident(valid?)operator(,) string<delimiter(")content(Saving r3)delimiter(")> + reserved(end) + + reserved(def) method(test_validate_uniqueness_with_scope_array) + constant(Reply)operator(.)ident(validates_uniqueness_of)operator(()symbol(:author_name)operator(,) symbol(:scope) operator(=)operator(>) operator([)symbol(:author_email_address)operator(,) symbol(:parent_id)operator(])operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(The earth is actually flat!)delimiter(")>operator(\)) + + ident(r1) operator(=) ident(t)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(author_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(jeremy)delimiter(")>operator(,) string<delimiter(")content(author_email_address)delimiter(")> operator(=)operator(>) string<delimiter(")content(jeremy@rubyonrails.com)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(You're crazy!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(Crazy reply)delimiter(")> + ident(assert) ident(r1)operator(.)ident(valid?)operator(,) string<delimiter(")content(Saving r1)delimiter(")> + + ident(r2) operator(=) ident(t)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(author_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(jeremy)delimiter(")>operator(,) string<delimiter(")content(author_email_address)delimiter(")> operator(=)operator(>) string<delimiter(")content(jeremy@rubyonrails.com)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(You're crazy!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(Crazy reply again...)delimiter(")> + ident(assert) operator(!)ident(r2)operator(.)ident(valid?)operator(,) string<delimiter(")content(Saving r2. Double reply by same author.)delimiter(")> + + ident(r2)operator(.)ident(author_email_address) operator(=) string<delimiter(")content(jeremy_alt_email@rubyonrails.com)delimiter(")> + ident(assert) ident(r2)operator(.)ident(save)operator(,) string<delimiter(")content(Saving r2 the second time.)delimiter(")> + + ident(r3) operator(=) ident(t)operator(.)ident(replies)operator(.)ident(create) string<delimiter(")content(author_name)delimiter(")> operator(=)operator(>) string<delimiter(")content(jeremy)delimiter(")>operator(,) string<delimiter(")content(author_email_address)delimiter(")> operator(=)operator(>) string<delimiter(")content(jeremy_alt_email@rubyonrails.com)delimiter(")>operator(,) string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(You're wrong)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(It's cubic)delimiter(")> + ident(assert) operator(!)ident(r3)operator(.)ident(valid?)operator(,) string<delimiter(")content(Saving r3)delimiter(")> + + ident(r3)operator(.)ident(author_name) operator(=) string<delimiter(")content(jj)delimiter(")> + ident(assert) ident(r3)operator(.)ident(save)operator(,) string<delimiter(")content(Saving r3 the second time.)delimiter(")> + + ident(r3)operator(.)ident(author_name) operator(=) string<delimiter(")content(jeremy)delimiter(")> + ident(assert) operator(!)ident(r3)operator(.)ident(save)operator(,) string<delimiter(")content(Saving r3 the third time.)delimiter(")> + reserved(end) + + reserved(def) method(test_validate_format) + constant(Topic)operator(.)ident(validates_format_of)operator(()symbol(:title)operator(,) symbol(:content)operator(,) symbol(:with) operator(=)operator(>) regexp<delimiter(/)content(^Validation)char(\\s)content(macros )char(\\w)content(+!$)delimiter(/)>operator(,) symbol(:message) operator(=)operator(>) string<delimiter(")content(is bad data)delimiter(")>operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(i'm incorrect)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(Validation macros rule!)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(save)operator(,) string<delimiter(")content(Shouldn't save because it's invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(is bad data)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_nil) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(Validation macros rule!)delimiter(")> + + ident(assert) ident(t)operator(.)ident(save) + ident(assert_nil) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_format_of)operator(()symbol(:title)operator(,) symbol(:content)operator(\)) operator(}) + reserved(end) + + comment(# testing ticket #3142) + reserved(def) method(test_validate_format_numeric) + constant(Topic)operator(.)ident(validates_format_of)operator(()symbol(:title)operator(,) symbol(:content)operator(,) symbol(:with) operator(=)operator(>) regexp<delimiter(/)content(^[1-9][0-9]*$)delimiter(/)>operator(,) symbol(:message) operator(=)operator(>) string<delimiter(")content(is bad data)delimiter(")>operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(72x)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(6789)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(save)operator(,) string<delimiter(")content(Shouldn't save because it's invalid)delimiter(")> + ident(assert_equal) string<delimiter(")content(is bad data)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_nil) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(-11)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(03)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(z44)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(5v7)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?)operator(,) string<delimiter(")content(Shouldn't be valid)delimiter(")> + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(1)delimiter(")> + + ident(assert) ident(t)operator(.)ident(save) + ident(assert_nil) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + reserved(end) + + reserved(def) method(test_validates_inclusion_of) + constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) string<delimiter(%w()content( a b c d e f g )delimiter(\))> operator(\)) + + ident(assert) operator(!)constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(a!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + ident(assert) operator(!)constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(a b)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + ident(assert) operator(!)constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) pre_constant(nil)operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(def)delimiter(")>operator(\))operator(.)ident(valid?) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(a)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(I know you are but what am I?)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(uhoh)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is not included in the list)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) pre_constant(nil) operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) integer(0)operator(\)) operator(}) + + ident(assert_nothing_raised)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) string<delimiter(")content(hi!)delimiter(")> operator(\)) operator(}) + ident(assert_nothing_raised)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) operator({)operator(}) operator(\)) operator(}) + ident(assert_nothing_raised)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) operator([)operator(]) operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_validates_inclusion_of_with_allow_nil) + constant(Topic)operator(.)ident(validates_inclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) string<delimiter(%w()content( a b c d e f g )delimiter(\))>operator(,) symbol(:allow_nil)operator(=)operator(>)pre_constant(true) operator(\)) + + ident(assert) operator(!)constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(a!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + ident(assert) operator(!)constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + ident(assert) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) pre_constant(nil)operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_numericality_with_allow_nil_and_getter_method) + constant(Developer)operator(.)ident(validates_numericality_of)operator(() symbol(:salary)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true)operator(\)) + ident(developer) operator(=) constant(Developer)operator(.)ident(new)operator(()string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(michael)delimiter(")>operator(,) string<delimiter(")content(salary)delimiter(")> operator(=)operator(>) pre_constant(nil)operator(\)) + ident(developer)operator(.)ident(instance_eval)operator(()string<delimiter(")content(def salary; read_attribute('salary'\) ? read_attribute('salary'\) : 100000; end)delimiter(")>operator(\)) + ident(assert) ident(developer)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_exclusion_of) + constant(Topic)operator(.)ident(validates_exclusion_of)operator(() symbol(:title)operator(,) symbol(:in) operator(=)operator(>) string<delimiter(%w()content( abe monkey )delimiter(\))> operator(\)) + + ident(assert) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(something)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + ident(assert) operator(!)constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(monkey)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(abc)delimiter(")>operator(\))operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_length_of_using_minimum) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:minimum) operator(=)operator(>) integer(5) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(not)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_minimum) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:minimum) operator(=)operator(>) integer(5)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_length_of_using_maximum) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:maximum) operator(=)operator(>) integer(5) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(notvalid)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too long (maximum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")delimiter(")> + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_maximum) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:maximum) operator(=)operator(>) integer(5)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_length_of_using_within) + constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(3)operator(..)integer(5)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(a!)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(I'm ooooooooh so very long)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 3 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too long (maximum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(t)operator(.)ident(content) operator(=) pre_constant(nil) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 3 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 3 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(abe)delimiter(")> + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(mad)delimiter(")> + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_within) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(3)operator(..)integer(5)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(')content(title)delimiter(')> operator(=)operator(>) string<delimiter(')content(abc)delimiter(')>operator(,) string<delimiter(')content(content)delimiter(')> operator(=)operator(>) string<delimiter(')content(abcd)delimiter(')>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_within_on_create) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(5)operator(..)integer(10)operator(,) symbol(:on) operator(=)operator(>) symbol(:create)operator(,) symbol(:too_long) operator(=)operator(>) string<delimiter(")content(my string is too long: %d)delimiter(")> + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(thisisnotvalid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(my string is too long: 10)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)symbol(:title)operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(butthisis)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(few)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(andthisislong)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(content) operator(=) ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(iamfine)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_within_on_update) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(5)operator(..)integer(10)operator(,) symbol(:on) operator(=)operator(>) symbol(:update)operator(,) symbol(:too_short) operator(=)operator(>) string<delimiter(")content(my string is too short: %d)delimiter(")> + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(vali)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(not)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(my string is too short: 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)symbol(:title)operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(valid)delimiter(")> + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(andthisistoolong)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(iamfine)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + + reserved(def) method(test_validates_length_of_using_is) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:is) operator(=)operator(>) integer(5) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(notvalid)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is the wrong length (should be 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_is) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:is) operator(=)operator(>) integer(5)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(valid)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_length_of_using_bignum) + ident(bigmin) operator(=) integer(2) operator(**) integer(30) + ident(bigmax) operator(=) integer(2) operator(**) integer(32) + ident(bigrange) operator(=) ident(bigmin)operator(...)ident(bigmax) + ident(assert_nothing_raised) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:is) operator(=)operator(>) ident(bigmin) operator(+) integer(5) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:within) operator(=)operator(>) ident(bigrange) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:in) operator(=)operator(>) ident(bigrange) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:minimum) operator(=)operator(>) ident(bigmin) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:maximum) operator(=)operator(>) ident(bigmax) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_length_with_globaly_modified_error_message) + constant(ActiveRecord)operator(::)constant(Errors)operator(.)ident(default_error_messages)operator([)symbol(:too_short)operator(]) operator(=) string<delimiter(')content(tu est trops petit hombre %d)delimiter(')> + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:minimum) operator(=)operator(>) integer(10) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()symbol(:title) operator(=)operator(>) string<delimiter(')content(too short)delimiter(')>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + + ident(assert_equal) string<delimiter(')content(tu est trops petit hombre 10)delimiter(')>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(')content(title)delimiter(')>operator(]) + reserved(end) + + reserved(def) method(test_validates_size_of_association) + ident(assert_nothing_raised) operator({) constant(Topic)operator(.)ident(validates_size_of) symbol(:replies)operator(,) symbol(:minimum) operator(=)operator(>) integer(1) operator(}) + ident(t) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(')content(title)delimiter(')> operator(=)operator(>) string<delimiter(')content(noreplies)delimiter(')>operator(,) string<delimiter(')content(content)delimiter(')> operator(=)operator(>) string<delimiter(')content(whatever)delimiter(')>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:replies)operator(\)) + ident(t)operator(.)ident(replies)operator(.)ident(create)operator(()string<delimiter(')content(title)delimiter(')> operator(=)operator(>) string<delimiter(')content(areply)delimiter(')>operator(,) string<delimiter(')content(content)delimiter(')> operator(=)operator(>) string<delimiter(')content(whateveragain)delimiter(')>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_length_of_nasty_params) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:minimum)operator(=)operator(>)integer(6)operator(,) symbol(:maximum)operator(=)operator(>)integer(9)operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:within)operator(=)operator(>)integer(6)operator(,) symbol(:maximum)operator(=)operator(>)integer(9)operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:within)operator(=)operator(>)integer(6)operator(,) symbol(:minimum)operator(=)operator(>)integer(9)operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:within)operator(=)operator(>)integer(6)operator(,) symbol(:is)operator(=)operator(>)integer(9)operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:minimum)operator(=)operator(>)string<delimiter(")content(a)delimiter(")>operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)string<delimiter(")content(a)delimiter(")>operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:within)operator(=)operator(>)string<delimiter(")content(a)delimiter(")>operator(\)) operator(}) + ident(assert_raise)operator(()constant(ArgumentError)operator(\)) operator({) constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:is)operator(=)operator(>)string<delimiter(")content(a)delimiter(")>operator(\)) operator(}) + reserved(end) + + reserved(def) method(test_validates_length_of_custom_errors_for_minimum_with_message) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:minimum)operator(=)operator(>)integer(5)operator(,) symbol(:message)operator(=)operator(>)string<delimiter(")content(boo %d)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(boo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_validates_length_of_custom_errors_for_minimum_with_too_short) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:minimum)operator(=)operator(>)integer(5)operator(,) symbol(:too_short)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(hoo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_validates_length_of_custom_errors_for_maximum_with_message) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:message)operator(=)operator(>)string<delimiter(")content(boo %d)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(boo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_validates_length_of_custom_errors_for_maximum_with_too_long) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(hoo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_validates_length_of_custom_errors_for_is_with_message) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:is)operator(=)operator(>)integer(5)operator(,) symbol(:message)operator(=)operator(>)string<delimiter(")content(boo %d)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(boo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_validates_length_of_custom_errors_for_is_with_wrong_length) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:is)operator(=)operator(>)integer(5)operator(,) symbol(:wrong_length)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(hoo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(kcode_scope)operator(()ident(kcode)operator(\)) + ident(orig_kcode) operator(=) global_variable($KCODE) + global_variable($KCODE) operator(=) ident(kcode) + reserved(begin) + reserved(yield) + reserved(ensure) + global_variable($KCODE) operator(=) ident(orig_kcode) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_length_of_using_minimum_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:minimum) operator(=)operator(>) integer(5) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(一二三四五)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二三四)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_length_of_using_maximum_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:maximum) operator(=)operator(>) integer(5) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(一二三四五)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二34五å…)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too long (maximum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_length_of_using_within_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of)operator(()symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(3)operator(..)integer(5)operator(\)) + + ident(t) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(一二)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(12三四五å…七)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert_equal) string<delimiter(")content(is too short (minimum is 3 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is too long (maximum is 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二三)delimiter(")> + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(12三)delimiter(")> + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_within_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(3)operator(..)integer(5)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(')content(title)delimiter(')> operator(=)operator(>) string<delimiter(')content(一二三)delimiter(')>operator(,) string<delimiter(')content(content)delimiter(')> operator(=)operator(>) string<delimiter(')content(一二三四五)delimiter(')>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) pre_constant(nil) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_within_on_create_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(5)operator(..)integer(10)operator(,) symbol(:on) operator(=)operator(>) symbol(:create)operator(,) symbol(:too_long) operator(=)operator(>) string<delimiter(")content(é•·ã™ãŽã¾ã™: %d)delimiter(")> + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(一二三四五å…七八ä¹åA)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(é•·ã™ãŽã¾ã™: 10)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)symbol(:title)operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二三四五å…七八ä¹)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二3)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(一二三四五å…七八ä¹å)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + + ident(t)operator(.)ident(content) operator(=) ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二三四五å…)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + reserved(end) + + reserved(def) method(test_optionally_validates_length_of_using_within_on_update_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:content)operator(,) symbol(:within) operator(=)operator(>) integer(5)operator(..)integer(10)operator(,) symbol(:on) operator(=)operator(>) symbol(:update)operator(,) symbol(:too_short) operator(=)operator(>) string<delimiter(")content(çŸã™ãŽã¾ã™: %d)delimiter(")> + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(一二三4)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(1二三4)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(çŸã™ãŽã¾ã™: 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)symbol(:title)operator(]) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(valid)delimiter(")> + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(一二三四五å…七八ä¹åA)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:content)operator(\)) + + ident(t)operator(.)ident(content) operator(=) string<delimiter(")content(一二345)delimiter(")> + ident(assert) ident(t)operator(.)ident(save) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_length_of_using_is_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + constant(Topic)operator(.)ident(validates_length_of) symbol(:title)operator(,) symbol(:is) operator(=)operator(>) integer(5) + + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(一二345)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + + ident(t)operator(.)ident(title) operator(=) string<delimiter(")content(一二345å…)delimiter(")> + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(is the wrong length (should be 5 characters\))delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_size_of_association_utf8) + ident(kcode_scope)operator(()string<delimiter(')content(UTF8)delimiter(')>operator(\)) reserved(do) + ident(assert_nothing_raised) operator({) constant(Topic)operator(.)ident(validates_size_of) symbol(:replies)operator(,) symbol(:minimum) operator(=)operator(>) integer(1) operator(}) + ident(t) operator(=) constant(Topic)operator(.)ident(new)operator(()string<delimiter(')content(title)delimiter(')> operator(=)operator(>) string<delimiter(')content(ã‚ã„ã†ãˆãŠ)delimiter(')>operator(,) string<delimiter(')content(content)delimiter(')> operator(=)operator(>) string<delimiter(')content(ã‹ããã‘ã“)delimiter(')>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(save) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:replies)operator(\)) + ident(t)operator(.)ident(replies)operator(.)ident(create)operator(()string<delimiter(')content(title)delimiter(')> operator(=)operator(>) string<delimiter(')content(ã‚ã„ã†ãˆãŠ)delimiter(')>operator(,) string<delimiter(')content(content)delimiter(')> operator(=)operator(>) string<delimiter(')content(ã‹ããã‘ã“)delimiter(')>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + reserved(end) + + reserved(def) method(test_validates_associated_many) + constant(Topic)operator(.)ident(validates_associated)operator(() symbol(:replies) operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(t)operator(.)ident(replies) operator(<<) operator([)ident(r) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(A reply)delimiter(")>operator(\))operator(,) ident(r2) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(Another reply)delimiter(")>operator(\))operator(]) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:replies)operator(\)) + ident(assert_equal) integer(1)operator(,) ident(r)operator(.)ident(errors)operator(.)ident(count) comment(# make sure all associated objects have been validated) + ident(assert_equal) integer(1)operator(,) ident(r2)operator(.)ident(errors)operator(.)ident(count) + ident(r)operator(.)ident(content) operator(=) ident(r2)operator(.)ident(content) operator(=) string<delimiter(")content(non-empty)delimiter(")> + ident(assert) ident(t)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validates_associated_one) + constant(Reply)operator(.)ident(validates_associated)operator(() symbol(:topic) operator(\)) + constant(Topic)operator(.)ident(validates_presence_of)operator(() symbol(:content) operator(\)) + ident(r) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(A reply)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(with content!)delimiter(")>operator(\)) + ident(r)operator(.)ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(\)) + ident(assert) operator(!)ident(r)operator(.)ident(valid?) + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:topic)operator(\)) + ident(r)operator(.)ident(topic)operator(.)ident(content) operator(=) string<delimiter(")content(non-empty)delimiter(")> + ident(assert) ident(r)operator(.)ident(valid?) + reserved(end) + + reserved(def) method(test_validate_block) + constant(Topic)operator(.)ident(validate) operator({) operator(|)ident(topic)operator(|) ident(topic)operator(.)ident(errors)operator(.)ident(add)operator(()string<delimiter(")content(title)delimiter(")>operator(,) string<delimiter(")content(will never be valid)delimiter(")>operator(\)) operator(}) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(Title)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(will never be valid)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_invalid_validator) + constant(Topic)operator(.)ident(validate) integer(3) + ident(assert_raise)operator(()constant(ActiveRecord)operator(::)constant(ActiveRecordError)operator(\)) operator({) ident(t) operator(=) constant(Topic)operator(.)ident(create) operator(}) + reserved(end) + + reserved(def) method(test_throw_away_typing) + ident(d) operator(=) constant(Developer)operator(.)ident(create) string<delimiter(")content(name)delimiter(")> operator(=)operator(>) string<delimiter(")content(David)delimiter(")>operator(,) string<delimiter(")content(salary)delimiter(")> operator(=)operator(>) string<delimiter(")content(100,000)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) integer(100)operator(,) ident(d)operator(.)ident(salary) + ident(assert_equal) string<delimiter(")content(100,000)delimiter(")>operator(,) ident(d)operator(.)ident(salary_before_type_cast) + reserved(end) + + reserved(def) method(test_validates_acceptance_of_with_custom_error_using_quotes) + constant(Developer)operator(.)ident(validates_acceptance_of) symbol(:salary)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(salary) operator(=) string<delimiter(")content(0)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:salary)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_confirmation_of_with_custom_error_using_quotes) + constant(Developer)operator(.)ident(validates_confirmation_of) symbol(:name)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(John)delimiter(")> + ident(d)operator(.)ident(name_confirmation) operator(=) string<delimiter(")content(Johnny)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:name)operator(\))operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_format_of_with_custom_error_using_quotes) + constant(Developer)operator(.)ident(validates_format_of) symbol(:name)operator(,) symbol(:with) operator(=)operator(>) regexp<delimiter(/)content(^(A-Z*\)$)delimiter(/)>operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(John 32)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:name)operator(\))operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_inclusion_of_with_custom_error_using_quotes) + constant(Developer)operator(.)ident(validates_inclusion_of) symbol(:salary)operator(,) symbol(:in) operator(=)operator(>) integer(1000)operator(..)integer(80000)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(salary) operator(=) string<delimiter(")content(90,000)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:salary)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_length_of_with_custom_too_long_using_quotes) + constant(Developer)operator(.)ident(validates_length_of) symbol(:name)operator(,) symbol(:maximum) operator(=)operator(>) integer(4)operator(,) symbol(:too_long)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(Jeffrey)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:name)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_length_of_with_custom_too_short_using_quotes) + constant(Developer)operator(.)ident(validates_length_of) symbol(:name)operator(,) symbol(:minimum) operator(=)operator(>) integer(4)operator(,) symbol(:too_short)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(Joe)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:name)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_length_of_with_custom_message_using_quotes) + constant(Developer)operator(.)ident(validates_length_of) symbol(:name)operator(,) symbol(:minimum) operator(=)operator(>) integer(4)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(Joe)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:name)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_presence_of_with_custom_message_using_quotes) + constant(Developer)operator(.)ident(validates_presence_of) symbol(:non_existent)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(Joe)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:non_existent)operator(\))operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_uniqueness_of_with_custom_message_using_quotes) + constant(Developer)operator(.)ident(validates_uniqueness_of) symbol(:name)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + ident(d) operator(=) constant(Developer)operator(.)ident(new) + ident(d)operator(.)ident(name) operator(=) string<delimiter(")content(David)delimiter(")> + ident(assert) operator(!)ident(d)operator(.)ident(valid?) + ident(assert_equal) ident(d)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:name)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_validates_associated_with_custom_message_using_quotes) + constant(Reply)operator(.)ident(validates_associated) symbol(:topic)operator(,) symbol(:message)operator(=)operator(>) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + constant(Topic)operator(.)ident(validates_presence_of) symbol(:content) + ident(r) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(A reply)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(with content!)delimiter(")>operator(\)) + ident(r)operator(.)ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(\)) + ident(assert) operator(!)ident(r)operator(.)ident(valid?) + ident(assert_equal) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:topic)operator(\))operator(.)ident(first)operator(,) string<delimiter(")content(This string contains 'single' and )char(\\")content(double)char(\\")content( quotes)delimiter(")> + reserved(end) + + reserved(def) method(test_conditional_validation_using_method_true) + comment(# When the method returns true) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")>operator(,) symbol(:if) operator(=)operator(>) symbol(:condition_is_true) operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(hoo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_conditional_validation_using_method_false) + comment(# When the method returns false) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")>operator(,) symbol(:if) operator(=)operator(>) symbol(:condition_is_true_but_its_not) operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + ident(assert) operator(!)ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + reserved(end) + + reserved(def) method(test_conditional_validation_using_string_true) + comment(# When the evaluated string returns true) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")>operator(,) symbol(:if) operator(=)operator(>) string<delimiter(")content(a = 1; a == 1)delimiter(")> operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(hoo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_conditional_validation_using_string_false) + comment(# When the evaluated string returns false) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")>operator(,) symbol(:if) operator(=)operator(>) string<delimiter(")content(false)delimiter(")>operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + ident(assert) operator(!)ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + reserved(end) + + reserved(def) method(test_conditional_validation_using_block_true) + comment(# When the block returns true) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")>operator(,) + symbol(:if) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(r)operator(|) ident(r)operator(.)ident(content)operator(.)ident(size) operator(>) integer(4) operator(}) operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) operator(!)ident(t)operator(.)ident(valid?) + ident(assert) ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + ident(assert_equal) string<delimiter(")content(hoo 5)delimiter(")>operator(,) ident(t)operator(.)ident(errors)operator([)string<delimiter(")content(title)delimiter(")>operator(]) + reserved(end) + + reserved(def) method(test_conditional_validation_using_block_false) + comment(# When the block returns false) + constant(Topic)operator(.)ident(validates_length_of)operator(() symbol(:title)operator(,) symbol(:maximum)operator(=)operator(>)integer(5)operator(,) symbol(:too_long)operator(=)operator(>)string<delimiter(")content(hoo %d)delimiter(")>operator(,) + symbol(:if) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(r)operator(|) ident(r)operator(.)ident(title) operator(!=) string<delimiter(")content(uhohuhoh)delimiter(")>operator(}) operator(\)) + ident(t) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(uhohuhoh)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(\)) + ident(assert) ident(t)operator(.)ident(valid?) + ident(assert) operator(!)ident(t)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:title)operator(\)) + reserved(end) + + reserved(def) method(test_validates_associated_missing) + constant(Reply)operator(.)ident(validates_presence_of)operator(()symbol(:topic)operator(\)) + ident(r) operator(=) constant(Reply)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(A reply)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(with content!)delimiter(")>operator(\)) + ident(assert) operator(!)ident(r)operator(.)ident(valid?) + ident(assert) ident(r)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:topic)operator(\)) + + ident(r)operator(.)ident(topic) operator(=) constant(Topic)operator(.)ident(find) symbol(:first) + ident(assert) ident(r)operator(.)ident(valid?) + reserved(end) +reserved(end) + + +reserved(class) class(ValidatesNumericalityTest) + constant(NIL) operator(=) operator([)pre_constant(nil)operator(,) string<delimiter(")delimiter(")>operator(,) string<delimiter(")content( )delimiter(")>operator(,) string<delimiter(")content( )char(\\t)content( )char(\\r)content( )char(\\n)delimiter(")>operator(]) + constant(FLOAT_STRINGS) operator(=) string<delimiter(%w()content(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1)delimiter(\))> + constant(INTEGER_STRINGS) operator(=) string<delimiter(%w()content(0 +0 -0 10 +10 -10 0090 -090)delimiter(\))> + constant(FLOATS) operator(=) operator([)float(0.0)operator(,) float(10.0)operator(,) float(10.5)operator(,) float(-10.5)operator(,) float(-0.0001)operator(]) operator(+) constant(FLOAT_STRINGS) + constant(INTEGERS) operator(=) operator([)integer(0)operator(,) integer(10)operator(,) integer(-10)operator(]) operator(+) constant(INTEGER_STRINGS) + constant(JUNK) operator(=) operator([)string<delimiter(")content(not a number)delimiter(")>operator(,) string<delimiter(")content(42 not a number)delimiter(")>operator(,) string<delimiter(")content(0xdeadbeef)delimiter(")>operator(,) string<delimiter(")content(00-1)delimiter(")>operator(,) string<delimiter(")content(--3)delimiter(")>operator(,) string<delimiter(")content(+-3)delimiter(")>operator(,) string<delimiter(")content(+3-1)delimiter(")>operator(,) string<delimiter(")content(-+019.0)delimiter(")>operator(,) string<delimiter(")content(12.12.13.12)delimiter(")>operator(]) + + reserved(def) method(setup) + constant(Topic)operator(.)ident(write_inheritable_attribute)operator(()symbol(:validate)operator(,) pre_constant(nil)operator(\)) + constant(Topic)operator(.)ident(write_inheritable_attribute)operator(()symbol(:validate_on_create)operator(,) pre_constant(nil)operator(\)) + constant(Topic)operator(.)ident(write_inheritable_attribute)operator(()symbol(:validate_on_update)operator(,) pre_constant(nil)operator(\)) + reserved(end) + + reserved(def) method(test_default_validates_numericality_of) + constant(Topic)operator(.)ident(validates_numericality_of) symbol(:approved) + + ident(invalid!)operator(()constant(NIL) operator(+) constant(JUNK)operator(\)) + ident(valid!)operator(()constant(FLOATS) operator(+) constant(INTEGERS)operator(\)) + reserved(end) + + reserved(def) method(test_validates_numericality_of_with_nil_allowed) + constant(Topic)operator(.)ident(validates_numericality_of) symbol(:approved)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(invalid!)operator(()constant(JUNK)operator(\)) + ident(valid!)operator(()constant(NIL) operator(+) constant(FLOATS) operator(+) constant(INTEGERS)operator(\)) + reserved(end) + + reserved(def) method(test_validates_numericality_of_with_integer_only) + constant(Topic)operator(.)ident(validates_numericality_of) symbol(:approved)operator(,) symbol(:only_integer) operator(=)operator(>) pre_constant(true) + + ident(invalid!)operator(()constant(NIL) operator(+) constant(JUNK) operator(+) constant(FLOATS)operator(\)) + ident(valid!)operator(()constant(INTEGERS)operator(\)) + reserved(end) + + reserved(def) method(test_validates_numericality_of_with_integer_only_and_nil_allowed) + constant(Topic)operator(.)ident(validates_numericality_of) symbol(:approved)operator(,) symbol(:only_integer) operator(=)operator(>) pre_constant(true)operator(,) symbol(:allow_nil) operator(=)operator(>) pre_constant(true) + + ident(invalid!)operator(()constant(JUNK) operator(+) constant(FLOATS)operator(\)) + ident(valid!)operator(()constant(NIL) operator(+) constant(INTEGERS)operator(\)) + reserved(end) + + ident(private) + reserved(def) method(invalid!)operator(()ident(values)operator(\)) + ident(values)operator(.)ident(each) reserved(do) operator(|)ident(value)operator(|) + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(numeric test)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(,) string<delimiter(")content(approved)delimiter(")> operator(=)operator(>) ident(value)operator(\)) + ident(assert) operator(!)ident(topic)operator(.)ident(valid?)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(value)inline_delimiter(})>content( not rejected as a number)delimiter(")> + ident(assert) ident(topic)operator(.)ident(errors)operator(.)ident(on)operator(()symbol(:approved)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(valid!)operator(()ident(values)operator(\)) + ident(values)operator(.)ident(each) reserved(do) operator(|)ident(value)operator(|) + ident(topic) operator(=) constant(Topic)operator(.)ident(create)operator(()string<delimiter(")content(title)delimiter(")> operator(=)operator(>) string<delimiter(")content(numeric test)delimiter(")>operator(,) string<delimiter(")content(content)delimiter(")> operator(=)operator(>) string<delimiter(")content(whatever)delimiter(")>operator(,) string<delimiter(")content(approved)delimiter(")> operator(=)operator(>) ident(value)operator(\)) + ident(assert) ident(topic)operator(.)ident(valid?)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(value)inline_delimiter(})>content( not accepted as a number)delimiter(")> + reserved(end) + reserved(end) +reserved(end) +reserved(begin) + ident(require) string<delimiter(')content(simplecc)delimiter(')> +reserved(rescue) constant(LoadError) + reserved(class) class(Continuation) comment(# :nodoc: # for RDoc) + reserved(end) + reserved(def) constant(Continuation)operator(.)ident(create)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) comment(# :nodoc:) + ident(cc) operator(=) pre_constant(nil)operator(;) ident(result) operator(=) ident(callcc) operator({)operator(|)ident(c)operator(|) ident(cc) operator(=) ident(c)operator(;) ident(block)operator(.)ident(call)operator(()ident(cc)operator(\)) reserved(if) ident(block) reserved(and) ident(args)operator(.)ident(empty?)operator(}) + ident(result) operator(||=) ident(args) + reserved(return) operator(*)operator([)ident(cc)operator(,) operator(*)ident(result)operator(]) + reserved(end) +reserved(end) + +reserved(class) class(Binding)operator(;) reserved(end) comment(# for RDoc) +comment(# This method returns the binding of the method that called your) +comment(# method. It will raise an Exception when you're not inside a method.) +comment(#) +comment(# It's used like this:) +comment(# def inc_counter(amount = 1\)) +comment(# Binding.of_caller do |binding|) +comment(# # Create a lambda that will increase the variable 'counter') +comment(# # in the caller of this method when called.) +comment(# inc = eval("lambda { |arg| counter += arg }", binding\)) +comment(# # We can refer to amount from inside this block safely.) +comment(# inc.call(amount\)) +comment(# end) +comment(# # No other statements can go here. Put them inside the block.) +comment(# end) +comment(# counter = 0) +comment(# 2.times { inc_counter }) +comment(# counter # => 2) +comment(#) +comment(# Binding.of_caller must be the last statement in the method.) +comment(# This means that you will have to put everything you want to) +comment(# do after the call to Binding.of_caller into the block of it.) +comment(# This should be no problem however, because Ruby has closures.) +comment(# If you don't do this an Exception will be raised. Because of) +comment(# the way that Binding.of_caller is implemented it has to be) +comment(# done this way.) +reserved(def) constant(Binding)operator(.)ident(of_caller)operator(()operator(&)ident(block)operator(\)) + ident(old_critical) operator(=) constant(Thread)operator(.)ident(critical) + constant(Thread)operator(.)ident(critical) operator(=) pre_constant(true) + ident(count) operator(=) integer(0) + ident(cc)operator(,) ident(result)operator(,) ident(error)operator(,) ident(extra_data) operator(=) constant(Continuation)operator(.)ident(create)operator(()pre_constant(nil)operator(,) pre_constant(nil)operator(\)) + ident(error)operator(.)ident(call) reserved(if) ident(error) + + ident(tracer) operator(=) ident(lambda) reserved(do) operator(|*)ident(args)operator(|) + ident(type)operator(,) ident(context)operator(,) ident(extra_data) operator(=) ident(args)operator([)integer(0)operator(])operator(,) ident(args)operator([)integer(4)operator(])operator(,) ident(args) + reserved(if) ident(type) operator(==) string<delimiter(")content(return)delimiter(")> + ident(count) operator(+=) integer(1) + comment(# First this method and then calling one will return --) + comment(# the trace event of the second event gets the context) + comment(# of the method which called the method that called this) + comment(# method.) + reserved(if) ident(count) operator(==) integer(2) + comment(# It would be nice if we could restore the trace_func) + comment(# that was set before we swapped in our own one, but) + comment(# this is impossible without overloading set_trace_func) + comment(# in current Ruby.) + ident(set_trace_func)operator(()pre_constant(nil)operator(\)) + ident(cc)operator(.)ident(call)operator(()ident(eval)operator(()string<delimiter(")content(binding)delimiter(")>operator(,) ident(context)operator(\))operator(,) pre_constant(nil)operator(,) ident(extra_data)operator(\)) + reserved(end) + reserved(elsif) ident(type) operator(==) string<delimiter(")content(line)delimiter(")> reserved(then) + pre_constant(nil) + reserved(elsif) ident(type) operator(==) string<delimiter(")content(c-return)delimiter(")> reserved(and) ident(extra_data)operator([)integer(3)operator(]) operator(==) symbol(:set_trace_func) reserved(then) + pre_constant(nil) + reserved(else) + ident(set_trace_func)operator(()pre_constant(nil)operator(\)) + ident(error_msg) operator(=) string<delimiter(")content(Binding.of_caller used in non-method context or )delimiter(")> operator(+) + string<delimiter(")content(trailing statements of method using it aren't in the block.)delimiter(")> + ident(cc)operator(.)ident(call)operator(()pre_constant(nil)operator(,) ident(lambda) operator({) ident(raise)operator(()constant(ArgumentError)operator(,) ident(error_msg)operator(\)) operator(})operator(,) pre_constant(nil)operator(\)) + reserved(end) + reserved(end) + + reserved(unless) ident(result) + ident(set_trace_func)operator(()ident(tracer)operator(\)) + reserved(return) pre_constant(nil) + reserved(else) + constant(Thread)operator(.)ident(critical) operator(=) ident(old_critical) + reserved(case) ident(block)operator(.)ident(arity) + reserved(when) integer(1) reserved(then) reserved(yield)operator(()ident(result)operator(\)) + reserved(else) reserved(yield)operator(()ident(result)operator(,) ident(extra_data)operator(\)) + reserved(end) + reserved(end) +reserved(end) +comment(# The Breakpoint library provides the convenience of) +comment(# being able to inspect and modify state, diagnose) +comment(# bugs all via IRB by simply setting breakpoints in) +comment(# your applications by the call of a method.) +comment(#) +comment(# This library was written and is supported by me,) +comment(# Florian Gross. I can be reached at flgr@ccan.de) +comment(# and enjoy getting feedback about my libraries.) +comment(#) +comment(# The whole library (including breakpoint_client.rb) +comment(# and binding_of_caller.rb\) is licensed under the) +comment(# same license that Ruby uses. (Which is currently) +comment(# either the GNU General Public License or a custom) +comment(# one that allows for commercial usage.\) If you for) +comment(# some good reason need to use this under another) +comment(# license please contact me.) + +ident(require) string<delimiter(')content(irb)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/binding_of_caller)delimiter(')> reserved(unless) reserved(defined?) constant(Binding)operator(.)ident(of_caller) +ident(require) string<delimiter(')content(drb)delimiter(')> +ident(require) string<delimiter(')content(drb/acl)delimiter(')> + +reserved(module) class(Breakpoint) + ident(id) operator(=) string<delimiter(%q$)content(Id: breakpoint.rb 92 2005-02-04 22:35:53Z flgr )delimiter($)> + constant(Version) operator(=) ident(id)operator(.)ident(split)operator(()string<delimiter(")content( )delimiter(")>operator(\))operator([)integer(2)operator(])operator(.)ident(to_i) + + ident(extend) pre_constant(self) + + comment(# This will pop up an interactive ruby session at a) + comment(# pre-defined break point in a Ruby application. In) + comment(# this session you can examine the environment of) + comment(# the break point.) + comment(#) + comment(# You can get a list of variables in the context using) + comment(# local_variables via +local_variables+. You can then) + comment(# examine their values by typing their names.) + comment(#) + comment(# You can have a look at the call stack via +caller+.) + comment(#) + comment(# The source code around the location where the breakpoint) + comment(# was executed can be examined via +source_lines+. Its) + comment(# argument specifies how much lines of context to display.) + comment(# The default amount of context is 5 lines. Note that) + comment(# the call to +source_lines+ can raise an exception when) + comment(# it isn't able to read in the source code.) + comment(#) + comment(# breakpoints can also return a value. They will execute) + comment(# a supplied block for getting a default return value.) + comment(# A custom value can be returned from the session by doing) + comment(# +throw(:debug_return, value\)+.) + comment(#) + comment(# You can also give names to break points which will be) + comment(# used in the message that is displayed upon execution ) + comment(# of them.) + comment(#) + comment(# Here's a sample of how breakpoints should be placed:) + comment(#) + comment(# class Person) + comment(# def initialize(name, age\)) + comment(# @name, @age = name, age) + comment(# breakpoint("Person#initialize"\)) + comment(# end) + comment(#) + comment(# attr_reader :age) + comment(# def name) + comment(# breakpoint("Person#name"\) { @name }) + comment(# end) + comment(# end) + comment(#) + comment(# person = Person.new("Random Person", 23\)) + comment(# puts "Name: #{person.name}") + comment(#) + comment(# And here is a sample debug session:) + comment(#) + comment(# Executing break point "Person#initialize" at file.rb:4 in `initialize') + comment(# irb(#<Person:0x292fbe8>\):001:0> local_variables) + comment(# => ["name", "age", "_", "__"]) + comment(# irb(#<Person:0x292fbe8>\):002:0> [name, age]) + comment(# => ["Random Person", 23]) + comment(# irb(#<Person:0x292fbe8>\):003:0> [@name, @age]) + comment(# => ["Random Person", 23]) + comment(# irb(#<Person:0x292fbe8>\):004:0> self) + comment(# => #<Person:0x292fbe8 @age=23, @name="Random Person">) + comment(# irb(#<Person:0x292fbe8>\):005:0> @age += 1; self) + comment(# => #<Person:0x292fbe8 @age=24, @name="Random Person">) + comment(# irb(#<Person:0x292fbe8>\):006:0> exit) + comment(# Executing break point "Person#name" at file.rb:9 in `name') + comment(# irb(#<Person:0x292fbe8>\):001:0> throw(:debug_return, "Overriden name"\)) + comment(# Name: Overriden name) + comment(#) + comment(# Breakpoint sessions will automatically have a few) + comment(# convenience methods available. See Breakpoint::CommandBundle) + comment(# for a list of them.) + comment(#) + comment(# Breakpoints can also be used remotely over sockets.) + comment(# This is implemented by running part of the IRB session) + comment(# in the application and part of it in a special client.) + comment(# You have to call Breakpoint.activate_drb to enable) + comment(# support for remote breakpoints and then run) + comment(# breakpoint_client.rb which is distributed with this) + comment(# library. See the documentation of Breakpoint.activate_drb) + comment(# for details.) + reserved(def) method(breakpoint)operator(()ident(id) operator(=) pre_constant(nil)operator(,) ident(context) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(callstack) operator(=) ident(caller) + ident(callstack)operator(.)ident(slice!)operator(()integer(0)operator(,) integer(3)operator(\)) reserved(if) ident(callstack)operator(.)ident(first)operator([)string<delimiter(")content(breakpoint)delimiter(")>operator(]) + ident(file)operator(,) ident(line)operator(,) ident(method) operator(=) operator(*)ident(callstack)operator(.)ident(first)operator(.)ident(match)operator(()regexp<delimiter(/)content(^(.+?\):()char(\\d)content(+\)(?::in `(.*?\)'\)?)delimiter(/)>operator(\))operator(.)ident(captures) + + ident(message) operator(=) string<delimiter(")content(Executing break point )delimiter(")> operator(+) operator(()ident(id) operator(?) string<delimiter(")inline<inline_delimiter(#{)ident(id)operator(.)ident(inspect)inline_delimiter(})>content( )delimiter(")> operator(:) string<delimiter(")delimiter(")>operator(\)) operator(+) + string<delimiter(")content(at )inline<inline_delimiter(#{)ident(file)inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(line)inline_delimiter(})>delimiter(")> operator(+) operator(()ident(method) operator(?) string<delimiter(")content( in `)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(')delimiter(")> operator(:) string<delimiter(")delimiter(")>operator(\)) + + reserved(if) ident(context) reserved(then) + reserved(return) ident(handle_breakpoint)operator(()ident(context)operator(,) ident(message)operator(,) ident(file)operator(,) ident(line)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + constant(Binding)operator(.)ident(of_caller) reserved(do) operator(|)ident(binding_context)operator(|) + ident(handle_breakpoint)operator(()ident(binding_context)operator(,) ident(message)operator(,) ident(file)operator(,) ident(line)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + reserved(end) + + reserved(module) class(CommandBundle) comment(#:nodoc:) + comment(# Proxy to a Breakpoint client. Lets you directly execute code) + comment(# in the context of the client.) + reserved(class) class(Client) comment(#:nodoc:) + reserved(def) method(initialize)operator(()ident(eval_handler)operator(\)) comment(# :nodoc:) + ident(eval_handler)operator(.)ident(untaint) + instance_variable(@eval_handler) operator(=) ident(eval_handler) + reserved(end) + + ident(instance_methods)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + reserved(next) reserved(if) ident(method)operator([)regexp<delimiter(/)content(^__.+__$)delimiter(/)>operator(]) + ident(undef_method) ident(method) + reserved(end) + + comment(# Executes the specified code at the client.) + reserved(def) method(eval)operator(()ident(code)operator(\)) + instance_variable(@eval_handler)operator(.)ident(call)operator(()ident(code)operator(\)) + reserved(end) + + comment(# Will execute the specified statement at the client.) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(if) ident(args)operator(.)ident(empty?) reserved(and) reserved(not) ident(block) + ident(result) operator(=) ident(eval) string<delimiter(")inline<inline_delimiter(#{)ident(method)inline_delimiter(})>delimiter(")> + reserved(else) + comment(# This is a bit ugly. The alternative would be using an) + comment(# eval context instead of an eval handler for executing) + comment(# the code at the client. The problem with that approach) + comment(# is that we would have to handle special expressions) + comment(# like "self", "nil" or constants ourself which is hard.) + ident(remote) operator(=) ident(eval) string<delimiter(%{)content( + result = lambda )nesting_delimiter({)content( |block, *args| )inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content((*args, &block\) )nesting_delimiter(})content( + def result.call_with_block(*args, &block\) + call(block, *args\) + end + result + )delimiter(})> + ident(remote)operator(.)ident(call_with_block)operator(()operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(return) ident(result) + reserved(end) + reserved(end) + + comment(# Returns the source code surrounding the location where the) + comment(# breakpoint was issued.) + reserved(def) method(source_lines)operator(()ident(context) operator(=) integer(5)operator(,) ident(return_line_numbers) operator(=) pre_constant(false)operator(\)) + ident(lines) operator(=) constant(File)operator(.)ident(readlines)operator(()instance_variable(@__bp_file)operator(\))operator(.)ident(map) operator({) operator(|)ident(line)operator(|) ident(line)operator(.)ident(chomp) operator(}) + + ident(break_line) operator(=) instance_variable(@__bp_line) + ident(start_line) operator(=) operator([)ident(break_line) operator(-) ident(context)operator(,) integer(1)operator(])operator(.)ident(max) + ident(end_line) operator(=) ident(break_line) operator(+) ident(context) + + ident(result) operator(=) ident(lines)operator([)operator(()ident(start_line) operator(-) integer(1)operator(\)) operator(..) operator(()ident(end_line) operator(-) integer(1)operator(\))operator(]) + + reserved(if) ident(return_line_numbers) reserved(then) + reserved(return) operator([)ident(start_line)operator(,) ident(break_line)operator(,) ident(result)operator(]) + reserved(else) + reserved(return) ident(result) + reserved(end) + reserved(end) + + comment(# Lets an object that will forward method calls to the breakpoint) + comment(# client. This is useful for outputting longer things at the client) + comment(# and so on. You can for example do these things:) + comment(#) + comment(# client.puts "Hello" # outputs "Hello" at client console) + comment(# # outputs "Hello" into the file temp.txt at the client) + comment(# client.File.open("temp.txt", "w"\) { |f| f.puts "Hello" } ) + reserved(def) method(client)operator(()operator(\)) + reserved(if) constant(Breakpoint)operator(.)ident(use_drb?) reserved(then) + ident(sleep)operator(()float(0.5)operator(\)) reserved(until) constant(Breakpoint)operator(.)ident(drb_service)operator(.)ident(eval_handler) + constant(Client)operator(.)ident(new)operator(()constant(Breakpoint)operator(.)ident(drb_service)operator(.)ident(eval_handler)operator(\)) + reserved(else) + constant(Client)operator(.)ident(new)operator(()ident(lambda) operator({) operator(|)ident(code)operator(|) ident(eval)operator(()ident(code)operator(,) constant(TOPLEVEL_BINDING)operator(\)) operator(})operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(handle_breakpoint)operator(()ident(context)operator(,) ident(message)operator(,) ident(file) operator(=) string<delimiter(")delimiter(")>operator(,) ident(line) operator(=) string<delimiter(")delimiter(")>operator(,) operator(&)ident(block)operator(\)) comment(# :nodoc:) + ident(catch)operator(()symbol(:debug_return)operator(\)) reserved(do) operator(|)ident(value)operator(|) + ident(eval)operator(()string<delimiter(%{)content( + @__bp_file = )inline<inline_delimiter(#{)ident(file)operator(.)ident(inspect)inline_delimiter(})>content( + @__bp_line = )inline<inline_delimiter(#{)ident(line)inline_delimiter(})>content( + extend Breakpoint::CommandBundle + extend DRbUndumped if self + )delimiter(})>operator(,) ident(context)operator(\)) reserved(rescue) pre_constant(nil) + + reserved(if) reserved(not) ident(use_drb?) reserved(then) + ident(puts) ident(message) + constant(IRB)operator(.)ident(start)operator(()pre_constant(nil)operator(,) constant(IRB)operator(::)constant(WorkSpace)operator(.)ident(new)operator(()ident(context)operator(\))operator(\)) + reserved(else) + instance_variable(@drb_service)operator(.)ident(add_breakpoint)operator(()ident(context)operator(,) ident(message)operator(\)) + reserved(end) + + ident(block)operator(.)ident(call) reserved(if) ident(block) + reserved(end) + reserved(end) + + comment(# These exceptions will be raised on failed asserts) + comment(# if Breakpoint.asserts_cause_exceptions is set to) + comment(# true.) + reserved(class) class(FailedAssertError) operator(<) constant(RuntimeError) comment(#:nodoc:) + reserved(end) + + comment(# This asserts that the block evaluates to true.) + comment(# If it doesn't evaluate to true a breakpoint will) + comment(# automatically be created at that execution point.) + comment(#) + comment(# You can disable assert checking in production) + comment(# code by setting Breakpoint.optimize_asserts to) + comment(# true. (It will still be enabled when Ruby is run) + comment(# via the -d argument.\)) + comment(#) + comment(# Example:) + comment(# person_name = "Foobar") + comment(# assert { not person_name.nil? }) + comment(#) + comment(# Note: If you want to use this method from an) + comment(# unit test, you will have to call it by its full) + comment(# name, Breakpoint.assert.) + reserved(def) method(assert)operator(()ident(context) operator(=) pre_constant(nil)operator(,) operator(&)ident(condition)operator(\)) + reserved(return) reserved(if) constant(Breakpoint)operator(.)ident(optimize_asserts) reserved(and) reserved(not) global_variable($DEBUG) + reserved(return) reserved(if) reserved(yield) + + ident(callstack) operator(=) ident(caller) + ident(callstack)operator(.)ident(slice!)operator(()integer(0)operator(,) integer(3)operator(\)) reserved(if) ident(callstack)operator(.)ident(first)operator([)string<delimiter(")content(assert)delimiter(")>operator(]) + ident(file)operator(,) ident(line)operator(,) ident(method) operator(=) operator(*)ident(callstack)operator(.)ident(first)operator(.)ident(match)operator(()regexp<delimiter(/)content(^(.+?\):()char(\\d)content(+\)(?::in `(.*?\)'\)?)delimiter(/)>operator(\))operator(.)ident(captures) + + ident(message) operator(=) string<delimiter(")content(Assert failed at )inline<inline_delimiter(#{)ident(file)inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(line)inline_delimiter(})>inline<inline_delimiter(#{)string<delimiter(")content( in `)inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content(')delimiter(")> reserved(if) ident(method)inline_delimiter(})>content(.)delimiter(")> + + reserved(if) constant(Breakpoint)operator(.)ident(asserts_cause_exceptions) reserved(and) reserved(not) global_variable($DEBUG) reserved(then) + ident(raise)operator(()constant(Breakpoint)operator(::)constant(FailedAssertError)operator(,) ident(message)operator(\)) + reserved(end) + + ident(message) operator(+=) string<delimiter(")content( Executing implicit breakpoint.)delimiter(")> + + reserved(if) ident(context) reserved(then) + reserved(return) ident(handle_breakpoint)operator(()ident(context)operator(,) ident(message)operator(,) ident(file)operator(,) ident(line)operator(\)) + reserved(end) + + constant(Binding)operator(.)ident(of_caller) reserved(do) operator(|)ident(context)operator(|) + ident(handle_breakpoint)operator(()ident(context)operator(,) ident(message)operator(,) ident(file)operator(,) ident(line)operator(\)) + reserved(end) + reserved(end) + + comment(# Whether asserts should be ignored if not in debug mode.) + comment(# Debug mode can be enabled by running ruby with the -d) + comment(# switch or by setting $DEBUG to true.) + ident(attr_accessor) symbol(:optimize_asserts) + pre_constant(self)operator(.)ident(optimize_asserts) operator(=) pre_constant(false) + + comment(# Whether an Exception should be raised on failed asserts) + comment(# in non-$DEBUG code or not. By default this is disabled.) + ident(attr_accessor) symbol(:asserts_cause_exceptions) + pre_constant(self)operator(.)ident(asserts_cause_exceptions) operator(=) pre_constant(false) + instance_variable(@use_drb) operator(=) pre_constant(false) + + ident(attr_reader) symbol(:drb_service) comment(# :nodoc:) + + reserved(class) class(DRbService) comment(# :nodoc:) + ident(include) constant(DRbUndumped) + + reserved(def) method(initialize) + instance_variable(@handler) operator(=) instance_variable(@eval_handler) operator(=) instance_variable(@collision_handler) operator(=) pre_constant(nil) + + constant(IRB)operator(.)ident(instance_eval) operator({) instance_variable(@CONF)operator([)symbol(:RC)operator(]) operator(=) pre_constant(true) operator(}) + constant(IRB)operator(.)ident(run_config) + reserved(end) + + reserved(def) method(collision) + ident(sleep)operator(()float(0.5)operator(\)) reserved(until) instance_variable(@collision_handler) + + instance_variable(@collision_handler)operator(.)ident(untaint) + + instance_variable(@collision_handler)operator(.)ident(call) + reserved(end) + + reserved(def) method(ping)operator(()operator(\)) reserved(end) + + reserved(def) method(add_breakpoint)operator(()ident(context)operator(,) ident(message)operator(\)) + ident(workspace) operator(=) constant(IRB)operator(::)constant(WorkSpace)operator(.)ident(new)operator(()ident(context)operator(\)) + ident(workspace)operator(.)ident(extend)operator(()constant(DRbUndumped)operator(\)) + + ident(sleep)operator(()float(0.5)operator(\)) reserved(until) instance_variable(@handler) + + instance_variable(@handler)operator(.)ident(untaint) + instance_variable(@handler)operator(.)ident(call)operator(()ident(workspace)operator(,) ident(message)operator(\)) + reserved(end) + + ident(attr_accessor) symbol(:handler)operator(,) symbol(:eval_handler)operator(,) symbol(:collision_handler) + reserved(end) + + comment(# Will run Breakpoint in DRb mode. This will spawn a server) + comment(# that can be attached to via the breakpoint-client command) + comment(# whenever a breakpoint is executed. This is useful when you) + comment(# are debugging CGI applications or other applications where) + comment(# you can't access debug sessions via the standard input and) + comment(# output of your application.) + comment(#) + comment(# You can specify an URI where the DRb server will run at.) + comment(# This way you can specify the port the server runs on. The) + comment(# default URI is druby://localhost:42531.) + comment(#) + comment(# Please note that breakpoints will be skipped silently in) + comment(# case the DRb server can not spawned. (This can happen if) + comment(# the port is already used by another instance of your) + comment(# application on CGI or another application.\)) + comment(#) + comment(# Also note that by default this will only allow access) + comment(# from localhost. You can however specify a list of) + comment(# allowed hosts or nil (to allow access from everywhere\).) + comment(# But that will still not protect you from somebody) + comment(# reading the data as it goes through the net.) + comment(#) + comment(# A good approach for getting security and remote access) + comment(# is setting up an SSH tunnel between the DRb service) + comment(# and the client. This is usually done like this:) + comment(#) + comment(# $ ssh -L20000:127.0.0.1:20000 -R10000:127.0.0.1:10000 example.com) + comment(# (This will connect port 20000 at the client side to port) + comment(# 20000 at the server side, and port 10000 at the server) + comment(# side to port 10000 at the client side.\)) + comment(#) + comment(# After that do this on the server side: (the code being debugged\)) + comment(# Breakpoint.activate_drb("druby://127.0.0.1:20000", "localhost"\)) + comment(#) + comment(# And at the client side:) + comment(# ruby breakpoint_client.rb -c druby://127.0.0.1:10000 -s druby://127.0.0.1:20000) + comment(#) + comment(# Running through such a SSH proxy will also let you use ) + comment(# breakpoint.rb in case you are behind a firewall.) + comment(#) + comment(# Detailed information about running DRb through firewalls is) + comment(# available at http://www.rubygarden.org/ruby?DrbTutorial) + reserved(def) method(activate_drb)operator(()ident(uri) operator(=) pre_constant(nil)operator(,) ident(allowed_hosts) operator(=) operator([)string<delimiter(')content(localhost)delimiter(')>operator(,) string<delimiter(')content(127.0.0.1)delimiter(')>operator(,) string<delimiter(')content(::1)delimiter(')>operator(])operator(,) + ident(ignore_collisions) operator(=) pre_constant(false)operator(\)) + + reserved(return) pre_constant(false) reserved(if) instance_variable(@use_drb) + + ident(uri) operator(||=) string<delimiter(')content(druby://localhost:42531)delimiter(')> + + reserved(if) ident(allowed_hosts) reserved(then) + ident(acl) operator(=) operator([)string<delimiter(")content(deny)delimiter(")>operator(,) string<delimiter(")content(all)delimiter(")>operator(]) + + ident(Array)operator(()ident(allowed_hosts)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(host)operator(|) + ident(acl) operator(+=) operator([)string<delimiter(")content(allow)delimiter(")>operator(,) ident(host)operator(]) + reserved(end) + + constant(DRb)operator(.)ident(install_acl)operator(()constant(ACL)operator(.)ident(new)operator(()ident(acl)operator(\))operator(\)) + reserved(end) + + instance_variable(@use_drb) operator(=) pre_constant(true) + instance_variable(@drb_service) operator(=) constant(DRbService)operator(.)ident(new) + ident(did_collision) operator(=) pre_constant(false) + reserved(begin) + instance_variable(@service) operator(=) constant(DRb)operator(.)ident(start_service)operator(()ident(uri)operator(,) instance_variable(@drb_service)operator(\)) + reserved(rescue) constant(Errno)operator(::)constant(EADDRINUSE) + reserved(if) ident(ignore_collisions) reserved(then) + pre_constant(nil) + reserved(else) + comment(# The port is already occupied by another) + comment(# Breakpoint service. We will try to tell) + comment(# the old service that we want its port.) + comment(# It will then forward that request to the) + comment(# user and retry.) + reserved(unless) ident(did_collision) reserved(then) + constant(DRbObject)operator(.)ident(new)operator(()pre_constant(nil)operator(,) ident(uri)operator(\))operator(.)ident(collision) + ident(did_collision) operator(=) pre_constant(true) + reserved(end) + ident(sleep)operator(()integer(10)operator(\)) + reserved(retry) + reserved(end) + reserved(end) + + reserved(return) pre_constant(true) + reserved(end) + + comment(# Deactivates a running Breakpoint service.) + reserved(def) method(deactivate_drb) + instance_variable(@service)operator(.)ident(stop_service) reserved(unless) instance_variable(@service)operator(.)ident(nil?) + instance_variable(@service) operator(=) pre_constant(nil) + instance_variable(@use_drb) operator(=) pre_constant(false) + instance_variable(@drb_service) operator(=) pre_constant(nil) + reserved(end) + + comment(# Returns true when Breakpoints are used over DRb.) + comment(# Breakpoint.activate_drb causes this to be true.) + reserved(def) method(use_drb?) + instance_variable(@use_drb) operator(==) pre_constant(true) + reserved(end) +reserved(end) + +reserved(module) class(IRB) comment(#:nodoc:) + reserved(class) operator(<<) class(self)operator(;) ident(remove_method) symbol(:start)operator(;) reserved(end) + reserved(def) pre_constant(self)operator(.)ident(start)operator(()ident(ap_path) operator(=) pre_constant(nil)operator(,) ident(main_context) operator(=) pre_constant(nil)operator(,) ident(workspace) operator(=) pre_constant(nil)operator(\)) + global_variable($0) operator(=) constant(File)operator(::)ident(basename)operator(()ident(ap_path)operator(,) string<delimiter(")content(.rb)delimiter(")>operator(\)) reserved(if) ident(ap_path) + + comment(# suppress some warnings about redefined constants) + ident(old_verbose)operator(,) global_variable($VERBOSE) operator(=) global_variable($VERBOSE)operator(,) pre_constant(nil) + constant(IRB)operator(.)ident(setup)operator(()ident(ap_path)operator(\)) + global_variable($VERBOSE) operator(=) ident(old_verbose) + + reserved(if) instance_variable(@CONF)operator([)symbol(:SCRIPT)operator(]) reserved(then) + ident(irb) operator(=) constant(Irb)operator(.)ident(new)operator(()ident(main_context)operator(,) instance_variable(@CONF)operator([)symbol(:SCRIPT)operator(])operator(\)) + reserved(else) + ident(irb) operator(=) constant(Irb)operator(.)ident(new)operator(()ident(main_context)operator(\)) + reserved(end) + + reserved(if) ident(workspace) reserved(then) + ident(irb)operator(.)ident(context)operator(.)ident(workspace) operator(=) ident(workspace) + reserved(end) + + instance_variable(@CONF)operator([)symbol(:IRB_RC)operator(])operator(.)ident(call)operator(()ident(irb)operator(.)ident(context)operator(\)) reserved(if) instance_variable(@CONF)operator([)symbol(:IRB_RC)operator(]) + instance_variable(@CONF)operator([)symbol(:MAIN_CONTEXT)operator(]) operator(=) ident(irb)operator(.)ident(context) + + ident(old_sigint) operator(=) ident(trap)operator(()string<delimiter(")content(SIGINT)delimiter(")>operator(\)) reserved(do) + reserved(begin) + ident(irb)operator(.)ident(signal_handle) + reserved(rescue) constant(RubyLex)operator(::)constant(TerminateLineInput) + comment(# ignored) + reserved(end) + reserved(end) + + ident(catch)operator(()symbol(:IRB_EXIT)operator(\)) reserved(do) + ident(irb)operator(.)ident(eval_input) + reserved(end) + reserved(ensure) + ident(trap)operator(()string<delimiter(")content(SIGINT)delimiter(")>operator(,) ident(old_sigint)operator(\)) + reserved(end) + + reserved(class) operator(<<) class(self) + reserved(alias) symbol(:old_CurrentContext) symbol(:CurrentContext) + ident(remove_method) symbol(:CurrentContext) + reserved(end) + reserved(def) constant(IRB)operator(.)constant(CurrentContext) + reserved(if) ident(old_CurrentContext)operator(.)ident(nil?) reserved(and) constant(Breakpoint)operator(.)ident(use_drb?) reserved(then) + ident(result) operator(=) constant(Object)operator(.)ident(new) + reserved(def) ident(result)operator(.)ident(last_value)operator(;) reserved(end) + reserved(return) ident(result) + reserved(else) + ident(old_CurrentContext) + reserved(end) + reserved(end) + reserved(def) constant(IRB)operator(.)ident(parse_opts)operator(()operator(\)) reserved(end) + + reserved(class) class(Context) comment(#:nodoc:) + reserved(alias) symbol(:old_evaluate) symbol(:evaluate) + reserved(def) method(evaluate)operator(()ident(line)operator(,) ident(line_no)operator(\)) + reserved(if) ident(line)operator(.)ident(chomp) operator(==) string<delimiter(")content(exit)delimiter(")> reserved(then) + ident(exit) + reserved(else) + ident(old_evaluate)operator(()ident(line)operator(,) ident(line_no)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(class) class(WorkSpace) comment(#:nodoc:) + reserved(alias) symbol(:old_evaluate) symbol(:evaluate) + + reserved(def) method(evaluate)operator(()operator(*)ident(args)operator(\)) + reserved(if) constant(Breakpoint)operator(.)ident(use_drb?) reserved(then) + ident(result) operator(=) ident(old_evaluate)operator(()operator(*)ident(args)operator(\)) + reserved(if) ident(args)operator([)integer(0)operator(]) operator(!=) symbol(:no_proxy) reserved(and) + reserved(not) operator([)pre_constant(true)operator(,) pre_constant(false)operator(,) pre_constant(nil)operator(])operator(.)ident(include?)operator(()ident(result)operator(\)) + reserved(then) + ident(result)operator(.)ident(extend)operator(()constant(DRbUndumped)operator(\)) reserved(rescue) pre_constant(nil) + reserved(end) + reserved(return) ident(result) + reserved(else) + ident(old_evaluate)operator(()operator(*)ident(args)operator(\)) + reserved(end) + reserved(end) + reserved(end) + + reserved(module) class(InputCompletor) comment(#:nodoc:) + reserved(def) pre_constant(self)operator(.)ident(eval)operator(()ident(code)operator(,) ident(context)operator(,) operator(*)ident(more)operator(\)) + comment(# Big hack, this assumes that InputCompletor) + comment(# will only call eval(\) when it wants code) + comment(# to be executed in the IRB context.) + constant(IRB)operator(.)ident(conf)operator([)symbol(:MAIN_CONTEXT)operator(])operator(.)ident(workspace)operator(.)ident(evaluate)operator(()symbol(:no_proxy)operator(,) ident(code)operator(,) operator(*)ident(more)operator(\)) + reserved(end) + reserved(end) +reserved(end) + +reserved(module) class(DRb) comment(# :nodoc:) + reserved(class) class(DRbObject) comment(#:nodoc:) + reserved(undef) symbol(:inspect) reserved(if) ident(method_defined?)operator(()symbol(:inspect)operator(\)) + reserved(undef) symbol(:clone) reserved(if) ident(method_defined?)operator(()symbol(:clone)operator(\)) + reserved(end) +reserved(end) + +comment(# See Breakpoint.breakpoint) +reserved(def) method(breakpoint)operator(()ident(id) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + constant(Binding)operator(.)ident(of_caller) reserved(do) operator(|)ident(context)operator(|) + constant(Breakpoint)operator(.)ident(breakpoint)operator(()ident(id)operator(,) ident(context)operator(,) operator(&)ident(block)operator(\)) + reserved(end) +reserved(end) + +comment(# See Breakpoint.assert) +reserved(def) method(assert)operator(()operator(&)ident(block)operator(\)) + constant(Binding)operator(.)ident(of_caller) reserved(do) operator(|)ident(context)operator(|) + constant(Breakpoint)operator(.)ident(assert)operator(()ident(context)operator(,) operator(&)ident(block)operator(\)) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) + reserved(module) class(CachingTools) comment(#:nodoc:) + + comment(# Provide shortcuts to simply the creation of nested default hashes. This) + comment(# pattern is useful, common practice, and unsightly when done manually.) + reserved(module) class(HashCaching) + comment(# Dynamically create a nested hash structure used to cache calls to +method_name+) + comment(# The cache method is named +#{method_name}_cache+ unless :as => :alternate_name) + comment(# is given.) + comment(#) + comment(# The hash structure is created using nested Hash.new. For example:) + comment(# ) + comment(# def slow_method(a, b\) a ** b end) + comment(# ) + comment(# can be cached using hash_cache :slow_method, which will define the method) + comment(# slow_method_cache. We can then find the result of a ** b using:) + comment(# ) + comment(# slow_method_cache[a][b]) + comment(# ) + comment(# The hash structure returned by slow_method_cache would look like this:) + comment(# ) + comment(# Hash.new do |as, a|) + comment(# as[a] = Hash.new do |bs, b|) + comment(# bs[b] = slow_method(a, b\)) + comment(# end) + comment(# end) + comment(# ) + comment(# The generated code is actually compressed onto a single line to maintain) + comment(# sensible backtrace signatures.) + comment(#) + reserved(def) method(hash_cache)operator(()ident(method_name)operator(,) ident(options) operator(=) operator({)operator(})operator(\)) + ident(selector) operator(=) ident(options)operator([)symbol(:as)operator(]) operator(||) string<delimiter(")inline<inline_delimiter(#{)ident(method_name)inline_delimiter(})>content(_cache)delimiter(")> + ident(method) operator(=) pre_constant(self)operator(.)ident(instance_method)operator(()ident(method_name)operator(\)) + + ident(args) operator(=) operator([)operator(]) + ident(code) operator(=) string<delimiter(")content(def )inline<inline_delimiter(#{)ident(selector)inline_delimiter(})>content((\); @)inline<inline_delimiter(#{)ident(selector)inline_delimiter(})>content( ||= )delimiter(")> + + operator(()integer(1)operator(..)ident(method)operator(.)ident(arity)operator(\))operator(.)ident(each) reserved(do) operator(|)ident(n)operator(|) + ident(args) operator(<<) string<delimiter(")content(v)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>delimiter(")> + ident(code) operator(<<) string<delimiter(")content(Hash.new {|h)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>content(, v)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>content(| h)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>content([v)inline<inline_delimiter(#{)ident(n)inline_delimiter(})>content(] = )delimiter(")> + reserved(end) + + comment(# Add the method call with arguments, followed by closing braces and end.) + ident(code) operator(<<) string<delimiter(")inline<inline_delimiter(#{)ident(method_name)inline_delimiter(})>content(()inline<inline_delimiter(#{)ident(args) operator(*) string<delimiter(')content(, )delimiter(')>inline_delimiter(})>content(\) )inline<inline_delimiter(#{)string<delimiter(')content(})delimiter(')> operator(*) ident(method)operator(.)ident(arity)inline_delimiter(})>content( end)delimiter(")> + + comment(# Extract the line number information from the caller. Exceptions arising) + comment(# in the generated code should point to the +hash_cache :...+ line.) + reserved(if) ident(caller)operator([)integer(0)operator(]) operator(&&) regexp<delimiter(/)content(^(.*\):()char(\\d)content(+\)$)delimiter(/)> operator(=)operator(~) ident(caller)operator([)integer(0)operator(]) + ident(file)operator(,) ident(line_number) operator(=) global_variable($1)operator(,) global_variable($2)operator(.)ident(to_i) + reserved(else) comment(# We can't give good trackback info; fallback to this line:) + ident(file)operator(,) ident(line_number) operator(=) pre_constant(__FILE__)operator(,) pre_constant(__LINE__) + reserved(end) + + comment(# We use eval rather than building proc's because it allows us to avoid) + comment(# linking the Hash's to this method's binding. Experience has shown that) + comment(# doing so can cause obtuse memory leaks.) + ident(class_eval) ident(code)operator(,) ident(file)operator(,) ident(line_number) + reserved(end) + reserved(end) + + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(logger)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/core_ext/class/attribute_accessors)delimiter(')> + +reserved(class) class(Logger) comment(#:nodoc:) + ident(cattr_accessor) symbol(:silencer) + pre_constant(self)operator(.)ident(silencer) operator(=) pre_constant(true) + + comment(# Silences the logger for the duration of the block.) + reserved(def) method(silence)operator(()ident(temporary_level) operator(=) constant(Logger)operator(::)constant(ERROR)operator(\)) + reserved(if) ident(silencer) + reserved(begin) + ident(old_logger_level)operator(,) pre_constant(self)operator(.)ident(level) operator(=) ident(level)operator(,) ident(temporary_level) + reserved(yield) pre_constant(self) + reserved(ensure) + pre_constant(self)operator(.)ident(level) operator(=) ident(old_logger_level) + reserved(end) + reserved(else) + reserved(yield) pre_constant(self) + reserved(end) + reserved(end) + + ident(private) + reserved(alias) method(old_format_message) method(format_message) + + comment(# Ruby 1.8.3 transposed the msg and progname arguments to format_message.) + comment(# We can't test RUBY_VERSION because some distributions don't keep Ruby) + comment(# and its standard library in sync, leading to installations of Ruby 1.8.2) + comment(# with Logger from 1.8.3 and vice versa.) + reserved(if) ident(method_defined?)operator(()symbol(:formatter=)operator(\)) + reserved(def) method(format_message)operator(()ident(severity)operator(,) ident(timestamp)operator(,) ident(progname)operator(,) ident(msg)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(msg)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + reserved(else) + reserved(def) method(format_message)operator(()ident(severity)operator(,) ident(timestamp)operator(,) ident(msg)operator(,) ident(progname)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(msg)inline_delimiter(})>char(\\n)delimiter(")> + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Array) comment(#:nodoc:) + reserved(module) class(Conversions) + comment(# Converts the array to comma-seperated sentence where the last element is joined by the connector word. Options:) + comment(# * <tt>:connector</tt>: The word used to join the last element in arrays with more than two elements (default: "and"\)) + comment(# * <tt>:skip_last_comma</tt>: Set to true to return "a, b, and c" instead of "a, b and c".) + reserved(def) method(to_sentence)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator(.)ident(assert_valid_keys)operator(()symbol(:connector)operator(,) symbol(:skip_last_comma)operator(\)) + ident(options)operator(.)ident(reverse_merge!) symbol(:connector) operator(=)operator(>) string<delimiter(')content(and)delimiter(')>operator(,) symbol(:skip_last_comma) operator(=)operator(>) pre_constant(false) + + reserved(case) ident(length) + reserved(when) integer(0) + string<delimiter(")delimiter(")> + reserved(when) integer(1) + pre_constant(self)operator([)integer(0)operator(]) + reserved(when) integer(2) + string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator([)integer(0)operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(options)operator([)symbol(:connector)operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)pre_constant(self)operator([)integer(1)operator(])inline_delimiter(})>delimiter(")> + reserved(else) + string<delimiter(")inline<inline_delimiter(#{)pre_constant(self)operator([)integer(0)operator(...)integer(-1)operator(])operator(.)ident(join)operator(()string<delimiter(')content(, )delimiter(')>operator(\))inline_delimiter(})>inline<inline_delimiter(#{)ident(options)operator([)symbol(:skip_last_comma)operator(]) operator(?) string<delimiter(')delimiter(')> operator(:) string<delimiter(')content(,)delimiter(')>inline_delimiter(})>content( )inline<inline_delimiter(#{)ident(options)operator([)symbol(:connector)operator(])inline_delimiter(})>content( )inline<inline_delimiter(#{)pre_constant(self)operator([)integer(-1)operator(])inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# When an array is given to url_for, it is converted to a slash separated string.) + reserved(def) method(to_param) + ident(join) string<delimiter(')content(/)delimiter(')> + reserved(end) + + reserved(def) method(to_xml)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(raise) string<delimiter(")content(Not all elements respond to to_xml)delimiter(")> reserved(unless) ident(all?) operator({) operator(|)ident(e)operator(|) ident(e)operator(.)ident(respond_to?) symbol(:to_xml) operator(}) + + ident(options)operator([)symbol(:root)operator(]) operator(||=) ident(all?) operator({) operator(|)ident(e)operator(|) ident(e)operator(.)ident(is_a?)operator(()ident(first)operator(.)ident(class)operator(\)) operator(&&) ident(first)operator(.)ident(class)operator(.)ident(to_s) operator(!=) string<delimiter(")content(Hash)delimiter(")> operator(}) operator(?) ident(first)operator(.)ident(class)operator(.)ident(to_s)operator(.)ident(underscore)operator(.)ident(pluralize) operator(:) string<delimiter(")content(records)delimiter(")> + ident(options)operator([)symbol(:children)operator(]) operator(||=) ident(options)operator([)symbol(:root)operator(])operator(.)ident(singularize) + ident(options)operator([)symbol(:indent)operator(]) operator(||=) integer(2) + ident(options)operator([)symbol(:builder)operator(]) operator(||=) constant(Builder)operator(::)constant(XmlMarkup)operator(.)ident(new)operator(()symbol(:indent) operator(=)operator(>) ident(options)operator([)symbol(:indent)operator(])operator(\)) + + ident(root) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:root)operator(\)) + ident(children) operator(=) ident(options)operator(.)ident(delete)operator(()symbol(:children)operator(\)) + + ident(options)operator([)symbol(:builder)operator(])operator(.)ident(instruct!) reserved(unless) ident(options)operator(.)ident(delete)operator(()symbol(:skip_instruct)operator(\)) + ident(options)operator([)symbol(:builder)operator(])operator(.)ident(tag!)operator(()ident(root)operator(.)ident(to_s)operator(.)ident(dasherize)operator(\)) operator({) ident(each) operator({) operator(|)ident(e)operator(|) ident(e)operator(.)ident(to_xml)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(,) symbol(:root) operator(=)operator(>) ident(children) operator(})operator(\))operator(\)) operator(}) operator(}) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/array/conversions)delimiter(')> + +reserved(class) class(Array) comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Array)operator(::)constant(Conversions) + + comment(# Iterate over an array in groups of a certain size, padding any remaining ) + comment(# slots with specified value (<tt>nil</tt> by default\).) + comment(# ) + comment(# E.g.) + comment(# ) + comment(# %w(1 2 3 4 5 6 7\).in_groups_of(3\) {|g| p g}) + comment(# ["1", "2", "3"]) + comment(# ["4", "5", "6"]) + comment(# ["7", nil, nil]) + reserved(def) method(in_groups_of)operator(()ident(number)operator(,) ident(fill_with) operator(=) pre_constant(nil)operator(,) operator(&)ident(block)operator(\)) + ident(require) string<delimiter(')content(enumerator)delimiter(')> + ident(collection) operator(=) ident(dup) + ident(collection) operator(<<) ident(fill_with) reserved(until) ident(collection)operator(.)ident(size)operator(.)ident(modulo)operator(()ident(number)operator(\))operator(.)ident(zero?) + ident(collection)operator(.)ident(each_slice)operator(()ident(number)operator(,) operator(&)ident(block)operator(\)) + reserved(end) +reserved(end) +reserved(class) class(Object) comment(#:nodoc:) + comment(# "", " ", nil, [], and {} are blank) + reserved(def) method(blank?) + reserved(if) ident(respond_to?)operator(()symbol(:empty?)operator(\)) operator(&&) ident(respond_to?)operator(()symbol(:strip)operator(\)) + ident(empty?) reserved(or) ident(strip)operator(.)ident(empty?) + reserved(elsif) ident(respond_to?)operator(()symbol(:empty?)operator(\)) + ident(empty?) + reserved(else) + operator(!)pre_constant(self) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(NilClass) comment(#:nodoc:) + reserved(def) method(blank?) + pre_constant(true) + reserved(end) +reserved(end) + +reserved(class) class(FalseClass) comment(#:nodoc:) + reserved(def) method(blank?) + pre_constant(true) + reserved(end) +reserved(end) + +reserved(class) class(TrueClass) comment(#:nodoc:) + reserved(def) method(blank?) + pre_constant(false) + reserved(end) +reserved(end) + +reserved(class) class(Array) comment(#:nodoc:) + ident(alias_method) symbol(:blank?)operator(,) symbol(:empty?) +reserved(end) + +reserved(class) class(Hash) comment(#:nodoc:) + ident(alias_method) symbol(:blank?)operator(,) symbol(:empty?) +reserved(end) + +reserved(class) class(String) comment(#:nodoc:) + reserved(def) method(blank?) + ident(empty?) operator(||) ident(strip)operator(.)ident(empty?) + reserved(end) +reserved(end) + +reserved(class) class(Numeric) comment(#:nodoc:) + reserved(def) method(blank?) + pre_constant(false) + reserved(end) +ident(endmodule) constant(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(CGI) comment(#:nodoc:) + reserved(module) class(EscapeSkippingSlashes) comment(#:nodoc:) + reserved(def) method(escape_skipping_slashes)operator(()ident(str)operator(\)) + ident(str) operator(=) ident(str)operator(.)ident(join)operator(()string<delimiter(')content(/)delimiter(')>operator(\)) reserved(if) ident(str)operator(.)ident(respond_to?) symbol(:join) + ident(str)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(([^ )char(\\/)content(a-zA-Z0-9_.-]\))delimiter(/)modifier(n)>operator(\)) reserved(do) + string<delimiter(")content(%)inline<inline_delimiter(#{)global_variable($1)operator(.)ident(unpack)operator(()string<delimiter(')content(H2)delimiter(')>operator(\))operator(.)ident(first)operator(.)ident(upcase)inline_delimiter(})>delimiter(")> + reserved(end)operator(.)ident(tr)operator(()string<delimiter(')content( )delimiter(')>operator(,) string<delimiter(')content(+)delimiter(')>operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/cgi/escape_skipping_slashes)delimiter(')> + +reserved(class) class(CGI) comment(#:nodoc:) + ident(extend)operator(()constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(CGI)operator(::)constant(EscapeSkippingSlashes)operator(\)) +reserved(end) +comment(# Extends the class object with class and instance accessors for class attributes,) +comment(# just like the native attr* accessors for instance attributes.) +reserved(class) class(Class) comment(# :nodoc:) + reserved(def) method(cattr_reader)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval)operator(()string<delimiter(<<-EOS)>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)operator(\))string<content( + unless defined? @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = nil + end + + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(cattr_writer)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval)operator(()string<delimiter(<<-EOS)>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)operator(\))string<content( + unless defined? @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = nil + end + + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(cattr_accessor)operator(()operator(*)ident(syms)operator(\)) + ident(cattr_reader)operator(()operator(*)ident(syms)operator(\)) + ident(cattr_writer)operator(()operator(*)ident(syms)operator(\)) + reserved(end) +reserved(end) +comment(# Retain for backward compatibility. Methods are now included in Class.) +reserved(module) class(ClassInheritableAttributes) comment(# :nodoc:) +reserved(end) + +comment(# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of) +comment(# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements) +comment(# to, for example, an array without those additions being shared with either their parent, siblings, or) +comment(# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.) +reserved(class) class(Class) comment(# :nodoc:) + reserved(def) method(class_inheritable_reader)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval) string<delimiter(<<-EOS)>string<content( + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + read_inheritable_attribute(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(\) + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + self.class.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(class_inheritable_writer)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval) string<delimiter(<<-EOS)>string<content( + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + write_inheritable_attribute(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(, obj\) + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + self.class.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(class_inheritable_array_writer)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval) string<delimiter(<<-EOS)>string<content( + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + write_inheritable_array(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(, obj\) + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + self.class.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(class_inheritable_hash_writer)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval) string<delimiter(<<-EOS)>string<content( + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + write_inheritable_hash(:)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(, obj\) + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + self.class.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(class_inheritable_accessor)operator(()operator(*)ident(syms)operator(\)) + ident(class_inheritable_reader)operator(()operator(*)ident(syms)operator(\)) + ident(class_inheritable_writer)operator(()operator(*)ident(syms)operator(\)) + reserved(end) + + reserved(def) method(class_inheritable_array)operator(()operator(*)ident(syms)operator(\)) + ident(class_inheritable_reader)operator(()operator(*)ident(syms)operator(\)) + ident(class_inheritable_array_writer)operator(()operator(*)ident(syms)operator(\)) + reserved(end) + + reserved(def) method(class_inheritable_hash)operator(()operator(*)ident(syms)operator(\)) + ident(class_inheritable_reader)operator(()operator(*)ident(syms)operator(\)) + ident(class_inheritable_hash_writer)operator(()operator(*)ident(syms)operator(\)) + reserved(end) + + reserved(def) method(inheritable_attributes) + instance_variable(@inheritable_attributes) operator(||=) operator({)operator(}) + reserved(end) + + reserved(def) method(write_inheritable_attribute)operator(()ident(key)operator(,) ident(value)operator(\)) + ident(inheritable_attributes)operator([)ident(key)operator(]) operator(=) ident(value) + reserved(end) + + reserved(def) method(write_inheritable_array)operator(()ident(key)operator(,) ident(elements)operator(\)) + ident(write_inheritable_attribute)operator(()ident(key)operator(,) operator([)operator(])operator(\)) reserved(if) ident(read_inheritable_attribute)operator(()ident(key)operator(\))operator(.)ident(nil?) + ident(write_inheritable_attribute)operator(()ident(key)operator(,) ident(read_inheritable_attribute)operator(()ident(key)operator(\)) operator(+) ident(elements)operator(\)) + reserved(end) + + reserved(def) method(write_inheritable_hash)operator(()ident(key)operator(,) ident(hash)operator(\)) + ident(write_inheritable_attribute)operator(()ident(key)operator(,) operator({)operator(})operator(\)) reserved(if) ident(read_inheritable_attribute)operator(()ident(key)operator(\))operator(.)ident(nil?) + ident(write_inheritable_attribute)operator(()ident(key)operator(,) ident(read_inheritable_attribute)operator(()ident(key)operator(\))operator(.)ident(merge)operator(()ident(hash)operator(\))operator(\)) + reserved(end) + + reserved(def) method(read_inheritable_attribute)operator(()ident(key)operator(\)) + ident(inheritable_attributes)operator([)ident(key)operator(]) + reserved(end) + + reserved(def) method(reset_inheritable_attributes) + ident(inheritable_attributes)operator(.)ident(clear) + reserved(end) + + ident(private) + reserved(def) method(inherited_with_inheritable_attributes)operator(()ident(child)operator(\)) + ident(inherited_without_inheritable_attributes)operator(()ident(child)operator(\)) reserved(if) ident(respond_to?)operator(()symbol(:inherited_without_inheritable_attributes)operator(\)) + ident(child)operator(.)ident(instance_variable_set)operator(()string<delimiter(')content(@inheritable_attributes)delimiter(')>operator(,) ident(inheritable_attributes)operator(.)ident(dup)operator(\)) + reserved(end) + + reserved(alias) method(inherited_without_inheritable_attributes) method(inherited) + reserved(alias) method(inherited) method(inherited_with_inheritable_attributes) +reserved(end) +reserved(class) class(Class) comment(#:nodoc:) + reserved(def) method(remove_subclasses) + constant(Object)operator(.)ident(remove_subclasses_of)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(subclasses) + constant(Object)operator(.)ident(subclasses_of)operator(()pre_constant(self)operator(\))operator(.)ident(map) operator({) operator(|)ident(o)operator(|) ident(o)operator(.)ident(to_s) operator(}) + reserved(end) + + reserved(def) method(remove_class)operator(()operator(*)ident(klasses)operator(\)) + ident(klasses)operator(.)ident(flatten)operator(.)ident(each) reserved(do) operator(|)ident(klass)operator(|) + comment(# Skip this class if there is nothing bound to this name) + reserved(next) reserved(unless) reserved(defined?)operator(()ident(klass)operator(.)ident(name)operator(\)) + + ident(basename) operator(=) ident(klass)operator(.)ident(to_s)operator(.)ident(split)operator(()string<delimiter(")content(::)delimiter(")>operator(\))operator(.)ident(last) + ident(parent) operator(=) ident(klass)operator(.)ident(parent) + + comment(# Skip this class if it does not match the current one bound to this name) + reserved(next) reserved(unless) ident(parent)operator(.)ident(const_defined?)operator(()ident(basename)operator(\)) operator(&&) ident(klass) operator(=) ident(parent)operator(.)ident(const_get)operator(()ident(basename)operator(\)) + + ident(parent)operator(.)ident(send) symbol(:remove_const)operator(,) ident(basename) reserved(unless) ident(parent) operator(==) ident(klass) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/class/attribute_accessors)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/class/inheritable_attributes)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/class/removal)delimiter(')>reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Date) comment(#:nodoc:) + comment(# Getting dates in different convenient string representations and other objects) + reserved(module) class(Conversions) + constant(DATE_FORMATS) operator(=) operator({) + symbol(:short) operator(=)operator(>) string<delimiter(")content(%e %b)delimiter(")>operator(,) + symbol(:long) operator(=)operator(>) string<delimiter(")content(%B %e, %Y)delimiter(")> + operator(}) + + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(klass)operator(\)) comment(#:nodoc:) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:to_default_s)operator(,) symbol(:to_s)operator(\)) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:to_s)operator(,) symbol(:to_formatted_s)operator(\)) + reserved(end) + + reserved(def) method(to_formatted_s)operator(()ident(format) operator(=) symbol(:default)operator(\)) + constant(DATE_FORMATS)operator([)ident(format)operator(]) operator(?) ident(strftime)operator(()constant(DATE_FORMATS)operator([)ident(format)operator(])operator(\))operator(.)ident(strip) operator(:) ident(to_default_s) + reserved(end) + + comment(# To be able to keep Dates and Times interchangeable on conversions) + reserved(def) method(to_date) + pre_constant(self) + reserved(end) + + reserved(def) method(to_time)operator(()ident(form) operator(=) symbol(:local)operator(\)) + operator(::)constant(Time)operator(.)ident(send)operator(()ident(form)operator(,) ident(year)operator(,) ident(month)operator(,) ident(day)operator(\)) + reserved(end) + + reserved(alias) symbol(:xmlschema) symbol(:to_s) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) string<delimiter(')content(date)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/date/conversions)delimiter(')> + +reserved(class) class(Date)comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Date)operator(::)constant(Conversions) +reserved(end) +reserved(module) class(Enumerable) comment(#:nodoc:) + reserved(def) method(first_match) + ident(match) operator(=) pre_constant(nil) + ident(each) reserved(do) operator(|)ident(items)operator(|) + reserved(break) reserved(if) ident(match) operator(=) reserved(yield)operator(()ident(items)operator(\)) + reserved(end) + ident(match) + reserved(end) + + comment(# Collect an enumerable into sets, grouped by the result of a block. Useful,) + comment(# for example, for grouping records by date.) + comment(#) + comment(# e.g. ) + comment(#) + comment(# latest_transcripts.group_by(&:day\).each do |day, transcripts| ) + comment(# p "#{day} -> #{transcripts.map(&:class\) * ', '}") + comment(# end) + comment(# "2006-03-01 -> Transcript") + comment(# "2006-02-28 -> Transcript") + comment(# "2006-02-27 -> Transcript, Transcript") + comment(# "2006-02-26 -> Transcript, Transcript") + comment(# "2006-02-25 -> Transcript") + comment(# "2006-02-24 -> Transcript, Transcript") + comment(# "2006-02-23 -> Transcript") + reserved(def) method(group_by) + ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(groups)operator(,) ident(element)operator(|) + operator(()ident(groups)operator([)reserved(yield)operator(()ident(element)operator(\))operator(]) operator(||=) operator([)operator(])operator(\)) operator(<<) ident(element) + ident(groups) + reserved(end) + reserved(end) +reserved(end) +reserved(class) class(Exception) comment(# :nodoc:) + reserved(def) method(clean_message) + constant(Pathname)operator(.)ident(clean_within) ident(message) + reserved(end) + + constant(TraceSubstitutions) operator(=) operator([)operator(]) + constant(FrameworkRegexp) operator(=) regexp<delimiter(/)content(generated|vendor|dispatch|ruby|script)char(\\/)char(\\w)content(+)delimiter(/)> + + reserved(def) method(clean_backtrace) + ident(backtrace)operator(.)ident(collect) reserved(do) operator(|)ident(line)operator(|) + constant(Pathname)operator(.)ident(clean_within)operator(()constant(TraceSubstitutions)operator(.)ident(inject)operator(()ident(line)operator(\)) reserved(do) operator(|)ident(line)operator(,) operator(()ident(regexp)operator(,) ident(sub)operator(\))operator(|) + ident(line)operator(.)ident(gsub) ident(regexp)operator(,) ident(sub) + reserved(end)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(application_backtrace) + ident(before_application_frame) operator(=) pre_constant(true) + + ident(trace) operator(=) ident(clean_backtrace)operator(.)ident(reject) reserved(do) operator(|)ident(line)operator(|) + ident(non_app_frame) operator(=) operator(()ident(line) operator(=)operator(~) constant(FrameworkRegexp)operator(\)) + ident(before_application_frame) operator(=) pre_constant(false) reserved(unless) ident(non_app_frame) + ident(non_app_frame) operator(&&) operator(!) ident(before_application_frame) + reserved(end) + + comment(# If we didn't find any application frames, return an empty app trace.) + ident(before_application_frame) operator(?) operator([)operator(]) operator(:) ident(trace) + reserved(end) + + reserved(def) method(framework_backtrace) + ident(clean_backtrace)operator(.)ident(select) operator({)operator(|)ident(line)operator(|) ident(line) operator(=)operator(~) constant(FrameworkRegexp)operator(}) + reserved(end) +ident(endmodule) constant(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Hash) comment(#:nodoc:) + reserved(module) class(Conversions) + constant(XML_TYPE_NAMES) operator(=) operator({) + string<delimiter(")content(Fixnum)delimiter(")> operator(=)operator(>) string<delimiter(")content(integer)delimiter(")>operator(,) + string<delimiter(")content(Date)delimiter(")> operator(=)operator(>) string<delimiter(")content(date)delimiter(")>operator(,) + string<delimiter(")content(Time)delimiter(")> operator(=)operator(>) string<delimiter(")content(datetime)delimiter(")>operator(,) + string<delimiter(")content(TrueClass)delimiter(")> operator(=)operator(>) string<delimiter(")content(boolean)delimiter(")>operator(,) + string<delimiter(")content(FalseClass)delimiter(")> operator(=)operator(>) string<delimiter(")content(boolean)delimiter(")> + operator(}) + + constant(XML_FORMATTING) operator(=) operator({) + string<delimiter(")content(date)delimiter(")> operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(date)operator(|) ident(date)operator(.)ident(to_s)operator(()symbol(:db)operator(\)) operator(})operator(,) + string<delimiter(")content(datetime)delimiter(")> operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(time)operator(|) ident(time)operator(.)ident(xmlschema) operator(}) + operator(}) + + reserved(def) method(to_xml)operator(()ident(options) operator(=) operator({)operator(})operator(\)) + ident(options)operator([)symbol(:indent)operator(]) operator(||=) integer(2) + ident(options)operator(.)ident(reverse_merge!)operator(()operator({) symbol(:builder) operator(=)operator(>) constant(Builder)operator(::)constant(XmlMarkup)operator(.)ident(new)operator(()symbol(:indent) operator(=)operator(>) ident(options)operator([)symbol(:indent)operator(])operator(\))operator(,) symbol(:root) operator(=)operator(>) string<delimiter(")content(hash)delimiter(")> operator(})operator(\)) + ident(options)operator([)symbol(:builder)operator(])operator(.)ident(instruct!) reserved(unless) ident(options)operator(.)ident(delete)operator(()symbol(:skip_instruct)operator(\)) + + ident(options)operator([)symbol(:builder)operator(])operator(.)ident(__send__)operator(()ident(options)operator([)symbol(:root)operator(])operator(.)ident(to_s)operator(.)ident(dasherize)operator(\)) reserved(do) + ident(each) reserved(do) operator(|)ident(key)operator(,) ident(value)operator(|) + reserved(case) ident(value) + reserved(when) operator(::)constant(Hash) + ident(value)operator(.)ident(to_xml)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:root) operator(=)operator(>) ident(key)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true) operator(})operator(\))operator(\)) + reserved(when) operator(::)constant(Array) + ident(value)operator(.)ident(to_xml)operator(()ident(options)operator(.)ident(merge)operator(()operator({) symbol(:root) operator(=)operator(>) ident(key)operator(,) symbol(:children) operator(=)operator(>) ident(key)operator(.)ident(to_s)operator(.)ident(singularize)operator(,) symbol(:skip_instruct) operator(=)operator(>) pre_constant(true)operator(})operator(\))operator(\)) + reserved(else) + ident(type_name) operator(=) constant(XML_TYPE_NAMES)operator([)ident(value)operator(.)ident(class)operator(.)ident(to_s)operator(]) + + ident(options)operator([)symbol(:builder)operator(])operator(.)ident(tag!)operator(()ident(key)operator(.)ident(to_s)operator(.)ident(dasherize)operator(,) + constant(XML_FORMATTING)operator([)ident(type_name)operator(]) operator(?) constant(XML_FORMATTING)operator([)ident(type_name)operator(])operator(.)ident(call)operator(()ident(value)operator(\)) operator(:) ident(value)operator(,) + ident(options)operator([)symbol(:skip_types)operator(]) operator(||) ident(value)operator(.)ident(nil?) operator(||) ident(type_name)operator(.)ident(nil?) operator(?) operator({) operator(}) operator(:) operator({) symbol(:type) operator(=)operator(>) ident(type_name) operator(}) + operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Hash) comment(#:nodoc:) + reserved(module) class(Diff) + reserved(def) method(diff)operator(()ident(h2)operator(\)) + pre_constant(self)operator(.)ident(dup)operator(.)ident(delete_if) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) ident(h2)operator([)ident(k)operator(]) operator(==) ident(v) operator(})operator(.)ident(merge)operator(()ident(h2)operator(.)ident(dup)operator(.)ident(delete_if) operator({) operator(|)ident(k)operator(,) ident(v)operator(|) pre_constant(self)operator(.)ident(has_key?)operator(()ident(k)operator(\)) operator(})operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +comment(# this class has dubious semantics and we only have it so that) +comment(# people can write params[:key] instead of params['key']) + +reserved(class) class(HashWithIndifferentAccess) operator(<) constant(Hash) + reserved(def) method(initialize)operator(()ident(constructor) operator(=) operator({)operator(})operator(\)) + reserved(if) ident(constructor)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) + reserved(super)operator(()operator(\)) + ident(update)operator(()ident(constructor)operator(\)) + reserved(else) + reserved(super)operator(()ident(constructor)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(default)operator(()ident(key)operator(\)) + pre_constant(self)operator([)ident(key)operator(.)ident(to_s)operator(]) reserved(if) ident(key)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + reserved(end) + + ident(alias_method) symbol(:regular_writer)operator(,) symbol(:[]=) reserved(unless) ident(method_defined?)operator(()symbol(:regular_writer)operator(\)) + ident(alias_method) symbol(:regular_update)operator(,) symbol(:update) reserved(unless) ident(method_defined?)operator(()symbol(:regular_update)operator(\)) + + reserved(def) method([]=)operator(()ident(key)operator(,) ident(value)operator(\)) + ident(regular_writer)operator(()ident(convert_key)operator(()ident(key)operator(\))operator(,) ident(convert_value)operator(()ident(value)operator(\))operator(\)) + reserved(end) + + reserved(def) method(update)operator(()ident(other_hash)operator(\)) + ident(other_hash)operator(.)ident(each_pair) operator({) operator(|)ident(key)operator(,) ident(value)operator(|) ident(regular_writer)operator(()ident(convert_key)operator(()ident(key)operator(\))operator(,) ident(convert_value)operator(()ident(value)operator(\))operator(\)) operator(}) + pre_constant(self) + reserved(end) + + ident(alias_method) symbol(:merge!)operator(,) symbol(:update) + + reserved(def) method(key?)operator(()ident(key)operator(\)) + reserved(super)operator(()ident(convert_key)operator(()ident(key)operator(\))operator(\)) + reserved(end) + + ident(alias_method) symbol(:include?)operator(,) symbol(:key?) + ident(alias_method) symbol(:has_key?)operator(,) symbol(:key?) + ident(alias_method) symbol(:member?)operator(,) symbol(:key?) + + reserved(def) method(fetch)operator(()ident(key)operator(,) operator(*)ident(extras)operator(\)) + reserved(super)operator(()ident(convert_key)operator(()ident(key)operator(\))operator(,) operator(*)ident(extras)operator(\)) + reserved(end) + + reserved(def) method(values_at)operator(()operator(*)ident(indices)operator(\)) + ident(indices)operator(.)ident(collect) operator({)operator(|)ident(key)operator(|) pre_constant(self)operator([)ident(convert_key)operator(()ident(key)operator(\))operator(])operator(}) + reserved(end) + + reserved(def) method(dup) + constant(HashWithIndifferentAccess)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(merge)operator(()ident(hash)operator(\)) + pre_constant(self)operator(.)ident(dup)operator(.)ident(update)operator(()ident(hash)operator(\)) + reserved(end) + + reserved(def) method(delete)operator(()ident(key)operator(\)) + reserved(super)operator(()ident(convert_key)operator(()ident(key)operator(\))operator(\)) + reserved(end) + + ident(protected) + reserved(def) method(convert_key)operator(()ident(key)operator(\)) + ident(key)operator(.)ident(kind_of?)operator(()constant(Symbol)operator(\)) operator(?) ident(key)operator(.)ident(to_s) operator(:) ident(key) + reserved(end) + reserved(def) method(convert_value)operator(()ident(value)operator(\)) + ident(value)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(?) ident(value)operator(.)ident(with_indifferent_access) operator(:) ident(value) + reserved(end) +reserved(end) + +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Hash) comment(#:nodoc:) + reserved(module) class(IndifferentAccess) comment(#:nodoc:) + reserved(def) method(with_indifferent_access) + constant(HashWithIndifferentAccess)operator(.)ident(new)operator(()pre_constant(self)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Hash) comment(#:nodoc:) + reserved(module) class(Keys) + comment(# Return a new hash with all keys converted to strings.) + reserved(def) method(stringify_keys) + ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(options)operator(,) operator(()ident(key)operator(,) ident(value)operator(\))operator(|) + ident(options)operator([)ident(key)operator(.)ident(to_s)operator(]) operator(=) ident(value) + ident(options) + reserved(end) + reserved(end) + + comment(# Destructively convert all keys to strings.) + reserved(def) method(stringify_keys!) + ident(keys)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + reserved(unless) ident(key)operator(.)ident(class)operator(.)ident(to_s) operator(==) string<delimiter(")content(String)delimiter(")> comment(# weird hack to make the tests run when string_ext_test.rb is also running) + pre_constant(self)operator([)ident(key)operator(.)ident(to_s)operator(]) operator(=) pre_constant(self)operator([)ident(key)operator(]) + ident(delete)operator(()ident(key)operator(\)) + reserved(end) + reserved(end) + pre_constant(self) + reserved(end) + + comment(# Return a new hash with all keys converted to symbols.) + reserved(def) method(symbolize_keys) + ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(options)operator(,) operator(()ident(key)operator(,) ident(value)operator(\))operator(|) + ident(options)operator([)ident(key)operator(.)ident(to_sym)operator(]) operator(=) ident(value) + ident(options) + reserved(end) + reserved(end) + + comment(# Destructively convert all keys to symbols.) + reserved(def) method(symbolize_keys!) + ident(keys)operator(.)ident(each) reserved(do) operator(|)ident(key)operator(|) + reserved(unless) ident(key)operator(.)ident(is_a?)operator(()constant(Symbol)operator(\)) + pre_constant(self)operator([)ident(key)operator(.)ident(to_sym)operator(]) operator(=) pre_constant(self)operator([)ident(key)operator(]) + ident(delete)operator(()ident(key)operator(\)) + reserved(end) + reserved(end) + pre_constant(self) + reserved(end) + + ident(alias_method) symbol(:to_options)operator(,) symbol(:symbolize_keys) + ident(alias_method) symbol(:to_options!)operator(,) symbol(:symbolize_keys!) + + reserved(def) method(assert_valid_keys)operator(()operator(*)ident(valid_keys)operator(\)) + ident(unknown_keys) operator(=) ident(keys) operator(-) operator([)ident(valid_keys)operator(])operator(.)ident(flatten) + ident(raise)operator(()constant(ArgumentError)operator(,) string<delimiter(")content(Unknown key(s\): )inline<inline_delimiter(#{)ident(unknown_keys)operator(.)ident(join)operator(()string<delimiter(")content(, )delimiter(")>operator(\))inline_delimiter(})>delimiter(")>operator(\)) reserved(unless) ident(unknown_keys)operator(.)ident(empty?) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Hash) comment(#:nodoc:) + comment(# Allows for reverse merging where its the keys in the calling hash that wins over those in the <tt>other_hash</tt>.) + comment(# This is particularly useful for initializing an incoming option hash with default values:) + comment(#) + comment(# def setup(options = {}\)) + comment(# options.reverse_merge! :size => 25, :velocity => 10) + comment(# end) + comment(#) + comment(# The default :size and :velocity is only set if the +options+ passed in doesn't already have those keys set.) + reserved(module) class(ReverseMerge) + reserved(def) method(reverse_merge)operator(()ident(other_hash)operator(\)) + ident(other_hash)operator(.)ident(merge)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(reverse_merge!)operator(()ident(other_hash)operator(\)) + ident(replace)operator(()ident(reverse_merge)operator(()ident(other_hash)operator(\))operator(\)) + reserved(end) + + ident(alias_method) symbol(:reverse_update)operator(,) symbol(:reverse_merge) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/hash/keys)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/hash/indifferent_access)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/hash/reverse_merge)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/hash/conversions)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/hash/diff)delimiter(')> + +reserved(class) class(Hash) comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Hash)operator(::)constant(Keys) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Hash)operator(::)constant(IndifferentAccess) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Hash)operator(::)constant(ReverseMerge) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Hash)operator(::)constant(Conversions) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Hash)operator(::)constant(Diff) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Integer) comment(#:nodoc:) + comment(# For checking if a fixnum is even or odd. ) + comment(# * 1.even? # => false) + comment(# * 1.odd? # => true) + comment(# * 2.even? # => true) + comment(# * 2.odd? # => false) + reserved(module) class(EvenOdd) + reserved(def) method(multiple_of?)operator(()ident(number)operator(\)) + pre_constant(self) operator(%) ident(number) operator(==) integer(0) + reserved(end) + + reserved(def) method(even?) + ident(multiple_of?) integer(2) + reserved(end) + + reserved(def) method(odd?) + operator(!)ident(even?) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../inflector)delimiter(')> reserved(unless) reserved(defined?) constant(Inflector) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Integer) comment(#:nodoc:) + reserved(module) class(Inflections) + comment(# 1.ordinalize # => "1st") + comment(# 3.ordinalize # => "3rd") + comment(# 10.ordinalize # => "10th") + reserved(def) method(ordinalize) + constant(Inflector)operator(.)ident(ordinalize)operator(()pre_constant(self)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/integer/even_odd)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/integer/inflections)delimiter(')> + +reserved(class) class(Integer) comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Integer)operator(::)constant(EvenOdd) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Integer)operator(::)constant(Inflections) +reserved(end) +reserved(class) class(Object) + comment(# Makes backticks behave (somewhat more\) similarly on all platforms.) + comment(# On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the) + comment(# spawned shell prints a message to stderr and sets $?. We emulate) + comment(# Unix on the former but not the latter.) + reserved(def) method(`)operator(()ident(command)operator(\)) comment(#:nodoc:) + reserved(super) + reserved(rescue) constant(Errno)operator(::)constant(ENOENT) operator(=)operator(>) ident(e) + constant(STDERR)operator(.)ident(puts) string<delimiter(")escape(#)global_variable($0)content(: )inline<inline_delimiter(#{)ident(e)inline_delimiter(})>delimiter(")> + reserved(end) +ident(endmodule) constant(Kernel) + comment(# Turns the current script into a daemon process that detaches from the console.) + comment(# It can be shut down with a TERM signal.) + reserved(def) method(daemonize) + ident(exit) reserved(if) ident(fork) comment(# Parent exits, child continues.) + constant(Process)operator(.)ident(setsid) comment(# Become session leader.) + ident(exit) reserved(if) ident(fork) comment(# Zap session leader. See [1].) + constant(Dir)operator(.)ident(chdir) string<delimiter(")content(/)delimiter(")> comment(# Release old working directory.) + constant(File)operator(.)ident(umask) integer(0000) comment(# Ensure sensible umask. Adjust as needed.) + constant(STDIN)operator(.)ident(reopen) string<delimiter(")content(/dev/null)delimiter(")> comment(# Free file descriptors and) + constant(STDOUT)operator(.)ident(reopen) string<delimiter(")content(/dev/null)delimiter(")>operator(,) string<delimiter(")content(a)delimiter(")> comment(# point them somewhere sensible.) + constant(STDERR)operator(.)ident(reopen) constant(STDOUT) comment(# STDOUT/ERR should better go to a logfile.) + ident(trap)operator(()string<delimiter(")content(TERM)delimiter(")>operator(\)) operator({) ident(exit) operator(}) + reserved(end) +ident(endmodule) constant(Kernel) + comment(# Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.) + comment(#) + comment(# silence_warnings do) + comment(# value = noisy_call # no warning voiced) + comment(# end) + comment(#) + comment(# noisy_call # warning voiced) + reserved(def) method(silence_warnings) + ident(old_verbose)operator(,) global_variable($VERBOSE) operator(=) global_variable($VERBOSE)operator(,) pre_constant(nil) + reserved(yield) + reserved(ensure) + global_variable($VERBOSE) operator(=) ident(old_verbose) + reserved(end) + + comment(# Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.) + reserved(def) method(enable_warnings) + ident(old_verbose)operator(,) global_variable($VERBOSE) operator(=) global_variable($VERBOSE)operator(,) pre_constant(true) + reserved(yield) + reserved(ensure) + global_variable($VERBOSE) operator(=) ident(old_verbose) + reserved(end) + + comment(# For compatibility) + reserved(def) method(silence_stderr) comment(#:nodoc:) + ident(silence_stream)operator(()constant(STDERR)operator(\)) operator({) reserved(yield) operator(}) + reserved(end) + + comment(# Silences any stream for the duration of the block.) + comment(#) + comment(# silence_stream(STDOUT\) do) + comment(# puts 'This will never be seen') + comment(# end) + comment(#) + comment(# puts 'But this will') + reserved(def) method(silence_stream)operator(()ident(stream)operator(\)) + ident(old_stream) operator(=) ident(stream)operator(.)ident(dup) + ident(stream)operator(.)ident(reopen)operator(()constant(RUBY_PLATFORM) operator(=)operator(~) regexp<delimiter(/)content(mswin)delimiter(/)> operator(?) string<delimiter(')content(NUL:)delimiter(')> operator(:) string<delimiter(')content(/dev/null)delimiter(')>operator(\)) + ident(stream)operator(.)ident(sync) operator(=) pre_constant(true) + reserved(yield) + reserved(ensure) + ident(stream)operator(.)ident(reopen)operator(()ident(old_stream)operator(\)) + reserved(end) + + reserved(def) method(suppress)operator(()operator(*)ident(exception_classes)operator(\)) + reserved(begin) reserved(yield) + reserved(rescue) constant(Exception) operator(=)operator(>) ident(e) + ident(raise) reserved(unless) ident(exception_classes)operator(.)ident(any?) operator({) operator(|)ident(cls)operator(|) ident(e)operator(.)ident(kind_of?)operator(()ident(cls)operator(\)) operator(}) + reserved(end) + reserved(end) +ident(endmodule) constant(Kernel) + comment(# Require a library with fallback to RubyGems. Warnings during library) + comment(# loading are silenced to increase signal/noise for application warnings.) + reserved(def) method(require_library_or_gem)operator(()ident(library_name)operator(\)) + ident(silence_warnings) reserved(do) + reserved(begin) + ident(require) ident(library_name) + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(cannot_require) + comment(# 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try.) + reserved(begin) + ident(require) string<delimiter(')content(rubygems)delimiter(')> + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(rubygems_not_installed) + ident(raise) ident(cannot_require) + reserved(end) + comment(# 2. Rubygems is installed and loaded. Try to load the library again) + reserved(begin) + ident(require) ident(library_name) + reserved(rescue) constant(LoadError) operator(=)operator(>) ident(gem_not_installed) + ident(raise) ident(cannot_require) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/kernel/daemonizing)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/kernel/reporting)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/kernel/agnostics)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/kernel/requires)delimiter(')> +reserved(class) class(MissingSourceFile) operator(<) constant(LoadError) comment(#:nodoc:) + ident(attr_reader) symbol(:path) + reserved(def) method(initialize)operator(()ident(message)operator(,) ident(path)operator(\)) + reserved(super)operator(()ident(message)operator(\)) + instance_variable(@path) operator(=) ident(path) + reserved(end) + + reserved(def) method(is_missing?)operator(()ident(path)operator(\)) + ident(path)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\.)content(rb$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) operator(==) pre_constant(self)operator(.)ident(path)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\.)content(rb$)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) pre_constant(self)operator(.)ident(from_message)operator(()ident(message)operator(\)) + constant(REGEXPS)operator(.)ident(each) reserved(do) operator(|)ident(regexp)operator(,) ident(capture)operator(|) + ident(match) operator(=) ident(regexp)operator(.)ident(match)operator(()ident(message)operator(\)) + reserved(return) constant(MissingSourceFile)operator(.)ident(new)operator(()ident(message)operator(,) ident(match)operator([)ident(capture)operator(])operator(\)) reserved(unless) ident(match)operator(.)ident(nil?) + reserved(end) + pre_constant(nil) + reserved(end) + + constant(REGEXPS) operator(=) operator([) + operator([)regexp<delimiter(/)content(^no such file to load -- (.+\)$)delimiter(/)modifier(i)>operator(,) integer(1)operator(])operator(,) + operator([)regexp<delimiter(/)content(^Missing )char(\\w)content(+ (file)char(\\s)content(*\)?([^)char(\\s)content(]+.rb\)$)delimiter(/)modifier(i)>operator(,) integer(2)operator(])operator(,) + operator([)regexp<delimiter(/)content(^Missing API definition file in (.+\)$)delimiter(/)modifier(i)>operator(,) integer(1)operator(]) + operator(]) +reserved(end) + +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(LoadErrorExtensions) comment(#:nodoc:) + reserved(module) class(LoadErrorClassMethods) comment(#:nodoc:) + reserved(def) method(new)operator(()operator(*)ident(args)operator(\)) + operator(()pre_constant(self) operator(==) constant(LoadError) operator(&&) constant(MissingSourceFile)operator(.)ident(from_message)operator(()ident(args)operator(.)ident(first)operator(\))operator(\)) operator(||) reserved(super) + reserved(end) + reserved(end) + operator(::)constant(LoadError)operator(.)ident(extend)operator(()constant(LoadErrorClassMethods)operator(\)) + reserved(end) + reserved(end) +reserved(end) +comment(# Adds the 'around_level' method to Logger.) + +reserved(class) class(Logger) + reserved(def) pre_constant(self)operator(.)ident(define_around_helper)operator(()ident(level)operator(\)) + ident(module_eval) string<delimiter(<<-end_eval)>string<content( + def around_)inline<inline_delimiter(#{)ident(level)inline_delimiter(})>content((before_message, after_message, &block\) + self.)inline<inline_delimiter(#{)ident(level)inline_delimiter(})>content((before_message\) + return_value = block.call(self\) + self.)inline<inline_delimiter(#{)ident(level)inline_delimiter(})>content((after_message\) + return return_value + end)delimiter( + end_eval)> + reserved(end) + operator([)symbol(:debug)operator(,) symbol(:info)operator(,) symbol(:error)operator(,) symbol(:fatal)operator(])operator(.)ident(each) operator({)operator(|)ident(level)operator(|) ident(define_around_helper)operator(()ident(level)operator(\)) operator(}) + +reserved(end)comment(# Extends the module object with module and instance accessors for class attributes, ) +comment(# just like the native attr* accessors for instance attributes.) +reserved(class) class(Module) comment(# :nodoc:) + reserved(def) method(mattr_reader)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval)operator(()string<delimiter(<<-EOS)>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)operator(\))string<content( + unless defined? @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = nil + end + + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(mattr_writer)operator(()operator(*)ident(syms)operator(\)) + ident(syms)operator(.)ident(each) reserved(do) operator(|)ident(sym)operator(|) + ident(class_eval)operator(()string<delimiter(<<-EOS)>operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)operator(\))string<content( + unless defined? @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = nil + end + + def self.)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end + + def )inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(=(obj\) + @@)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content( = obj + end)delimiter( + EOS)> + reserved(end) + reserved(end) + + reserved(def) method(mattr_accessor)operator(()operator(*)ident(syms)operator(\)) + ident(mattr_reader)operator(()operator(*)ident(syms)operator(\)) + ident(mattr_writer)operator(()operator(*)ident(syms)operator(\)) + reserved(end) +reserved(end) +reserved(class) class(Module) + reserved(def) method(delegate)operator(()operator(*)ident(methods)operator(\)) + ident(options) operator(=) ident(methods)operator(.)ident(pop) + reserved(unless) ident(options)operator(.)ident(is_a?)operator(()constant(Hash)operator(\)) operator(&&) ident(to) operator(=) ident(options)operator([)symbol(:to)operator(]) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(Delegation needs a target. Supply an options hash with a :to key)delimiter(")> + reserved(end) + + ident(methods)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(module_eval)operator(()string<delimiter(<<-EOS)>operator(,) string<delimiter(")content((__DELEGATION__\))delimiter(")>operator(,) integer(1)operator(\))string<content( + def )inline<inline_delimiter(#{)ident(method)inline_delimiter(})>content((*args, &block\) + )inline<inline_delimiter(#{)ident(to)inline_delimiter(})>content(.__send__()inline<inline_delimiter(#{)ident(method)operator(.)ident(inspect)inline_delimiter(})>content(, *args, &block\) + end)delimiter( + EOS)> + reserved(end) + reserved(end) +ident(endclass) constant(Module) + reserved(def) method(included_in_classes) + ident(classes) operator(=) operator([)operator(]) + constant(ObjectSpace)operator(.)ident(each_object)operator(()constant(Class)operator(\)) operator({) operator(|)ident(k)operator(|) ident(classes) operator(<<) ident(k) reserved(if) ident(k)operator(.)ident(included_modules)operator(.)ident(include?)operator(()pre_constant(self)operator(\)) operator(}) + + ident(classes)operator(.)ident(reverse)operator(.)ident(inject)operator(()operator([)operator(])operator(\)) reserved(do) operator(|)ident(unique_classes)operator(,) ident(klass)operator(|) + ident(unique_classes) operator(<<) ident(klass) reserved(unless) ident(unique_classes)operator(.)ident(collect) operator({) operator(|)ident(k)operator(|) ident(k)operator(.)ident(to_s) operator(})operator(.)ident(include?)operator(()ident(klass)operator(.)ident(to_s)operator(\)) + ident(unique_classes) + reserved(end) + reserved(end) +ident(endclass) constant(Module) + comment(# Return the module which contains this one; if this is a root module, such as) + comment(# +::MyModule+, then Object is returned.) + reserved(def) method(parent) + ident(parent_name) operator(=) ident(name)operator(.)ident(split)operator(()string<delimiter(')content(::)delimiter(')>operator(\))operator([)integer(0)operator(..)integer(-2)operator(]) operator(*) string<delimiter(')content(::)delimiter(')> + ident(parent_name)operator(.)ident(empty?) operator(?) constant(Object) operator(:) ident(parent_name)operator(.)ident(constantize) + reserved(end) + + comment(# Return all the parents of this module, ordered from nested outwards. The) + comment(# receiver is not contained within the result.) + reserved(def) method(parents) + ident(parents) operator(=) operator([)operator(]) + ident(parts) operator(=) ident(name)operator(.)ident(split)operator(()string<delimiter(')content(::)delimiter(')>operator(\))operator([)integer(0)operator(..)integer(-2)operator(]) + reserved(until) ident(parts)operator(.)ident(empty?) + ident(parents) operator(<<) operator(()ident(parts) operator(*) string<delimiter(')content(::)delimiter(')>operator(\))operator(.)ident(constantize) + ident(parts)operator(.)ident(pop) + reserved(end) + ident(parents) operator(<<) constant(Object) reserved(unless) ident(parents)operator(.)ident(include?) constant(Object) + ident(parents) + reserved(end) +reserved(end) +reserved(class) class(Module) + reserved(def) method(as_load_path) + reserved(if) pre_constant(self) operator(==) constant(Object) operator(||) pre_constant(self) operator(==) constant(Kernel) + string<delimiter(')delimiter(')> + reserved(elsif) ident(is_a?) constant(Class) + ident(parent) operator(==) pre_constant(self) operator(?) string<delimiter(')delimiter(')> operator(:) ident(parent)operator(.)ident(as_load_path) + reserved(else) + ident(name)operator(.)ident(split)operator(()string<delimiter(')content(::)delimiter(')>operator(\))operator(.)ident(collect) reserved(do) operator(|)ident(word)operator(|) + ident(word)operator(.)ident(underscore) + reserved(end) operator(*) string<delimiter(')content(/)delimiter(')> + reserved(end) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/module/inclusion)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/module/attribute_accessors)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/module/delegation)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/module/introspection)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/module/loading)delimiter(')> +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Numeric) comment(#:nodoc:) + comment(# Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes) + reserved(module) class(Bytes) + reserved(def) method(bytes) + pre_constant(self) + reserved(end) + reserved(alias) symbol(:byte) symbol(:bytes) + + reserved(def) method(kilobytes) + pre_constant(self) operator(*) integer(1024) + reserved(end) + reserved(alias) symbol(:kilobyte) symbol(:kilobytes) + + reserved(def) method(megabytes) + pre_constant(self) operator(*) integer(1024)operator(.)ident(kilobytes) + reserved(end) + reserved(alias) symbol(:megabyte) symbol(:megabytes) + + reserved(def) method(gigabytes) + pre_constant(self) operator(*) integer(1024)operator(.)ident(megabytes) + reserved(end) + reserved(alias) symbol(:gigabyte) symbol(:gigabytes) + + reserved(def) method(terabytes) + pre_constant(self) operator(*) integer(1024)operator(.)ident(gigabytes) + reserved(end) + reserved(alias) symbol(:terabyte) symbol(:terabytes) + + reserved(def) method(petabytes) + pre_constant(self) operator(*) integer(1024)operator(.)ident(terabytes) + reserved(end) + reserved(alias) symbol(:petabyte) symbol(:petabytes) + + reserved(def) method(exabytes) + pre_constant(self) operator(*) integer(1024)operator(.)ident(petabytes) + reserved(end) + reserved(alias) symbol(:exabyte) symbol(:exabytes) + + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Numeric) comment(#:nodoc:) + comment(# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.) + comment(#) + comment(# If you need precise date calculations that doesn't just treat months as 30 days, then have) + comment(# a look at Time#advance.) + comment(# ) + comment(# Some of these methods are approximations, Ruby's core ) + comment(# Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and ) + comment(# Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision) + comment(# date and time arithmetic) + reserved(module) class(Time) + reserved(def) method(seconds) + pre_constant(self) + reserved(end) + reserved(alias) symbol(:second) symbol(:seconds) + + reserved(def) method(minutes) + pre_constant(self) operator(*) integer(60) + reserved(end) + reserved(alias) symbol(:minute) symbol(:minutes) + + reserved(def) method(hours) + pre_constant(self) operator(*) integer(60)operator(.)ident(minutes) + reserved(end) + reserved(alias) symbol(:hour) symbol(:hours) + + reserved(def) method(days) + pre_constant(self) operator(*) integer(24)operator(.)ident(hours) + reserved(end) + reserved(alias) symbol(:day) symbol(:days) + + reserved(def) method(weeks) + pre_constant(self) operator(*) integer(7)operator(.)ident(days) + reserved(end) + reserved(alias) symbol(:week) symbol(:weeks) + + reserved(def) method(fortnights) + pre_constant(self) operator(*) integer(2)operator(.)ident(weeks) + reserved(end) + reserved(alias) symbol(:fortnight) symbol(:fortnights) + + reserved(def) method(months) + pre_constant(self) operator(*) integer(30)operator(.)ident(days) + reserved(end) + reserved(alias) symbol(:month) symbol(:months) + + reserved(def) method(years) + operator(()pre_constant(self) operator(*) float(365.25)operator(.)ident(days)operator(\))operator(.)ident(to_i) + reserved(end) + reserved(alias) symbol(:year) symbol(:years) + + comment(# Reads best without arguments: 10.minutes.ago) + reserved(def) method(ago)operator(()ident(time) operator(=) operator(::)constant(Time)operator(.)ident(now)operator(\)) + ident(time) operator(-) pre_constant(self) + reserved(end) + + comment(# Reads best with argument: 10.minutes.until(time\)) + reserved(alias) symbol(:until) symbol(:ago) + + comment(# Reads best with argument: 10.minutes.since(time\)) + reserved(def) method(since)operator(()ident(time) operator(=) operator(::)constant(Time)operator(.)ident(now)operator(\)) + ident(time) operator(+) pre_constant(self) + reserved(end) + + comment(# Reads best without arguments: 10.minutes.from_now) + reserved(alias) symbol(:from_now) symbol(:since) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/numeric/time)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/numeric/bytes)delimiter(')> + +reserved(class) class(Numeric) comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Numeric)operator(::)constant(Time) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Numeric)operator(::)constant(Bytes) +reserved(end) +reserved(class) class(Object) comment(#:nodoc:) + reserved(def) method(remove_subclasses_of)operator(()operator(*)ident(superclasses)operator(\)) + constant(Class)operator(.)ident(remove_class)operator(()operator(*)ident(subclasses_of)operator(()operator(*)ident(superclasses)operator(\))operator(\)) + reserved(end) + + reserved(def) method(subclasses_of)operator(()operator(*)ident(superclasses)operator(\)) + ident(subclasses) operator(=) operator([)operator(]) + constant(ObjectSpace)operator(.)ident(each_object)operator(()constant(Class)operator(\)) reserved(do) operator(|)ident(k)operator(|) + reserved(next) reserved(if) comment(# Exclude this class if) + operator(()ident(k)operator(.)ident(ancestors) operator(&) ident(superclasses)operator(\))operator(.)ident(empty?) operator(||) comment(# It's not a subclass of our supers) + ident(superclasses)operator(.)ident(include?)operator(()ident(k)operator(\)) operator(||) comment(# It *is* one of the supers) + ident(eval)operator(()string<delimiter(")content(! defined?(::)inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content(\))delimiter(")>operator(\)) operator(||) comment(# It's not defined.) + ident(eval)operator(()string<delimiter(")content(::)inline<inline_delimiter(#{)ident(k)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(object_id) operator(!=) ident(k)operator(.)ident(object_id) + ident(subclasses) operator(<<) ident(k) + reserved(end) + ident(subclasses) + reserved(end) + + reserved(def) method(extended_by) + ident(ancestors) operator(=) reserved(class) operator(<<) class(self)operator(;) ident(ancestors) reserved(end) + ident(ancestors)operator(.)ident(select) operator({) operator(|)ident(mod)operator(|) ident(mod)operator(.)ident(class) operator(==) constant(Module) operator(}) operator(-) operator([) constant(Object)operator(,) constant(Kernel) operator(]) + reserved(end) + + reserved(def) method(copy_instance_variables_from)operator(()ident(object)operator(,) ident(exclude) operator(=) operator([)operator(])operator(\)) + ident(exclude) operator(+=) ident(object)operator(.)ident(protected_instance_variables) reserved(if) ident(object)operator(.)ident(respond_to?) symbol(:protected_instance_variables) + + ident(instance_variables) operator(=) ident(object)operator(.)ident(instance_variables) operator(-) ident(exclude)operator(.)ident(map) operator({) operator(|)ident(name)operator(|) ident(name)operator(.)ident(to_s) operator(}) + ident(instance_variables)operator(.)ident(each) operator({) operator(|)ident(name)operator(|) ident(instance_variable_set)operator(()ident(name)operator(,) ident(object)operator(.)ident(instance_variable_get)operator(()ident(name)operator(\))operator(\)) operator(}) + reserved(end) + + reserved(def) method(extend_with_included_modules_from)operator(()ident(object)operator(\)) + ident(object)operator(.)ident(extended_by)operator(.)ident(each) operator({) operator(|)ident(mod)operator(|) ident(extend) ident(mod) operator(}) + reserved(end) + + reserved(def) method(instance_values) + ident(instance_variables)operator(.)ident(inject)operator(()operator({)operator(})operator(\)) reserved(do) operator(|)ident(values)operator(,) ident(name)operator(|) + ident(values)operator([)ident(name)operator([)integer(1)operator(..)integer(-1)operator(])operator(]) operator(=) ident(instance_variable_get)operator(()ident(name)operator(\)) + ident(values) + reserved(end) + reserved(end) + + reserved(unless) reserved(defined?) ident(instance_exec) comment(# 1.9) + reserved(def) method(instance_exec)operator(()operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + ident(block)operator(.)ident(bind)operator(()pre_constant(self)operator(\))operator([)operator(*)ident(arguments)operator(]) + reserved(end) + reserved(end) +reserved(end) +reserved(class) class(Object) comment(#:nodoc:) + comment(# A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman.) + comment(#) + comment(# def foo) + comment(# returning values = [] do) + comment(# values << 'bar') + comment(# values << 'baz') + comment(# end) + comment(# end) + comment(#) + comment(# foo # => ['bar', 'baz']) + comment(#) + comment(# def foo) + comment(# returning [] do |values|) + comment(# values << 'bar') + comment(# values << 'baz') + comment(# end) + comment(# end) + comment(#) + comment(# foo # => ['bar', 'baz']) + comment(#) + reserved(def) method(returning)operator(()ident(value)operator(\)) + reserved(yield)operator(()ident(value)operator(\)) + ident(value) + reserved(end) + + reserved(def) method(with_options)operator(()ident(options)operator(\)) + reserved(yield) constant(ActiveSupport)operator(::)constant(OptionMerger)operator(.)ident(new)operator(()pre_constant(self)operator(,) ident(options)operator(\)) + reserved(end) + + reserved(def) method(to_json) + constant(ActiveSupport)operator(::)constant(JSON)operator(.)ident(encode)operator(()pre_constant(self)operator(\)) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/object/extending)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/object/misc)delimiter(')>reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Pathname) comment(#:nodoc:) + reserved(module) class(CleanWithin) + comment(# Clean the paths contained in the provided string.) + reserved(def) method(clean_within)operator(()ident(string)operator(\)) + ident(string)operator(.)ident(gsub)operator(()regexp<delimiter(%r{)content([)char(\\w)content(. ]+(/[)char(\\w)content(. ]+\)+()char(\\.)content(rb\)?()char(\\b)content(|$\))delimiter(})>operator(\)) reserved(do) operator(|)ident(path)operator(|) + ident(new)operator(()ident(path)operator(\))operator(.)ident(cleanpath) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(pathname)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/pathname/clean_within)delimiter(')> + +reserved(class) class(Pathname)comment(#:nodoc:) + ident(extend) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Pathname)operator(::)constant(CleanWithin) +reserved(end) + +reserved(class) class(Proc) comment(#:nodoc:) + reserved(def) method(bind)operator(()ident(object)operator(\)) + ident(block)operator(,) ident(time) operator(=) pre_constant(self)operator(,) constant(Time)operator(.)ident(now) + operator(()reserved(class) operator(<<) class(object)operator(;) pre_constant(self) reserved(end)operator(\))operator(.)ident(class_eval) reserved(do) + ident(method_name) operator(=) string<delimiter(")content(__bind_)inline<inline_delimiter(#{)ident(time)operator(.)ident(to_i)inline_delimiter(})>content(_)inline<inline_delimiter(#{)ident(time)operator(.)ident(usec)inline_delimiter(})>delimiter(")> + ident(define_method)operator(()ident(method_name)operator(,) operator(&)ident(block)operator(\)) + ident(method) operator(=) ident(instance_method)operator(()ident(method_name)operator(\)) + ident(remove_method)operator(()ident(method_name)operator(\)) + ident(method) + reserved(end)operator(.)ident(bind)operator(()ident(object)operator(\)) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Range) comment(#:nodoc:) + comment(# Getting dates in different convenient string representations and other objects) + reserved(module) class(Conversions) + constant(DATE_FORMATS) operator(=) operator({) + symbol(:db) operator(=)operator(>) constant(Proc)operator(.)ident(new) operator({) operator(|)ident(start)operator(,) ident(stop)operator(|) string<delimiter(")content(BETWEEN ')inline<inline_delimiter(#{)ident(start)operator(.)ident(to_s)operator(()symbol(:db)operator(\))inline_delimiter(})>content(' AND ')inline<inline_delimiter(#{)ident(stop)operator(.)ident(to_s)operator(()symbol(:db)operator(\))inline_delimiter(})>content(')delimiter(")> operator(}) + operator(}) + + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(klass)operator(\)) comment(#:nodoc:) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:to_default_s)operator(,) symbol(:to_s)operator(\)) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:to_s)operator(,) symbol(:to_formatted_s)operator(\)) + reserved(end) + + reserved(def) method(to_formatted_s)operator(()ident(format) operator(=) symbol(:default)operator(\)) + constant(DATE_FORMATS)operator([)ident(format)operator(]) operator(?) constant(DATE_FORMATS)operator([)ident(format)operator(])operator(.)ident(call)operator(()ident(first)operator(,) ident(last)operator(\)) operator(:) ident(to_default_s) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/range/conversions)delimiter(')> + +reserved(class) class(Range) comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Range)operator(::)constant(Conversions) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(String) comment(#:nodoc:) + comment(# Makes it easier to access parts of a string, such as specific characters and substrings.) + reserved(module) class(Access) + comment(# Returns the character at the +position+ treating the string as an array (where 0 is the first character\).) + comment(#) + comment(# Examples: ) + comment(# "hello".at(0\) # => "h") + comment(# "hello".at(4\) # => "o") + comment(# "hello".at(10\) # => nil) + reserved(def) method(at)operator(()ident(position)operator(\)) + pre_constant(self)operator([)ident(position)operator(,) integer(1)operator(]) + reserved(end) + + comment(# Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character\).) + comment(#) + comment(# Examples: ) + comment(# "hello".from(0\) # => "hello") + comment(# "hello".from(2\) # => "llo") + comment(# "hello".from(10\) # => nil) + reserved(def) method(from)operator(()ident(position)operator(\)) + pre_constant(self)operator([)ident(position)operator(..)integer(-1)operator(]) + reserved(end) + + comment(# Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character\).) + comment(#) + comment(# Examples: ) + comment(# "hello".to(0\) # => "h") + comment(# "hello".to(2\) # => "hel") + comment(# "hello".to(10\) # => "hello") + reserved(def) method(to)operator(()ident(position)operator(\)) + pre_constant(self)operator([)integer(0)operator(..)ident(position)operator(]) + reserved(end) + + comment(# Returns the first character of the string or the first +limit+ characters.) + comment(#) + comment(# Examples: ) + comment(# "hello".first # => "h") + comment(# "hello".first(2\) # => "he") + comment(# "hello".first(10\) # => "hello") + reserved(def) method(first)operator(()ident(limit) operator(=) integer(1)operator(\)) + pre_constant(self)operator([)integer(0)operator(..)operator(()ident(limit) operator(-) integer(1)operator(\))operator(]) + reserved(end) + + comment(# Returns the last character of the string or the last +limit+ characters.) + comment(#) + comment(# Examples: ) + comment(# "hello".last # => "o") + comment(# "hello".last(2\) # => "lo") + comment(# "hello".last(10\) # => "hello") + reserved(def) method(last)operator(()ident(limit) operator(=) integer(1)operator(\)) + pre_constant(self)operator([)operator(()operator(-)ident(limit)operator(\))operator(..)integer(-1)operator(]) operator(||) pre_constant(self) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(parsedate)delimiter(')> + +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(String) comment(#:nodoc:) + comment(# Converting strings to other objects) + reserved(module) class(Conversions) + comment(# Form can be either :utc (default\) or :local.) + reserved(def) method(to_time)operator(()ident(form) operator(=) symbol(:utc)operator(\)) + operator(::)constant(Time)operator(.)ident(send)operator(()ident(form)operator(,) operator(*)constant(ParseDate)operator(.)ident(parsedate)operator(()pre_constant(self)operator(\))operator(\)) + reserved(end) + + reserved(def) method(to_date) + operator(::)constant(Date)operator(.)ident(new)operator(()operator(*)constant(ParseDate)operator(.)ident(parsedate)operator(()pre_constant(self)operator(\))operator([)integer(0)operator(..)integer(2)operator(])operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +ident(endrequire) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/../../inflector)delimiter(')> reserved(unless) reserved(defined?) constant(Inflector) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(String) comment(#:nodoc:) + comment(# Makes it possible to do "posts".singularize that returns "post" and "MegaCoolClass".underscore that returns "mega_cool_class".) + reserved(module) class(Inflections) + reserved(def) method(pluralize) + constant(Inflector)operator(.)ident(pluralize)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(singularize) + constant(Inflector)operator(.)ident(singularize)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(camelize)operator(()ident(first_letter) operator(=) symbol(:upper)operator(\)) + reserved(case) ident(first_letter) + reserved(when) symbol(:upper) reserved(then) constant(Inflector)operator(.)ident(camelize)operator(()pre_constant(self)operator(,) pre_constant(true)operator(\)) + reserved(when) symbol(:lower) reserved(then) constant(Inflector)operator(.)ident(camelize)operator(()pre_constant(self)operator(,) pre_constant(false)operator(\)) + reserved(end) + reserved(end) + ident(alias_method) symbol(:camelcase)operator(,) symbol(:camelize) + + reserved(def) method(titleize) + constant(Inflector)operator(.)ident(titleize)operator(()pre_constant(self)operator(\)) + reserved(end) + ident(alias_method) symbol(:titlecase)operator(,) symbol(:titleize) + + reserved(def) method(underscore) + constant(Inflector)operator(.)ident(underscore)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(dasherize) + constant(Inflector)operator(.)ident(dasherize)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(demodulize) + constant(Inflector)operator(.)ident(demodulize)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(tableize) + constant(Inflector)operator(.)ident(tableize)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(classify) + constant(Inflector)operator(.)ident(classify)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Capitalizes the first word and turns underscores into spaces and strips _id, so "employee_salary" becomes "Employee salary" ) + comment(# and "author_id" becomes "Author".) + reserved(def) method(humanize) + constant(Inflector)operator(.)ident(humanize)operator(()pre_constant(self)operator(\)) + reserved(end) + + reserved(def) method(foreign_key)operator(()ident(separate_class_name_and_id_with_underscore) operator(=) pre_constant(true)operator(\)) + constant(Inflector)operator(.)ident(foreign_key)operator(()pre_constant(self)operator(,) ident(separate_class_name_and_id_with_underscore)operator(\)) + reserved(end) + + reserved(def) method(constantize) + constant(Inflector)operator(.)ident(constantize)operator(()pre_constant(self)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(strscan)delimiter(')> + +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(String) comment(#:nodoc:) + comment(# Custom string iterators) + reserved(module) class(Iterators) + comment(# Yields a single-character string for each character in the string.) + comment(# When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.) + reserved(def) method(each_char) + ident(scanner)operator(,) ident(char) operator(=) constant(StringScanner)operator(.)ident(new)operator(()pre_constant(self)operator(\))operator(,) regexp<delimiter(/)content(.)delimiter(/)modifier(mu)> + ident(loop) operator({) reserved(yield)operator(()ident(scanner)operator(.)ident(scan)operator(()ident(char)operator(\)) operator(||) reserved(break)operator(\)) operator(}) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(String) comment(#:nodoc:) + comment(# Additional string tests.) + reserved(module) class(StartsEndsWith) + comment(# Does the string start with the specified +prefix+?) + reserved(def) method(starts_with?)operator(()ident(prefix)operator(\)) + ident(prefix) operator(=) ident(prefix)operator(.)ident(to_s) + pre_constant(self)operator([)integer(0)operator(,) ident(prefix)operator(.)ident(length)operator(]) operator(==) ident(prefix) + reserved(end) + + comment(# Does the string end with the specified +suffix+?) + reserved(def) method(ends_with?)operator(()ident(suffix)operator(\)) + ident(suffix) operator(=) ident(suffix)operator(.)ident(to_s) + pre_constant(self)operator([)operator(-)ident(suffix)operator(.)ident(length)operator(,) ident(suffix)operator(.)ident(length)operator(]) operator(==) ident(suffix) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/string/inflections)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/string/conversions)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/string/access)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/string/starts_ends_with)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/string/iterators)delimiter(')> + +reserved(class) class(String) comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(String)operator(::)constant(Access) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(String)operator(::)constant(Conversions) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(String)operator(::)constant(Inflections) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(String)operator(::)constant(StartsEndsWith) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(String)operator(::)constant(Iterators) +reserved(end) +reserved(class) class(Symbol) + comment(# Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:) + comment(#) + comment(# # The same as people.collect { |p| p.name }) + comment(# people.collect(&:name\)) + comment(#) + comment(# # The same as people.select { |p| p.manager? }.collect { |p| p.salary }) + comment(# people.select(&:manager?\).collect(&:salary\)) + reserved(def) method(to_proc) + constant(Proc)operator(.)ident(new) operator({) operator(|)ident(obj)operator(,) operator(*)ident(args)operator(|) ident(obj)operator(.)ident(send)operator(()pre_constant(self)operator(,) operator(*)ident(args)operator(\)) operator(}) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Time) comment(#:nodoc:) + comment(# Enables the use of time calculations within Time itself) + reserved(module) class(Calculations) + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(base)operator(\)) comment(#:nodoc:) + reserved(super) + ident(base)operator(.)ident(extend)operator(()constant(ClassMethods)operator(\)) + reserved(end) + + reserved(module) class(ClassMethods) + comment(# Return the number of days in the given month. If a year is given,) + comment(# February will return the correct number of days for leap years.) + comment(# Otherwise, this method will always report February as having 28) + comment(# days.) + reserved(def) method(days_in_month)operator(()ident(month)operator(,) ident(year)operator(=)pre_constant(nil)operator(\)) + reserved(if) ident(month) operator(==) integer(2) + operator(!)ident(year)operator(.)ident(nil?) operator(&&) operator(()ident(year) operator(%) integer(4) operator(==) integer(0)operator(\)) operator(&&) operator(()operator(()ident(year) operator(%) integer(100) operator(!=) integer(0)operator(\)) operator(||) operator(()ident(year) operator(%) integer(400) operator(==) integer(0)operator(\))operator(\)) operator(?) integer(29) operator(:) integer(28) + reserved(elsif) ident(month) operator(<=) integer(7) + ident(month) operator(%) integer(2) operator(==) integer(0) operator(?) integer(30) operator(:) integer(31) + reserved(else) + ident(month) operator(%) integer(2) operator(==) integer(0) operator(?) integer(31) operator(:) integer(30) + reserved(end) + reserved(end) + reserved(end) + + comment(# Seconds since midnight: Time.now.seconds_since_midnight) + reserved(def) method(seconds_since_midnight) + pre_constant(self)operator(.)ident(hour)operator(.)ident(hours) operator(+) pre_constant(self)operator(.)ident(min)operator(.)ident(minutes) operator(+) pre_constant(self)operator(.)ident(sec) operator(+) operator(()pre_constant(self)operator(.)ident(usec)operator(/)float(1.0e+6)operator(\)) + reserved(end) + + comment(# Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options) + comment(# (hour, minute, sec, usec\) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and ) + comment(# minute is passed, then sec and usec is set to 0.) + reserved(def) method(change)operator(()ident(options)operator(\)) + operator(::)constant(Time)operator(.)ident(send)operator(() + pre_constant(self)operator(.)ident(utc?) operator(?) symbol(:utc) operator(:) symbol(:local)operator(,) + ident(options)operator([)symbol(:year)operator(]) operator(||) pre_constant(self)operator(.)ident(year)operator(,) + ident(options)operator([)symbol(:month)operator(]) operator(||) pre_constant(self)operator(.)ident(month)operator(,) + ident(options)operator([)symbol(:mday)operator(]) operator(||) pre_constant(self)operator(.)ident(mday)operator(,) + ident(options)operator([)symbol(:hour)operator(]) operator(||) pre_constant(self)operator(.)ident(hour)operator(,) + ident(options)operator([)symbol(:min)operator(]) operator(||) operator(()ident(options)operator([)symbol(:hour)operator(]) operator(?) integer(0) operator(:) pre_constant(self)operator(.)ident(min)operator(\))operator(,) + ident(options)operator([)symbol(:sec)operator(]) operator(||) operator(()operator(()ident(options)operator([)symbol(:hour)operator(]) operator(||) ident(options)operator([)symbol(:min)operator(])operator(\)) operator(?) integer(0) operator(:) pre_constant(self)operator(.)ident(sec)operator(\))operator(,) + ident(options)operator([)symbol(:usec)operator(]) operator(||) operator(()operator(()ident(options)operator([)symbol(:hour)operator(]) operator(||) ident(options)operator([)symbol(:min)operator(]) operator(||) ident(options)operator([)symbol(:sec)operator(])operator(\)) operator(?) integer(0) operator(:) pre_constant(self)operator(.)ident(usec)operator(\)) + operator(\)) + reserved(end) + + comment(# Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with ) + comment(# any of these keys: :months, :days, :years.) + reserved(def) method(advance)operator(()ident(options)operator(\)) + ident(d) operator(=) operator(::)constant(Date)operator(.)ident(new)operator(()ident(year) operator(+) operator(()ident(options)operator(.)ident(delete)operator(()symbol(:years)operator(\)) operator(||) integer(0)operator(\))operator(,) ident(month)operator(,) ident(day)operator(\)) + ident(d) operator(=) ident(d) operator(>>) ident(options)operator(.)ident(delete)operator(()symbol(:months)operator(\)) reserved(if) ident(options)operator([)symbol(:months)operator(]) + ident(d) operator(=) ident(d) operator(+) ident(options)operator(.)ident(delete)operator(()symbol(:days)operator(\)) reserved(if) ident(options)operator([)symbol(:days)operator(]) + ident(change)operator(()ident(options)operator(.)ident(merge)operator(()symbol(:year) operator(=)operator(>) ident(d)operator(.)ident(year)operator(,) symbol(:month) operator(=)operator(>) ident(d)operator(.)ident(month)operator(,) symbol(:mday) operator(=)operator(>) ident(d)operator(.)ident(day)operator(\))operator(\)) + reserved(end) + + comment(# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension) + comment(# Do not use this method in combination with x.months, use months_ago instead!) + reserved(def) method(ago)operator(()ident(seconds)operator(\)) + ident(seconds)operator(.)ident(until)operator(()pre_constant(self)operator(\)) + reserved(end) + + comment(# Returns a new Time representing the time a number of seconds since the instance time, this is basically a wrapper around ) + comment(#the Numeric extension. Do not use this method in combination with x.months, use months_since instead!) + reserved(def) method(since)operator(()ident(seconds)operator(\)) + ident(seconds)operator(.)ident(since)operator(()pre_constant(self)operator(\)) + reserved(end) + reserved(alias) symbol(:in) symbol(:since) + + comment(# Returns a new Time representing the time a number of specified months ago) + reserved(def) method(months_ago)operator(()ident(months)operator(\)) + ident(months_since)operator(()operator(-)ident(months)operator(\)) + reserved(end) + + reserved(def) method(months_since)operator(()ident(months)operator(\)) + ident(year)operator(,) ident(month)operator(,) ident(mday) operator(=) pre_constant(self)operator(.)ident(year)operator(,) pre_constant(self)operator(.)ident(month)operator(,) pre_constant(self)operator(.)ident(mday) + + ident(month) operator(+=) ident(months) + + comment(# in case months is negative) + reserved(while) ident(month) operator(<) integer(1) + ident(month) operator(+=) integer(12) + ident(year) operator(-=) integer(1) + reserved(end) + + comment(# in case months is positive) + reserved(while) ident(month) operator(>) integer(12) + ident(month) operator(-=) integer(12) + ident(year) operator(+=) integer(1) + reserved(end) + + ident(max) operator(=) operator(::)constant(Time)operator(.)ident(days_in_month)operator(()ident(month)operator(,) ident(year)operator(\)) + ident(mday) operator(=) ident(max) reserved(if) ident(mday) operator(>) ident(max) + + ident(change)operator(()symbol(:year) operator(=)operator(>) ident(year)operator(,) symbol(:month) operator(=)operator(>) ident(month)operator(,) symbol(:mday) operator(=)operator(>) ident(mday)operator(\)) + reserved(end) + + comment(# Returns a new Time representing the time a number of specified years ago) + reserved(def) method(years_ago)operator(()ident(years)operator(\)) + ident(change)operator(()symbol(:year) operator(=)operator(>) pre_constant(self)operator(.)ident(year) operator(-) ident(years)operator(\)) + reserved(end) + + reserved(def) method(years_since)operator(()ident(years)operator(\)) + ident(change)operator(()symbol(:year) operator(=)operator(>) pre_constant(self)operator(.)ident(year) operator(+) ident(years)operator(\)) + reserved(end) + + comment(# Short-hand for years_ago(1\)) + reserved(def) method(last_year) + ident(years_ago)operator(()integer(1)operator(\)) + reserved(end) + + comment(# Short-hand for years_since(1\)) + reserved(def) method(next_year) + ident(years_since)operator(()integer(1)operator(\)) + reserved(end) + + + comment(# Short-hand for months_ago(1\)) + reserved(def) method(last_month) + ident(months_ago)operator(()integer(1)operator(\)) + reserved(end) + + comment(# Short-hand for months_since(1\)) + reserved(def) method(next_month) + ident(months_since)operator(()integer(1)operator(\)) + reserved(end) + + comment(# Returns a new Time representing the "start" of this week (Monday, 0:00\)) + reserved(def) method(beginning_of_week) + ident(days_to_monday) operator(=) pre_constant(self)operator(.)ident(wday!)operator(=)integer(0) operator(?) pre_constant(self)operator(.)ident(wday)operator(-)integer(1) operator(:) integer(6) + operator(()pre_constant(self) operator(-) ident(days_to_monday)operator(.)ident(days)operator(\))operator(.)ident(midnight) + reserved(end) + reserved(alias) symbol(:monday) symbol(:beginning_of_week) + reserved(alias) symbol(:at_beginning_of_week) symbol(:beginning_of_week) + + comment(# Returns a new Time representing the start of the given day in next week (default is Monday\).) + reserved(def) method(next_week)operator(()ident(day) operator(=) symbol(:monday)operator(\)) + ident(days_into_week) operator(=) operator({) symbol(:monday) operator(=)operator(>) integer(0)operator(,) symbol(:tuesday) operator(=)operator(>) integer(1)operator(,) symbol(:wednesday) operator(=)operator(>) integer(2)operator(,) symbol(:thursday) operator(=)operator(>) integer(3)operator(,) symbol(:friday) operator(=)operator(>) integer(4)operator(,) symbol(:saturday) operator(=)operator(>) integer(5)operator(,) symbol(:sunday) operator(=)operator(>) integer(6)operator(}) + ident(since)operator(()integer(1)operator(.)ident(week)operator(\))operator(.)ident(beginning_of_week)operator(.)ident(since)operator(()ident(days_into_week)operator([)ident(day)operator(])operator(.)ident(day)operator(\))operator(.)ident(change)operator(()symbol(:hour) operator(=)operator(>) integer(0)operator(\)) + reserved(end) + + comment(# Returns a new Time representing the start of the day (0:00\)) + reserved(def) method(beginning_of_day) + operator(()pre_constant(self) operator(-) pre_constant(self)operator(.)ident(seconds_since_midnight)operator(\))operator(.)ident(change)operator(()symbol(:usec) operator(=)operator(>) integer(0)operator(\)) + reserved(end) + reserved(alias) symbol(:midnight) symbol(:beginning_of_day) + reserved(alias) symbol(:at_midnight) symbol(:beginning_of_day) + reserved(alias) symbol(:at_beginning_of_day) symbol(:beginning_of_day) + + comment(# Returns a new Time representing the start of the month (1st of the month, 0:00\)) + reserved(def) method(beginning_of_month) + comment(#self - ((self.mday-1\).days + self.seconds_since_midnight\)) + ident(change)operator(()symbol(:mday) operator(=)operator(>) integer(1)operator(,)symbol(:hour) operator(=)operator(>) integer(0)operator(,) symbol(:min) operator(=)operator(>) integer(0)operator(,) symbol(:sec) operator(=)operator(>) integer(0)operator(,) symbol(:usec) operator(=)operator(>) integer(0)operator(\)) + reserved(end) + reserved(alias) symbol(:at_beginning_of_month) symbol(:beginning_of_month) + + comment(# Returns a new Time representing the end of the month (last day of the month, 0:00\)) + reserved(def) method(end_of_month) + comment(#self - ((self.mday-1\).days + self.seconds_since_midnight\)) + ident(last_day) operator(=) operator(::)constant(Time)operator(.)ident(days_in_month)operator(() pre_constant(self)operator(.)ident(month)operator(,) pre_constant(self)operator(.)ident(year) operator(\)) + ident(change)operator(()symbol(:mday) operator(=)operator(>) ident(last_day)operator(,)symbol(:hour) operator(=)operator(>) integer(0)operator(,) symbol(:min) operator(=)operator(>) integer(0)operator(,) symbol(:sec) operator(=)operator(>) integer(0)operator(,) symbol(:usec) operator(=)operator(>) integer(0)operator(\)) + reserved(end) + reserved(alias) symbol(:at_end_of_month) symbol(:end_of_month) + + comment(# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00\)) + reserved(def) method(beginning_of_quarter) + ident(beginning_of_month)operator(.)ident(change)operator(()symbol(:month) operator(=)operator(>) operator([)integer(10)operator(,) integer(7)operator(,) integer(4)operator(,) integer(1)operator(])operator(.)ident(detect) operator({) operator(|)ident(m)operator(|) ident(m) operator(<=) pre_constant(self)operator(.)ident(month) operator(})operator(\)) + reserved(end) + reserved(alias) symbol(:at_beginning_of_quarter) symbol(:beginning_of_quarter) + + comment(# Returns a new Time representing the start of the year (1st of january, 0:00\)) + reserved(def) method(beginning_of_year) + ident(change)operator(()symbol(:month) operator(=)operator(>) integer(1)operator(,)symbol(:mday) operator(=)operator(>) integer(1)operator(,)symbol(:hour) operator(=)operator(>) integer(0)operator(,) symbol(:min) operator(=)operator(>) integer(0)operator(,) symbol(:sec) operator(=)operator(>) integer(0)operator(,) symbol(:usec) operator(=)operator(>) integer(0)operator(\)) + reserved(end) + reserved(alias) symbol(:at_beginning_of_year) symbol(:beginning_of_year) + + comment(# Convenience method which returns a new Time representing the time 1 day ago) + reserved(def) method(yesterday) + pre_constant(self)operator(.)ident(ago)operator(()integer(1)operator(.)ident(day)operator(\)) + reserved(end) + + comment(# Convenience method which returns a new Time representing the time 1 day since the instance time) + reserved(def) method(tomorrow) + pre_constant(self)operator(.)ident(since)operator(()integer(1)operator(.)ident(day)operator(\)) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) string<delimiter(')content(date)delimiter(')> +ident(require) string<delimiter(')content(time)delimiter(')> + +reserved(module) class(ActiveSupport) comment(#:nodoc:) + reserved(module) class(CoreExtensions) comment(#:nodoc:) + reserved(module) class(Time) comment(#:nodoc:) + comment(# Getting times in different convenient string representations and other objects) + reserved(module) class(Conversions) + constant(DATE_FORMATS) operator(=) operator({) + symbol(:db) operator(=)operator(>) string<delimiter(")content(%Y-%m-%d %H:%M:%S)delimiter(")>operator(,) + symbol(:short) operator(=)operator(>) string<delimiter(")content(%d %b %H:%M)delimiter(")>operator(,) + symbol(:long) operator(=)operator(>) string<delimiter(")content(%B %d, %Y %H:%M)delimiter(")>operator(,) + symbol(:rfc822) operator(=)operator(>) string<delimiter(")content(%a, %d %b %Y %H:%M:%S %z)delimiter(")> + operator(}) + + reserved(def) pre_constant(self)operator(.)ident(append_features)operator(()ident(klass)operator(\)) + reserved(super) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:to_default_s)operator(,) symbol(:to_s)operator(\)) + ident(klass)operator(.)ident(send)operator(()symbol(:alias_method)operator(,) symbol(:to_s)operator(,) symbol(:to_formatted_s)operator(\)) + reserved(end) + + reserved(def) method(to_formatted_s)operator(()ident(format) operator(=) symbol(:default)operator(\)) + constant(DATE_FORMATS)operator([)ident(format)operator(]) operator(?) ident(strftime)operator(()constant(DATE_FORMATS)operator([)ident(format)operator(])operator(\))operator(.)ident(strip) operator(:) ident(to_default_s) + reserved(end) + + reserved(def) method(to_date) + operator(::)constant(Date)operator(.)ident(new)operator(()ident(year)operator(,) ident(month)operator(,) ident(day)operator(\)) + reserved(end) + + comment(# To be able to keep Dates and Times interchangeable on conversions) + reserved(def) method(to_time) + pre_constant(self) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/time/calculations)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/time/conversions)delimiter(')> + +reserved(class) class(Time)comment(#:nodoc:) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Time)operator(::)constant(Calculations) + ident(include) constant(ActiveSupport)operator(::)constant(CoreExtensions)operator(::)constant(Time)operator(::)constant(Conversions) +reserved(end) +constant(Dir)operator([)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/core_ext/*.rb)delimiter(")>operator(])operator(.)ident(each) operator({) operator(|)ident(file)operator(|) ident(require)operator(()ident(file)operator(\)) operator(}) +ident(require) string<delimiter(')content(set)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/core_ext/module/attribute_accessors)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/core_ext/load_error)delimiter(')> +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/core_ext/kernel)delimiter(')> + +reserved(module) class(Dependencies) comment(#:nodoc:) + ident(extend) pre_constant(self) + + comment(# Should we turn on Ruby warnings on the first load of dependent files?) + ident(mattr_accessor) symbol(:warnings_on_first_load) + pre_constant(self)operator(.)ident(warnings_on_first_load) operator(=) pre_constant(false) + + comment(# All files ever loaded.) + ident(mattr_accessor) symbol(:history) + pre_constant(self)operator(.)ident(history) operator(=) constant(Set)operator(.)ident(new) + + comment(# All files currently loaded.) + ident(mattr_accessor) symbol(:loaded) + pre_constant(self)operator(.)ident(loaded) operator(=) constant(Set)operator(.)ident(new) + + comment(# Should we load files or require them?) + ident(mattr_accessor) symbol(:mechanism) + pre_constant(self)operator(.)ident(mechanism) operator(=) symbol(:load) + + reserved(def) method(load?) + ident(mechanism) operator(==) symbol(:load) + reserved(end) + + reserved(def) method(depend_on)operator(()ident(file_name)operator(,) ident(swallow_load_errors) operator(=) pre_constant(false)operator(\)) + ident(require_or_load)operator(()ident(file_name)operator(\)) + reserved(rescue) constant(LoadError) + ident(raise) reserved(unless) ident(swallow_load_errors) + reserved(end) + + reserved(def) method(associate_with)operator(()ident(file_name)operator(\)) + ident(depend_on)operator(()ident(file_name)operator(,) pre_constant(true)operator(\)) + reserved(end) + + reserved(def) method(clear) + ident(loaded)operator(.)ident(clear) + reserved(end) + + reserved(def) method(require_or_load)operator(()ident(file_name)operator(\)) + ident(file_name) operator(=) global_variable($1) reserved(if) ident(file_name) operator(=)operator(~) regexp<delimiter(/)content(^(.*\))char(\\.)content(rb$)delimiter(/)> + reserved(return) reserved(if) ident(loaded)operator(.)ident(include?)operator(()ident(file_name)operator(\)) + + comment(# Record that we've seen this file *before* loading it to avoid an) + comment(# infinite loop with mutual dependencies.) + ident(loaded) operator(<<) ident(file_name) + + reserved(if) ident(load?) + reserved(begin) + comment(# Enable warnings iff this file has not been loaded before and) + comment(# warnings_on_first_load is set.) + reserved(if) operator(!)ident(warnings_on_first_load) reserved(or) ident(history)operator(.)ident(include?)operator(()ident(file_name)operator(\)) + ident(load) string<delimiter(")inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>content(.rb)delimiter(")> + reserved(else) + ident(enable_warnings) operator({) ident(load) string<delimiter(")inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>content(.rb)delimiter(")> operator(}) + reserved(end) + reserved(rescue) + ident(loaded)operator(.)ident(delete) ident(file_name) + ident(raise) + reserved(end) + reserved(else) + ident(require) ident(file_name) + reserved(end) + + comment(# Record history *after* loading so first load gets warnings.) + ident(history) operator(<<) ident(file_name) + reserved(end) + + reserved(class) class(LoadingModule) + comment(# Old style environment.rb referenced this method directly. Please note, it doesn't) + comment(# actualy *do* anything any more.) + reserved(def) pre_constant(self)operator(.)ident(root)operator(()operator(*)ident(args)operator(\)) + reserved(if) reserved(defined?)operator(()constant(RAILS_DEFAULT_LOGGER)operator(\)) + constant(RAILS_DEFAULT_LOGGER)operator(.)ident(warn) string<delimiter(")content(Your environment.rb uses the old syntax, it may not continue to work in future releases.)delimiter(")> + constant(RAILS_DEFAULT_LOGGER)operator(.)ident(warn) string<delimiter(")content(For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19)delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) + +constant(Object)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:require_or_load)operator(\)) operator({) operator(|)ident(file_name)operator(|) constant(Dependencies)operator(.)ident(require_or_load)operator(()ident(file_name)operator(\)) operator(}) reserved(unless) constant(Object)operator(.)ident(respond_to?)operator(()symbol(:require_or_load)operator(\)) +constant(Object)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:require_dependency)operator(\)) operator({) operator(|)ident(file_name)operator(|) constant(Dependencies)operator(.)ident(depend_on)operator(()ident(file_name)operator(\)) operator(}) reserved(unless) constant(Object)operator(.)ident(respond_to?)operator(()symbol(:require_dependency)operator(\)) +constant(Object)operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:require_association)operator(\)) operator({) operator(|)ident(file_name)operator(|) constant(Dependencies)operator(.)ident(associate_with)operator(()ident(file_name)operator(\)) operator(}) reserved(unless) constant(Object)operator(.)ident(respond_to?)operator(()symbol(:require_association)operator(\)) + +reserved(class) class(Module) comment(#:nodoc:) + comment(# Rename the original handler so we can chain it to the new one) + reserved(alias) symbol(:rails_original_const_missing) symbol(:const_missing) + + comment(# Use const_missing to autoload associations so we don't have to) + comment(# require_association when using single-table inheritance.) + reserved(def) method(const_missing)operator(()ident(class_id)operator(\)) + ident(file_name) operator(=) ident(class_id)operator(.)ident(to_s)operator(.)ident(demodulize)operator(.)ident(underscore) + ident(file_path) operator(=) ident(as_load_path)operator(.)ident(empty?) operator(?) ident(file_name) operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(as_load_path)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(file_name)inline_delimiter(})>delimiter(")> + reserved(begin) + ident(require_dependency)operator(()ident(file_path)operator(\)) + ident(brief_name) operator(=) pre_constant(self) operator(==) constant(Object) operator(?) string<delimiter(')delimiter(')> operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(name)inline_delimiter(})>content(::)delimiter(")> + ident(raise) constant(NameError)operator(.)ident(new)operator(()string<delimiter(")content(uninitialized constant )inline<inline_delimiter(#{)ident(brief_name)inline_delimiter(})>inline<inline_delimiter(#{)ident(class_id)inline_delimiter(})>delimiter(")>operator(\)) reserved(unless) ident(const_defined?)operator(()ident(class_id)operator(\)) + reserved(return) ident(const_get)operator(()ident(class_id)operator(\)) + reserved(rescue) constant(MissingSourceFile) operator(=)operator(>) ident(e) + comment(# Re-raise the error if it does not concern the file we were trying to load.) + ident(raise) reserved(unless) ident(e)operator(.)ident(is_missing?) ident(file_path) + + comment(# Look for a directory in the load path that we ought to load.) + reserved(if) global_variable($LOAD_PATH)operator(.)ident(any?) operator({) operator(|)ident(base)operator(|) constant(File)operator(.)ident(directory?) string<delimiter(")inline<inline_delimiter(#{)ident(base)inline_delimiter(})>content(/)inline<inline_delimiter(#{)ident(file_path)inline_delimiter(})>delimiter(")> operator(}) + ident(mod) operator(=) constant(Module)operator(.)ident(new) + ident(const_set) ident(class_id)operator(,) ident(mod) comment(# Create the new module) + reserved(return) ident(mod) + reserved(end) + + comment(# Attempt to access the name from the parent, unless we don't have a valid) + comment(# parent, or the constant is already defined in the parent. If the latter) + comment(# is the case, then we are being queried via self::class_id, and we should) + comment(# avoid returning the constant from the parent if possible.) + reserved(if) ident(parent) operator(&&) ident(parent) operator(!=) pre_constant(self) operator(&&) operator(!) ident(parents)operator(.)ident(any?) operator({) operator(|)ident(p)operator(|) ident(p)operator(.)ident(const_defined?)operator(()ident(class_id)operator(\)) operator(}) + ident(suppress)operator(()constant(NameError)operator(\)) reserved(do) + reserved(return) ident(parent)operator(.)ident(send)operator(()symbol(:const_missing)operator(,) ident(class_id)operator(\)) + reserved(end) + reserved(end) + + ident(raise) constant(NameError)operator(.)ident(new)operator(()string<delimiter(")content(uninitialized constant )inline<inline_delimiter(#{)ident(class_id)inline_delimiter(})>delimiter(")>operator(\))operator(.)ident(copy_blame!)operator(()ident(e)operator(\)) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(Class) + reserved(def) method(const_missing)operator(()ident(class_id)operator(\)) + reserved(if) operator([)constant(Object)operator(,) constant(Kernel)operator(])operator(.)ident(include?)operator(()pre_constant(self)operator(\)) operator(||) ident(parent) operator(==) pre_constant(self) + reserved(super) + reserved(else) + ident(parent)operator(.)ident(send) symbol(:const_missing)operator(,) ident(class_id) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(Object) comment(#:nodoc:) + reserved(def) method(load)operator(()ident(file)operator(,) operator(*)ident(extras)operator(\)) + reserved(super)operator(()ident(file)operator(,) operator(*)ident(extras)operator(\)) + reserved(rescue) constant(Object) operator(=)operator(>) ident(exception) + ident(exception)operator(.)ident(blame_file!) ident(file) + ident(raise) + reserved(end) + + reserved(def) method(require)operator(()ident(file)operator(,) operator(*)ident(extras)operator(\)) + reserved(super)operator(()ident(file)operator(,) operator(*)ident(extras)operator(\)) + reserved(rescue) constant(Object) operator(=)operator(>) ident(exception) + ident(exception)operator(.)ident(blame_file!) ident(file) + ident(raise) + reserved(end) +reserved(end) + +comment(# Add file-blaming to exceptions) +reserved(class) class(Exception) comment(#:nodoc:) + reserved(def) method(blame_file!)operator(()ident(file)operator(\)) + operator(()instance_variable(@blamed_files) operator(||=) operator([)operator(])operator(\))operator(.)ident(unshift) ident(file) + reserved(end) + + reserved(def) method(blamed_files) + instance_variable(@blamed_files) operator(||=) operator([)operator(]) + reserved(end) + + reserved(def) method(describe_blame) + reserved(return) pre_constant(nil) reserved(if) ident(blamed_files)operator(.)ident(empty?) + string<delimiter(")content(This error occured while loading the following files:)char(\\n)content( )inline<inline_delimiter(#{)ident(blamed_files)operator(.)ident(join) string<delimiter(")char(\\n)content( )delimiter(")>inline_delimiter(})>delimiter(")> + reserved(end) + + reserved(def) method(copy_blame!)operator(()ident(exc)operator(\)) + instance_variable(@blamed_files) operator(=) ident(exc)operator(.)ident(blamed_files)operator(.)ident(clone) + pre_constant(self) + reserved(end) +ident(endInflector)operator(.)ident(inflections) reserved(do) operator(|)ident(inflect)operator(|) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content($)delimiter(/)>operator(,) string<delimiter(')content(s)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(s$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(s)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((ax|test\)is$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(es)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((octop|vir\)us$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(i)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((alias|status\)$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(es)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((bu\)s$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ses)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((buffal|tomat\)o$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(oes)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(([ti]\)um$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(a)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(sis$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(ses)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((?:([^f]\)fe|([lr]\)f\)$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(\\2)content(ves)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((hive\)$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(s)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(([^aeiouy]|qu\)y$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ies)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(([^aeiouy]|qu\)ies$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(y)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((x|ch|ss|sh\)$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(es)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((matr|vert|ind\)ix|ex$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ices)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(([m|l]\)ouse$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ice)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content(^(ox\)$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(en)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(plural)operator(()regexp<delimiter(/)content((quiz\)$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(zes)delimiter(')>operator(\)) + + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(s$)delimiter(/)modifier(i)>operator(,) string<delimiter(')delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((n\)ews$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ews)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(([ti]\)a$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(um)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(((a\)naly|(b\)a|(d\)iagno|(p\)arenthe|(p\)rogno|(s\)ynop|(t\)he\)ses$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(\\2)content(sis)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((^analy\)ses$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(sis)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(([^f]\)ves$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(fe)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((hive\)s$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((tive\)s$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(([lr]\)ves$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(f)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(([^aeiouy]|qu\)ies$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(y)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((s\)eries$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(eries)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((m\)ovies$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ovie)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((x|ch|ss|sh\)es$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(([m|l]\)ice$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ouse)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((bus\)es$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((o\)es$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((shoe\)s$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((cris|ax|test\)es$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(is)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(([octop|vir]\)i$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(us)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((alias|status\)es$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content(^(ox\)en)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((vert|ind\)ices$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ex)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((matr\)ices$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)content(ix)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(singular)operator(()regexp<delimiter(/)content((quiz\)zes$)delimiter(/)modifier(i)>operator(,) string<delimiter(')content(\\1)delimiter(')>operator(\)) + + ident(inflect)operator(.)ident(irregular)operator(()string<delimiter(')content(person)delimiter(')>operator(,) string<delimiter(')content(people)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(irregular)operator(()string<delimiter(')content(man)delimiter(')>operator(,) string<delimiter(')content(men)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(irregular)operator(()string<delimiter(')content(child)delimiter(')>operator(,) string<delimiter(')content(children)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(irregular)operator(()string<delimiter(')content(sex)delimiter(')>operator(,) string<delimiter(')content(sexes)delimiter(')>operator(\)) + ident(inflect)operator(.)ident(irregular)operator(()string<delimiter(')content(move)delimiter(')>operator(,) string<delimiter(')content(moves)delimiter(')>operator(\)) + + ident(inflect)operator(.)ident(uncountable)operator(()string<delimiter(%w()content(equipment information rice money species series fish sheep)delimiter(\))>operator(\)) +reserved(end) +ident(require) string<delimiter(')content(singleton)delimiter(')> + +comment(# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,) +comment(# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept) +comment(# in inflections.rb.) +reserved(module) class(Inflector) + comment(# A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional) + comment(# inflection rules. Examples:) + comment(#) + comment(# Inflector.inflections do |inflect|) + comment(# inflect.plural /^(ox\)$/i, '\\1\\2en') + comment(# inflect.singular /^(ox\)en/i, '\\1') + comment(#) + comment(# inflect.irregular 'octopus', 'octopi') + comment(#) + comment(# inflect.uncountable "equipment") + comment(# end) + comment(#) + comment(# New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the) + comment(# pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may) + comment(# already have been loaded.) + reserved(class) class(Inflections) + ident(include) constant(Singleton) + + ident(attr_reader) symbol(:plurals)operator(,) symbol(:singulars)operator(,) symbol(:uncountables) + + reserved(def) method(initialize) + instance_variable(@plurals)operator(,) instance_variable(@singulars)operator(,) instance_variable(@uncountables) operator(=) operator([)operator(])operator(,) operator([)operator(])operator(,) operator([)operator(]) + reserved(end) + + comment(# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. ) + comment(# The replacement should always be a string that may include references to the matched data from the rule.) + reserved(def) method(plural)operator(()ident(rule)operator(,) ident(replacement)operator(\)) + instance_variable(@plurals)operator(.)ident(insert)operator(()integer(0)operator(,) operator([)ident(rule)operator(,) ident(replacement)operator(])operator(\)) + reserved(end) + + comment(# Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. ) + comment(# The replacement should always be a string that may include references to the matched data from the rule.) + reserved(def) method(singular)operator(()ident(rule)operator(,) ident(replacement)operator(\)) + instance_variable(@singulars)operator(.)ident(insert)operator(()integer(0)operator(,) operator([)ident(rule)operator(,) ident(replacement)operator(])operator(\)) + reserved(end) + + comment(# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used) + comment(# for strings, not regular expressions. You simply pass the irregular in singular and plural form.) + comment(# ) + comment(# Examples:) + comment(# irregular 'octopus', 'octopi') + comment(# irregular 'person', 'people') + reserved(def) method(irregular)operator(()ident(singular)operator(,) ident(plural)operator(\)) + ident(plural)operator(()constant(Regexp)operator(.)ident(new)operator(()string<delimiter(")content(()inline<inline_delimiter(#{)ident(singular)operator([)integer(0)operator(,)integer(1)operator(])inline_delimiter(})>content(\))inline<inline_delimiter(#{)ident(singular)operator([)integer(1)operator(..)integer(-1)operator(])inline_delimiter(})>content($)delimiter(")>operator(,) string<delimiter(")content(i)delimiter(")>operator(\))operator(,) string<delimiter(')content(\\1)delimiter(')> operator(+) ident(plural)operator([)integer(1)operator(..)integer(-1)operator(])operator(\)) + ident(singular)operator(()constant(Regexp)operator(.)ident(new)operator(()string<delimiter(")content(()inline<inline_delimiter(#{)ident(plural)operator([)integer(0)operator(,)integer(1)operator(])inline_delimiter(})>content(\))inline<inline_delimiter(#{)ident(plural)operator([)integer(1)operator(..)integer(-1)operator(])inline_delimiter(})>content($)delimiter(")>operator(,) string<delimiter(")content(i)delimiter(")>operator(\))operator(,) string<delimiter(')content(\\1)delimiter(')> operator(+) ident(singular)operator([)integer(1)operator(..)integer(-1)operator(])operator(\)) + reserved(end) + + comment(# Add uncountable words that shouldn't be attempted inflected.) + comment(# ) + comment(# Examples:) + comment(# uncountable "money") + comment(# uncountable "money", "information") + comment(# uncountable %w( money information rice \)) + reserved(def) method(uncountable)operator(()operator(*)ident(words)operator(\)) + operator(()instance_variable(@uncountables) operator(<<) ident(words)operator(\))operator(.)ident(flatten!) + reserved(end) + + comment(# Clears the loaded inflections within a given scope (default is :all\). Give the scope as a symbol of the inflection type,) + comment(# the options are: :plurals, :singulars, :uncountables) + comment(#) + comment(# Examples:) + comment(# clear :all) + comment(# clear :plurals) + reserved(def) method(clear)operator(()ident(scope) operator(=) symbol(:all)operator(\)) + reserved(case) ident(scope) + reserved(when) symbol(:all) + instance_variable(@plurals)operator(,) instance_variable(@singulars)operator(,) instance_variable(@uncountables) operator(=) operator([)operator(])operator(,) operator([)operator(])operator(,) operator([)operator(]) + reserved(else) + ident(instance_variable_set) string<delimiter(")content(@)inline<inline_delimiter(#{)ident(scope)inline_delimiter(})>delimiter(")>operator(,) operator([)operator(]) + reserved(end) + reserved(end) + reserved(end) + + ident(extend) pre_constant(self) + + reserved(def) method(inflections) + reserved(if) ident(block_given?) + reserved(yield) constant(Inflections)operator(.)ident(instance) + reserved(else) + constant(Inflections)operator(.)ident(instance) + reserved(end) + reserved(end) + + reserved(def) method(pluralize)operator(()ident(word)operator(\)) + ident(result) operator(=) ident(word)operator(.)ident(to_s)operator(.)ident(dup) + + reserved(if) ident(inflections)operator(.)ident(uncountables)operator(.)ident(include?)operator(()ident(result)operator(.)ident(downcase)operator(\)) + ident(result) + reserved(else) + ident(inflections)operator(.)ident(plurals)operator(.)ident(each) operator({) operator(|)operator(()ident(rule)operator(,) ident(replacement)operator(\))operator(|) reserved(break) reserved(if) ident(result)operator(.)ident(gsub!)operator(()ident(rule)operator(,) ident(replacement)operator(\)) operator(}) + ident(result) + reserved(end) + reserved(end) + + reserved(def) method(singularize)operator(()ident(word)operator(\)) + ident(result) operator(=) ident(word)operator(.)ident(to_s)operator(.)ident(dup) + + reserved(if) ident(inflections)operator(.)ident(uncountables)operator(.)ident(include?)operator(()ident(result)operator(.)ident(downcase)operator(\)) + ident(result) + reserved(else) + ident(inflections)operator(.)ident(singulars)operator(.)ident(each) operator({) operator(|)operator(()ident(rule)operator(,) ident(replacement)operator(\))operator(|) reserved(break) reserved(if) ident(result)operator(.)ident(gsub!)operator(()ident(rule)operator(,) ident(replacement)operator(\)) operator(}) + ident(result) + reserved(end) + reserved(end) + + reserved(def) method(camelize)operator(()ident(lower_case_and_underscored_word)operator(,) ident(first_letter_in_uppercase) operator(=) pre_constant(true)operator(\)) + reserved(if) ident(first_letter_in_uppercase) + ident(lower_case_and_underscored_word)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\/)content((.?\))delimiter(/)>operator(\)) operator({) string<delimiter(")content(::)delimiter(")> operator(+) global_variable($1)operator(.)ident(upcase) operator(})operator(.)ident(gsub)operator(()regexp<delimiter(/)content((^|_\)(.\))delimiter(/)>operator(\)) operator({) global_variable($2)operator(.)ident(upcase) operator(}) + reserved(else) + ident(lower_case_and_underscored_word)operator(.)ident(first) operator(+) ident(camelize)operator(()ident(lower_case_and_underscored_word)operator(\))operator([)integer(1)operator(..)integer(-1)operator(]) + reserved(end) + reserved(end) + + reserved(def) method(titleize)operator(()ident(word)operator(\)) + ident(humanize)operator(()ident(underscore)operator(()ident(word)operator(\))operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)char(\\b)content(([a-z]\))delimiter(/)>operator(\)) operator({) global_variable($1)operator(.)ident(capitalize) operator(}) + reserved(end) + + reserved(def) method(underscore)operator(()ident(camel_cased_word)operator(\)) + ident(camel_cased_word)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(::)delimiter(/)>operator(,) string<delimiter(')content(/)delimiter(')>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(/)content(([A-Z]+\)([A-Z][a-z]\))delimiter(/)>operator(,)string<delimiter(')content(\\1)content(_)content(\\2)delimiter(')>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(/)content(([a-z)char(\\d)content(]\)([A-Z]\))delimiter(/)>operator(,)string<delimiter(')content(\\1)content(_)content(\\2)delimiter(')>operator(\))operator(.) + ident(tr)operator(()string<delimiter(")content(-)delimiter(")>operator(,) string<delimiter(")content(_)delimiter(")>operator(\))operator(.) + ident(downcase) + reserved(end) + + reserved(def) method(dasherize)operator(()ident(underscored_word)operator(\)) + ident(underscored_word)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(_)delimiter(/)>operator(,) string<delimiter(')content(-)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(humanize)operator(()ident(lower_case_and_underscored_word)operator(\)) + ident(lower_case_and_underscored_word)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(_id$)delimiter(/)>operator(,) string<delimiter(")delimiter(")>operator(\))operator(.)ident(gsub)operator(()regexp<delimiter(/)content(_)delimiter(/)>operator(,) string<delimiter(")content( )delimiter(")>operator(\))operator(.)ident(capitalize) + reserved(end) + + reserved(def) method(demodulize)operator(()ident(class_name_in_module)operator(\)) + ident(class_name_in_module)operator(.)ident(to_s)operator(.)ident(gsub)operator(()regexp<delimiter(/)content(^.*::)delimiter(/)>operator(,) string<delimiter(')delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(tableize)operator(()ident(class_name)operator(\)) + ident(pluralize)operator(()ident(underscore)operator(()ident(class_name)operator(\))operator(\)) + reserved(end) + + reserved(def) method(classify)operator(()ident(table_name)operator(\)) + ident(camelize)operator(()ident(singularize)operator(()ident(table_name)operator(\))operator(\)) + reserved(end) + + reserved(def) method(foreign_key)operator(()ident(class_name)operator(,) ident(separate_class_name_and_id_with_underscore) operator(=) pre_constant(true)operator(\)) + ident(underscore)operator(()ident(demodulize)operator(()ident(class_name)operator(\))operator(\)) operator(+) operator(()ident(separate_class_name_and_id_with_underscore) operator(?) string<delimiter(")content(_id)delimiter(")> operator(:) string<delimiter(")content(id)delimiter(")>operator(\)) + reserved(end) + + reserved(def) method(constantize)operator(()ident(camel_cased_word)operator(\)) + ident(raise) constant(NameError)operator(,) string<delimiter(")inline<inline_delimiter(#{)ident(camel_cased_word)operator(.)ident(inspect)inline_delimiter(})>content( is not a valid constant name!)delimiter(")> reserved(unless) + regexp<delimiter(/)content(^(::\)?([A-Z])char(\\w)content(*\)(::[A-Z])char(\\w)content(*\)*$)delimiter(/)> operator(=)operator(~) ident(camel_cased_word) + + ident(camel_cased_word) operator(=) string<delimiter(")content(::)inline<inline_delimiter(#{)ident(camel_cased_word)inline_delimiter(})>delimiter(")> reserved(unless) global_variable($1) + constant(Object)operator(.)ident(module_eval)operator(()ident(camel_cased_word)operator(,) pre_constant(__FILE__)operator(,) pre_constant(__LINE__)operator(\)) + reserved(end) + + reserved(def) method(ordinalize)operator(()ident(number)operator(\)) + reserved(if) operator(()integer(11)operator(..)integer(13)operator(\))operator(.)ident(include?)operator(()ident(number)operator(.)ident(to_i) operator(%) integer(100)operator(\)) + string<delimiter(")inline<inline_delimiter(#{)ident(number)inline_delimiter(})>content(th)delimiter(")> + reserved(else) + reserved(case) ident(number)operator(.)ident(to_i) operator(%) integer(10) + reserved(when) integer(1)operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(number)inline_delimiter(})>content(st)delimiter(")> + reserved(when) integer(2)operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(number)inline_delimiter(})>content(nd)delimiter(")> + reserved(when) integer(3)operator(:) string<delimiter(")inline<inline_delimiter(#{)ident(number)inline_delimiter(})>content(rd)delimiter(")> + reserved(else) string<delimiter(")inline<inline_delimiter(#{)ident(number)inline_delimiter(})>content(th)delimiter(")> + reserved(end) + reserved(end) + reserved(end) +reserved(end) + +ident(require) constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/inflections)delimiter(')> +reserved(module) class(ActiveSupport) + reserved(module) class(JSON) comment(#:nodoc:) + reserved(module) class(Encoders) comment(#:nodoc:) + ident(define_encoder) constant(Object) reserved(do) operator(|)ident(object)operator(|) + ident(object)operator(.)ident(instance_values)operator(.)ident(to_json) + reserved(end) + + ident(define_encoder) constant(TrueClass) reserved(do) + string<delimiter(')content(true)delimiter(')> + reserved(end) + + ident(define_encoder) constant(FalseClass) reserved(do) + string<delimiter(')content(false)delimiter(')> + reserved(end) + + ident(define_encoder) constant(NilClass) reserved(do) + string<delimiter(')content(null)delimiter(')> + reserved(end) + + ident(define_encoder) constant(String) reserved(do) operator(|)ident(string)operator(|) + ident(returning) ident(value) operator(=) string<delimiter(')content(")delimiter(')> reserved(do) + ident(string)operator(.)ident(each_char) reserved(do) operator(|)ident(char)operator(|) + ident(value) operator(<<) reserved(case) + reserved(when) ident(char) operator(==) string<delimiter(")char(\\010)delimiter(")>operator(:) string<delimiter(')content(\\b)delimiter(')> + reserved(when) ident(char) operator(==) string<delimiter(")char(\\f)delimiter(")>operator(:) string<delimiter(')content(\\f)delimiter(')> + reserved(when) ident(char) operator(==) string<delimiter(")char(\\n)delimiter(")>operator(:) string<delimiter(')content(\\n)delimiter(')> + reserved(when) ident(char) operator(==) string<delimiter(")char(\\r)delimiter(")>operator(:) string<delimiter(')content(\\r)delimiter(')> + reserved(when) ident(char) operator(==) string<delimiter(")char(\\t)delimiter(")>operator(:) string<delimiter(')content(\\t)delimiter(')> + reserved(when) ident(char) operator(==) string<delimiter(')content(")delimiter(')>operator(:) string<delimiter(')content(\\")delimiter(')> + reserved(when) ident(char) operator(==) string<delimiter(')char(\\\\)delimiter(')>operator(:) string<delimiter(')char(\\\\)char(\\\\)delimiter(')> + reserved(when) ident(char)operator(.)ident(length) operator(>) integer(1)operator(:) string<delimiter(")char(\\\\)content(u)inline<inline_delimiter(#{)string<delimiter(')content(%04x)delimiter(')> operator(%) ident(char)operator(.)ident(unpack)operator(()string<delimiter(')content(U)delimiter(')>operator(\))operator(.)ident(first)inline_delimiter(})>delimiter(")> + reserved(else)operator(;) ident(char) + reserved(end) + reserved(end) + ident(value) operator(<<) string<delimiter(')content(")delimiter(')> + reserved(end) + reserved(end) + + ident(define_encoder) constant(Numeric) reserved(do) operator(|)ident(numeric)operator(|) + ident(numeric)operator(.)ident(to_s) + reserved(end) + + ident(define_encoder) constant(Symbol) reserved(do) operator(|)ident(symbol)operator(|) + ident(symbol)operator(.)ident(to_s)operator(.)ident(to_json) + reserved(end) + + ident(define_encoder) constant(Enumerable) reserved(do) operator(|)ident(enumerable)operator(|) + string<delimiter(")content([)inline<inline_delimiter(#{)ident(enumerable)operator(.)ident(map) operator({) operator(|)ident(value)operator(|) ident(value)operator(.)ident(to_json) operator(}) operator(*) string<delimiter(')content(, )delimiter(')>inline_delimiter(})>content(])delimiter(")> + reserved(end) + + ident(define_encoder) constant(Hash) reserved(do) operator(|)ident(hash)operator(|) + ident(returning) ident(result) operator(=) string<delimiter(')content({)delimiter(')> reserved(do) + ident(result) operator(<<) ident(hash)operator(.)ident(map) reserved(do) operator(|)ident(pair)operator(|) + ident(pair)operator(.)ident(map) operator({) operator(|)ident(value)operator(|) ident(value)operator(.)ident(to_json) operator(}) operator(*) string<delimiter(')content(: )delimiter(')> + reserved(end) operator(*) string<delimiter(')content(, )delimiter(')> + ident(result) operator(<<) string<delimiter(')content(})delimiter(')> + reserved(end) + reserved(end) + + ident(define_encoder) constant(Regexp) reserved(do) operator(|)ident(regexp)operator(|) + ident(regexp)operator(.)ident(inspect) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) + reserved(module) class(JSON) comment(#:nodoc:) + reserved(module) class(Encoders) + ident(mattr_accessor) symbol(:encoders) + class_variable(@@encoders) operator(=) operator({)operator(}) + + reserved(class) operator(<<) class(self) + reserved(def) method(define_encoder)operator(()ident(klass)operator(,) operator(&)ident(block)operator(\)) + ident(encoders)operator([)ident(klass)operator(]) operator(=) ident(block) + reserved(end) + + reserved(def) method([])operator(()ident(klass)operator(\)) + ident(klass)operator(.)ident(ancestors)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(|) + ident(encoder) operator(=) ident(encoders)operator([)ident(k)operator(]) + reserved(return) ident(encoder) reserved(if) ident(encoder) + reserved(end) + reserved(end) + reserved(end) + reserved(end) + reserved(end) +reserved(end) + +constant(Dir)operator([)constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(')content(/encoders/*.rb)delimiter(')>operator(])operator(.)ident(each) reserved(do) operator(|)ident(file)operator(|) + ident(require) ident(file)operator([)integer(0)operator(..)integer(-4)operator(]) +reserved(end) +ident(require) string<delimiter(')content(active_support/json/encoders)delimiter(')> + +reserved(module) class(ActiveSupport) + reserved(module) class(JSON) comment(#:nodoc:) + reserved(class) class(CircularReferenceError) operator(<) constant(StandardError) comment(#:nodoc:) + reserved(end) + comment(# returns the literal string as its JSON encoded form. Useful for passing javascript variables into functions.) + comment(#) + comment(# page.call 'Element.show', ActiveSupport::JSON::Variable.new("$$(#items li\)"\)) + reserved(class) class(Variable) operator(<) constant(String) comment(#:nodoc:) + reserved(def) method(to_json) + pre_constant(self) + reserved(end) + reserved(end) + + reserved(class) operator(<<) class(self) + constant(REFERENCE_STACK_VARIABLE) operator(=) symbol(:json_reference_stack) + + reserved(def) method(encode)operator(()ident(value)operator(\)) + ident(raise_on_circular_reference)operator(()ident(value)operator(\)) reserved(do) + constant(Encoders)operator([)ident(value)operator(.)ident(class)operator(])operator(.)ident(call)operator(()ident(value)operator(\)) + reserved(end) + reserved(end) + + ident(protected) + reserved(def) method(raise_on_circular_reference)operator(()ident(value)operator(\)) + ident(stack) operator(=) constant(Thread)operator(.)ident(current)operator([)constant(REFERENCE_STACK_VARIABLE)operator(]) operator(||=) operator([)operator(]) + ident(raise) constant(CircularReferenceError)operator(,) string<delimiter(')content(object references itself)delimiter(')> reserved(if) + ident(stack)operator(.)ident(include?) ident(value) + ident(stack) operator(<<) ident(value) + reserved(yield) + reserved(ensure) + ident(stack)operator(.)ident(pop) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(module) class(ActiveSupport) + reserved(class) class(OptionMerger) comment(#:nodoc:) + ident(instance_methods)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + ident(undef_method)operator(()ident(method)operator(\)) reserved(if) ident(method) operator(!)operator(~) regexp<delimiter(/)content(^(__|instance_eval\))delimiter(/)> + reserved(end) + + reserved(def) method(initialize)operator(()ident(context)operator(,) ident(options)operator(\)) + instance_variable(@context)operator(,) instance_variable(@options) operator(=) ident(context)operator(,) ident(options) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + ident(merge_argument_options!) ident(arguments) + instance_variable(@context)operator(.)ident(send)operator(()ident(method)operator(,) operator(*)ident(arguments)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + reserved(def) method(merge_argument_options!)operator(()ident(arguments)operator(\)) + ident(arguments) operator(<<) reserved(if) ident(arguments)operator(.)ident(last)operator(.)ident(respond_to?) symbol(:merge!) + ident(arguments)operator(.)ident(pop)operator(.)ident(dup)operator(.)ident(merge!)operator(()instance_variable(@options)operator(\)) + reserved(else) + instance_variable(@options)operator(.)ident(dup) + reserved(end) + reserved(end) + reserved(end) +reserved(end) +reserved(class) class(OrderedHash) operator(<) constant(Array) comment(#:nodoc:) + reserved(def) method([]=)operator(()ident(key)operator(,) ident(value)operator(\)) + reserved(if) ident(pair) operator(=) ident(find_pair)operator(()ident(key)operator(\)) + ident(pair)operator(.)ident(pop) + ident(pair) operator(<<) ident(value) + reserved(else) + pre_constant(self) operator(<<) operator([)ident(key)operator(,) ident(value)operator(]) + reserved(end) + reserved(end) + + reserved(def) method([])operator(()ident(key)operator(\)) + ident(pair) operator(=) ident(find_pair)operator(()ident(key)operator(\)) + ident(pair) operator(?) ident(pair)operator(.)ident(last) operator(:) pre_constant(nil) + reserved(end) + + reserved(def) method(keys) + pre_constant(self)operator(.)ident(collect) operator({) operator(|)ident(i)operator(|) ident(i)operator(.)ident(first) operator(}) + reserved(end) + + ident(private) + reserved(def) method(find_pair)operator(()ident(key)operator(\)) + pre_constant(self)operator(.)ident(each) operator({) operator(|)ident(i)operator(|) reserved(return) ident(i) reserved(if) ident(i)operator(.)ident(first) operator(==) ident(key) operator(}) + reserved(return) pre_constant(false) + reserved(end) +reserved(end) + +reserved(class) class(OrderedOptions) operator(<) constant(OrderedHash) comment(#:nodoc:) + reserved(def) method([]=)operator(()ident(key)operator(,) ident(value)operator(\)) + reserved(super)operator(()ident(key)operator(.)ident(to_sym)operator(,) ident(value)operator(\)) + reserved(end) + + reserved(def) method([])operator(()ident(key)operator(\)) + reserved(super)operator(()ident(key)operator(.)ident(to_sym)operator(\)) + reserved(end) + + reserved(def) method(method_missing)operator(()ident(name)operator(,) operator(*)ident(args)operator(\)) + reserved(if) ident(name)operator(.)ident(to_s) operator(=)operator(~) regexp<delimiter(/)content((.*\)=$)delimiter(/)> + pre_constant(self)operator([)global_variable($1)operator(.)ident(to_sym)operator(]) operator(=) ident(args)operator(.)ident(first) + reserved(else) + pre_constant(self)operator([)ident(name)operator(]) + reserved(end) + reserved(end) +reserved(end)comment(# Classes that include this module will automatically be reloaded) +comment(# by the Rails dispatcher when Dependencies.mechanism = :load.) +reserved(module) class(Reloadable) + reserved(class) operator(<<) class(self) + reserved(def) method(included)operator(()ident(base)operator(\)) comment(#nodoc:) + ident(raise) constant(TypeError)operator(,) string<delimiter(")content(Only Classes can be Reloadable!)delimiter(")> reserved(unless) ident(base)operator(.)ident(is_a?) constant(Class) + + reserved(unless) ident(base)operator(.)ident(respond_to?)operator(()symbol(:reloadable?)operator(\)) + reserved(class) operator(<<) class(base) + ident(define_method)operator(()symbol(:reloadable?)operator(\)) operator({) pre_constant(true) operator(}) + reserved(end) + reserved(end) + reserved(end) + + reserved(def) method(reloadable_classes) + ident(included_in_classes)operator(.)ident(select) operator({) operator(|)ident(klass)operator(|) ident(klass)operator(.)ident(reloadable?) operator(}) + reserved(end) + reserved(end) + + comment(# Captures the common pattern where a base class should not be reloaded,) + comment(# but its subclasses should be.) + reserved(module) class(Subclasses) + reserved(def) pre_constant(self)operator(.)ident(included)operator(()ident(base)operator(\)) comment(#nodoc:) + ident(base)operator(.)ident(send) symbol(:include)operator(,) constant(Reloadable) + operator(()reserved(class) operator(<<) class(base)operator(;) pre_constant(self)operator(;) reserved(end)operator(\))operator(.)ident(send)operator(()symbol(:define_method)operator(,) symbol(:reloadable?)operator(\)) reserved(do) + ident(base) operator(!=) pre_constant(self) + reserved(end) + reserved(end) + reserved(end) +reserved(end)comment(# A value object representing a time zone. A time zone is simply a named) +comment(# offset (in seconds\) from GMT. Note that two time zone objects are only) +comment(# equivalent if they have both the same offset, and the same name.) +comment(#) +comment(# A TimeZone instance may be used to convert a Time value to the corresponding) +comment(# time zone.) +comment(#) +comment(# The class also includes #all, which returns a list of all TimeZone objects.) +reserved(class) class(TimeZone) + ident(include) constant(Comparable) + + ident(attr_reader) symbol(:name)operator(,) symbol(:utc_offset) + + comment(# Create a new TimeZone object with the given name and offset. The offset is) + comment(# the number of seconds that this time zone is offset from UTC (GMT\). Seconds) + comment(# were chosen as the offset unit because that is the unit that Ruby uses) + comment(# to represent time zone offsets (see Time#utc_offset\).) + reserved(def) method(initialize)operator(()ident(name)operator(,) ident(utc_offset)operator(\)) + instance_variable(@name) operator(=) ident(name) + instance_variable(@utc_offset) operator(=) ident(utc_offset) + reserved(end) + + comment(# Returns the offset of this time zone as a formatted string, of the) + comment(# format "+HH:MM". If the offset is zero, this returns the empty) + comment(# string. If +colon+ is false, a colon will not be inserted into the) + comment(# result.) + reserved(def) method(formatted_offset)operator(() ident(colon)operator(=)pre_constant(true) operator(\)) + reserved(return) string<delimiter(")delimiter(")> reserved(if) ident(utc_offset) operator(==) integer(0) + ident(sign) operator(=) operator(()ident(utc_offset) operator(<) integer(0) operator(?) integer(-1) operator(:) integer(1)operator(\)) + ident(hours) operator(=) ident(utc_offset)operator(.)ident(abs) operator(/) integer(3600) + ident(minutes) operator(=) operator(()ident(utc_offset)operator(.)ident(abs) operator(%) integer(3600)operator(\)) operator(/) integer(60) + string<delimiter(")content(%+03d%s%02d)delimiter(")> operator(%) operator([) ident(hours) operator(*) ident(sign)operator(,) ident(colon) operator(?) string<delimiter(")content(:)delimiter(")> operator(:) string<delimiter(")delimiter(")>operator(,) ident(minutes) operator(]) + reserved(end) + + comment(# Compute and return the current time, in the time zone represented by) + comment(# +self+.) + reserved(def) method(now) + ident(adjust)operator(()constant(Time)operator(.)ident(now)operator(\)) + reserved(end) + + comment(# Return the current date in this time zone.) + reserved(def) method(today) + ident(now)operator(.)ident(to_date) + reserved(end) + + comment(# Adjust the given time to the time zone represented by +self+.) + reserved(def) method(adjust)operator(()ident(time)operator(\)) + ident(time) operator(=) ident(time)operator(.)ident(to_time) + ident(time) operator(+) ident(utc_offset) operator(-) ident(time)operator(.)ident(utc_offset) + reserved(end) + + comment(# Reinterprets the given time value as a time in the current time) + comment(# zone, and then adjusts it to return the corresponding time in the) + comment(# local time zone.) + reserved(def) method(unadjust)operator(()ident(time)operator(\)) + ident(time) operator(=) constant(Time)operator(.)ident(local)operator(()operator(*)ident(time)operator(.)ident(to_time)operator(.)ident(to_a)operator(\)) + ident(time) operator(-) ident(utc_offset) operator(+) ident(time)operator(.)ident(utc_offset) + reserved(end) + + comment(# Compare this time zone to the parameter. The two are comapred first on) + comment(# their offsets, and then by name.) + reserved(def) method(<=>)operator(()ident(zone)operator(\)) + ident(result) operator(=) operator(()ident(utc_offset) operator(<=>) ident(zone)operator(.)ident(utc_offset)operator(\)) + ident(result) operator(=) operator(()ident(name) operator(<=>) ident(zone)operator(.)ident(name)operator(\)) reserved(if) ident(result) operator(==) integer(0) + ident(result) + reserved(end) + + comment(# Returns a textual representation of this time zone.) + reserved(def) method(to_s) + string<delimiter(")content((GMT)inline<inline_delimiter(#{)ident(formatted_offset)inline_delimiter(})>content(\) )inline<inline_delimiter(#{)ident(name)inline_delimiter(})>delimiter(")> + reserved(end) + + class_variable(@@zones) operator(=) pre_constant(nil) + + reserved(class) operator(<<) class(self) + comment(# Create a new TimeZone instance with the given name and offset.) + reserved(def) method(create)operator(()ident(name)operator(,) ident(offset)operator(\)) + ident(zone) operator(=) ident(allocate) + ident(zone)operator(.)ident(send) symbol(:initialize)operator(,) ident(name)operator(,) ident(offset) + ident(zone) + reserved(end) + + comment(# Return a TimeZone instance with the given name, or +nil+ if no) + comment(# such TimeZone instance exists. (This exists to support the use of) + comment(# this class with the #composed_of macro.\)) + reserved(def) method(new)operator(()ident(name)operator(\)) + pre_constant(self)operator([)ident(name)operator(]) + reserved(end) + + comment(# Return an array of all TimeZone objects. There are multiple TimeZone) + comment(# objects per time zone, in many cases, to make it easier for users to) + comment(# find their own time zone.) + reserved(def) method(all) + reserved(unless) class_variable(@@zones) + class_variable(@@zones) operator(=) operator([)operator(]) + operator([)operator([)integer(-43_200)operator(,) string<delimiter(")content(International Date Line West)delimiter(")> operator(])operator(,) + operator([)integer(-39_600)operator(,) string<delimiter(")content(Midway Island)delimiter(")>operator(,) string<delimiter(")content(Samoa)delimiter(")> operator(])operator(,) + operator([)integer(-36_000)operator(,) string<delimiter(")content(Hawaii)delimiter(")> operator(])operator(,) + operator([)integer(-32_400)operator(,) string<delimiter(")content(Alaska)delimiter(")> operator(])operator(,) + operator([)integer(-28_800)operator(,) string<delimiter(")content(Pacific Time (US & Canada\))delimiter(")>operator(,) string<delimiter(")content(Tijuana)delimiter(")> operator(])operator(,) + operator([)integer(-25_200)operator(,) string<delimiter(")content(Mountain Time (US & Canada\))delimiter(")>operator(,) string<delimiter(")content(Chihuahua)delimiter(")>operator(,) string<delimiter(")content(La Paz)delimiter(")>operator(,) + string<delimiter(")content(Mazatlan)delimiter(")>operator(,) string<delimiter(")content(Arizona)delimiter(")> operator(])operator(,) + operator([)integer(-21_600)operator(,) string<delimiter(")content(Central Time (US & Canada\))delimiter(")>operator(,) string<delimiter(")content(Saskatchewan)delimiter(")>operator(,) string<delimiter(")content(Guadalajara)delimiter(")>operator(,) + string<delimiter(")content(Mexico City)delimiter(")>operator(,) string<delimiter(")content(Monterrey)delimiter(")>operator(,) string<delimiter(")content(Central America)delimiter(")> operator(])operator(,) + operator([)integer(-18_000)operator(,) string<delimiter(")content(Eastern Time (US & Canada\))delimiter(")>operator(,) string<delimiter(")content(Indiana (East\))delimiter(")>operator(,) string<delimiter(")content(Bogota)delimiter(")>operator(,) + string<delimiter(")content(Lima)delimiter(")>operator(,) string<delimiter(")content(Quito)delimiter(")> operator(])operator(,) + operator([)integer(-14_400)operator(,) string<delimiter(")content(Atlantic Time (Canada\))delimiter(")>operator(,) string<delimiter(")content(Caracas)delimiter(")>operator(,) string<delimiter(")content(La Paz)delimiter(")>operator(,) string<delimiter(")content(Santiago)delimiter(")> operator(])operator(,) + operator([)integer(-12_600)operator(,) string<delimiter(")content(Newfoundland)delimiter(")> operator(])operator(,) + operator([)integer(-10_800)operator(,) string<delimiter(")content(Brasilia)delimiter(")>operator(,) string<delimiter(")content(Buenos Aires)delimiter(")>operator(,) string<delimiter(")content(Georgetown)delimiter(")>operator(,) string<delimiter(")content(Greenland)delimiter(")> operator(])operator(,) + operator([) integer(-7_200)operator(,) string<delimiter(")content(Mid-Atlantic)delimiter(")> operator(])operator(,) + operator([) integer(-3_600)operator(,) string<delimiter(")content(Azores)delimiter(")>operator(,) string<delimiter(")content(Cape Verde Is.)delimiter(")> operator(])operator(,) + operator([) integer(0)operator(,) string<delimiter(")content(Dublin)delimiter(")>operator(,) string<delimiter(")content(Edinburgh)delimiter(")>operator(,) string<delimiter(")content(Lisbon)delimiter(")>operator(,) string<delimiter(")content(London)delimiter(")>operator(,) string<delimiter(")content(Casablanca)delimiter(")>operator(,) + string<delimiter(")content(Monrovia)delimiter(")> operator(])operator(,) + operator([) integer(3_600)operator(,) string<delimiter(")content(Belgrade)delimiter(")>operator(,) string<delimiter(")content(Bratislava)delimiter(")>operator(,) string<delimiter(")content(Budapest)delimiter(")>operator(,) string<delimiter(")content(Ljubljana)delimiter(")>operator(,) string<delimiter(")content(Prague)delimiter(")>operator(,) + string<delimiter(")content(Sarajevo)delimiter(")>operator(,) string<delimiter(")content(Skopje)delimiter(")>operator(,) string<delimiter(")content(Warsaw)delimiter(")>operator(,) string<delimiter(")content(Zagreb)delimiter(")>operator(,) string<delimiter(")content(Brussels)delimiter(")>operator(,) + string<delimiter(")content(Copenhagen)delimiter(")>operator(,) string<delimiter(")content(Madrid)delimiter(")>operator(,) string<delimiter(")content(Paris)delimiter(")>operator(,) string<delimiter(")content(Amsterdam)delimiter(")>operator(,) string<delimiter(")content(Berlin)delimiter(")>operator(,) + string<delimiter(")content(Bern)delimiter(")>operator(,) string<delimiter(")content(Rome)delimiter(")>operator(,) string<delimiter(")content(Stockholm)delimiter(")>operator(,) string<delimiter(")content(Vienna)delimiter(")>operator(,) + string<delimiter(")content(West Central Africa)delimiter(")> operator(])operator(,) + operator([) integer(7_200)operator(,) string<delimiter(")content(Bucharest)delimiter(")>operator(,) string<delimiter(")content(Cairo)delimiter(")>operator(,) string<delimiter(")content(Helsinki)delimiter(")>operator(,) string<delimiter(")content(Kyev)delimiter(")>operator(,) string<delimiter(")content(Riga)delimiter(")>operator(,) string<delimiter(")content(Sofia)delimiter(")>operator(,) + string<delimiter(")content(Tallinn)delimiter(")>operator(,) string<delimiter(")content(Vilnius)delimiter(")>operator(,) string<delimiter(")content(Athens)delimiter(")>operator(,) string<delimiter(")content(Istanbul)delimiter(")>operator(,) string<delimiter(")content(Minsk)delimiter(")>operator(,) + string<delimiter(")content(Jerusalem)delimiter(")>operator(,) string<delimiter(")content(Harare)delimiter(")>operator(,) string<delimiter(")content(Pretoria)delimiter(")> operator(])operator(,) + operator([) integer(10_800)operator(,) string<delimiter(")content(Moscow)delimiter(")>operator(,) string<delimiter(")content(St. Petersburg)delimiter(")>operator(,) string<delimiter(")content(Volgograd)delimiter(")>operator(,) string<delimiter(")content(Kuwait)delimiter(")>operator(,) string<delimiter(")content(Riyadh)delimiter(")>operator(,) + string<delimiter(")content(Nairobi)delimiter(")>operator(,) string<delimiter(")content(Baghdad)delimiter(")> operator(])operator(,) + operator([) integer(12_600)operator(,) string<delimiter(")content(Tehran)delimiter(")> operator(])operator(,) + operator([) integer(14_400)operator(,) string<delimiter(")content(Abu Dhabi)delimiter(")>operator(,) string<delimiter(")content(Muscat)delimiter(")>operator(,) string<delimiter(")content(Baku)delimiter(")>operator(,) string<delimiter(")content(Tbilisi)delimiter(")>operator(,) string<delimiter(")content(Yerevan)delimiter(")> operator(])operator(,) + operator([) integer(16_200)operator(,) string<delimiter(")content(Kabul)delimiter(")> operator(])operator(,) + operator([) integer(18_000)operator(,) string<delimiter(")content(Ekaterinburg)delimiter(")>operator(,) string<delimiter(")content(Islamabad)delimiter(")>operator(,) string<delimiter(")content(Karachi)delimiter(")>operator(,) string<delimiter(")content(Tashkent)delimiter(")> operator(])operator(,) + operator([) integer(19_800)operator(,) string<delimiter(")content(Chennai)delimiter(")>operator(,) string<delimiter(")content(Kolkata)delimiter(")>operator(,) string<delimiter(")content(Mumbai)delimiter(")>operator(,) string<delimiter(")content(New Delhi)delimiter(")> operator(])operator(,) + operator([) integer(20_700)operator(,) string<delimiter(")content(Kathmandu)delimiter(")> operator(])operator(,) + operator([) integer(21_600)operator(,) string<delimiter(")content(Astana)delimiter(")>operator(,) string<delimiter(")content(Dhaka)delimiter(")>operator(,) string<delimiter(")content(Sri Jayawardenepura)delimiter(")>operator(,) string<delimiter(")content(Almaty)delimiter(")>operator(,) + string<delimiter(")content(Novosibirsk)delimiter(")> operator(])operator(,) + operator([) integer(23_400)operator(,) string<delimiter(")content(Rangoon)delimiter(")> operator(])operator(,) + operator([) integer(25_200)operator(,) string<delimiter(")content(Bangkok)delimiter(")>operator(,) string<delimiter(")content(Hanoi)delimiter(")>operator(,) string<delimiter(")content(Jakarta)delimiter(")>operator(,) string<delimiter(")content(Krasnoyarsk)delimiter(")> operator(])operator(,) + operator([) integer(28_800)operator(,) string<delimiter(")content(Beijing)delimiter(")>operator(,) string<delimiter(")content(Chongqing)delimiter(")>operator(,) string<delimiter(")content(Hong Kong)delimiter(")>operator(,) string<delimiter(")content(Urumqi)delimiter(")>operator(,) + string<delimiter(")content(Kuala Lumpur)delimiter(")>operator(,) string<delimiter(")content(Singapore)delimiter(")>operator(,) string<delimiter(")content(Taipei)delimiter(")>operator(,) string<delimiter(")content(Perth)delimiter(")>operator(,) string<delimiter(")content(Irkutsk)delimiter(")>operator(,) + string<delimiter(")content(Ulaan Bataar)delimiter(")> operator(])operator(,) + operator([) integer(32_400)operator(,) string<delimiter(")content(Seoul)delimiter(")>operator(,) string<delimiter(")content(Osaka)delimiter(")>operator(,) string<delimiter(")content(Sapporo)delimiter(")>operator(,) string<delimiter(")content(Tokyo)delimiter(")>operator(,) string<delimiter(")content(Yakutsk)delimiter(")> operator(])operator(,) + operator([) integer(34_200)operator(,) string<delimiter(")content(Darwin)delimiter(")>operator(,) string<delimiter(")content(Adelaide)delimiter(")> operator(])operator(,) + operator([) integer(36_000)operator(,) string<delimiter(")content(Canberra)delimiter(")>operator(,) string<delimiter(")content(Melbourne)delimiter(")>operator(,) string<delimiter(")content(Sydney)delimiter(")>operator(,) string<delimiter(")content(Brisbane)delimiter(")>operator(,) string<delimiter(")content(Hobart)delimiter(")>operator(,) + string<delimiter(")content(Vladivostok)delimiter(")>operator(,) string<delimiter(")content(Guam)delimiter(")>operator(,) string<delimiter(")content(Port Moresby)delimiter(")> operator(])operator(,) + operator([) integer(39_600)operator(,) string<delimiter(")content(Magadan)delimiter(")>operator(,) string<delimiter(")content(Solomon Is.)delimiter(")>operator(,) string<delimiter(")content(New Caledonia)delimiter(")> operator(])operator(,) + operator([) integer(43_200)operator(,) string<delimiter(")content(Fiji)delimiter(")>operator(,) string<delimiter(")content(Kamchatka)delimiter(")>operator(,) string<delimiter(")content(Marshall Is.)delimiter(")>operator(,) string<delimiter(")content(Auckland)delimiter(")>operator(,) + string<delimiter(")content(Wellington)delimiter(")> operator(])operator(,) + operator([) integer(46_800)operator(,) string<delimiter(")content(Nuku'alofa)delimiter(")> operator(])operator(])operator(.) + ident(each) reserved(do) operator(|)ident(offset)operator(,) operator(*)ident(places)operator(|) + ident(places)operator(.)ident(each) operator({) operator(|)ident(place)operator(|) class_variable(@@zones) operator(<<) ident(create)operator(()ident(place)operator(,) ident(offset)operator(\))operator(.)ident(freeze) operator(}) + reserved(end) + class_variable(@@zones)operator(.)ident(sort!) + reserved(end) + class_variable(@@zones) + reserved(end) + + comment(# Locate a specific time zone object. If the argument is a string, it) + comment(# is interpreted to mean the name of the timezone to locate. If it is a) + comment(# numeric value it is either the hour offset, or the second offset, of the) + comment(# timezone to find. (The first one with that offset will be returned.\)) + comment(# Returns +nil+ if no such time zone is known to the system.) + reserved(def) method([])operator(()ident(arg)operator(\)) + reserved(case) ident(arg) + reserved(when) constant(String) + ident(all)operator(.)ident(find) operator({) operator(|)ident(z)operator(|) ident(z)operator(.)ident(name) operator(==) ident(arg) operator(}) + reserved(when) constant(Numeric) + ident(arg) operator(*=) integer(3600) reserved(if) ident(arg)operator(.)ident(abs) operator(<=) integer(13) + ident(all)operator(.)ident(find) operator({) operator(|)ident(z)operator(|) ident(z)operator(.)ident(utc_offset) operator(==) ident(arg)operator(.)ident(to_i) operator(}) + reserved(else) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(invalid argument to TimeZone[]: )inline<inline_delimiter(#{)ident(arg)operator(.)ident(inspect)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + + comment(# A regular expression that matches the names of all time zones in) + comment(# the USA.) + constant(US_ZONES) operator(=) regexp<delimiter(/)content(US|Arizona|Indiana|Hawaii|Alaska)delimiter(/)> + + comment(# A convenience method for returning a collection of TimeZone objects) + comment(# for time zones in the USA.) + reserved(def) method(us_zones) + ident(all)operator(.)ident(find_all) operator({) operator(|)ident(z)operator(|) ident(z)operator(.)ident(name) operator(=)operator(~) constant(US_ZONES) operator(}) + reserved(end) + reserved(end) +reserved(end) +comment(#!/usr/bin/env ruby) +comment(#--) +comment(# Copyright 2004 by Jim Weirich (jim@weirichhouse.org\).) +comment(# All rights reserved.) + +comment(# Permission is granted for use, copying, modification, distribution,) +comment(# and distribution of modified versions of this work as long as the) +comment(# above copyright notice is included.) +comment(#++) + +reserved(module) class(Builder) comment(#:nodoc:) + + comment(# BlankSlate provides an abstract base class with no predefined) + comment(# methods (except for <tt>\\_\\_send__</tt> and <tt>\\_\\_id__</tt>\).) + comment(# BlankSlate is useful as a base class when writing classes that) + comment(# depend upon <tt>method_missing</tt> (e.g. dynamic proxies\).) + reserved(class) class(BlankSlate) comment(#:nodoc:) + reserved(class) operator(<<) class(self) + reserved(def) method(hide)operator(()ident(name)operator(\)) + ident(undef_method) ident(name) reserved(if) + ident(instance_methods)operator(.)ident(include?)operator(()ident(name)operator(.)ident(to_s)operator(\)) reserved(and) + ident(name) operator(!)operator(~) regexp<delimiter(/)content(^(__|instance_eval\))delimiter(/)> + reserved(end) + reserved(end) + + ident(instance_methods)operator(.)ident(each) operator({) operator(|)ident(m)operator(|) ident(hide)operator(()ident(m)operator(\)) operator(}) + reserved(end) +reserved(end) + +comment(# Since Ruby is very dynamic, methods added to the ancestors of) +comment(# BlankSlate <em>after BlankSlate is defined</em> will show up in the) +comment(# list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined ) +reserved(module) class(Kernel) comment(#:nodoc:) + reserved(class) operator(<<) class(self) + ident(alias_method) symbol(:blank_slate_method_added)operator(,) symbol(:method_added) + reserved(def) method(method_added)operator(()ident(name)operator(\)) + ident(blank_slate_method_added)operator(()ident(name)operator(\)) + reserved(return) reserved(if) pre_constant(self) operator(!=) constant(Kernel) + constant(Builder)operator(::)constant(BlankSlate)operator(.)ident(hide)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) +reserved(end) + +reserved(class) class(Object) comment(#:nodoc:) + reserved(class) operator(<<) class(self) + ident(alias_method) symbol(:blank_slate_method_added)operator(,) symbol(:method_added) + reserved(def) method(method_added)operator(()ident(name)operator(\)) + ident(blank_slate_method_added)operator(()ident(name)operator(\)) + reserved(return) reserved(if) pre_constant(self) operator(!=) constant(Object) + constant(Builder)operator(::)constant(BlankSlate)operator(.)ident(hide)operator(()ident(name)operator(\)) + reserved(end) + reserved(end) +reserved(end) +comment(#!/usr/bin/env ruby) + +ident(require) string<delimiter(')content(builder/blankslate)delimiter(')> + +reserved(module) class(Builder) comment(#:nodoc:) + + comment(# Generic error for builder) + reserved(class) class(IllegalBlockError) operator(<) constant(RuntimeError) comment(#:nodoc:) + reserved(end) + + comment(# XmlBase is a base class for building XML builders. See) + comment(# Builder::XmlMarkup and Builder::XmlEvents for examples.) + reserved(class) class(XmlBase) operator(<) constant(BlankSlate) comment(#:nodoc:) + + comment(# Create an XML markup builder.) + comment(#) + comment(# out:: Object receiving the markup.1 +out+ must respond to) + comment(# <tt><<</tt>.) + comment(# indent:: Number of spaces used for indentation (0 implies no) + comment(# indentation and no line breaks\).) + comment(# initial:: Level of initial indentation.) + comment(#) + reserved(def) method(initialize)operator(()ident(indent)operator(=)integer(0)operator(,) ident(initial)operator(=)integer(0)operator(\)) + instance_variable(@indent) operator(=) ident(indent) + instance_variable(@level) operator(=) ident(initial) + reserved(end) + + comment(# Create a tag named +sym+. Other than the first argument which) + comment(# is the tag name, the arguements are the same as the tags) + comment(# implemented via <tt>method_missing</tt>.) + reserved(def) method(tag!)operator(()ident(sym)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + pre_constant(self)operator(.)ident(__send__)operator(()ident(sym)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + reserved(end) + + comment(# Create XML markup based on the name of the method. This method) + comment(# is never invoked directly, but is called for each markup method) + comment(# in the markup block.) + reserved(def) method(method_missing)operator(()ident(sym)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(text) operator(=) pre_constant(nil) + ident(attrs) operator(=) pre_constant(nil) + ident(sym) operator(=) string<delimiter(")inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(:)inline<inline_delimiter(#{)ident(args)operator(.)ident(shift)inline_delimiter(})>delimiter(")> reserved(if) ident(args)operator(.)ident(first)operator(.)ident(kind_of?)operator(()constant(Symbol)operator(\)) + ident(args)operator(.)ident(each) reserved(do) operator(|)ident(arg)operator(|) + reserved(case) ident(arg) + reserved(when) constant(Hash) + ident(attrs) operator(||=) operator({)operator(}) + ident(attrs)operator(.)ident(merge!)operator(()ident(arg)operator(\)) + reserved(else) + ident(text) operator(||=) string<delimiter(')delimiter(')> + ident(text) operator(<<) ident(arg)operator(.)ident(to_s) + reserved(end) + reserved(end) + reserved(if) ident(block) + reserved(unless) ident(text)operator(.)ident(nil?) + ident(raise) constant(ArgumentError)operator(,) string<delimiter(")content(XmlMarkup cannot mix a text argument with a block)delimiter(")> + reserved(end) + ident(_capture_outer_self)operator(()ident(block)operator(\)) reserved(if) instance_variable(@self)operator(.)ident(nil?) + ident(_indent) + ident(_start_tag)operator(()ident(sym)operator(,) ident(attrs)operator(\)) + ident(_newline) + ident(_nested_structures)operator(()ident(block)operator(\)) + ident(_indent) + ident(_end_tag)operator(()ident(sym)operator(\)) + ident(_newline) + reserved(elsif) ident(text)operator(.)ident(nil?) + ident(_indent) + ident(_start_tag)operator(()ident(sym)operator(,) ident(attrs)operator(,) pre_constant(true)operator(\)) + ident(_newline) + reserved(else) + ident(_indent) + ident(_start_tag)operator(()ident(sym)operator(,) ident(attrs)operator(\)) + ident(text!) ident(text) + ident(_end_tag)operator(()ident(sym)operator(\)) + ident(_newline) + reserved(end) + instance_variable(@target) + reserved(end) + + comment(# Append text to the output target. Escape any markup. May be) + comment(# used within the markup brackets as:) + comment(#) + comment(# builder.p { br; text! "HI" } #=> <p><br/>HI</p>) + reserved(def) method(text!)operator(()ident(text)operator(\)) + ident(_text)operator(()ident(_escape)operator(()ident(text)operator(\))operator(\)) + reserved(end) + + comment(# Append text to the output target without escaping any markup.) + comment(# May be used within the markup brackets as:) + comment(#) + comment(# builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>) + comment(#) + comment(# This is useful when using non-builder enabled software that) + comment(# generates strings. Just insert the string directly into the) + comment(# builder without changing the inserted markup.) + comment(#) + comment(# It is also useful for stacking builder objects. Builders only) + comment(# use <tt><<</tt> to append to the target, so by supporting this) + comment(# method/operation builders can use other builders as their) + comment(# targets.) + reserved(def) method(<<)operator(()ident(text)operator(\)) + ident(_text)operator(()ident(text)operator(\)) + reserved(end) + + comment(# For some reason, nil? is sent to the XmlMarkup object. If nil?) + comment(# is not defined and method_missing is invoked, some strange kind) + comment(# of recursion happens. Since nil? won't ever be an XML tag, it) + comment(# is pretty safe to define it here. (Note: this is an example of) + comment(# cargo cult programming,) + comment(# cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming\).) + reserved(def) method(nil?) + pre_constant(false) + reserved(end) + + ident(private) + + reserved(def) method(_escape)operator(()ident(text)operator(\)) + ident(text)operator(.) + ident(gsub)operator(()regexp<delimiter(%r{)content(&)delimiter(})>operator(,) string<delimiter(')content(&)delimiter(')>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(%r{)content(<)delimiter(})>operator(,) string<delimiter(')content(<)delimiter(')>operator(\))operator(.) + ident(gsub)operator(()regexp<delimiter(%r{)content(>)delimiter(})>operator(,) string<delimiter(')content(>)delimiter(')>operator(\)) + reserved(end) + + reserved(def) method(_capture_outer_self)operator(()ident(block)operator(\)) + instance_variable(@self) operator(=) ident(eval)operator(()string<delimiter(")content(self)delimiter(")>operator(,) ident(block)operator(\)) + reserved(end) + + reserved(def) method(_newline) + reserved(return) reserved(if) instance_variable(@indent) operator(==) integer(0) + ident(text!) string<delimiter(")char(\\n)delimiter(")> + reserved(end) + + reserved(def) method(_indent) + reserved(return) reserved(if) instance_variable(@indent) operator(==) integer(0) operator(||) instance_variable(@level) operator(==) integer(0) + ident(text!)operator(()string<delimiter(")content( )delimiter(")> operator(*) operator(()instance_variable(@level) operator(*) instance_variable(@indent)operator(\))operator(\)) + reserved(end) + + reserved(def) method(_nested_structures)operator(()ident(block)operator(\)) + instance_variable(@level) operator(+=) integer(1) + ident(block)operator(.)ident(call)operator(()pre_constant(self)operator(\)) + reserved(ensure) + instance_variable(@level) operator(-=) integer(1) + reserved(end) + reserved(end) +reserved(end) +comment(#!/usr/bin/env ruby) + +comment(#--) +comment(# Copyright 2004 by Jim Weirich (jim@weirichhouse.org\).) +comment(# All rights reserved.) + +comment(# Permission is granted for use, copying, modification, distribution,) +comment(# and distribution of modified versions of this work as long as the) +comment(# above copyright notice is included.) +comment(#++) + +ident(require) string<delimiter(')content(builder/xmlmarkup)delimiter(')> + +reserved(module) class(Builder) + + comment(# Create a series of SAX-like XML events (e.g. start_tag, end_tag\)) + comment(# from the markup code. XmlEvent objects are used in a way similar) + comment(# to XmlMarkup objects, except that a series of events are generated) + comment(# and passed to a handler rather than generating character-based) + comment(# markup.) + comment(#) + comment(# Usage:) + comment(# xe = Builder::XmlEvents.new(hander\)) + comment(# xe.title("HI"\) # Sends start_tag/end_tag/text messages to the handler.) + comment(#) + comment(# Indentation may also be selected by providing value for the) + comment(# indentation size and initial indentation level.) + comment(#) + comment(# xe = Builder::XmlEvents.new(handler, indent_size, initial_indent_level\)) + comment(#) + comment(# == XML Event Handler) + comment(#) + comment(# The handler object must expect the following events.) + comment(#) + comment(# [<tt>start_tag(tag, attrs\)</tt>]) + comment(# Announces that a new tag has been found. +tag+ is the name of) + comment(# the tag and +attrs+ is a hash of attributes for the tag.) + comment(#) + comment(# [<tt>end_tag(tag\)</tt>]) + comment(# Announces that an end tag for +tag+ has been found.) + comment(#) + comment(# [<tt>text(text\)</tt>]) + comment(# Announces that a string of characters (+text+\) has been found.) + comment(# A series of characters may be broken up into more than one) + comment(# +text+ call, so the client cannot assume that a single) + comment(# callback contains all the text data.) + comment(#) + reserved(class) class(XmlEvents) operator(<) constant(XmlMarkup) comment(#:nodoc:) + reserved(def) method(text!)operator(()ident(text)operator(\)) + instance_variable(@target)operator(.)ident(text)operator(()ident(text)operator(\)) + reserved(end) + + reserved(def) method(_start_tag)operator(()ident(sym)operator(,) ident(attrs)operator(,) ident(end_too)operator(=)pre_constant(false)operator(\)) + instance_variable(@target)operator(.)ident(start_tag)operator(()ident(sym)operator(,) ident(attrs)operator(\)) + ident(_end_tag)operator(()ident(sym)operator(\)) reserved(if) ident(end_too) + reserved(end) + + reserved(def) method(_end_tag)operator(()ident(sym)operator(\)) + instance_variable(@target)operator(.)ident(end_tag)operator(()ident(sym)operator(\)) + reserved(end) + reserved(end) + +reserved(end) +comment(#!/usr/bin/env ruby) +comment(#--) +comment(# Copyright 2004 by Jim Weirich (jim@weirichhouse.org\).) +comment(# All rights reserved.) + +comment(# Permission is granted for use, copying, modification, distribution,) +comment(# and distribution of modified versions of this work as long as the) +comment(# above copyright notice is included.) +comment(#++) + +comment(# Provide a flexible and easy to use Builder for creating XML markup.) +comment(# See XmlBuilder for usage details.) + +ident(require) string<delimiter(')content(builder/xmlbase)delimiter(')> + +reserved(module) class(Builder) + + comment(# Create XML markup easily. All (well, almost all\) methods sent to) + comment(# an XmlMarkup object will be translated to the equivalent XML) + comment(# markup. Any method with a block will be treated as an XML markup) + comment(# tag with nested markup in the block.) + comment(#) + comment(# Examples will demonstrate this easier than words. In the) + comment(# following, +xm+ is an +XmlMarkup+ object.) + comment(#) + comment(# xm.em("emphasized"\) # => <em>emphasized</em>) + comment(# xm.em { xmm.b("emp & bold"\) } # => <em><b>emph & bold</b></em>) + comment(# xm.a("A Link", "href"=>"http://onestepback.org"\)) + comment(# # => <a href="http://onestepback.org">A Link</a>) + comment(# xm.div { br } # => <div><br/></div>) + comment(# xm.target("name"=>"compile", "option"=>"fast"\)) + comment(# # => <target option="fast" name="compile"\\>) + comment(# # NOTE: order of attributes is not specified.) + comment(#) + comment(# xm.instruct! # <?xml version="1.0" encoding="UTF-8"?>) + comment(# xm.html { # <html>) + comment(# xm.head { # <head>) + comment(# xm.title("History"\) # <title>History</title>) + comment(# } # </head>) + comment(# xm.body { # <body>) + comment(# xm.comment! "HI" # <!-- HI -->) + comment(# xm.h1("Header"\) # <h1>Header</h1>) + comment(# xm.p("paragraph"\) # <p>paragraph</p>) + comment(# } # </body>) + comment(# } # </html>) + comment(#) + comment(# == Notes:) + comment(#) + comment(# * The order that attributes are inserted in markup tags is) + comment(# undefined. ) + comment(#) + comment(# * Sometimes you wish to insert text without enclosing tags. Use) + comment(# the <tt>text!</tt> method to accomplish this.) + comment(#) + comment(# Example:) + comment(#) + comment(# xm.div { # <div>) + comment(# xm.text! "line"; xm.br # line<br/>) + comment(# xm.text! "another line"; xmbr # another line<br/>) + comment(# } # </div>) + comment(#) + comment(# * The special XML characters <, >, and & are converted to <,) + comment(# > and & automatically. Use the <tt><<</tt> operation to) + comment(# insert text without modification.) + comment(#) + comment(# * Sometimes tags use special characters not allowed in ruby) + comment(# identifiers. Use the <tt>tag!</tt> method to handle these) + comment(# cases.) + comment(#) + comment(# Example:) + comment(#) + comment(# xml.tag!("SOAP:Envelope"\) { ... }) + comment(#) + comment(# will produce ...) + comment(#) + comment(# <SOAP:Envelope> ... </SOAP:Envelope>") + comment(#) + comment(# <tt>tag!</tt> will also take text and attribute arguments (after) + comment(# the tag name\) like normal markup methods. (But see the next) + comment(# bullet item for a better way to handle XML namespaces\).) + comment(# ) + comment(# * Direct support for XML namespaces is now available. If the) + comment(# first argument to a tag call is a symbol, it will be joined to) + comment(# the tag to produce a namespace:tag combination. It is easier to) + comment(# show this than describe it.) + comment(#) + comment(# xml.SOAP :Envelope do ... end) + comment(#) + comment(# Just put a space before the colon in a namespace to produce the) + comment(# right form for builder (e.g. "<tt>SOAP:Envelope</tt>" =>) + comment(# "<tt>xml.SOAP :Envelope</tt>"\)) + comment(#) + comment(# * XmlMarkup builds the markup in any object (called a _target_\)) + comment(# that accepts the <tt><<</tt> method. If no target is given,) + comment(# then XmlMarkup defaults to a string target.) + comment(# ) + comment(# Examples:) + comment(#) + comment(# xm = Builder::XmlMarkup.new) + comment(# result = xm.title("yada"\)) + comment(# # result is a string containing the markup.) + comment(#) + comment(# buffer = "") + comment(# xm = Builder::XmlMarkup.new(buffer\)) + comment(# # The markup is appended to buffer (using <<\)) + comment(#) + comment(# xm = Builder::XmlMarkup.new(STDOUT\)) + comment(# # The markup is written to STDOUT (using <<\)) + comment(#) + comment(# xm = Builder::XmlMarkup.new) + comment(# x2 = Builder::XmlMarkup.new(:target=>xm\)) + comment(# # Markup written to +x2+ will be send to +xm+.) + comment(# ) + comment(# * Indentation is enabled by providing the number of spaces to) + comment(# indent for each level as a second argument to XmlBuilder.new.) + comment(# Initial indentation may be specified using a third parameter.) + comment(#) + comment(# Example:) + comment(#) + comment(# xm = Builder.new(:ident=>2\)) + comment(# # xm will produce nicely formatted and indented XML.) + comment(# ) + comment(# xm = Builder.new(:indent=>2, :margin=>4\)) + comment(# # xm will produce nicely formatted and indented XML with 2) + comment(# # spaces per indent and an over all indentation level of 4.) + comment(#) + comment(# builder = Builder::XmlMarkup.new(:target=>$stdout, :indent=>2\)) + comment(# builder.name { |b| b.first("Jim"\); b.last("Weirich\) }) + comment(# # prints:) + comment(# # <name>) + comment(# # <first>Jim</first>) + comment(# # <last>Weirich</last>) + comment(# # </name>) + comment(#) + comment(# * The instance_eval implementation which forces self to refer to) + comment(# the message receiver as self is now obsolete. We now use normal) + comment(# block calls to execute the markup block. This means that all) + comment(# markup methods must now be explicitly send to the xml builder.) + comment(# For instance, instead of) + comment(#) + comment(# xml.div { strong("text"\) }) + comment(#) + comment(# you need to write:) + comment(#) + comment(# xml.div { xml.strong("text"\) }) + comment(#) + comment(# Although more verbose, the subtle change in semantics within the) + comment(# block was found to be prone to error. To make this change a) + comment(# little less cumbersome, the markup block now gets the markup) + comment(# object sent as an argument, allowing you to use a shorter alias) + comment(# within the block.) + comment(#) + comment(# For example:) + comment(#) + comment(# xml_builder = Builder::XmlMarkup.new) + comment(# xml_builder.div { |xml|) + comment(# xml.stong("text"\)) + comment(# }) + comment(#) + reserved(class) class(XmlMarkup) operator(<) constant(XmlBase) + + comment(# Create an XML markup builder. Parameters are specified by an) + comment(# option hash.) + comment(#) + comment(# :target=><em>target_object</em>::) + comment(# Object receiving the markup. +out+ must respond to the) + comment(# <tt><<</tt> operator. The default is a plain string target.) + comment(# :indent=><em>indentation</em>::) + comment(# Number of spaces used for indentation. The default is no) + comment(# indentation and no line breaks.) + comment(# :margin=><em>initial_indentation_level</em>::) + comment(# Amount of initial indentation (specified in levels, not) + comment(# spaces\).) + comment(# ) + reserved(def) method(initialize)operator(()ident(options)operator(=)operator({)operator(})operator(\)) + ident(indent) operator(=) ident(options)operator([)symbol(:indent)operator(]) operator(||) integer(0) + ident(margin) operator(=) ident(options)operator([)symbol(:margin)operator(]) operator(||) integer(0) + reserved(super)operator(()ident(indent)operator(,) ident(margin)operator(\)) + instance_variable(@target) operator(=) ident(options)operator([)symbol(:target)operator(]) operator(||) string<delimiter(")delimiter(")> + reserved(end) + + comment(# Return the target of the builder.) + reserved(def) method(target!) + instance_variable(@target) + reserved(end) + + reserved(def) method(comment!)operator(()ident(comment_text)operator(\)) + ident(_ensure_no_block) ident(block_given?) + ident(_special)operator(()string<delimiter(")content(<!-- )delimiter(")>operator(,) string<delimiter(")content( -->)delimiter(")>operator(,) ident(comment_text)operator(,) pre_constant(nil)operator(\)) + reserved(end) + + comment(# Insert an XML declaration into the XML markup.) + comment(#) + comment(# For example:) + comment(#) + comment(# xml.declare! :ELEMENT, :blah, "yada") + comment(# # => <!ELEMENT blah "yada">) + reserved(def) method(declare!)operator(()ident(inst)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(_indent) + instance_variable(@target) operator(<<) string<delimiter(")content(<!)inline<inline_delimiter(#{)ident(inst)inline_delimiter(})>delimiter(")> + ident(args)operator(.)ident(each) reserved(do) operator(|)ident(arg)operator(|) + reserved(case) ident(arg) + reserved(when) constant(String) + instance_variable(@target) operator(<<) string<delimiter(%{)content( ")inline<inline_delimiter(#{)ident(arg)inline_delimiter(})>content(")delimiter(})> + reserved(when) constant(Symbol) + instance_variable(@target) operator(<<) string<delimiter(")content( )inline<inline_delimiter(#{)ident(arg)inline_delimiter(})>delimiter(")> + reserved(end) + reserved(end) + reserved(if) ident(block_given?) + instance_variable(@target) operator(<<) string<delimiter(")content( [)delimiter(")> + ident(_newline) + ident(_nested_structures)operator(()ident(block)operator(\)) + instance_variable(@target) operator(<<) string<delimiter(")content(])delimiter(")> + reserved(end) + instance_variable(@target) operator(<<) string<delimiter(")content(>)delimiter(")> + ident(_newline) + reserved(end) + + comment(# Insert a processing instruction into the XML markup. E.g.) + comment(#) + comment(# For example:) + comment(#) + comment(# xml.instruct!) + comment(# #=> <?xml version="1.0" encoding="UTF-8"?>) + comment(# xml.instruct! :aaa, :bbb=>"ccc") + comment(# #=> <?aaa bbb="ccc"?>) + comment(#) + reserved(def) method(instruct!)operator(()ident(directive_tag)operator(=)symbol(:xml)operator(,) ident(attrs)operator(=)operator({)operator(})operator(\)) + ident(_ensure_no_block) ident(block_given?) + reserved(if) ident(directive_tag) operator(==) symbol(:xml) + ident(a) operator(=) operator({) symbol(:version)operator(=)operator(>)string<delimiter(")content(1.0)delimiter(")>operator(,) symbol(:encoding)operator(=)operator(>)string<delimiter(")content(UTF-8)delimiter(")> operator(}) + ident(attrs) operator(=) ident(a)operator(.)ident(merge) ident(attrs) + reserved(end) + ident(_special)operator(() + string<delimiter(")content(<?)inline<inline_delimiter(#{)ident(directive_tag)inline_delimiter(})>delimiter(")>operator(,) + string<delimiter(")content(?>)delimiter(")>operator(,) + pre_constant(nil)operator(,) + ident(attrs)operator(,) + operator([)symbol(:version)operator(,) symbol(:encoding)operator(,) symbol(:standalone)operator(])operator(\)) + reserved(end) + + comment(# Surrounds the given text with a CDATA tag) + comment(#) + comment(# For example:) + comment(#) + comment(# xml.cdata! "blah blah blah") + comment(# # => <![CDATA[blah blah blah]]>) + reserved(def) method(cdata!)operator(()ident(text)operator(\)) + ident(_ensure_no_block) ident(block_given?) + ident(_special)operator(()string<delimiter(")content(<![CDATA[)delimiter(")>operator(,) string<delimiter(")content(]]>)delimiter(")>operator(,) ident(text)operator(,) pre_constant(nil)operator(\)) + reserved(end) + + ident(private) + + comment(# NOTE: All private methods of a builder object are prefixed when) + comment(# a "_" character to avoid possible conflict with XML tag names.) + + comment(# Insert text directly in to the builder's target.) + reserved(def) method(_text)operator(()ident(text)operator(\)) + instance_variable(@target) operator(<<) ident(text) + reserved(end) + + comment(# Insert special instruction. ) + reserved(def) method(_special)operator(()ident(open)operator(,) ident(close)operator(,) ident(data)operator(=)pre_constant(nil)operator(,) ident(attrs)operator(=)pre_constant(nil)operator(,) ident(order)operator(=)operator([)operator(])operator(\)) + ident(_indent) + instance_variable(@target) operator(<<) ident(open) + instance_variable(@target) operator(<<) ident(data) reserved(if) ident(data) + ident(_insert_attributes)operator(()ident(attrs)operator(,) ident(order)operator(\)) reserved(if) ident(attrs) + instance_variable(@target) operator(<<) ident(close) + ident(_newline) + reserved(end) + + comment(# Start an XML tag. If <tt>end_too</tt> is true, then the start) + comment(# tag is also the end tag (e.g. <br/>) + reserved(def) method(_start_tag)operator(()ident(sym)operator(,) ident(attrs)operator(,) ident(end_too)operator(=)pre_constant(false)operator(\)) + instance_variable(@target) operator(<<) string<delimiter(")content(<)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>delimiter(")> + ident(_insert_attributes)operator(()ident(attrs)operator(\)) + instance_variable(@target) operator(<<) string<delimiter(")content(/)delimiter(")> reserved(if) ident(end_too) + instance_variable(@target) operator(<<) string<delimiter(")content(>)delimiter(")> + reserved(end) + + comment(# Insert an ending tag.) + reserved(def) method(_end_tag)operator(()ident(sym)operator(\)) + instance_variable(@target) operator(<<) string<delimiter(")content(</)inline<inline_delimiter(#{)ident(sym)inline_delimiter(})>content(>)delimiter(")> + reserved(end) + + comment(# Insert the attributes (given in the hash\).) + reserved(def) method(_insert_attributes)operator(()ident(attrs)operator(,) ident(order)operator(=)operator([)operator(])operator(\)) + reserved(return) reserved(if) ident(attrs)operator(.)ident(nil?) + ident(order)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(|) + ident(v) operator(=) ident(attrs)operator([)ident(k)operator(]) + instance_variable(@target) operator(<<) string<delimiter(%{)content( )inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content(=")inline<inline_delimiter(#{)ident(v)inline_delimiter(})>content(")delimiter(})> reserved(if) ident(v) + reserved(end) + ident(attrs)operator(.)ident(each) reserved(do) operator(|)ident(k)operator(,) ident(v)operator(|) + instance_variable(@target) operator(<<) string<delimiter(%{)content( )inline<inline_delimiter(#{)ident(k)inline_delimiter(})>content(=")inline<inline_delimiter(#{)ident(v)inline_delimiter(})>content(")delimiter(})> reserved(unless) ident(order)operator(.)ident(member?)operator(()ident(k)operator(\)) + reserved(end) + reserved(end) + + reserved(def) method(_ensure_no_block)operator(()ident(got_block)operator(\)) + reserved(if) ident(got_block) + ident(fail) constant(IllegalBlockError)operator(,) + string<delimiter(")content(Blocks are not allowed on XML instructions)delimiter(")> + reserved(end) + reserved(end) + + reserved(end) + +reserved(end) +comment(#!/usr/bin/env ruby) + +comment(#--) +comment(# Copyright 2004 by Jim Weirich (jim@weirichhouse.org\).) +comment(# All rights reserved.) + +comment(# Permission is granted for use, copying, modification, distribution,) +comment(# and distribution of modified versions of this work as long as the) +comment(# above copyright notice is included.) +comment(#++) + +ident(require) string<delimiter(')content(builder/xmlmarkup)delimiter(')> +ident(require) string<delimiter(')content(builder/xmlevents)delimiter(')> +reserved(module) class(ActiveSupport) + reserved(module) class(VERSION) comment(#:nodoc:) + constant(MAJOR) operator(=) integer(1) + constant(MINOR) operator(=) integer(3) + constant(TINY) operator(=) integer(1) + + constant(STRING) operator(=) operator([)constant(MAJOR)operator(,) constant(MINOR)operator(,) constant(TINY)operator(])operator(.)ident(join)operator(()string<delimiter(')content(.)delimiter(')>operator(\)) + reserved(end) +reserved(end) +comment(# Extensions to nil which allow for more helpful error messages for ) +comment(# people who are new to rails.) +comment(#) +comment(# The aim is to ensure that when users pass nil to methods where that isn't) +comment(# appropriate, instead of NoMethodError and the name of some method used) +comment(# by the framework users will see a message explaining what type of object ) +comment(# was expected.) + +reserved(class) class(NilClass) + constant(WHINERS) operator(=) operator([) operator(::)constant(ActiveRecord)operator(::)constant(Base)operator(,) operator(::)constant(Array) operator(]) + + class_variable(@@method_class_map) operator(=) constant(Hash)operator(.)ident(new) + + constant(WHINERS)operator(.)ident(each) reserved(do) operator(|)ident(klass)operator(|) + ident(methods) operator(=) ident(klass)operator(.)ident(public_instance_methods) operator(-) ident(public_instance_methods) + ident(methods)operator(.)ident(each) reserved(do) operator(|)ident(method)operator(|) + class_variable(@@method_class_map)operator([)ident(method)operator(.)ident(to_sym)operator(]) operator(=) ident(klass) + reserved(end) + reserved(end) + + reserved(def) method(id) + ident(raise) constant(RuntimeError)operator(,) string<delimiter(")content(Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id)delimiter(")>operator(,) ident(caller) + reserved(end) + + ident(private) + reserved(def) method(method_missing)operator(()ident(method)operator(,) operator(*)ident(args)operator(,) operator(&)ident(block)operator(\)) + ident(raise_nil_warning_for) class_variable(@@method_class_map)operator([)ident(method)operator(])operator(,) ident(method)operator(,) ident(caller) + reserved(end) + + reserved(def) method(raise_nil_warning_for)operator(()ident(klass) operator(=) pre_constant(nil)operator(,) ident(selector) operator(=) pre_constant(nil)operator(,) ident(with_caller) operator(=) pre_constant(nil)operator(\)) + ident(message) operator(=) string<delimiter(")content(You have a nil object when you didn't expect it!)delimiter(")> + ident(message) operator(<<) string<delimiter(")char(\\n)content(You might have expected an instance of )inline<inline_delimiter(#{)ident(klass)inline_delimiter(})>content(.)delimiter(")> reserved(if) ident(klass) + ident(message) operator(<<) string<delimiter(")char(\\n)content(The error occured while evaluating nil.)inline<inline_delimiter(#{)ident(selector)inline_delimiter(})>delimiter(")> reserved(if) ident(selector) + + ident(raise) constant(NoMethodError)operator(,) ident(message)operator(,) ident(with_caller) operator(||) ident(caller) + reserved(end) +reserved(end) + +comment(#--) +comment(# Copyright (c\) 2005 David Heinemeier Hansson) +comment(#) +comment(# Permission is hereby granted, free of charge, to any person obtaining) +comment(# a copy of this software and associated documentation files (the) +comment(# "Software"\), to deal in the Software without restriction, including) +comment(# without limitation the rights to use, copy, modify, merge, publish,) +comment(# distribute, sublicense, and/or sell copies of the Software, and to) +comment(# permit persons to whom the Software is furnished to do so, subject to) +comment(# the following conditions:) +comment(#) +comment(# The above copyright notice and this permission notice shall be) +comment(# included in all copies or substantial portions of the Software.) +comment(#) +comment(# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,) +comment(# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF) +comment(# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND) +comment(# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE) +comment(# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION) +comment(# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION) +comment(# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.) +comment(#++) + +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\))operator(\)) +global_variable($:)operator(.)ident(unshift)operator(()constant(File)operator(.)ident(dirname)operator(()pre_constant(__FILE__)operator(\)) operator(+) string<delimiter(")content(/active_support/vendor)delimiter(")>operator(\)) + +ident(require) string<delimiter(')content(builder)delimiter(')> + +ident(require) string<delimiter(')content(active_support/inflector)delimiter(')> + +ident(require) string<delimiter(')content(active_support/core_ext)delimiter(')> +ident(require) string<delimiter(')content(active_support/clean_logger)delimiter(')> +ident(require) string<delimiter(')content(active_support/dependencies)delimiter(')> +ident(require) string<delimiter(')content(active_support/reloadable)delimiter(')> + +ident(require) string<delimiter(')content(active_support/ordered_options)delimiter(')> +ident(require) string<delimiter(')content(active_support/option_merger)delimiter(')> + +ident(require) string<delimiter(')content(active_support/values/time_zone)delimiter(')> + +ident(require) string<delimiter(')content(active_support/json)delimiter(')>
\ No newline at end of file diff --git a/test/scanners/ruby/rails.in.rb b/test/scanners/ruby/rails.in.rb new file mode 100644 index 0000000..587b56d --- /dev/null +++ b/test/scanners/ruby/rails.in.rb @@ -0,0 +1,74259 @@ +require 'rbconfig' +require 'find' +require 'ftools' + +include Config + +# this was adapted from rdoc's install.rb by way of Log4r + +$sitedir = CONFIG["sitelibdir"] +unless $sitedir + version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"] + $libdir = File.join(CONFIG["libdir"], "ruby", version) + $sitedir = $:.find {|x| x =~ /site_ruby/ } + if !$sitedir + $sitedir = File.join($libdir, "site_ruby") + elsif $sitedir !~ Regexp.quote(version) + $sitedir = File.join($sitedir, version) + end +end + +# the acual gruntwork +Dir.chdir("lib") + +Find.find("action_mailer", "action_mailer.rb") { |f| + if f[-3..-1] == ".rb" + File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true) + else + File::makedirs(File.join($sitedir, *f.split(/\//))) + end +} +module ActionMailer + module AdvAttrAccessor #:nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + module ClassMethods #:nodoc: + def adv_attr_accessor(*names) + names.each do |name| + ivar = "@#{name}" + + define_method("#{name}=") do |value| + instance_variable_set(ivar, value) + end + + define_method(name) do |*parameters| + raise ArgumentError, "expected 0 or 1 parameters" unless parameters.length <= 1 + if parameters.empty? + if instance_variables.include?(ivar) + instance_variable_get(ivar) + end + else + instance_variable_set(ivar, parameters.first) + end + end + end + end + end + end +end +require 'action_mailer/adv_attr_accessor' +require 'action_mailer/part' +require 'action_mailer/part_container' +require 'action_mailer/utils' +require 'tmail/net' + +module ActionMailer #:nodoc: + # ActionMailer allows you to send email from your application using a mailer model and views. + # + # = Mailer Models + # To use ActionMailer, you need to create a mailer model. + # + # $ script/generate mailer Notifier + # + # The generated model inherits from ActionMailer::Base. Emails are defined by creating methods within the model which are then + # used to set variables to be used in the mail template, to change options on the mail, or + # to add attachments. + # + # Examples: + # + # class Notifier < ActionMailer::Base + # def signup_notification(recipient) + # recipients recipient.email_address_with_name + # from "system@example.com" + # subject "New account information" + # body "account" => recipient + # end + # end + # + # Mailer methods have the following configuration methods available. + # + # * <tt>recipients</tt> - Takes one or more email addresses. These addresses are where your email will be delivered to. Sets the <tt>To:</tt> header. + # * <tt>subject</tt> - The subject of your email. Sets the <tt>Subject:</tt> header. + # * <tt>from</tt> - Who the email you are sending is from. Sets the <tt>From:</tt> header. + # * <tt>cc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header. + # * <tt>bcc</tt> - Takes one or more email address. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc</tt> header. + # * <tt>sent_on</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent. + # * <tt>content_type</tt> - Specify the content type of the message. Defaults to <tt>text/plain</tt>. + # * <tt>headers</tt> - Specify additional headers to be set for the message, e.g. <tt>headers 'X-Mail-Count' => 107370</tt>. + # + # The <tt>body</tt> method has special behavior. It takes a hash which generates an instance variable + # named after each key in the hash containing the value that that key points to. + # + # So, for example, <tt>body "account" => recipient</tt> would result + # in an instance variable <tt>@account</tt> with the value of <tt>recipient</tt> being accessible in the + # view. + # + # = Mailer Views + # Like ActionController, each mailer class has a corresponding view directory + # in which each method of the class looks for a template with its name. + # To define a template to be used with a mailing, create an <tt>.rhtml</tt> file with the same name as the method + # in your mailer model. For example, in the mailer defined above, the template at + # <tt>app/views/notifier/signup_notification.rhtml</tt> would be used to generate the email. + # + # Variables defined in the model are accessible as instance variables in the view. + # + # Emails by default are sent in plain text, so a sample view for our model example might look like this: + # + # Hi <%= @account.name %>, + # Thanks for joining our service! Please check back often. + # + # = Sending Mail + # Once a mailer action and template are defined, you can deliver your message or create it and save it + # for delivery later: + # + # Notifier.deliver_signup_notification(david) # sends the email + # mail = Notifier.create_signup_notification(david) # => a tmail object + # Notifier.deliver(mail) + # + # You never instantiate your mailer class. Rather, your delivery instance + # methods are automatically wrapped in class methods that start with the word + # <tt>deliver_</tt> followed by the name of the mailer method that you would + # like to deliver. The <tt>signup_notification</tt> method defined above is + # delivered by invoking <tt>Notifier.deliver_signup_notification</tt>. + # + # = HTML Email + # To send mail as HTML, make sure your view (the <tt>.rhtml</tt> file) generates HTML and + # set the content type to html. + # + # class MyMailer < ActionMailer::Base + # def signup_notification(recipient) + # recipients recipient.email_address_with_name + # subject "New account information" + # body "account" => recipient + # from "system@example.com" + # content_type "text/html" # Here's where the magic happens + # end + # end + # + # = Multipart Email + # You can explicitly specify multipart messages: + # + # class ApplicationMailer < ActionMailer::Base + # def signup_notification(recipient) + # recipients recipient.email_address_with_name + # subject "New account information" + # from "system@example.com" + # + # part :content_type => "text/html", + # :body => render_message("signup-as-html", :account => recipient) + # + # part "text/plain" do |p| + # p.body = render_message("signup-as-plain", :account => recipient) + # p.transfer_encoding = "base64" + # end + # end + # end + # + # Multipart messages can also be used implicitly because ActionMailer will automatically + # detect and use multipart templates, where each template is named after the name of the action, followed + # by the content type. Each such detected template will be added as separate part to the message. + # + # For example, if the following templates existed: + # * signup_notification.text.plain.rhtml + # * signup_notification.text.html.rhtml + # * signup_notification.text.xml.rxml + # * signup_notification.text.x-yaml.rhtml + # + # Each would be rendered and added as a separate part to the message, + # with the corresponding content type. The same body hash is passed to + # each template. + # + # = Attachments + # Attachments can be added by using the +attachment+ method. + # + # Example: + # + # class ApplicationMailer < ActionMailer::Base + # # attachments + # def signup_notification(recipient) + # recipients recipient.email_address_with_name + # subject "New account information" + # from "system@example.com" + # + # attachment :content_type => "image/jpeg", + # :body => File.read("an-image.jpg") + # + # attachment "application/pdf" do |a| + # a.body = generate_your_pdf_here() + # end + # end + # end + # + # = Configuration options + # + # These options are specified on the class level, like <tt>ActionMailer::Base.template_root = "/my/templates"</tt> + # + # * <tt>template_root</tt> - template root determines the base from which template references will be made. + # + # * <tt>logger</tt> - the logger is used for generating information on the mailing run if available. + # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. + # + # * <tt>server_settings</tt> - Allows detailed configuration of the server: + # * <tt>:address</tt> Allows you to use a remote mail server. Just change it from its default "localhost" setting. + # * <tt>:port</tt> On the off chance that your mail server doesn't run on port 25, you can change it. + # * <tt>:domain</tt> If you need to specify a HELO domain, you can do it here. + # * <tt>:user_name</tt> If your mail server requires authentication, set the username in this setting. + # * <tt>:password</tt> If your mail server requires authentication, set the password in this setting. + # * <tt>:authentication</tt> If your mail server requires authentication, you need to specify the authentication type here. + # This is a symbol and one of :plain, :login, :cram_md5 + # + # * <tt>raise_delivery_errors</tt> - whether or not errors should be raised if the email fails to be delivered. + # + # * <tt>delivery_method</tt> - Defines a delivery method. Possible values are :smtp (default), :sendmail, and :test. + # Sendmail is assumed to be present at "/usr/sbin/sendmail". + # + # * <tt>perform_deliveries</tt> - Determines whether deliver_* methods are actually carried out. By default they are, + # but this can be turned off to help functional testing. + # + # * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful + # for unit and functional testing. + # + # * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also + # pick a different charset from inside a method with <tt>@charset</tt>. + # * <tt>default_content_type</tt> - The default content type used for the main part of the message. Defaults to "text/plain". You + # can also pick a different content type from inside a method with <tt>@content_type</tt>. + # * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to nil. You + # can also pick a different value from inside a method with <tt>@mime_version</tt>. When multipart messages are in + # use, <tt>@mime_version</tt> will be set to "1.0" if it is not set inside a method. + # * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates + # which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to + # ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client + # and appear last in the mime encoded message. You can also pick a different order from inside a method with + # <tt>@implicit_parts_order</tt>. + class Base + include AdvAttrAccessor, PartContainer + + # Action Mailer subclasses should be reloaded by the dispatcher in Rails + # when Dependencies.mechanism = :load. + include Reloadable::Subclasses + + private_class_method :new #:nodoc: + + class_inheritable_accessor :template_root + cattr_accessor :logger + + @@server_settings = { + :address => "localhost", + :port => 25, + :domain => 'localhost.localdomain', + :user_name => nil, + :password => nil, + :authentication => nil + } + cattr_accessor :server_settings + + @@raise_delivery_errors = true + cattr_accessor :raise_delivery_errors + + @@delivery_method = :smtp + cattr_accessor :delivery_method + + @@perform_deliveries = true + cattr_accessor :perform_deliveries + + @@deliveries = [] + cattr_accessor :deliveries + + @@default_charset = "utf-8" + cattr_accessor :default_charset + + @@default_content_type = "text/plain" + cattr_accessor :default_content_type + + @@default_mime_version = nil + cattr_accessor :default_mime_version + + @@default_implicit_parts_order = [ "text/html", "text/enriched", "text/plain" ] + cattr_accessor :default_implicit_parts_order + + # Specify the BCC addresses for the message + adv_attr_accessor :bcc + + # Define the body of the message. This is either a Hash (in which case it + # specifies the variables to pass to the template when it is rendered), + # or a string, in which case it specifies the actual text of the message. + adv_attr_accessor :body + + # Specify the CC addresses for the message. + adv_attr_accessor :cc + + # Specify the charset to use for the message. This defaults to the + # +default_charset+ specified for ActionMailer::Base. + adv_attr_accessor :charset + + # Specify the content type for the message. This defaults to <tt>text/plain</tt> + # in most cases, but can be automatically set in some situations. + adv_attr_accessor :content_type + + # Specify the from address for the message. + adv_attr_accessor :from + + # Specify additional headers to be added to the message. + adv_attr_accessor :headers + + # Specify the order in which parts should be sorted, based on content-type. + # This defaults to the value for the +default_implicit_parts_order+. + adv_attr_accessor :implicit_parts_order + + # Override the mailer name, which defaults to an inflected version of the + # mailer's class name. If you want to use a template in a non-standard + # location, you can use this to specify that location. + adv_attr_accessor :mailer_name + + # Defaults to "1.0", but may be explicitly given if needed. + adv_attr_accessor :mime_version + + # The recipient addresses for the message, either as a string (for a single + # address) or an array (for multiple addresses). + adv_attr_accessor :recipients + + # The date on which the message was sent. If not set (the default), the + # header will be set by the delivery agent. + adv_attr_accessor :sent_on + + # Specify the subject of the message. + adv_attr_accessor :subject + + # Specify the template name to use for current message. This is the "base" + # template name, without the extension or directory, and may be used to + # have multiple mailer methods share the same template. + adv_attr_accessor :template + + # The mail object instance referenced by this mailer. + attr_reader :mail + + class << self + def method_missing(method_symbol, *parameters)#:nodoc: + case method_symbol.id2name + when /^create_([_a-z]\w*)/ then new($1, *parameters).mail + when /^deliver_([_a-z]\w*)/ then new($1, *parameters).deliver! + when "new" then nil + else super + end + end + + # Receives a raw email, parses it into an email object, decodes it, + # instantiates a new mailer, and passes the email object to the mailer + # object's #receive method. If you want your mailer to be able to + # process incoming messages, you'll need to implement a #receive + # method that accepts the email object as a parameter: + # + # class MyMailer < ActionMailer::Base + # def receive(mail) + # ... + # end + # end + def receive(raw_email) + logger.info "Received mail:\n #{raw_email}" unless logger.nil? + mail = TMail::Mail.parse(raw_email) + mail.base64_decode + new.receive(mail) + end + + # Deliver the given mail object directly. This can be used to deliver + # a preconstructed mail object, like: + # + # email = MyMailer.create_some_mail(parameters) + # email.set_some_obscure_header "frobnicate" + # MyMailer.deliver(email) + def deliver(mail) + new.deliver!(mail) + end + end + + # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer + # will be initialized according to the named method. If not, the mailer will + # remain uninitialized (useful when you only need to invoke the "receive" + # method, for instance). + def initialize(method_name=nil, *parameters) #:nodoc: + create!(method_name, *parameters) if method_name + end + + # Initialize the mailer via the given +method_name+. The body will be + # rendered and a new TMail::Mail object created. + def create!(method_name, *parameters) #:nodoc: + initialize_defaults(method_name) + send(method_name, *parameters) + + # If an explicit, textual body has not been set, we check assumptions. + unless String === @body + # First, we look to see if there are any likely templates that match, + # which include the content-type in their file name (i.e., + # "the_template_file.text.html.rhtml", etc.). Only do this if parts + # have not already been specified manually. + if @parts.empty? + templates = Dir.glob("#{template_path}/#{@template}.*") + templates.each do |path| + # TODO: don't hardcode rhtml|rxml + basename = File.basename(path) + next unless md = /^([^\.]+)\.([^\.]+\.[^\+]+)\.(rhtml|rxml)$/.match(basename) + template_name = basename + content_type = md.captures[1].gsub('.', '/') + @parts << Part.new(:content_type => content_type, + :disposition => "inline", :charset => charset, + :body => render_message(template_name, @body)) + end + unless @parts.empty? + @content_type = "multipart/alternative" + @parts = sort_parts(@parts, @implicit_parts_order) + end + end + + # Then, if there were such templates, we check to see if we ought to + # also render a "normal" template (without the content type). If a + # normal template exists (or if there were no implicit parts) we render + # it. + template_exists = @parts.empty? + template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| File.basename(i).split(".").length == 2 } + @body = render_message(@template, @body) if template_exists + + # Finally, if there are other message parts and a textual body exists, + # we shift it onto the front of the parts and set the body to nil (so + # that create_mail doesn't try to render it in addition to the parts). + if !@parts.empty? && String === @body + @parts.unshift Part.new(:charset => charset, :body => @body) + @body = nil + end + end + + # If this is a multipart e-mail add the mime_version if it is not + # already set. + @mime_version ||= "1.0" if !@parts.empty? + + # build the mail object itself + @mail = create_mail + end + + # Delivers a TMail::Mail object. By default, it delivers the cached mail + # object (from the #create! method). If no cached mail object exists, and + # no alternate has been given as the parameter, this will fail. + def deliver!(mail = @mail) + raise "no mail object available for delivery!" unless mail + logger.info "Sent mail:\n #{mail.encoded}" unless logger.nil? + + begin + send("perform_delivery_#{delivery_method}", mail) if perform_deliveries + rescue Object => e + raise e if raise_delivery_errors + end + + return mail + end + + private + # Set up the default values for the various instance variables of this + # mailer. Subclasses may override this method to provide different + # defaults. + def initialize_defaults(method_name) + @charset ||= @@default_charset.dup + @content_type ||= @@default_content_type.dup + @implicit_parts_order ||= @@default_implicit_parts_order.dup + @template ||= method_name + @mailer_name ||= Inflector.underscore(self.class.name) + @parts ||= [] + @headers ||= {} + @body ||= {} + @mime_version = @@default_mime_version.dup if @@default_mime_version + end + + def render_message(method_name, body) + render :file => method_name, :body => body + end + + def render(opts) + body = opts.delete(:body) + initialize_template_class(body).render(opts) + end + + def template_path + "#{template_root}/#{mailer_name}" + end + + def initialize_template_class(assigns) + ActionView::Base.new(template_path, assigns, self) + end + + def sort_parts(parts, order = []) + order = order.collect { |s| s.downcase } + + parts = parts.sort do |a, b| + a_ct = a.content_type.downcase + b_ct = b.content_type.downcase + + a_in = order.include? a_ct + b_in = order.include? b_ct + + s = case + when a_in && b_in + order.index(a_ct) <=> order.index(b_ct) + when a_in + -1 + when b_in + 1 + else + a_ct <=> b_ct + end + + # reverse the ordering because parts that come last are displayed + # first in mail clients + (s * -1) + end + + parts + end + + def create_mail + m = TMail::Mail.new + + m.subject, = quote_any_if_necessary(charset, subject) + m.to, m.from = quote_any_address_if_necessary(charset, recipients, from) + m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil? + m.cc = quote_address_if_necessary(cc, charset) unless cc.nil? + + m.mime_version = mime_version unless mime_version.nil? + m.date = sent_on.to_time rescue sent_on if sent_on + headers.each { |k, v| m[k] = v } + + real_content_type, ctype_attrs = parse_content_type + + if @parts.empty? + m.set_content_type(real_content_type, nil, ctype_attrs) + m.body = Utils.normalize_new_lines(body) + else + if String === body + part = TMail::Mail.new + part.body = Utils.normalize_new_lines(body) + part.set_content_type(real_content_type, nil, ctype_attrs) + part.set_content_disposition "inline" + m.parts << part + end + + @parts.each do |p| + part = (TMail::Mail === p ? p : p.to_mail(self)) + m.parts << part + end + + if real_content_type =~ /multipart/ + ctype_attrs.delete "charset" + m.set_content_type(real_content_type, nil, ctype_attrs) + end + end + + @mail = m + end + + def perform_delivery_smtp(mail) + destinations = mail.destinations + mail.ready_to_send + + Net::SMTP.start(server_settings[:address], server_settings[:port], server_settings[:domain], + server_settings[:user_name], server_settings[:password], server_settings[:authentication]) do |smtp| + smtp.sendmail(mail.encoded, mail.from, destinations) + end + end + + def perform_delivery_sendmail(mail) + IO.popen("/usr/sbin/sendmail -i -t","w+") do |sm| + sm.print(mail.encoded.gsub(/\r/, '')) + sm.flush + end + end + + def perform_delivery_test(mail) + deliveries << mail + end + end +end +module ActionMailer + module Helpers #:nodoc: + def self.append_features(base) #:nodoc: + super + + # Initialize the base module to aggregate its helpers. + base.class_inheritable_accessor :master_helper_module + base.master_helper_module = Module.new + + # Extend base with class methods to declare helpers. + base.extend(ClassMethods) + + base.class_eval do + # Wrap inherited to create a new master helper module for subclasses. + class << self + alias_method :inherited_without_helper, :inherited + alias_method :inherited, :inherited_with_helper + end + + # Wrap initialize_template_class to extend new template class + # instances with the master helper module. + alias_method :initialize_template_class_without_helper, :initialize_template_class + alias_method :initialize_template_class, :initialize_template_class_with_helper + end + end + + module ClassMethods + # Makes all the (instance) methods in the helper module available to templates rendered through this controller. + # See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules + # available to the templates. + def add_template_helper(helper_module) #:nodoc: + master_helper_module.module_eval "include #{helper_module}" + end + + # Declare a helper: + # helper :foo + # requires 'foo_helper' and includes FooHelper in the template class. + # helper FooHelper + # includes FooHelper in the template class. + # helper { def foo() "#{bar} is the very best" end } + # evaluates the block in the template class, adding method #foo. + # helper(:three, BlindHelper) { def mice() 'mice' end } + # does all three. + def helper(*args, &block) + args.flatten.each do |arg| + case arg + when Module + add_template_helper(arg) + when String, Symbol + file_name = arg.to_s.underscore + '_helper' + class_name = file_name.camelize + + begin + require_dependency(file_name) + rescue LoadError => load_error + requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1] + msg = (requiree == file_name) ? "Missing helper file helpers/#{file_name}.rb" : "Can't load file: #{requiree}" + raise LoadError.new(msg).copy_blame!(load_error) + end + + add_template_helper(class_name.constantize) + else + raise ArgumentError, 'helper expects String, Symbol, or Module argument' + end + end + + # Evaluate block in template class if given. + master_helper_module.module_eval(&block) if block_given? + end + + # Declare a controller method as a helper. For example, + # helper_method :link_to + # def link_to(name, options) ... end + # makes the link_to controller method available in the view. + def helper_method(*methods) + methods.flatten.each do |method| + master_helper_module.module_eval <<-end_eval + def #{method}(*args, &block) + controller.send(%(#{method}), *args, &block) + end + end_eval + end + end + + # Declare a controller attribute as a helper. For example, + # helper_attr :name + # attr_accessor :name + # makes the name and name= controller methods available in the view. + # The is a convenience wrapper for helper_method. + def helper_attr(*attrs) + attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") } + end + + private + def inherited_with_helper(child) + inherited_without_helper(child) + begin + child.master_helper_module = Module.new + child.master_helper_module.send :include, master_helper_module + child.helper child.name.underscore + rescue MissingSourceFile => e + raise unless e.is_missing?("helpers/#{child.name.underscore}_helper") + end + end + end + + private + # Extend the template class instance with our controller's helper module. + def initialize_template_class_with_helper(assigns) + returning(template = initialize_template_class_without_helper(assigns)) do + template.extend self.class.master_helper_module + end + end + end +endrequire 'text/format' + +module MailHelper + # Uses Text::Format to take the text and format it, indented two spaces for + # each line, and wrapped at 72 columns. + def block_format(text) + formatted = text.split(/\n\r\n/).collect { |paragraph| + Text::Format.new( + :columns => 72, :first_indent => 2, :body_indent => 2, :text => paragraph + ).format + }.join("\n") + + # Make list points stand on their own line + formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { |s| " #{$1} #{$2.strip}\n" } + formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { |s| " #{$1} #{$2.strip}\n" } + + formatted + end +end +require 'action_mailer/adv_attr_accessor' +require 'action_mailer/part_container' +require 'action_mailer/utils' + +module ActionMailer + # Represents a subpart of an email message. It shares many similar + # attributes of ActionMailer::Base. Although you can create parts manually + # and add them to the #parts list of the mailer, it is easier + # to use the helper methods in ActionMailer::PartContainer. + class Part + include ActionMailer::AdvAttrAccessor + include ActionMailer::PartContainer + + # Represents the body of the part, as a string. This should not be a + # Hash (like ActionMailer::Base), but if you want a template to be rendered + # into the body of a subpart you can do it with the mailer's #render method + # and assign the result here. + adv_attr_accessor :body + + # Specify the charset for this subpart. By default, it will be the charset + # of the containing part or mailer. + adv_attr_accessor :charset + + # The content disposition of this part, typically either "inline" or + # "attachment". + adv_attr_accessor :content_disposition + + # The content type of the part. + adv_attr_accessor :content_type + + # The filename to use for this subpart (usually for attachments). + adv_attr_accessor :filename + + # Accessor for specifying additional headers to include with this part. + adv_attr_accessor :headers + + # The transfer encoding to use for this subpart, like "base64" or + # "quoted-printable". + adv_attr_accessor :transfer_encoding + + # Create a new part from the given +params+ hash. The valid params keys + # correspond to the accessors. + def initialize(params) + @content_type = params[:content_type] + @content_disposition = params[:disposition] || "inline" + @charset = params[:charset] + @body = params[:body] + @filename = params[:filename] + @transfer_encoding = params[:transfer_encoding] || "quoted-printable" + @headers = params[:headers] || {} + @parts = [] + end + + # Convert the part to a mail object which can be included in the parts + # list of another mail object. + def to_mail(defaults) + part = TMail::Mail.new + + real_content_type, ctype_attrs = parse_content_type(defaults) + + if @parts.empty? + part.content_transfer_encoding = transfer_encoding || "quoted-printable" + case (transfer_encoding || "").downcase + when "base64" then + part.body = TMail::Base64.folding_encode(body) + when "quoted-printable" + part.body = [Utils.normalize_new_lines(body)].pack("M*") + else + part.body = body + end + + # Always set the content_type after setting the body and or parts! + # Also don't set filename and name when there is none (like in + # non-attachment parts) + if content_disposition == "attachment" + ctype_attrs.delete "charset" + part.set_content_type(real_content_type, nil, + squish("name" => filename).merge(ctype_attrs)) + part.set_content_disposition(content_disposition, + squish("filename" => filename).merge(ctype_attrs)) + else + part.set_content_type(real_content_type, nil, ctype_attrs) + part.set_content_disposition(content_disposition) + end + else + if String === body + part = TMail::Mail.new + part.body = body + part.set_content_type(real_content_type, nil, ctype_attrs) + part.set_content_disposition "inline" + m.parts << part + end + + @parts.each do |p| + prt = (TMail::Mail === p ? p : p.to_mail(defaults)) + part.parts << prt + end + + part.set_content_type(real_content_type, nil, ctype_attrs) if real_content_type =~ /multipart/ + end + + headers.each { |k,v| part[k] = v } + + part + end + + private + + def squish(values={}) + values.delete_if { |k,v| v.nil? } + end + end +end +module ActionMailer + # Accessors and helpers that ActionMailer::Base and ActionMailer::Part have + # in common. Using these helpers you can easily add subparts or attachments + # to your message: + # + # def my_mail_message(...) + # ... + # part "text/plain" do |p| + # p.body "hello, world" + # p.transfer_encoding "base64" + # end + # + # attachment "image/jpg" do |a| + # a.body = File.read("hello.jpg") + # a.filename = "hello.jpg" + # end + # end + module PartContainer + # The list of subparts of this container + attr_reader :parts + + # Add a part to a multipart message, with the given content-type. The + # part itself is yielded to the block so that other properties (charset, + # body, headers, etc.) can be set on it. + def part(params) + params = {:content_type => params} if String === params + part = Part.new(params) + yield part if block_given? + @parts << part + end + + # Add an attachment to a multipart message. This is simply a part with the + # content-disposition set to "attachment". + def attachment(params, &block) + params = { :content_type => params } if String === params + params = { :disposition => "attachment", + :transfer_encoding => "base64" }.merge(params) + part(params, &block) + end + + private + + def parse_content_type(defaults=nil) + return [defaults && defaults.content_type, {}] if content_type.blank? + ctype, *attrs = content_type.split(/;\s*/) + attrs = attrs.inject({}) { |h,s| k,v = s.split(/=/, 2); h[k] = v; h } + [ctype, {"charset" => charset || defaults && defaults.charset}.merge(attrs)] + end + + end +end +module ActionMailer + module Quoting #:nodoc: + # Convert the given text into quoted printable format, with an instruction + # that the text be eventually interpreted in the given charset. + def quoted_printable(text, charset) + text = text.gsub( /[^a-z ]/i ) { quoted_printable_encode($&) }. + gsub( / /, "_" ) + "=?#{charset}?Q?#{text}?=" + end + + # Convert the given character to quoted printable format, taking into + # account multi-byte characters (if executing with $KCODE="u", for instance) + def quoted_printable_encode(character) + result = "" + character.each_byte { |b| result << "=%02x" % b } + result + end + + # A quick-and-dirty regexp for determining whether a string contains any + # characters that need escaping. + if !defined?(CHARS_NEEDING_QUOTING) + CHARS_NEEDING_QUOTING = /[\000-\011\013\014\016-\037\177-\377]/ + end + + # Quote the given text if it contains any "illegal" characters + def quote_if_necessary(text, charset) + (text =~ CHARS_NEEDING_QUOTING) ? + quoted_printable(text, charset) : + text + end + + # Quote any of the given strings if they contain any "illegal" characters + def quote_any_if_necessary(charset, *args) + args.map { |v| quote_if_necessary(v, charset) } + end + + # Quote the given address if it needs to be. The address may be a + # regular email address, or it can be a phrase followed by an address in + # brackets. The phrase is the only part that will be quoted, and only if + # it needs to be. This allows extended characters to be used in the + # "to", "from", "cc", and "bcc" headers. + def quote_address_if_necessary(address, charset) + if Array === address + address.map { |a| quote_address_if_necessary(a, charset) } + elsif address =~ /^(\S.*)\s+(<.*>)$/ + address = $2 + phrase = quote_if_necessary($1.gsub(/^['"](.*)['"]$/, '\1'), charset) + "\"#{phrase}\" #{address}" + else + address + end + end + + # Quote any of the given addresses, if they need to be. + def quote_any_address_if_necessary(charset, *args) + args.map { |v| quote_address_if_necessary(v, charset) } + end + end +end +module ActionMailer + module Utils #:nodoc: + def normalize_new_lines(text) + text.to_s.gsub(/\r\n?/, "\n") + end + module_function :normalize_new_lines + end +end +#-- +# Text::Format for Ruby +# Version 0.63 +# +# Copyright (c) 2002 - 2003 Austin Ziegler +# +# $Id: format.rb,v 1.1.1.1 2004/10/14 11:59:57 webster132 Exp $ +# +# ========================================================================== +# Revision History :: +# YYYY.MM.DD Change ID Developer +# Description +# -------------------------------------------------------------------------- +# 2002.10.18 Austin Ziegler +# Fixed a minor problem with tabs not being counted. Changed +# abbreviations from Hash to Array to better suit Ruby's +# capabilities. Fixed problems with the way that Array arguments +# are handled in calls to the major object types, excepting in +# Text::Format#expand and Text::Format#unexpand (these will +# probably need to be fixed). +# 2002.10.30 Austin Ziegler +# Fixed the ordering of the <=> for binary tests. Fixed +# Text::Format#expand and Text::Format#unexpand to handle array +# arguments better. +# 2003.01.24 Austin Ziegler +# Fixed a problem with Text::Format::RIGHT_FILL handling where a +# single word is larger than #columns. Removed Comparable +# capabilities (<=> doesn't make sense; == does). Added Symbol +# equivalents for the Hash initialization. Hash initialization has +# been modified so that values are set as follows (Symbols are +# highest priority; strings are middle; defaults are lowest): +# @columns = arg[:columns] || arg['columns'] || @columns +# Added #hard_margins, #split_rules, #hyphenator, and #split_words. +# 2003.02.07 Austin Ziegler +# Fixed the installer for proper case-sensitive handling. +# 2003.03.28 Austin Ziegler +# Added the ability for a hyphenator to receive the formatter +# object. Fixed a bug for strings matching /\A\s*\Z/ failing +# entirely. Fixed a test case failing under 1.6.8. +# 2003.04.04 Austin Ziegler +# Handle the case of hyphenators returning nil for first/rest. +# 2003.09.17 Austin Ziegler +# Fixed a problem where #paragraphs(" ") was raising +# NoMethodError. +# +# ========================================================================== +#++ + +module Text #:nodoc: + # Text::Format for Ruby is copyright 2002 - 2005 by Austin Ziegler. It + # is available under Ruby's licence, the Perl Artistic licence, or the + # GNU GPL version 2 (or at your option, any later version). As a + # special exception, for use with official Rails (provided by the + # rubyonrails.org development team) and any project created with + # official Rails, the following alternative MIT-style licence may be + # used: + # + # == Text::Format Licence for Rails and Rails Applications + # Permission is hereby granted, free of charge, to any person + # obtaining a copy of this software and associated documentation files + # (the "Software"), to deal in the Software without restriction, + # including without limitation the rights to use, copy, modify, merge, + # publish, distribute, sublicense, and/or sell copies of the Software, + # and to permit persons to whom the Software is furnished to do so, + # subject to the following conditions: + # + # * The names of its contributors may not be used to endorse or + # promote products derived from this software without specific prior + # written permission. + # + # The above copyright notice and this permission notice shall be + # included in all copies or substantial portions of the Software. + # + # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + # SOFTWARE. + class Format + VERSION = '0.63' + + # Local abbreviations. More can be added with Text::Format.abbreviations + ABBREV = [ 'Mr', 'Mrs', 'Ms', 'Jr', 'Sr' ] + + # Formatting values + LEFT_ALIGN = 0 + RIGHT_ALIGN = 1 + RIGHT_FILL = 2 + JUSTIFY = 3 + + # Word split modes (only applies when #hard_margins is true). + SPLIT_FIXED = 1 + SPLIT_CONTINUATION = 2 + SPLIT_HYPHENATION = 4 + SPLIT_CONTINUATION_FIXED = SPLIT_CONTINUATION | SPLIT_FIXED + SPLIT_HYPHENATION_FIXED = SPLIT_HYPHENATION | SPLIT_FIXED + SPLIT_HYPHENATION_CONTINUATION = SPLIT_HYPHENATION | SPLIT_CONTINUATION + SPLIT_ALL = SPLIT_HYPHENATION | SPLIT_CONTINUATION | SPLIT_FIXED + + # Words forcibly split by Text::Format will be stored as split words. + # This class represents a word forcibly split. + class SplitWord + # The word that was split. + attr_reader :word + # The first part of the word that was split. + attr_reader :first + # The remainder of the word that was split. + attr_reader :rest + + def initialize(word, first, rest) #:nodoc: + @word = word + @first = first + @rest = rest + end + end + + private + LEQ_RE = /[.?!]['"]?$/ + + def brk_re(i) #:nodoc: + %r/((?:\S+\s+){#{i}})(.+)/ + end + + def posint(p) #:nodoc: + p.to_i.abs + end + + public + # Compares two Text::Format objects. All settings of the objects are + # compared *except* #hyphenator. Generated results (e.g., #split_words) + # are not compared, either. + def ==(o) + (@text == o.text) && + (@columns == o.columns) && + (@left_margin == o.left_margin) && + (@right_margin == o.right_margin) && + (@hard_margins == o.hard_margins) && + (@split_rules == o.split_rules) && + (@first_indent == o.first_indent) && + (@body_indent == o.body_indent) && + (@tag_text == o.tag_text) && + (@tabstop == o.tabstop) && + (@format_style == o.format_style) && + (@extra_space == o.extra_space) && + (@tag_paragraph == o.tag_paragraph) && + (@nobreak == o.nobreak) && + (@abbreviations == o.abbreviations) && + (@nobreak_regex == o.nobreak_regex) + end + + # The text to be manipulated. Note that value is optional, but if the + # formatting functions are called without values, this text is what will + # be formatted. + # + # *Default*:: <tt>[]</tt> + # <b>Used in</b>:: All methods + attr_accessor :text + + # The total width of the format area. The margins, indentation, and text + # are formatted into this space. + # + # COLUMNS + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin indent text is formatted into here right margin + # + # *Default*:: <tt>72</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>, + # <tt>#center</tt> + attr_reader :columns + + # The total width of the format area. The margins, indentation, and text + # are formatted into this space. The value provided is silently + # converted to a positive integer. + # + # COLUMNS + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin indent text is formatted into here right margin + # + # *Default*:: <tt>72</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>, + # <tt>#center</tt> + def columns=(c) + @columns = posint(c) + end + + # The number of spaces used for the left margin. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # LEFT MARGIN indent text is formatted into here right margin + # + # *Default*:: <tt>0</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>, + # <tt>#center</tt> + attr_reader :left_margin + + # The number of spaces used for the left margin. The value provided is + # silently converted to a positive integer value. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # LEFT MARGIN indent text is formatted into here right margin + # + # *Default*:: <tt>0</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>, + # <tt>#center</tt> + def left_margin=(left) + @left_margin = posint(left) + end + + # The number of spaces used for the right margin. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin indent text is formatted into here RIGHT MARGIN + # + # *Default*:: <tt>0</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>, + # <tt>#center</tt> + attr_reader :right_margin + + # The number of spaces used for the right margin. The value provided is + # silently converted to a positive integer value. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin indent text is formatted into here RIGHT MARGIN + # + # *Default*:: <tt>0</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt>, + # <tt>#center</tt> + def right_margin=(r) + @right_margin = posint(r) + end + + # The number of spaces to indent the first line of a paragraph. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin INDENT text is formatted into here right margin + # + # *Default*:: <tt>4</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_reader :first_indent + + # The number of spaces to indent the first line of a paragraph. The + # value provided is silently converted to a positive integer value. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin INDENT text is formatted into here right margin + # + # *Default*:: <tt>4</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def first_indent=(f) + @first_indent = posint(f) + end + + # The number of spaces to indent all lines after the first line of a + # paragraph. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin INDENT text is formatted into here right margin + # + # *Default*:: <tt>0</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_reader :body_indent + + # The number of spaces to indent all lines after the first line of + # a paragraph. The value provided is silently converted to a + # positive integer value. + # + # columns + # <--------------------------------------------------------------> + # <-----------><------><---------------------------><------------> + # left margin INDENT text is formatted into here right margin + # + # *Default*:: <tt>0</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def body_indent=(b) + @body_indent = posint(b) + end + + # Normally, words larger than the format area will be placed on a line + # by themselves. Setting this to +true+ will force words larger than the + # format area to be split into one or more "words" each at most the size + # of the format area. The first line and the original word will be + # placed into <tt>#split_words</tt>. Note that this will cause the + # output to look *similar* to a #format_style of JUSTIFY. (Lines will be + # filled as much as possible.) + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :hard_margins + + # An array of words split during formatting if #hard_margins is set to + # +true+. + # #split_words << Text::Format::SplitWord.new(word, first, rest) + attr_reader :split_words + + # The object responsible for hyphenating. It must respond to + # #hyphenate_to(word, size) or #hyphenate_to(word, size, formatter) and + # return an array of the word split into two parts; if there is a + # hyphenation mark to be applied, responsibility belongs to the + # hyphenator object. The size is the MAXIMUM size permitted, including + # any hyphenation marks. If the #hyphenate_to method has an arity of 3, + # the formatter will be provided to the method. This allows the + # hyphenator to make decisions about the hyphenation based on the + # formatting rules. + # + # *Default*:: +nil+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_reader :hyphenator + + # The object responsible for hyphenating. It must respond to + # #hyphenate_to(word, size) and return an array of the word hyphenated + # into two parts. The size is the MAXIMUM size permitted, including any + # hyphenation marks. + # + # *Default*:: +nil+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def hyphenator=(h) + raise ArgumentError, "#{h.inspect} is not a valid hyphenator." unless h.respond_to?(:hyphenate_to) + arity = h.method(:hyphenate_to).arity + raise ArgumentError, "#{h.inspect} must have exactly two or three arguments." unless [2, 3].include?(arity) + @hyphenator = h + @hyphenator_arity = arity + end + + # Specifies the split mode; used only when #hard_margins is set to + # +true+. Allowable values are: + # [+SPLIT_FIXED+] The word will be split at the number of + # characters needed, with no marking at all. + # repre + # senta + # ion + # [+SPLIT_CONTINUATION+] The word will be split at the number of + # characters needed, with a C-style continuation + # character. If a word is the only item on a + # line and it cannot be split into an + # appropriate size, SPLIT_FIXED will be used. + # repr\ + # esen\ + # tati\ + # on + # [+SPLIT_HYPHENATION+] The word will be split according to the + # hyphenator specified in #hyphenator. If there + # is no #hyphenator specified, works like + # SPLIT_CONTINUATION. The example is using + # TeX::Hyphen. If a word is the only item on a + # line and it cannot be split into an + # appropriate size, SPLIT_CONTINUATION mode will + # be used. + # rep- + # re- + # sen- + # ta- + # tion + # + # *Default*:: <tt>Text::Format::SPLIT_FIXED</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_reader :split_rules + + # Specifies the split mode; used only when #hard_margins is set to + # +true+. Allowable values are: + # [+SPLIT_FIXED+] The word will be split at the number of + # characters needed, with no marking at all. + # repre + # senta + # ion + # [+SPLIT_CONTINUATION+] The word will be split at the number of + # characters needed, with a C-style continuation + # character. + # repr\ + # esen\ + # tati\ + # on + # [+SPLIT_HYPHENATION+] The word will be split according to the + # hyphenator specified in #hyphenator. If there + # is no #hyphenator specified, works like + # SPLIT_CONTINUATION. The example is using + # TeX::Hyphen as the #hyphenator. + # rep- + # re- + # sen- + # ta- + # tion + # + # These values can be bitwise ORed together (e.g., <tt>SPLIT_FIXED | + # SPLIT_CONTINUATION</tt>) to provide fallback split methods. In the + # example given, an attempt will be made to split the word using the + # rules of SPLIT_CONTINUATION; if there is not enough room, the word + # will be split with the rules of SPLIT_FIXED. These combinations are + # also available as the following values: + # * +SPLIT_CONTINUATION_FIXED+ + # * +SPLIT_HYPHENATION_FIXED+ + # * +SPLIT_HYPHENATION_CONTINUATION+ + # * +SPLIT_ALL+ + # + # *Default*:: <tt>Text::Format::SPLIT_FIXED</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def split_rules=(s) + raise ArgumentError, "Invalid value provided for split_rules." if ((s < SPLIT_FIXED) || (s > SPLIT_ALL)) + @split_rules = s + end + + # Indicates whether sentence terminators should be followed by a single + # space (+false+), or two spaces (+true+). + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :extra_space + + # Defines the current abbreviations as an array. This is only used if + # extra_space is turned on. + # + # If one is abbreviating "President" as "Pres." (abbreviations = + # ["Pres"]), then the results of formatting will be as illustrated in + # the table below: + # + # extra_space | include? | !include? + # true | Pres. Lincoln | Pres. Lincoln + # false | Pres. Lincoln | Pres. Lincoln + # + # *Default*:: <tt>{}</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :abbreviations + + # Indicates whether the formatting of paragraphs should be done with + # tagged paragraphs. Useful only with <tt>#tag_text</tt>. + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :tag_paragraph + + # The array of text to be placed before each paragraph when + # <tt>#tag_paragraph</tt> is +true+. When <tt>#format()</tt> is called, + # only the first element of the array is used. When <tt>#paragraphs</tt> + # is called, then each entry in the array will be used once, with + # corresponding paragraphs. If the tag elements are exhausted before the + # text is exhausted, then the remaining paragraphs will not be tagged. + # Regardless of indentation settings, a blank line will be inserted + # between all paragraphs when <tt>#tag_paragraph</tt> is +true+. + # + # *Default*:: <tt>[]</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :tag_text + + # Indicates whether or not the non-breaking space feature should be + # used. + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :nobreak + + # A hash which holds the regular expressions on which spaces should not + # be broken. The hash is set up such that the key is the first word and + # the value is the second word. + # + # For example, if +nobreak_regex+ contains the following hash: + # + # { '^Mrs?\.$' => '\S+$', '^\S+$' => '^(?:S|J)r\.$'} + # + # Then "Mr. Jones", "Mrs. Jones", and "Jones Jr." would not be broken. + # If this simple matching algorithm indicates that there should not be a + # break at the current end of line, then a backtrack is done until there + # are two words on which line breaking is permitted. If two such words + # are not found, then the end of the line will be broken *regardless*. + # If there is a single word on the current line, then no backtrack is + # done and the word is stuck on the end. + # + # *Default*:: <tt>{}</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_accessor :nobreak_regex + + # Indicates the number of spaces that a single tab represents. + # + # *Default*:: <tt>8</tt> + # <b>Used in</b>:: <tt>#expand</tt>, <tt>#unexpand</tt>, + # <tt>#paragraphs</tt> + attr_reader :tabstop + + # Indicates the number of spaces that a single tab represents. + # + # *Default*:: <tt>8</tt> + # <b>Used in</b>:: <tt>#expand</tt>, <tt>#unexpand</tt>, + # <tt>#paragraphs</tt> + def tabstop=(t) + @tabstop = posint(t) + end + + # Specifies the format style. Allowable values are: + # [+LEFT_ALIGN+] Left justified, ragged right. + # |A paragraph that is| + # |left aligned.| + # [+RIGHT_ALIGN+] Right justified, ragged left. + # |A paragraph that is| + # | right aligned.| + # [+RIGHT_FILL+] Left justified, right ragged, filled to width by + # spaces. (Essentially the same as +LEFT_ALIGN+ except + # that lines are padded on the right.) + # |A paragraph that is| + # |left aligned. | + # [+JUSTIFY+] Fully justified, words filled to width by spaces, + # except the last line. + # |A paragraph that| + # |is justified.| + # + # *Default*:: <tt>Text::Format::LEFT_ALIGN</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + attr_reader :format_style + + # Specifies the format style. Allowable values are: + # [+LEFT_ALIGN+] Left justified, ragged right. + # |A paragraph that is| + # |left aligned.| + # [+RIGHT_ALIGN+] Right justified, ragged left. + # |A paragraph that is| + # | right aligned.| + # [+RIGHT_FILL+] Left justified, right ragged, filled to width by + # spaces. (Essentially the same as +LEFT_ALIGN+ except + # that lines are padded on the right.) + # |A paragraph that is| + # |left aligned. | + # [+JUSTIFY+] Fully justified, words filled to width by spaces. + # |A paragraph that| + # |is justified.| + # + # *Default*:: <tt>Text::Format::LEFT_ALIGN</tt> + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def format_style=(fs) + raise ArgumentError, "Invalid value provided for format_style." if ((fs < LEFT_ALIGN) || (fs > JUSTIFY)) + @format_style = fs + end + + # Indicates that the format style is left alignment. + # + # *Default*:: +true+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def left_align? + return @format_style == LEFT_ALIGN + end + + # Indicates that the format style is right alignment. + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def right_align? + return @format_style == RIGHT_ALIGN + end + + # Indicates that the format style is right fill. + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def right_fill? + return @format_style == RIGHT_FILL + end + + # Indicates that the format style is full justification. + # + # *Default*:: +false+ + # <b>Used in</b>:: <tt>#format</tt>, <tt>#paragraphs</tt> + def justify? + return @format_style == JUSTIFY + end + + # The default implementation of #hyphenate_to implements + # SPLIT_CONTINUATION. + def hyphenate_to(word, size) + [word[0 .. (size - 2)] + "\\", word[(size - 1) .. -1]] + end + + private + def __do_split_word(word, size) #:nodoc: + [word[0 .. (size - 1)], word[size .. -1]] + end + + def __format(to_wrap) #:nodoc: + words = to_wrap.split(/\s+/).compact + words.shift if words[0].nil? or words[0].empty? + to_wrap = [] + + abbrev = false + width = @columns - @first_indent - @left_margin - @right_margin + indent_str = ' ' * @first_indent + first_line = true + line = words.shift + abbrev = __is_abbrev(line) unless line.nil? || line.empty? + + while w = words.shift + if (w.size + line.size < (width - 1)) || + ((line !~ LEQ_RE || abbrev) && (w.size + line.size < width)) + line << " " if (line =~ LEQ_RE) && (not abbrev) + line << " #{w}" + else + line, w = __do_break(line, w) if @nobreak + line, w = __do_hyphenate(line, w, width) if @hard_margins + if w.index(/\s+/) + w, *w2 = w.split(/\s+/) + words.unshift(w2) + words.flatten! + end + to_wrap << __make_line(line, indent_str, width, w.nil?) unless line.nil? + if first_line + first_line = false + width = @columns - @body_indent - @left_margin - @right_margin + indent_str = ' ' * @body_indent + end + line = w + end + + abbrev = __is_abbrev(w) unless w.nil? + end + + loop do + break if line.nil? or line.empty? + line, w = __do_hyphenate(line, w, width) if @hard_margins + to_wrap << __make_line(line, indent_str, width, w.nil?) + line = w + end + + if (@tag_paragraph && (to_wrap.size > 0)) then + clr = %r{`(\w+)'}.match([caller(1)].flatten[0])[1] + clr = "" if clr.nil? + + if ((not @tag_text[0].nil?) && (@tag_cur.size < 1) && + (clr != "__paragraphs")) then + @tag_cur = @tag_text[0] + end + + fchar = /(\S)/.match(to_wrap[0])[1] + white = to_wrap[0].index(fchar) + if ((white - @left_margin - 1) > @tag_cur.size) then + white = @tag_cur.size + @left_margin + to_wrap[0].gsub!(/^ {#{white}}/, "#{' ' * @left_margin}#{@tag_cur}") + else + to_wrap.unshift("#{' ' * @left_margin}#{@tag_cur}\n") + end + end + to_wrap.join('') + end + + # format lines in text into paragraphs with each element of @wrap a + # paragraph; uses Text::Format.format for the formatting + def __paragraphs(to_wrap) #:nodoc: + if ((@first_indent == @body_indent) || @tag_paragraph) then + p_end = "\n" + else + p_end = '' + end + + cnt = 0 + ret = [] + to_wrap.each do |tw| + @tag_cur = @tag_text[cnt] if @tag_paragraph + @tag_cur = '' if @tag_cur.nil? + line = __format(tw) + ret << "#{line}#{p_end}" if (not line.nil?) && (line.size > 0) + cnt += 1 + end + + ret[-1].chomp! unless ret.empty? + ret.join('') + end + + # center text using spaces on left side to pad it out empty lines + # are preserved + def __center(to_center) #:nodoc: + tabs = 0 + width = @columns - @left_margin - @right_margin + centered = [] + to_center.each do |tc| + s = tc.strip + tabs = s.count("\t") + tabs = 0 if tabs.nil? + ct = ((width - s.size - (tabs * @tabstop) + tabs) / 2) + ct = (width - @left_margin - @right_margin) - ct + centered << "#{s.rjust(ct)}\n" + end + centered.join('') + end + + # expand tabs to spaces should be similar to Text::Tabs::expand + def __expand(to_expand) #:nodoc: + expanded = [] + to_expand.split("\n").each { |te| expanded << te.gsub(/\t/, ' ' * @tabstop) } + expanded.join('') + end + + def __unexpand(to_unexpand) #:nodoc: + unexpanded = [] + to_unexpand.split("\n").each { |tu| unexpanded << tu.gsub(/ {#{@tabstop}}/, "\t") } + unexpanded.join('') + end + + def __is_abbrev(word) #:nodoc: + # remove period if there is one. + w = word.gsub(/\.$/, '') unless word.nil? + return true if (!@extra_space || ABBREV.include?(w) || @abbreviations.include?(w)) + false + end + + def __make_line(line, indent, width, last = false) #:nodoc: + lmargin = " " * @left_margin + fill = " " * (width - line.size) if right_fill? && (line.size <= width) + + if (justify? && ((not line.nil?) && (not line.empty?)) && line =~ /\S+\s+\S+/ && !last) + spaces = width - line.size + words = line.split(/(\s+)/) + ws = spaces / (words.size / 2) + spaces = spaces % (words.size / 2) if ws > 0 + words.reverse.each do |rw| + next if (rw =~ /^\S/) + rw.sub!(/^/, " " * ws) + next unless (spaces > 0) + rw.sub!(/^/, " ") + spaces -= 1 + end + line = words.join('') + end + line = "#{lmargin}#{indent}#{line}#{fill}\n" unless line.nil? + if right_align? && (not line.nil?) + line.sub(/^/, " " * (@columns - @right_margin - (line.size - 1))) + else + line + end + end + + def __do_hyphenate(line, next_line, width) #:nodoc: + rline = line.dup rescue line + rnext = next_line.dup rescue next_line + loop do + if rline.size == width + break + elsif rline.size > width + words = rline.strip.split(/\s+/) + word = words[-1].dup + size = width - rline.size + word.size + if (size <= 0) + words[-1] = nil + rline = words.join(' ').strip + rnext = "#{word} #{rnext}".strip + next + end + + first = rest = nil + + if ((@split_rules & SPLIT_HYPHENATION) != 0) + if @hyphenator_arity == 2 + first, rest = @hyphenator.hyphenate_to(word, size) + else + first, rest = @hyphenator.hyphenate_to(word, size, self) + end + end + + if ((@split_rules & SPLIT_CONTINUATION) != 0) and first.nil? + first, rest = self.hyphenate_to(word, size) + end + + if ((@split_rules & SPLIT_FIXED) != 0) and first.nil? + first.nil? or @split_rules == SPLIT_FIXED + first, rest = __do_split_word(word, size) + end + + if first.nil? + words[-1] = nil + rest = word + else + words[-1] = first + @split_words << SplitWord.new(word, first, rest) + end + rline = words.join(' ').strip + rnext = "#{rest} #{rnext}".strip + break + else + break if rnext.nil? or rnext.empty? or rline.nil? or rline.empty? + words = rnext.split(/\s+/) + word = words.shift + size = width - rline.size - 1 + + if (size <= 0) + rnext = "#{word} #{words.join(' ')}".strip + break + end + + first = rest = nil + + if ((@split_rules & SPLIT_HYPHENATION) != 0) + if @hyphenator_arity == 2 + first, rest = @hyphenator.hyphenate_to(word, size) + else + first, rest = @hyphenator.hyphenate_to(word, size, self) + end + end + + first, rest = self.hyphenate_to(word, size) if ((@split_rules & SPLIT_CONTINUATION) != 0) and first.nil? + + first, rest = __do_split_word(word, size) if ((@split_rules & SPLIT_FIXED) != 0) and first.nil? + + if (rline.size + (first ? first.size : 0)) < width + @split_words << SplitWord.new(word, first, rest) + rline = "#{rline} #{first}".strip + rnext = "#{rest} #{words.join(' ')}".strip + end + break + end + end + [rline, rnext] + end + + def __do_break(line, next_line) #:nodoc: + no_brk = false + words = [] + words = line.split(/\s+/) unless line.nil? + last_word = words[-1] + + @nobreak_regex.each { |k, v| no_brk = ((last_word =~ /#{k}/) and (next_line =~ /#{v}/)) } + + if no_brk && words.size > 1 + i = words.size + while i > 0 + no_brk = false + @nobreak_regex.each { |k, v| no_brk = ((words[i + 1] =~ /#{k}/) && (words[i] =~ /#{v}/)) } + i -= 1 + break if not no_brk + end + if i > 0 + l = brk_re(i).match(line) + line.sub!(brk_re(i), l[1]) + next_line = "#{l[2]} #{next_line}" + line.sub!(/\s+$/, '') + end + end + [line, next_line] + end + + def __create(arg = nil, &block) #:nodoc: + # Format::Text.new(text-to-wrap) + @text = arg unless arg.nil? + # Defaults + @columns = 72 + @tabstop = 8 + @first_indent = 4 + @body_indent = 0 + @format_style = LEFT_ALIGN + @left_margin = 0 + @right_margin = 0 + @extra_space = false + @text = Array.new if @text.nil? + @tag_paragraph = false + @tag_text = Array.new + @tag_cur = "" + @abbreviations = Array.new + @nobreak = false + @nobreak_regex = Hash.new + @split_words = Array.new + @hard_margins = false + @split_rules = SPLIT_FIXED + @hyphenator = self + @hyphenator_arity = self.method(:hyphenate_to).arity + + instance_eval(&block) unless block.nil? + end + + public + # Formats text into a nice paragraph format. The text is separated + # into words and then reassembled a word at a time using the settings + # of this Format object. If a word is larger than the number of + # columns available for formatting, then that word will appear on the + # line by itself. + # + # If +to_wrap+ is +nil+, then the value of <tt>#text</tt> will be + # worked on. + def format(to_wrap = nil) + to_wrap = @text if to_wrap.nil? + if to_wrap.class == Array + __format(to_wrap[0]) + else + __format(to_wrap) + end + end + + # Considers each element of text (provided or internal) as a paragraph. + # If <tt>#first_indent</tt> is the same as <tt>#body_indent</tt>, then + # paragraphs will be separated by a single empty line in the result; + # otherwise, the paragraphs will follow immediately after each other. + # Uses <tt>#format</tt> to do the heavy lifting. + def paragraphs(to_wrap = nil) + to_wrap = @text if to_wrap.nil? + __paragraphs([to_wrap].flatten) + end + + # Centers the text, preserving empty lines and tabs. + def center(to_center = nil) + to_center = @text if to_center.nil? + __center([to_center].flatten) + end + + # Replaces all tab characters in the text with <tt>#tabstop</tt> spaces. + def expand(to_expand = nil) + to_expand = @text if to_expand.nil? + if to_expand.class == Array + to_expand.collect { |te| __expand(te) } + else + __expand(to_expand) + end + end + + # Replaces all occurrences of <tt>#tabstop</tt> consecutive spaces + # with a tab character. + def unexpand(to_unexpand = nil) + to_unexpand = @text if to_unexpand.nil? + if to_unexpand.class == Array + to_unexpand.collect { |te| v << __unexpand(te) } + else + __unexpand(to_unexpand) + end + end + + # This constructor takes advantage of a technique for Ruby object + # construction introduced by Andy Hunt and Dave Thomas (see reference), + # where optional values are set using commands in a block. + # + # Text::Format.new { + # columns = 72 + # left_margin = 0 + # right_margin = 0 + # first_indent = 4 + # body_indent = 0 + # format_style = Text::Format::LEFT_ALIGN + # extra_space = false + # abbreviations = {} + # tag_paragraph = false + # tag_text = [] + # nobreak = false + # nobreak_regex = {} + # tabstop = 8 + # text = nil + # } + # + # As shown above, +arg+ is optional. If +arg+ is specified and is a + # +String+, then arg is used as the default value of <tt>#text</tt>. + # Alternately, an existing Text::Format object can be used or a Hash can + # be used. With all forms, a block can be specified. + # + # *Reference*:: "Object Construction and Blocks" + # <http://www.pragmaticprogrammer.com/ruby/articles/insteval.html> + # + def initialize(arg = nil, &block) + case arg + when Text::Format + __create(arg.text) do + @columns = arg.columns + @tabstop = arg.tabstop + @first_indent = arg.first_indent + @body_indent = arg.body_indent + @format_style = arg.format_style + @left_margin = arg.left_margin + @right_margin = arg.right_margin + @extra_space = arg.extra_space + @tag_paragraph = arg.tag_paragraph + @tag_text = arg.tag_text + @abbreviations = arg.abbreviations + @nobreak = arg.nobreak + @nobreak_regex = arg.nobreak_regex + @text = arg.text + @hard_margins = arg.hard_margins + @split_words = arg.split_words + @split_rules = arg.split_rules + @hyphenator = arg.hyphenator + end + instance_eval(&block) unless block.nil? + when Hash + __create do + @columns = arg[:columns] || arg['columns'] || @columns + @tabstop = arg[:tabstop] || arg['tabstop'] || @tabstop + @first_indent = arg[:first_indent] || arg['first_indent'] || @first_indent + @body_indent = arg[:body_indent] || arg['body_indent'] || @body_indent + @format_style = arg[:format_style] || arg['format_style'] || @format_style + @left_margin = arg[:left_margin] || arg['left_margin'] || @left_margin + @right_margin = arg[:right_margin] || arg['right_margin'] || @right_margin + @extra_space = arg[:extra_space] || arg['extra_space'] || @extra_space + @text = arg[:text] || arg['text'] || @text + @tag_paragraph = arg[:tag_paragraph] || arg['tag_paragraph'] || @tag_paragraph + @tag_text = arg[:tag_text] || arg['tag_text'] || @tag_text + @abbreviations = arg[:abbreviations] || arg['abbreviations'] || @abbreviations + @nobreak = arg[:nobreak] || arg['nobreak'] || @nobreak + @nobreak_regex = arg[:nobreak_regex] || arg['nobreak_regex'] || @nobreak_regex + @hard_margins = arg[:hard_margins] || arg['hard_margins'] || @hard_margins + @split_rules = arg[:split_rules] || arg['split_rules'] || @split_rules + @hyphenator = arg[:hyphenator] || arg['hyphenator'] || @hyphenator + end + instance_eval(&block) unless block.nil? + when String + __create(arg, &block) + when NilClass + __create(&block) + else + raise TypeError + end + end + end +end + +if __FILE__ == $0 + require 'test/unit' + + class TestText__Format < Test::Unit::TestCase #:nodoc: + attr_accessor :format_o + + GETTYSBURG = <<-'EOS' + Four score and seven years ago our fathers brought forth on this + continent a new nation, conceived in liberty and dedicated to the + proposition that all men are created equal. Now we are engaged in + a great civil war, testing whether that nation or any nation so + conceived and so dedicated can long endure. We are met on a great + battlefield of that war. We have come to dedicate a portion of + that field as a final resting-place for those who here gave their + lives that that nation might live. It is altogether fitting and + proper that we should do this. But in a larger sense, we cannot + dedicate, we cannot consecrate, we cannot hallow this ground. + The brave men, living and dead who struggled here have consecrated + it far above our poor power to add or detract. The world will + little note nor long remember what we say here, but it can never + forget what they did here. It is for us the living rather to be + dedicated here to the unfinished work which they who fought here + have thus far so nobly advanced. It is rather for us to be here + dedicated to the great task remaining before us--that from these + honored dead we take increased devotion to that cause for which + they gave the last full measure of devotion--that we here highly + resolve that these dead shall not have died in vain, that this + nation under God shall have a new birth of freedom, and that + government of the people, by the people, for the people shall + not perish from the earth. + + -- Pres. Abraham Lincoln, 19 November 1863 + EOS + + FIVE_COL = "Four \nscore\nand s\neven \nyears\nago o\nur fa\nthers\nbroug\nht fo\nrth o\nn thi\ns con\ntinen\nt a n\new na\ntion,\nconce\nived \nin li\nberty\nand d\nedica\nted t\no the\npropo\nsitio\nn tha\nt all\nmen a\nre cr\neated\nequal\n. Now\nwe ar\ne eng\naged \nin a \ngreat\ncivil\nwar, \ntesti\nng wh\nether\nthat \nnatio\nn or \nany n\nation\nso co\nnceiv\ned an\nd so \ndedic\nated \ncan l\nong e\nndure\n. We \nare m\net on\na gre\nat ba\nttlef\nield \nof th\nat wa\nr. We\nhave \ncome \nto de\ndicat\ne a p\nortio\nn of \nthat \nfield\nas a \nfinal\nresti\nng-pl\nace f\nor th\nose w\nho he\nre ga\nve th\neir l\nives \nthat \nthat \nnatio\nn mig\nht li\nve. I\nt is \naltog\nether\nfitti\nng an\nd pro\nper t\nhat w\ne sho\nuld d\no thi\ns. Bu\nt in \na lar\nger s\nense,\nwe ca\nnnot \ndedic\nate, \nwe ca\nnnot \nconse\ncrate\n, we \ncanno\nt hal\nlow t\nhis g\nround\n. The\nbrave\nmen, \nlivin\ng and\ndead \nwho s\ntrugg\nled h\nere h\nave c\nonsec\nrated\nit fa\nr abo\nve ou\nr poo\nr pow\ner to\nadd o\nr det\nract.\nThe w\norld \nwill \nlittl\ne not\ne nor\nlong \nremem\nber w\nhat w\ne say\nhere,\nbut i\nt can\nnever\nforge\nt wha\nt the\ny did\nhere.\nIt is\nfor u\ns the\nlivin\ng rat\nher t\no be \ndedic\nated \nhere \nto th\ne unf\ninish\ned wo\nrk wh\nich t\nhey w\nho fo\nught \nhere \nhave \nthus \nfar s\no nob\nly ad\nvance\nd. It\nis ra\nther \nfor u\ns to \nbe he\nre de\ndicat\ned to\nthe g\nreat \ntask \nremai\nning \nbefor\ne us-\n-that\nfrom \nthese\nhonor\ned de\nad we\ntake \nincre\nased \ndevot\nion t\no tha\nt cau\nse fo\nr whi\nch th\ney ga\nve th\ne las\nt ful\nl mea\nsure \nof de\nvotio\nn--th\nat we\nhere \nhighl\ny res\nolve \nthat \nthese\ndead \nshall\nnot h\nave d\nied i\nn vai\nn, th\nat th\nis na\ntion \nunder\nGod s\nhall \nhave \na new\nbirth\nof fr\needom\n, and\nthat \ngover\nnment\nof th\ne peo\nple, \nby th\ne peo\nple, \nfor t\nhe pe\nople \nshall\nnot p\nerish\nfrom \nthe e\narth.\n-- Pr\nes. A\nbraha\nm Lin\ncoln,\n19 No\nvembe\nr 186\n3 \n" + + FIVE_CNT = "Four \nscore\nand \nseven\nyears\nago \nour \nfath\\\ners \nbrou\\\nght \nforth\non t\\\nhis \ncont\\\ninent\na new\nnati\\\non, \nconc\\\neived\nin l\\\niber\\\nty a\\\nnd d\\\nedic\\\nated \nto t\\\nhe p\\\nropo\\\nsiti\\\non t\\\nhat \nall \nmen \nare \ncrea\\\nted \nequa\\\nl. N\\\now we\nare \nenga\\\nged \nin a \ngreat\ncivil\nwar, \ntest\\\ning \nwhet\\\nher \nthat \nnati\\\non or\nany \nnati\\\non so\nconc\\\neived\nand \nso d\\\nedic\\\nated \ncan \nlong \nendu\\\nre. \nWe a\\\nre m\\\net on\na gr\\\neat \nbatt\\\nlefi\\\neld \nof t\\\nhat \nwar. \nWe h\\\nave \ncome \nto d\\\nedic\\\nate a\nport\\\nion \nof t\\\nhat \nfield\nas a \nfinal\nrest\\\ning-\\\nplace\nfor \nthose\nwho \nhere \ngave \ntheir\nlives\nthat \nthat \nnati\\\non m\\\night \nlive.\nIt is\nalto\\\ngeth\\\ner f\\\nitti\\\nng a\\\nnd p\\\nroper\nthat \nwe s\\\nhould\ndo t\\\nhis. \nBut \nin a \nlarg\\\ner s\\\nense,\nwe c\\\nannot\ndedi\\\ncate,\nwe c\\\nannot\ncons\\\necra\\\nte, \nwe c\\\nannot\nhall\\\now t\\\nhis \ngrou\\\nnd. \nThe \nbrave\nmen, \nlivi\\\nng a\\\nnd d\\\nead \nwho \nstru\\\nggled\nhere \nhave \ncons\\\necra\\\nted \nit f\\\nar a\\\nbove \nour \npoor \npower\nto a\\\ndd or\ndetr\\\nact. \nThe \nworld\nwill \nlitt\\\nle n\\\note \nnor \nlong \nreme\\\nmber \nwhat \nwe s\\\nay h\\\nere, \nbut \nit c\\\nan n\\\never \nforg\\\net w\\\nhat \nthey \ndid \nhere.\nIt is\nfor \nus t\\\nhe l\\\niving\nrath\\\ner to\nbe d\\\nedic\\\nated \nhere \nto t\\\nhe u\\\nnfin\\\nished\nwork \nwhich\nthey \nwho \nfoug\\\nht h\\\nere \nhave \nthus \nfar \nso n\\\nobly \nadva\\\nnced.\nIt is\nrath\\\ner f\\\nor us\nto be\nhere \ndedi\\\ncated\nto t\\\nhe g\\\nreat \ntask \nrema\\\nining\nbefo\\\nre u\\\ns--t\\\nhat \nfrom \nthese\nhono\\\nred \ndead \nwe t\\\nake \nincr\\\neased\ndevo\\\ntion \nto t\\\nhat \ncause\nfor \nwhich\nthey \ngave \nthe \nlast \nfull \nmeas\\\nure \nof d\\\nevot\\\nion-\\\n-that\nwe h\\\nere \nhigh\\\nly r\\\nesol\\\nve t\\\nhat \nthese\ndead \nshall\nnot \nhave \ndied \nin v\\\nain, \nthat \nthis \nnati\\\non u\\\nnder \nGod \nshall\nhave \na new\nbirth\nof f\\\nreed\\\nom, \nand \nthat \ngove\\\nrnme\\\nnt of\nthe \npeop\\\nle, \nby t\\\nhe p\\\neopl\\\ne, f\\\nor t\\\nhe p\\\neople\nshall\nnot \nperi\\\nsh f\\\nrom \nthe \neart\\\nh. --\nPres.\nAbra\\\nham \nLinc\\\noln, \n19 N\\\novem\\\nber \n1863 \n" + + # Tests both abbreviations and abbreviations= + def test_abbreviations + abbr = [" Pres. Abraham Lincoln\n", " Pres. Abraham Lincoln\n"] + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal([], @format_o.abbreviations) + assert_nothing_raised { @format_o.abbreviations = [ 'foo', 'bar' ] } + assert_equal([ 'foo', 'bar' ], @format_o.abbreviations) + assert_equal(abbr[0], @format_o.format(abbr[0])) + assert_nothing_raised { @format_o.extra_space = true } + assert_equal(abbr[1], @format_o.format(abbr[0])) + assert_nothing_raised { @format_o.abbreviations = [ "Pres" ] } + assert_equal([ "Pres" ], @format_o.abbreviations) + assert_equal(abbr[0], @format_o.format(abbr[0])) + assert_nothing_raised { @format_o.extra_space = false } + assert_equal(abbr[0], @format_o.format(abbr[0])) + end + + # Tests both body_indent and body_indent= + def test_body_indent + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(0, @format_o.body_indent) + assert_nothing_raised { @format_o.body_indent = 7 } + assert_equal(7, @format_o.body_indent) + assert_nothing_raised { @format_o.body_indent = -3 } + assert_equal(3, @format_o.body_indent) + assert_nothing_raised { @format_o.body_indent = "9" } + assert_equal(9, @format_o.body_indent) + assert_nothing_raised { @format_o.body_indent = "-2" } + assert_equal(2, @format_o.body_indent) + assert_match(/^ [^ ]/, @format_o.format(GETTYSBURG).split("\n")[1]) + end + + # Tests both columns and columns= + def test_columns + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(72, @format_o.columns) + assert_nothing_raised { @format_o.columns = 7 } + assert_equal(7, @format_o.columns) + assert_nothing_raised { @format_o.columns = -3 } + assert_equal(3, @format_o.columns) + assert_nothing_raised { @format_o.columns = "9" } + assert_equal(9, @format_o.columns) + assert_nothing_raised { @format_o.columns = "-2" } + assert_equal(2, @format_o.columns) + assert_nothing_raised { @format_o.columns = 40 } + assert_equal(40, @format_o.columns) + assert_match(/this continent$/, + @format_o.format(GETTYSBURG).split("\n")[1]) + end + + # Tests both extra_space and extra_space= + def test_extra_space + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.extra_space) + assert_nothing_raised { @format_o.extra_space = true } + assert(@format_o.extra_space) + # The behaviour of extra_space is tested in test_abbreviations. There + # is no need to reproduce it here. + end + + # Tests both first_indent and first_indent= + def test_first_indent + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(4, @format_o.first_indent) + assert_nothing_raised { @format_o.first_indent = 7 } + assert_equal(7, @format_o.first_indent) + assert_nothing_raised { @format_o.first_indent = -3 } + assert_equal(3, @format_o.first_indent) + assert_nothing_raised { @format_o.first_indent = "9" } + assert_equal(9, @format_o.first_indent) + assert_nothing_raised { @format_o.first_indent = "-2" } + assert_equal(2, @format_o.first_indent) + assert_match(/^ [^ ]/, @format_o.format(GETTYSBURG).split("\n")[0]) + end + + def test_format_style + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(Text::Format::LEFT_ALIGN, @format_o.format_style) + assert_match(/^November 1863$/, + @format_o.format(GETTYSBURG).split("\n")[-1]) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_ALIGN + } + assert_equal(Text::Format::RIGHT_ALIGN, @format_o.format_style) + assert_match(/^ +November 1863$/, + @format_o.format(GETTYSBURG).split("\n")[-1]) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_FILL + } + assert_equal(Text::Format::RIGHT_FILL, @format_o.format_style) + assert_match(/^November 1863 +$/, + @format_o.format(GETTYSBURG).split("\n")[-1]) + assert_nothing_raised { @format_o.format_style = Text::Format::JUSTIFY } + assert_equal(Text::Format::JUSTIFY, @format_o.format_style) + assert_match(/^of freedom, and that government of the people, by the people, for the$/, + @format_o.format(GETTYSBURG).split("\n")[-3]) + assert_raises(ArgumentError) { @format_o.format_style = 33 } + end + + def test_tag_paragraph + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.tag_paragraph) + assert_nothing_raised { @format_o.tag_paragraph = true } + assert(@format_o.tag_paragraph) + assert_not_equal(@format_o.paragraphs([GETTYSBURG, GETTYSBURG]), + Text::Format.new.paragraphs([GETTYSBURG, GETTYSBURG])) + end + + def test_tag_text + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal([], @format_o.tag_text) + assert_equal(@format_o.format(GETTYSBURG), + Text::Format.new.format(GETTYSBURG)) + assert_nothing_raised { + @format_o.tag_paragraph = true + @format_o.tag_text = ["Gettysburg Address", "---"] + } + assert_not_equal(@format_o.format(GETTYSBURG), + Text::Format.new.format(GETTYSBURG)) + assert_not_equal(@format_o.paragraphs([GETTYSBURG, GETTYSBURG]), + Text::Format.new.paragraphs([GETTYSBURG, GETTYSBURG])) + assert_not_equal(@format_o.paragraphs([GETTYSBURG, GETTYSBURG, + GETTYSBURG]), + Text::Format.new.paragraphs([GETTYSBURG, GETTYSBURG, + GETTYSBURG])) + end + + def test_justify? + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.justify?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_ALIGN + } + assert(!@format_o.justify?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_FILL + } + assert(!@format_o.justify?) + assert_nothing_raised { + @format_o.format_style = Text::Format::JUSTIFY + } + assert(@format_o.justify?) + # The format testing is done in test_format_style + end + + def test_left_align? + assert_nothing_raised { @format_o = Text::Format.new } + assert(@format_o.left_align?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_ALIGN + } + assert(!@format_o.left_align?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_FILL + } + assert(!@format_o.left_align?) + assert_nothing_raised { @format_o.format_style = Text::Format::JUSTIFY } + assert(!@format_o.left_align?) + # The format testing is done in test_format_style + end + + def test_left_margin + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(0, @format_o.left_margin) + assert_nothing_raised { @format_o.left_margin = -3 } + assert_equal(3, @format_o.left_margin) + assert_nothing_raised { @format_o.left_margin = "9" } + assert_equal(9, @format_o.left_margin) + assert_nothing_raised { @format_o.left_margin = "-2" } + assert_equal(2, @format_o.left_margin) + assert_nothing_raised { @format_o.left_margin = 7 } + assert_equal(7, @format_o.left_margin) + assert_nothing_raised { + ft = @format_o.format(GETTYSBURG).split("\n") + assert_match(/^ {11}Four score/, ft[0]) + assert_match(/^ {7}November/, ft[-1]) + } + end + + def test_hard_margins + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.hard_margins) + assert_nothing_raised { + @format_o.hard_margins = true + @format_o.columns = 5 + @format_o.first_indent = 0 + @format_o.format_style = Text::Format::RIGHT_FILL + } + assert(@format_o.hard_margins) + assert_equal(FIVE_COL, @format_o.format(GETTYSBURG)) + assert_nothing_raised { + @format_o.split_rules |= Text::Format::SPLIT_CONTINUATION + assert_equal(Text::Format::SPLIT_CONTINUATION_FIXED, + @format_o.split_rules) + } + assert_equal(FIVE_CNT, @format_o.format(GETTYSBURG)) + end + + # Tests both nobreak and nobreak_regex, since one is only useful + # with the other. + def test_nobreak + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.nobreak) + assert(@format_o.nobreak_regex.empty?) + assert_nothing_raised { + @format_o.nobreak = true + @format_o.nobreak_regex = { '^this$' => '^continent$' } + @format_o.columns = 77 + } + assert(@format_o.nobreak) + assert_equal({ '^this$' => '^continent$' }, @format_o.nobreak_regex) + assert_match(/^this continent/, + @format_o.format(GETTYSBURG).split("\n")[1]) + end + + def test_right_align? + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.right_align?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_ALIGN + } + assert(@format_o.right_align?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_FILL + } + assert(!@format_o.right_align?) + assert_nothing_raised { @format_o.format_style = Text::Format::JUSTIFY } + assert(!@format_o.right_align?) + # The format testing is done in test_format_style + end + + def test_right_fill? + assert_nothing_raised { @format_o = Text::Format.new } + assert(!@format_o.right_fill?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_ALIGN + } + assert(!@format_o.right_fill?) + assert_nothing_raised { + @format_o.format_style = Text::Format::RIGHT_FILL + } + assert(@format_o.right_fill?) + assert_nothing_raised { + @format_o.format_style = Text::Format::JUSTIFY + } + assert(!@format_o.right_fill?) + # The format testing is done in test_format_style + end + + def test_right_margin + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(0, @format_o.right_margin) + assert_nothing_raised { @format_o.right_margin = -3 } + assert_equal(3, @format_o.right_margin) + assert_nothing_raised { @format_o.right_margin = "9" } + assert_equal(9, @format_o.right_margin) + assert_nothing_raised { @format_o.right_margin = "-2" } + assert_equal(2, @format_o.right_margin) + assert_nothing_raised { @format_o.right_margin = 7 } + assert_equal(7, @format_o.right_margin) + assert_nothing_raised { + ft = @format_o.format(GETTYSBURG).split("\n") + assert_match(/^ {4}Four score.*forth on$/, ft[0]) + assert_match(/^November/, ft[-1]) + } + end + + def test_tabstop + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(8, @format_o.tabstop) + assert_nothing_raised { @format_o.tabstop = 7 } + assert_equal(7, @format_o.tabstop) + assert_nothing_raised { @format_o.tabstop = -3 } + assert_equal(3, @format_o.tabstop) + assert_nothing_raised { @format_o.tabstop = "9" } + assert_equal(9, @format_o.tabstop) + assert_nothing_raised { @format_o.tabstop = "-2" } + assert_equal(2, @format_o.tabstop) + end + + def test_text + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal([], @format_o.text) + assert_nothing_raised { @format_o.text = "Test Text" } + assert_equal("Test Text", @format_o.text) + assert_nothing_raised { @format_o.text = ["Line 1", "Line 2"] } + assert_equal(["Line 1", "Line 2"], @format_o.text) + end + + def test_s_new + # new(NilClass) { block } + assert_nothing_raised do + @format_o = Text::Format.new { + self.text = "Test 1, 2, 3" + } + end + assert_equal("Test 1, 2, 3", @format_o.text) + + # new(Hash Symbols) + assert_nothing_raised { @format_o = Text::Format.new(:columns => 72) } + assert_equal(72, @format_o.columns) + + # new(Hash String) + assert_nothing_raised { @format_o = Text::Format.new('columns' => 72) } + assert_equal(72, @format_o.columns) + + # new(Hash) { block } + assert_nothing_raised do + @format_o = Text::Format.new('columns' => 80) { + self.text = "Test 4, 5, 6" + } + end + assert_equal("Test 4, 5, 6", @format_o.text) + assert_equal(80, @format_o.columns) + + # new(Text::Format) + assert_nothing_raised do + fo = Text::Format.new(@format_o) + assert(fo == @format_o) + end + + # new(Text::Format) { block } + assert_nothing_raised do + fo = Text::Format.new(@format_o) { self.columns = 79 } + assert(fo != @format_o) + end + + # new(String) + assert_nothing_raised { @format_o = Text::Format.new("Test A, B, C") } + assert_equal("Test A, B, C", @format_o.text) + + # new(String) { block } + assert_nothing_raised do + @format_o = Text::Format.new("Test X, Y, Z") { self.columns = -5 } + end + assert_equal("Test X, Y, Z", @format_o.text) + assert_equal(5, @format_o.columns) + end + + def test_center + assert_nothing_raised { @format_o = Text::Format.new } + assert_nothing_raised do + ct = @format_o.center(GETTYSBURG.split("\n")).split("\n") + assert_match(/^ Four score and seven years ago our fathers brought forth on this/, ct[0]) + assert_match(/^ not perish from the earth./, ct[-3]) + end + end + + def test_expand + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal(" ", @format_o.expand("\t ")) + assert_nothing_raised { @format_o.tabstop = 4 } + assert_equal(" ", @format_o.expand("\t ")) + end + + def test_unexpand + assert_nothing_raised { @format_o = Text::Format.new } + assert_equal("\t ", @format_o.unexpand(" ")) + assert_nothing_raised { @format_o.tabstop = 4 } + assert_equal("\t ", @format_o.unexpand(" ")) + end + + def test_space_only + assert_equal("", Text::Format.new.format(" ")) + assert_equal("", Text::Format.new.format("\n")) + assert_equal("", Text::Format.new.format(" ")) + assert_equal("", Text::Format.new.format(" \n")) + assert_equal("", Text::Format.new.paragraphs("\n")) + assert_equal("", Text::Format.new.paragraphs(" ")) + assert_equal("", Text::Format.new.paragraphs(" ")) + assert_equal("", Text::Format.new.paragraphs(" \n")) + assert_equal("", Text::Format.new.paragraphs(["\n"])) + assert_equal("", Text::Format.new.paragraphs([" "])) + assert_equal("", Text::Format.new.paragraphs([" "])) + assert_equal("", Text::Format.new.paragraphs([" \n"])) + end + + def test_splendiferous + h = nil + test = "This is a splendiferous test" + assert_nothing_raised { @format_o = Text::Format.new(:columns => 6, :left_margin => 0, :indent => 0, :first_indent => 0) } + assert_match(/^splendiferous$/, @format_o.format(test)) + assert_nothing_raised { @format_o.hard_margins = true } + assert_match(/^lendif$/, @format_o.format(test)) + assert_nothing_raised { h = Object.new } + assert_nothing_raised do + @format_o.split_rules = Text::Format::SPLIT_HYPHENATION + class << h #:nodoc: + def hyphenate_to(word, size) + return ["", word] if size < 2 + [word[0 ... size], word[size .. -1]] + end + end + @format_o.hyphenator = h + end + assert_match(/^iferou$/, @format_o.format(test)) + assert_nothing_raised { h = Object.new } + assert_nothing_raised do + class << h #:nodoc: + def hyphenate_to(word, size, formatter) + return ["", word] if word.size < formatter.columns + [word[0 ... size], word[size .. -1]] + end + end + @format_o.hyphenator = h + end + assert_match(/^ferous$/, @format_o.format(test)) + end + end +end +# +# address.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/encode' +require 'tmail/parser' + + +module TMail + + class Address + + include TextUtils + + def Address.parse( str ) + Parser.parse :ADDRESS, str + end + + def address_group? + false + end + + def initialize( local, domain ) + if domain + domain.each do |s| + raise SyntaxError, 'empty word in domain' if s.empty? + end + end + @local = local + @domain = domain + @name = nil + @routes = [] + end + + attr_reader :name + + def name=( str ) + @name = str + @name = nil if str and str.empty? + end + + alias phrase name + alias phrase= name= + + attr_reader :routes + + def inspect + "#<#{self.class} #{address()}>" + end + + def local + return nil unless @local + return '""' if @local.size == 1 and @local[0].empty? + @local.map {|i| quote_atom(i) }.join('.') + end + + def domain + return nil unless @domain + join_domain(@domain) + end + + def spec + s = self.local + d = self.domain + if s and d + s + '@' + d + else + s + end + end + + alias address spec + + + def ==( other ) + other.respond_to? :spec and self.spec == other.spec + end + + alias eql? == + + def hash + @local.hash ^ @domain.hash + end + + def dup + obj = self.class.new(@local.dup, @domain.dup) + obj.name = @name.dup if @name + obj.routes.replace @routes + obj + end + + include StrategyInterface + + def accept( strategy, dummy1 = nil, dummy2 = nil ) + unless @local + strategy.meta '<>' # empty return-path + return + end + + spec_p = (not @name and @routes.empty?) + if @name + strategy.phrase @name + strategy.space + end + tmp = spec_p ? '' : '<' + unless @routes.empty? + tmp << @routes.map {|i| '@' + i }.join(',') << ':' + end + tmp << self.spec + tmp << '>' unless spec_p + strategy.meta tmp + strategy.lwsp '' + end + + end + + + class AddressGroup + + include Enumerable + + def address_group? + true + end + + def initialize( name, addrs ) + @name = name + @addresses = addrs + end + + attr_reader :name + + def ==( other ) + other.respond_to? :to_a and @addresses == other.to_a + end + + alias eql? == + + def hash + map {|i| i.hash }.hash + end + + def []( idx ) + @addresses[idx] + end + + def size + @addresses.size + end + + def empty? + @addresses.empty? + end + + def each( &block ) + @addresses.each(&block) + end + + def to_a + @addresses.dup + end + + alias to_ary to_a + + def include?( a ) + @addresses.include? a + end + + def flatten + set = [] + @addresses.each do |a| + if a.respond_to? :flatten + set.concat a.flatten + else + set.push a + end + end + set + end + + def each_address( &block ) + flatten.each(&block) + end + + def add( a ) + @addresses.push a + end + + alias push add + + def delete( a ) + @addresses.delete a + end + + include StrategyInterface + + def accept( strategy, dummy1 = nil, dummy2 = nil ) + strategy.phrase @name + strategy.meta ':' + strategy.space + first = true + each do |mbox| + if first + first = false + else + strategy.meta ',' + end + strategy.space + mbox.accept strategy + end + strategy.meta ';' + strategy.lwsp '' + end + + end + +end # module TMail +require 'stringio' + +module TMail + class Attachment < StringIO + attr_accessor :original_filename, :content_type + end + + class Mail + def has_attachments? + multipart? && parts.any? { |part| attachment?(part) } + end + + def attachment?(part) + (part['content-disposition'] && part['content-disposition'].disposition == "attachment") || + part.header['content-type'].main_type != "text" + end + + def attachments + if multipart? + parts.collect { |part| + if attachment?(part) + content = part.body # unquoted automatically by TMail#body + file_name = (part['content-location'] && + part['content-location'].body) || + part.sub_header("content-type", "name") || + part.sub_header("content-disposition", "filename") + + next if file_name.blank? || content.blank? + + attachment = Attachment.new(content) + attachment.original_filename = file_name.strip + attachment.content_type = part.content_type + attachment + end + }.compact + end + end + end +end +# +# base64.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +module TMail + + module Base64 + + module_function + + def rb_folding_encode( str, eol = "\n", limit = 60 ) + [str].pack('m') + end + + def rb_encode( str ) + [str].pack('m').tr( "\r\n", '' ) + end + + def rb_decode( str, strict = false ) + str.unpack('m') + end + + begin + require 'tmail/base64.so' + alias folding_encode c_folding_encode + alias encode c_encode + alias decode c_decode + class << self + alias folding_encode c_folding_encode + alias encode c_encode + alias decode c_decode + end + rescue LoadError + alias folding_encode rb_folding_encode + alias encode rb_encode + alias decode rb_decode + class << self + alias folding_encode rb_folding_encode + alias encode rb_encode + alias decode rb_decode + end + end + + end + +end +# +# config.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +module TMail + + class Config + + def initialize( strict ) + @strict_parse = strict + @strict_base64decode = strict + end + + def strict_parse? + @strict_parse + end + + attr_writer :strict_parse + + def strict_base64decode? + @strict_base64decode + end + + attr_writer :strict_base64decode + + def new_body_port( mail ) + StringPort.new + end + + alias new_preamble_port new_body_port + alias new_part_port new_body_port + + end + + DEFAULT_CONFIG = Config.new(false) + DEFAULT_STRICT_CONFIG = Config.new(true) + + def Config.to_config( arg ) + return DEFAULT_STRICT_CONFIG if arg == true + return DEFAULT_CONFIG if arg == false + arg or DEFAULT_CONFIG + end + +end +# +# encode.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'nkf' +require 'tmail/base64.rb' +require 'tmail/stringio' +require 'tmail/utils' + + +module TMail + + module StrategyInterface + + def create_dest( obj ) + case obj + when nil + StringOutput.new + when String + StringOutput.new(obj) + when IO, StringOutput + obj + else + raise TypeError, 'cannot handle this type of object for dest' + end + end + module_function :create_dest + + def encoded( eol = "\r\n", charset = 'j', dest = nil ) + accept_strategy Encoder, eol, charset, dest + end + + def decoded( eol = "\n", charset = 'e', dest = nil ) + accept_strategy Decoder, eol, charset, dest + end + + alias to_s decoded + + def accept_strategy( klass, eol, charset, dest = nil ) + dest ||= '' + accept klass.new(create_dest(dest), charset, eol) + dest + end + + end + + + ### + ### MIME B encoding decoder + ### + + class Decoder + + include TextUtils + + encoded = '=\?(?:iso-2022-jp|euc-jp|shift_jis)\?[QB]\?[a-z0-9+/=]+\?=' + ENCODED_WORDS = /#{encoded}(?:\s+#{encoded})*/i + + OUTPUT_ENCODING = { + 'EUC' => 'e', + 'SJIS' => 's', + } + + def self.decode( str, encoding = nil ) + encoding ||= (OUTPUT_ENCODING[$KCODE] || 'j') + opt = '-m' + encoding + str.gsub(ENCODED_WORDS) {|s| NKF.nkf(opt, s) } + end + + def initialize( dest, encoding = nil, eol = "\n" ) + @f = StrategyInterface.create_dest(dest) + @encoding = (/\A[ejs]/ === encoding) ? encoding[0,1] : nil + @eol = eol + end + + def decode( str ) + self.class.decode(str, @encoding) + end + private :decode + + def terminate + end + + def header_line( str ) + @f << decode(str) + end + + def header_name( nm ) + @f << nm << ': ' + end + + def header_body( str ) + @f << decode(str) + end + + def space + @f << ' ' + end + + alias spc space + + def lwsp( str ) + @f << str + end + + def meta( str ) + @f << str + end + + def text( str ) + @f << decode(str) + end + + def phrase( str ) + @f << quote_phrase(decode(str)) + end + + def kv_pair( k, v ) + @f << k << '=' << v + end + + def puts( str = nil ) + @f << str if str + @f << @eol + end + + def write( str ) + @f << str + end + + end + + + ### + ### MIME B-encoding encoder + ### + + # + # FIXME: This class can handle only (euc-jp/shift_jis -> iso-2022-jp). + # + class Encoder + + include TextUtils + + BENCODE_DEBUG = false unless defined?(BENCODE_DEBUG) + + def Encoder.encode( str ) + e = new() + e.header_body str + e.terminate + e.dest.string + end + + SPACER = "\t" + MAX_LINE_LEN = 70 + + OPTIONS = { + 'EUC' => '-Ej -m0', + 'SJIS' => '-Sj -m0', + 'UTF8' => nil, # FIXME + 'NONE' => nil + } + + def initialize( dest = nil, encoding = nil, eol = "\r\n", limit = nil ) + @f = StrategyInterface.create_dest(dest) + @opt = OPTIONS[$KCODE] + @eol = eol + reset + end + + def normalize_encoding( str ) + if @opt + then NKF.nkf(@opt, str) + else str + end + end + + def reset + @text = '' + @lwsp = '' + @curlen = 0 + end + + def terminate + add_lwsp '' + reset + end + + def dest + @f + end + + def puts( str = nil ) + @f << str if str + @f << @eol + end + + def write( str ) + @f << str + end + + # + # add + # + + def header_line( line ) + scanadd line + end + + def header_name( name ) + add_text name.split(/-/).map {|i| i.capitalize }.join('-') + add_text ':' + add_lwsp ' ' + end + + def header_body( str ) + scanadd normalize_encoding(str) + end + + def space + add_lwsp ' ' + end + + alias spc space + + def lwsp( str ) + add_lwsp str.sub(/[\r\n]+[^\r\n]*\z/, '') + end + + def meta( str ) + add_text str + end + + def text( str ) + scanadd normalize_encoding(str) + end + + def phrase( str ) + str = normalize_encoding(str) + if CONTROL_CHAR === str + scanadd str + else + add_text quote_phrase(str) + end + end + + # FIXME: implement line folding + # + def kv_pair( k, v ) + return if v.nil? + v = normalize_encoding(v) + if token_safe?(v) + add_text k + '=' + v + elsif not CONTROL_CHAR === v + add_text k + '=' + quote_token(v) + else + # apply RFC2231 encoding + kv = k + '*=' + "iso-2022-jp'ja'" + encode_value(v) + add_text kv + end + end + + def encode_value( str ) + str.gsub(TOKEN_UNSAFE) {|s| '%%%02x' % s[0] } + end + + private + + def scanadd( str, force = false ) + types = '' + strs = [] + + until str.empty? + if m = /\A[^\e\t\r\n ]+/.match(str) + types << (force ? 'j' : 'a') + strs.push m[0] + + elsif m = /\A[\t\r\n ]+/.match(str) + types << 's' + strs.push m[0] + + elsif m = /\A\e../.match(str) + esc = m[0] + str = m.post_match + if esc != "\e(B" and m = /\A[^\e]+/.match(str) + types << 'j' + strs.push m[0] + end + + else + raise 'TMail FATAL: encoder scan fail' + end + (str = m.post_match) unless m.nil? + end + + do_encode types, strs + end + + def do_encode( types, strs ) + # + # result : (A|E)(S(A|E))* + # E : W(SW)* + # W : (J|A)+ but must contain J # (J|A)*J(J|A)* + # A : <<A character string not to be encoded>> + # J : <<A character string to be encoded>> + # S : <<LWSP>> + # + # An encoding unit is `E'. + # Input (parameter `types') is (J|A)(J|A|S)*(J|A) + # + if BENCODE_DEBUG + puts + puts '-- do_encode ------------' + puts types.split(//).join(' ') + p strs + end + + e = /[ja]*j[ja]*(?:s[ja]*j[ja]*)*/ + + while m = e.match(types) + pre = m.pre_match + concat_A_S pre, strs[0, pre.size] unless pre.empty? + concat_E m[0], strs[m.begin(0) ... m.end(0)] + types = m.post_match + strs.slice! 0, m.end(0) + end + concat_A_S types, strs + end + + def concat_A_S( types, strs ) + i = 0 + types.each_byte do |t| + case t + when ?a then add_text strs[i] + when ?s then add_lwsp strs[i] + else + raise "TMail FATAL: unknown flag: #{t.chr}" + end + i += 1 + end + end + + METHOD_ID = { + ?j => :extract_J, + ?e => :extract_E, + ?a => :extract_A, + ?s => :extract_S + } + + def concat_E( types, strs ) + if BENCODE_DEBUG + puts '---- concat_E' + puts "types=#{types.split(//).join(' ')}" + puts "strs =#{strs.inspect}" + end + + flush() unless @text.empty? + + chunk = '' + strs.each_with_index do |s,i| + mid = METHOD_ID[types[i]] + until s.empty? + unless c = __send__(mid, chunk.size, s) + add_with_encode chunk unless chunk.empty? + flush + chunk = '' + fold + c = __send__(mid, 0, s) + raise 'TMail FATAL: extract fail' unless c + end + chunk << c + end + end + add_with_encode chunk unless chunk.empty? + end + + def extract_J( chunksize, str ) + size = max_bytes(chunksize, str.size) - 6 + size = (size % 2 == 0) ? (size) : (size - 1) + return nil if size <= 0 + "\e$B#{str.slice!(0, size)}\e(B" + end + + def extract_A( chunksize, str ) + size = max_bytes(chunksize, str.size) + return nil if size <= 0 + str.slice!(0, size) + end + + alias extract_S extract_A + + def max_bytes( chunksize, ssize ) + (restsize() - '=?iso-2022-jp?B??='.size) / 4 * 3 - chunksize + end + + # + # free length buffer + # + + def add_text( str ) + @text << str + # puts '---- text -------------------------------------' + # puts "+ #{str.inspect}" + # puts "txt >>>#{@text.inspect}<<<" + end + + def add_with_encode( str ) + @text << "=?iso-2022-jp?B?#{Base64.encode(str)}?=" + end + + def add_lwsp( lwsp ) + # puts '---- lwsp -------------------------------------' + # puts "+ #{lwsp.inspect}" + fold if restsize() <= 0 + flush + @lwsp = lwsp + end + + def flush + # puts '---- flush ----' + # puts "spc >>>#{@lwsp.inspect}<<<" + # puts "txt >>>#{@text.inspect}<<<" + @f << @lwsp << @text + @curlen += (@lwsp.size + @text.size) + @text = '' + @lwsp = '' + end + + def fold + # puts '---- fold ----' + @f << @eol + @curlen = 0 + @lwsp = SPACER + end + + def restsize + MAX_LINE_LEN - (@curlen + @lwsp.size + @text.size) + end + + end + +end # module TMail +# +# facade.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/utils' + + +module TMail + + class Mail + + def header_string( name, default = nil ) + h = @header[name.downcase] or return default + h.to_s + end + + ### + ### attributes + ### + + include TextUtils + + def set_string_array_attr( key, strs ) + strs.flatten! + if strs.empty? + @header.delete key.downcase + else + store key, strs.join(', ') + end + strs + end + private :set_string_array_attr + + def set_string_attr( key, str ) + if str + store key, str + else + @header.delete key.downcase + end + str + end + private :set_string_attr + + def set_addrfield( name, arg ) + if arg + h = HeaderField.internal_new(name, @config) + h.addrs.replace [arg].flatten + @header[name] = h + else + @header.delete name + end + arg + end + private :set_addrfield + + def addrs2specs( addrs ) + return nil unless addrs + list = addrs.map {|addr| + if addr.address_group? + then addr.map {|a| a.spec } + else addr.spec + end + }.flatten + return nil if list.empty? + list + end + private :addrs2specs + + + # + # date time + # + + def date( default = nil ) + if h = @header['date'] + h.date + else + default + end + end + + def date=( time ) + if time + store 'Date', time2str(time) + else + @header.delete 'date' + end + time + end + + def strftime( fmt, default = nil ) + if t = date + t.strftime(fmt) + else + default + end + end + + + # + # destination + # + + def to_addrs( default = nil ) + if h = @header['to'] + h.addrs + else + default + end + end + + def cc_addrs( default = nil ) + if h = @header['cc'] + h.addrs + else + default + end + end + + def bcc_addrs( default = nil ) + if h = @header['bcc'] + h.addrs + else + default + end + end + + def to_addrs=( arg ) + set_addrfield 'to', arg + end + + def cc_addrs=( arg ) + set_addrfield 'cc', arg + end + + def bcc_addrs=( arg ) + set_addrfield 'bcc', arg + end + + def to( default = nil ) + addrs2specs(to_addrs(nil)) || default + end + + def cc( default = nil ) + addrs2specs(cc_addrs(nil)) || default + end + + def bcc( default = nil ) + addrs2specs(bcc_addrs(nil)) || default + end + + def to=( *strs ) + set_string_array_attr 'To', strs + end + + def cc=( *strs ) + set_string_array_attr 'Cc', strs + end + + def bcc=( *strs ) + set_string_array_attr 'Bcc', strs + end + + + # + # originator + # + + def from_addrs( default = nil ) + if h = @header['from'] + h.addrs + else + default + end + end + + def from_addrs=( arg ) + set_addrfield 'from', arg + end + + def from( default = nil ) + addrs2specs(from_addrs(nil)) || default + end + + def from=( *strs ) + set_string_array_attr 'From', strs + end + + def friendly_from( default = nil ) + h = @header['from'] + a, = h.addrs + return default unless a + return a.phrase if a.phrase + return h.comments.join(' ') unless h.comments.empty? + a.spec + end + + + def reply_to_addrs( default = nil ) + if h = @header['reply-to'] + h.addrs + else + default + end + end + + def reply_to_addrs=( arg ) + set_addrfield 'reply-to', arg + end + + def reply_to( default = nil ) + addrs2specs(reply_to_addrs(nil)) || default + end + + def reply_to=( *strs ) + set_string_array_attr 'Reply-To', strs + end + + + def sender_addr( default = nil ) + f = @header['sender'] or return default + f.addr or return default + end + + def sender_addr=( addr ) + if addr + h = HeaderField.internal_new('sender', @config) + h.addr = addr + @header['sender'] = h + else + @header.delete 'sender' + end + addr + end + + def sender( default ) + f = @header['sender'] or return default + a = f.addr or return default + a.spec + end + + def sender=( str ) + set_string_attr 'Sender', str + end + + + # + # subject + # + + def subject( default = nil ) + if h = @header['subject'] + h.body + else + default + end + end + alias quoted_subject subject + + def subject=( str ) + set_string_attr 'Subject', str + end + + + # + # identity & threading + # + + def message_id( default = nil ) + if h = @header['message-id'] + h.id || default + else + default + end + end + + def message_id=( str ) + set_string_attr 'Message-Id', str + end + + def in_reply_to( default = nil ) + if h = @header['in-reply-to'] + h.ids + else + default + end + end + + def in_reply_to=( *idstrs ) + set_string_array_attr 'In-Reply-To', idstrs + end + + def references( default = nil ) + if h = @header['references'] + h.refs + else + default + end + end + + def references=( *strs ) + set_string_array_attr 'References', strs + end + + + # + # MIME headers + # + + def mime_version( default = nil ) + if h = @header['mime-version'] + h.version || default + else + default + end + end + + def mime_version=( m, opt = nil ) + if opt + if h = @header['mime-version'] + h.major = m + h.minor = opt + else + store 'Mime-Version', "#{m}.#{opt}" + end + else + store 'Mime-Version', m + end + m + end + + + def content_type( default = nil ) + if h = @header['content-type'] + h.content_type || default + else + default + end + end + + def main_type( default = nil ) + if h = @header['content-type'] + h.main_type || default + else + default + end + end + + def sub_type( default = nil ) + if h = @header['content-type'] + h.sub_type || default + else + default + end + end + + def set_content_type( str, sub = nil, param = nil ) + if sub + main, sub = str, sub + else + main, sub = str.split(%r</>, 2) + raise ArgumentError, "sub type missing: #{str.inspect}" unless sub + end + if h = @header['content-type'] + h.main_type = main + h.sub_type = sub + h.params.clear + else + store 'Content-Type', "#{main}/#{sub}" + end + @header['content-type'].params.replace param if param + + str + end + + alias content_type= set_content_type + + def type_param( name, default = nil ) + if h = @header['content-type'] + h[name] || default + else + default + end + end + + def charset( default = nil ) + if h = @header['content-type'] + h['charset'] or default + else + default + end + end + + def charset=( str ) + if str + if h = @header[ 'content-type' ] + h['charset'] = str + else + store 'Content-Type', "text/plain; charset=#{str}" + end + end + str + end + + + def transfer_encoding( default = nil ) + if h = @header['content-transfer-encoding'] + h.encoding || default + else + default + end + end + + def transfer_encoding=( str ) + set_string_attr 'Content-Transfer-Encoding', str + end + + alias encoding transfer_encoding + alias encoding= transfer_encoding= + alias content_transfer_encoding transfer_encoding + alias content_transfer_encoding= transfer_encoding= + + + def disposition( default = nil ) + if h = @header['content-disposition'] + h.disposition || default + else + default + end + end + + alias content_disposition disposition + + def set_disposition( str, params = nil ) + if h = @header['content-disposition'] + h.disposition = str + h.params.clear + else + store('Content-Disposition', str) + h = @header['content-disposition'] + end + h.params.replace params if params + end + + alias disposition= set_disposition + alias set_content_disposition set_disposition + alias content_disposition= set_disposition + + def disposition_param( name, default = nil ) + if h = @header['content-disposition'] + h[name] || default + else + default + end + end + + ### + ### utils + ### + + def create_reply + mail = TMail::Mail.parse('') + mail.subject = 'Re: ' + subject('').sub(/\A(?:\[[^\]]+\])?(?:\s*Re:)*\s*/i, '') + mail.to_addrs = reply_addresses([]) + mail.in_reply_to = [message_id(nil)].compact + mail.references = references([]) + [message_id(nil)].compact + mail.mime_version = '1.0' + mail + end + + + def base64_encode + store 'Content-Transfer-Encoding', 'Base64' + self.body = Base64.folding_encode(self.body) + end + + def base64_decode + if /base64/i === self.transfer_encoding('') + store 'Content-Transfer-Encoding', '8bit' + self.body = Base64.decode(self.body, @config.strict_base64decode?) + end + end + + + def destinations( default = nil ) + ret = [] + %w( to cc bcc ).each do |nm| + if h = @header[nm] + h.addrs.each {|i| ret.push i.address } + end + end + ret.empty? ? default : ret + end + + def each_destination( &block ) + destinations([]).each do |i| + if Address === i + yield i + else + i.each(&block) + end + end + end + + alias each_dest each_destination + + + def reply_addresses( default = nil ) + reply_to_addrs(nil) or from_addrs(nil) or default + end + + def error_reply_addresses( default = nil ) + if s = sender(nil) + [s] + else + from_addrs(default) + end + end + + + def multipart? + main_type('').downcase == 'multipart' + end + + end # class Mail + +end # module TMail +# +# header.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/encode' +require 'tmail/address' +require 'tmail/parser' +require 'tmail/config' +require 'tmail/utils' + + +module TMail + + class HeaderField + + include TextUtils + + class << self + + alias newobj new + + def new( name, body, conf = DEFAULT_CONFIG ) + klass = FNAME_TO_CLASS[name.downcase] || UnstructuredHeader + klass.newobj body, conf + end + + def new_from_port( port, name, conf = DEFAULT_CONFIG ) + re = Regep.new('\A(' + Regexp.quote(name) + '):', 'i') + str = nil + port.ropen {|f| + f.each do |line| + if m = re.match(line) then str = m.post_match.strip + elsif str and /\A[\t ]/ === line then str << ' ' << line.strip + elsif /\A-*\s*\z/ === line then break + elsif str then break + end + end + } + new(name, str, Config.to_config(conf)) + end + + def internal_new( name, conf ) + FNAME_TO_CLASS[name].newobj('', conf, true) + end + + end # class << self + + def initialize( body, conf, intern = false ) + @body = body + @config = conf + + @illegal = false + @parsed = false + if intern + @parsed = true + parse_init + end + end + + def inspect + "#<#{self.class} #{@body.inspect}>" + end + + def illegal? + @illegal + end + + def empty? + ensure_parsed + return true if @illegal + isempty? + end + + private + + def ensure_parsed + return if @parsed + @parsed = true + parse + end + + # defabstract parse + # end + + def clear_parse_status + @parsed = false + @illegal = false + end + + public + + def body + ensure_parsed + v = Decoder.new(s = '') + do_accept v + v.terminate + s + end + + def body=( str ) + @body = str + clear_parse_status + end + + include StrategyInterface + + def accept( strategy, dummy1 = nil, dummy2 = nil ) + ensure_parsed + do_accept strategy + strategy.terminate + end + + # abstract do_accept + + end + + + class UnstructuredHeader < HeaderField + + def body + ensure_parsed + @body + end + + def body=( arg ) + ensure_parsed + @body = arg + end + + private + + def parse_init + end + + def parse + @body = Decoder.decode(@body.gsub(/\n|\r\n|\r/, '')) + end + + def isempty? + not @body + end + + def do_accept( strategy ) + strategy.text @body + end + + end + + + class StructuredHeader < HeaderField + + def comments + ensure_parsed + @comments + end + + private + + def parse + save = nil + + begin + parse_init + do_parse + rescue SyntaxError + if not save and mime_encoded? @body + save = @body + @body = Decoder.decode(save) + retry + elsif save + @body = save + end + + @illegal = true + raise if @config.strict_parse? + end + end + + def parse_init + @comments = [] + init + end + + def do_parse + obj = Parser.parse(self.class::PARSE_TYPE, @body, @comments) + set obj if obj + end + + end + + + class DateTimeHeader < StructuredHeader + + PARSE_TYPE = :DATETIME + + def date + ensure_parsed + @date + end + + def date=( arg ) + ensure_parsed + @date = arg + end + + private + + def init + @date = nil + end + + def set( t ) + @date = t + end + + def isempty? + not @date + end + + def do_accept( strategy ) + strategy.meta time2str(@date) + end + + end + + + class AddressHeader < StructuredHeader + + PARSE_TYPE = :MADDRESS + + def addrs + ensure_parsed + @addrs + end + + private + + def init + @addrs = [] + end + + def set( a ) + @addrs = a + end + + def isempty? + @addrs.empty? + end + + def do_accept( strategy ) + first = true + @addrs.each do |a| + if first + first = false + else + strategy.meta ',' + strategy.space + end + a.accept strategy + end + + @comments.each do |c| + strategy.space + strategy.meta '(' + strategy.text c + strategy.meta ')' + end + end + + end + + + class ReturnPathHeader < AddressHeader + + PARSE_TYPE = :RETPATH + + def addr + addrs()[0] + end + + def spec + a = addr() or return nil + a.spec + end + + def routes + a = addr() or return nil + a.routes + end + + private + + def do_accept( strategy ) + a = addr() + + strategy.meta '<' + unless a.routes.empty? + strategy.meta a.routes.map {|i| '@' + i }.join(',') + strategy.meta ':' + end + spec = a.spec + strategy.meta spec if spec + strategy.meta '>' + end + + end + + + class SingleAddressHeader < AddressHeader + + def addr + addrs()[0] + end + + private + + def do_accept( strategy ) + a = addr() + a.accept strategy + @comments.each do |c| + strategy.space + strategy.meta '(' + strategy.text c + strategy.meta ')' + end + end + + end + + + class MessageIdHeader < StructuredHeader + + def id + ensure_parsed + @id + end + + def id=( arg ) + ensure_parsed + @id = arg + end + + private + + def init + @id = nil + end + + def isempty? + not @id + end + + def do_parse + @id = @body.slice(MESSAGE_ID) or + raise SyntaxError, "wrong Message-ID format: #{@body}" + end + + def do_accept( strategy ) + strategy.meta @id + end + + end + + + class ReferencesHeader < StructuredHeader + + def refs + ensure_parsed + @refs + end + + def each_id + self.refs.each do |i| + yield i if MESSAGE_ID === i + end + end + + def ids + ensure_parsed + @ids + end + + def each_phrase + self.refs.each do |i| + yield i unless MESSAGE_ID === i + end + end + + def phrases + ret = [] + each_phrase {|i| ret.push i } + ret + end + + private + + def init + @refs = [] + @ids = [] + end + + def isempty? + @ids.empty? + end + + def do_parse + str = @body + while m = MESSAGE_ID.match(str) + pre = m.pre_match.strip + @refs.push pre unless pre.empty? + @refs.push s = m[0] + @ids.push s + str = m.post_match + end + str = str.strip + @refs.push str unless str.empty? + end + + def do_accept( strategy ) + first = true + @ids.each do |i| + if first + first = false + else + strategy.space + end + strategy.meta i + end + end + + end + + + class ReceivedHeader < StructuredHeader + + PARSE_TYPE = :RECEIVED + + def from + ensure_parsed + @from + end + + def from=( arg ) + ensure_parsed + @from = arg + end + + def by + ensure_parsed + @by + end + + def by=( arg ) + ensure_parsed + @by = arg + end + + def via + ensure_parsed + @via + end + + def via=( arg ) + ensure_parsed + @via = arg + end + + def with + ensure_parsed + @with + end + + def id + ensure_parsed + @id + end + + def id=( arg ) + ensure_parsed + @id = arg + end + + def _for + ensure_parsed + @_for + end + + def _for=( arg ) + ensure_parsed + @_for = arg + end + + def date + ensure_parsed + @date + end + + def date=( arg ) + ensure_parsed + @date = arg + end + + private + + def init + @from = @by = @via = @with = @id = @_for = nil + @with = [] + @date = nil + end + + def set( args ) + @from, @by, @via, @with, @id, @_for, @date = *args + end + + def isempty? + @with.empty? and not (@from or @by or @via or @id or @_for or @date) + end + + def do_accept( strategy ) + list = [] + list.push 'from ' + @from if @from + list.push 'by ' + @by if @by + list.push 'via ' + @via if @via + @with.each do |i| + list.push 'with ' + i + end + list.push 'id ' + @id if @id + list.push 'for <' + @_for + '>' if @_for + + first = true + list.each do |i| + strategy.space unless first + strategy.meta i + first = false + end + if @date + strategy.meta ';' + strategy.space + strategy.meta time2str(@date) + end + end + + end + + + class KeywordsHeader < StructuredHeader + + PARSE_TYPE = :KEYWORDS + + def keys + ensure_parsed + @keys + end + + private + + def init + @keys = [] + end + + def set( a ) + @keys = a + end + + def isempty? + @keys.empty? + end + + def do_accept( strategy ) + first = true + @keys.each do |i| + if first + first = false + else + strategy.meta ',' + end + strategy.meta i + end + end + + end + + + class EncryptedHeader < StructuredHeader + + PARSE_TYPE = :ENCRYPTED + + def encrypter + ensure_parsed + @encrypter + end + + def encrypter=( arg ) + ensure_parsed + @encrypter = arg + end + + def keyword + ensure_parsed + @keyword + end + + def keyword=( arg ) + ensure_parsed + @keyword = arg + end + + private + + def init + @encrypter = nil + @keyword = nil + end + + def set( args ) + @encrypter, @keyword = args + end + + def isempty? + not (@encrypter or @keyword) + end + + def do_accept( strategy ) + if @key + strategy.meta @encrypter + ',' + strategy.space + strategy.meta @keyword + else + strategy.meta @encrypter + end + end + + end + + + class MimeVersionHeader < StructuredHeader + + PARSE_TYPE = :MIMEVERSION + + def major + ensure_parsed + @major + end + + def major=( arg ) + ensure_parsed + @major = arg + end + + def minor + ensure_parsed + @minor + end + + def minor=( arg ) + ensure_parsed + @minor = arg + end + + def version + sprintf('%d.%d', major, minor) + end + + private + + def init + @major = nil + @minor = nil + end + + def set( args ) + @major, @minor = *args + end + + def isempty? + not (@major or @minor) + end + + def do_accept( strategy ) + strategy.meta sprintf('%d.%d', @major, @minor) + end + + end + + + class ContentTypeHeader < StructuredHeader + + PARSE_TYPE = :CTYPE + + def main_type + ensure_parsed + @main + end + + def main_type=( arg ) + ensure_parsed + @main = arg.downcase + end + + def sub_type + ensure_parsed + @sub + end + + def sub_type=( arg ) + ensure_parsed + @sub = arg.downcase + end + + def content_type + ensure_parsed + @sub ? sprintf('%s/%s', @main, @sub) : @main + end + + def params + ensure_parsed + @params + end + + def []( key ) + ensure_parsed + @params and @params[key] + end + + def []=( key, val ) + ensure_parsed + (@params ||= {})[key] = val + end + + private + + def init + @main = @sub = @params = nil + end + + def set( args ) + @main, @sub, @params = *args + end + + def isempty? + not (@main or @sub) + end + + def do_accept( strategy ) + if @sub + strategy.meta sprintf('%s/%s', @main, @sub) + else + strategy.meta @main + end + @params.each do |k,v| + if v + strategy.meta ';' + strategy.space + strategy.kv_pair k, v + end + end + end + + end + + + class ContentTransferEncodingHeader < StructuredHeader + + PARSE_TYPE = :CENCODING + + def encoding + ensure_parsed + @encoding + end + + def encoding=( arg ) + ensure_parsed + @encoding = arg + end + + private + + def init + @encoding = nil + end + + def set( s ) + @encoding = s + end + + def isempty? + not @encoding + end + + def do_accept( strategy ) + strategy.meta @encoding.capitalize + end + + end + + + class ContentDispositionHeader < StructuredHeader + + PARSE_TYPE = :CDISPOSITION + + def disposition + ensure_parsed + @disposition + end + + def disposition=( str ) + ensure_parsed + @disposition = str.downcase + end + + def params + ensure_parsed + @params + end + + def []( key ) + ensure_parsed + @params and @params[key] + end + + def []=( key, val ) + ensure_parsed + (@params ||= {})[key] = val + end + + private + + def init + @disposition = @params = nil + end + + def set( args ) + @disposition, @params = *args + end + + def isempty? + not @disposition and (not @params or @params.empty?) + end + + def do_accept( strategy ) + strategy.meta @disposition + @params.each do |k,v| + strategy.meta ';' + strategy.space + strategy.kv_pair k, v + end + end + + end + + + class HeaderField # redefine + + FNAME_TO_CLASS = { + 'date' => DateTimeHeader, + 'resent-date' => DateTimeHeader, + 'to' => AddressHeader, + 'cc' => AddressHeader, + 'bcc' => AddressHeader, + 'from' => AddressHeader, + 'reply-to' => AddressHeader, + 'resent-to' => AddressHeader, + 'resent-cc' => AddressHeader, + 'resent-bcc' => AddressHeader, + 'resent-from' => AddressHeader, + 'resent-reply-to' => AddressHeader, + 'sender' => SingleAddressHeader, + 'resent-sender' => SingleAddressHeader, + 'return-path' => ReturnPathHeader, + 'message-id' => MessageIdHeader, + 'resent-message-id' => MessageIdHeader, + 'in-reply-to' => ReferencesHeader, + 'received' => ReceivedHeader, + 'references' => ReferencesHeader, + 'keywords' => KeywordsHeader, + 'encrypted' => EncryptedHeader, + 'mime-version' => MimeVersionHeader, + 'content-type' => ContentTypeHeader, + 'content-transfer-encoding' => ContentTransferEncodingHeader, + 'content-disposition' => ContentDispositionHeader, + 'content-id' => MessageIdHeader, + 'subject' => UnstructuredHeader, + 'comments' => UnstructuredHeader, + 'content-description' => UnstructuredHeader + } + + end + +end # module TMail +# +# info.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +module TMail + + Version = '0.10.7' + Copyright = 'Copyright (c) 1998-2002 Minero Aoki' + +end +require 'tmail/mailbox' +# +# mail.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/facade' +require 'tmail/encode' +require 'tmail/header' +require 'tmail/port' +require 'tmail/config' +require 'tmail/utils' +require 'tmail/attachments' +require 'tmail/quoting' +require 'socket' + + +module TMail + + class Mail + + class << self + def load( fname ) + new(FilePort.new(fname)) + end + + alias load_from load + alias loadfrom load + + def parse( str ) + new(StringPort.new(str)) + end + end + + def initialize( port = nil, conf = DEFAULT_CONFIG ) + @port = port || StringPort.new + @config = Config.to_config(conf) + + @header = {} + @body_port = nil + @body_parsed = false + @epilogue = '' + @parts = [] + + @port.ropen {|f| + parse_header f + parse_body f unless @port.reproducible? + } + end + + attr_reader :port + + def inspect + "\#<#{self.class} port=#{@port.inspect} bodyport=#{@body_port.inspect}>" + end + + # + # to_s interfaces + # + + public + + include StrategyInterface + + def write_back( eol = "\n", charset = 'e' ) + parse_body + @port.wopen {|stream| encoded eol, charset, stream } + end + + def accept( strategy ) + with_multipart_encoding(strategy) { + ordered_each do |name, field| + next if field.empty? + strategy.header_name canonical(name) + field.accept strategy + strategy.puts + end + strategy.puts + body_port().ropen {|r| + strategy.write r.read + } + } + end + + private + + def canonical( name ) + name.split(/-/).map {|s| s.capitalize }.join('-') + end + + def with_multipart_encoding( strategy ) + if parts().empty? # DO NOT USE @parts + yield + + else + bound = ::TMail.new_boundary + if @header.key? 'content-type' + @header['content-type'].params['boundary'] = bound + else + store 'Content-Type', %<multipart/mixed; boundary="#{bound}"> + end + + yield + + parts().each do |tm| + strategy.puts + strategy.puts '--' + bound + tm.accept strategy + end + strategy.puts + strategy.puts '--' + bound + '--' + strategy.write epilogue() + end + end + + ### + ### header + ### + + public + + ALLOW_MULTIPLE = { + 'received' => true, + 'resent-date' => true, + 'resent-from' => true, + 'resent-sender' => true, + 'resent-to' => true, + 'resent-cc' => true, + 'resent-bcc' => true, + 'resent-message-id' => true, + 'comments' => true, + 'keywords' => true + } + USE_ARRAY = ALLOW_MULTIPLE + + def header + @header.dup + end + + def []( key ) + @header[key.downcase] + end + + def sub_header(key, param) + (hdr = self[key]) ? hdr[param] : nil + end + + alias fetch [] + + def []=( key, val ) + dkey = key.downcase + + if val.nil? + @header.delete dkey + return nil + end + + case val + when String + header = new_hf(key, val) + when HeaderField + ; + when Array + ALLOW_MULTIPLE.include? dkey or + raise ArgumentError, "#{key}: Header must not be multiple" + @header[dkey] = val + return val + else + header = new_hf(key, val.to_s) + end + if ALLOW_MULTIPLE.include? dkey + (@header[dkey] ||= []).push header + else + @header[dkey] = header + end + + val + end + + alias store []= + + def each_header + @header.each do |key, val| + [val].flatten.each {|v| yield key, v } + end + end + + alias each_pair each_header + + def each_header_name( &block ) + @header.each_key(&block) + end + + alias each_key each_header_name + + def each_field( &block ) + @header.values.flatten.each(&block) + end + + alias each_value each_field + + FIELD_ORDER = %w( + return-path received + resent-date resent-from resent-sender resent-to + resent-cc resent-bcc resent-message-id + date from sender reply-to to cc bcc + message-id in-reply-to references + subject comments keywords + mime-version content-type content-transfer-encoding + content-disposition content-description + ) + + def ordered_each + list = @header.keys + FIELD_ORDER.each do |name| + if list.delete(name) + [@header[name]].flatten.each {|v| yield name, v } + end + end + list.each do |name| + [@header[name]].flatten.each {|v| yield name, v } + end + end + + def clear + @header.clear + end + + def delete( key ) + @header.delete key.downcase + end + + def delete_if + @header.delete_if do |key,val| + if Array === val + val.delete_if {|v| yield key, v } + val.empty? + else + yield key, val + end + end + end + + def keys + @header.keys + end + + def key?( key ) + @header.key? key.downcase + end + + def values_at( *args ) + args.map {|k| @header[k.downcase] }.flatten + end + + alias indexes values_at + alias indices values_at + + private + + def parse_header( f ) + name = field = nil + unixfrom = nil + + while line = f.gets + case line + when /\A[ \t]/ # continue from prev line + raise SyntaxError, 'mail is began by space' unless field + field << ' ' << line.strip + + when /\A([^\: \t]+):\s*/ # new header line + add_hf name, field if field + name = $1 + field = $' #.strip + + when /\A\-*\s*\z/ # end of header + add_hf name, field if field + name = field = nil + break + + when /\AFrom (\S+)/ + unixfrom = $1 + + when /^charset=.*/ + + else + raise SyntaxError, "wrong mail header: '#{line.inspect}'" + end + end + add_hf name, field if name + + if unixfrom + add_hf 'Return-Path', "<#{unixfrom}>" unless @header['return-path'] + end + end + + def add_hf( name, field ) + key = name.downcase + field = new_hf(name, field) + + if ALLOW_MULTIPLE.include? key + (@header[key] ||= []).push field + else + @header[key] = field + end + end + + def new_hf( name, field ) + HeaderField.new(name, field, @config) + end + + ### + ### body + ### + + public + + def body_port + parse_body + @body_port + end + + def each( &block ) + body_port().ropen {|f| f.each(&block) } + end + + def quoted_body + parse_body + @body_port.ropen {|f| + return f.read + } + end + + def body=( str ) + parse_body + @body_port.wopen {|f| f.write str } + str + end + + alias preamble body + alias preamble= body= + + def epilogue + parse_body + @epilogue.dup + end + + def epilogue=( str ) + parse_body + @epilogue = str + str + end + + def parts + parse_body + @parts + end + + def each_part( &block ) + parts().each(&block) + end + + private + + def parse_body( f = nil ) + return if @body_parsed + if f + parse_body_0 f + else + @port.ropen {|f| + skip_header f + parse_body_0 f + } + end + @body_parsed = true + end + + def skip_header( f ) + while line = f.gets + return if /\A[\r\n]*\z/ === line + end + end + + def parse_body_0( f ) + if multipart? + read_multipart f + else + @body_port = @config.new_body_port(self) + @body_port.wopen {|w| + w.write f.read + } + end + end + + def read_multipart( src ) + bound = @header['content-type'].params['boundary'] + is_sep = /\A--#{Regexp.quote bound}(?:--)?[ \t]*(?:\n|\r\n|\r)/ + lastbound = "--#{bound}--" + + ports = [ @config.new_preamble_port(self) ] + begin + f = ports.last.wopen + while line = src.gets + if is_sep === line + f.close + break if line.strip == lastbound + ports.push @config.new_part_port(self) + f = ports.last.wopen + else + f << line + end + end + @epilogue = (src.read || '') + ensure + f.close if f and not f.closed? + end + + @body_port = ports.shift + @parts = ports.map {|p| self.class.new(p, @config) } + end + + end # class Mail + +end # module TMail +# +# mailbox.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/port' +require 'socket' +require 'mutex_m' + + +unless [].respond_to?(:sort_by) +module Enumerable#:nodoc: + def sort_by + map {|i| [yield(i), i] }.sort {|a,b| a.first <=> b.first }.map {|i| i[1] } + end +end +end + + +module TMail + + class MhMailbox + + PORT_CLASS = MhPort + + def initialize( dir ) + edir = File.expand_path(dir) + raise ArgumentError, "not directory: #{dir}"\ + unless FileTest.directory? edir + @dirname = edir + @last_file = nil + @last_atime = nil + end + + def directory + @dirname + end + + alias dirname directory + + attr_accessor :last_atime + + def inspect + "#<#{self.class} #{@dirname}>" + end + + def close + end + + def new_port + PORT_CLASS.new(next_file_name()) + end + + def each_port + mail_files().each do |path| + yield PORT_CLASS.new(path) + end + @last_atime = Time.now + end + + alias each each_port + + def reverse_each_port + mail_files().reverse_each do |path| + yield PORT_CLASS.new(path) + end + @last_atime = Time.now + end + + alias reverse_each reverse_each_port + + # old #each_mail returns Port + #def each_mail + # each_port do |port| + # yield Mail.new(port) + # end + #end + + def each_new_port( mtime = nil, &block ) + mtime ||= @last_atime + return each_port(&block) unless mtime + return unless File.mtime(@dirname) >= mtime + + mail_files().each do |path| + yield PORT_CLASS.new(path) if File.mtime(path) > mtime + end + @last_atime = Time.now + end + + private + + def mail_files + Dir.entries(@dirname)\ + .select {|s| /\A\d+\z/ === s }\ + .map {|s| s.to_i }\ + .sort\ + .map {|i| "#{@dirname}/#{i}" }\ + .select {|path| FileTest.file? path } + end + + def next_file_name + unless n = @last_file + n = 0 + Dir.entries(@dirname)\ + .select {|s| /\A\d+\z/ === s }\ + .map {|s| s.to_i }.sort\ + .each do |i| + next unless FileTest.file? "#{@dirname}/#{i}" + n = i + end + end + begin + n += 1 + end while FileTest.exist? "#{@dirname}/#{n}" + @last_file = n + + "#{@dirname}/#{n}" + end + + end # MhMailbox + + MhLoader = MhMailbox + + + class UNIXMbox + + def UNIXMbox.lock( fname ) + begin + f = File.open(fname) + f.flock File::LOCK_EX + yield f + ensure + f.flock File::LOCK_UN + f.close if f and not f.closed? + end + end + + class << self + alias newobj new + end + + def UNIXMbox.new( fname, tmpdir = nil, readonly = false ) + tmpdir = ENV['TEMP'] || ENV['TMP'] || '/tmp' + newobj(fname, "#{tmpdir}/ruby_tmail_#{$$}_#{rand()}", readonly, false) + end + + def UNIXMbox.static_new( fname, dir, readonly = false ) + newobj(fname, dir, readonly, true) + end + + def initialize( fname, mhdir, readonly, static ) + @filename = fname + @readonly = readonly + @closed = false + + Dir.mkdir mhdir + @real = MhMailbox.new(mhdir) + @finalizer = UNIXMbox.mkfinal(@real, @filename, !@readonly, !static) + ObjectSpace.define_finalizer self, @finalizer + end + + def UNIXMbox.mkfinal( mh, mboxfile, writeback_p, cleanup_p ) + lambda { + if writeback_p + lock(mboxfile) {|f| + mh.each_port do |port| + f.puts create_from_line(port) + port.ropen {|r| + f.puts r.read + } + end + } + end + if cleanup_p + Dir.foreach(mh.dirname) do |fname| + next if /\A\.\.?\z/ === fname + File.unlink "#{mh.dirname}/#{fname}" + end + Dir.rmdir mh.dirname + end + } + end + + # make _From line + def UNIXMbox.create_from_line( port ) + sprintf 'From %s %s', + fromaddr(), TextUtils.time2str(File.mtime(port.filename)) + end + + def UNIXMbox.fromaddr + h = HeaderField.new_from_port(port, 'Return-Path') || + HeaderField.new_from_port(port, 'From') or return 'nobody' + a = h.addrs[0] or return 'nobody' + a.spec + end + private_class_method :fromaddr + + def close + return if @closed + + ObjectSpace.undefine_finalizer self + @finalizer.call + @finalizer = nil + @real = nil + @closed = true + @updated = nil + end + + def each_port( &block ) + close_check + update + @real.each_port(&block) + end + + alias each each_port + + def reverse_each_port( &block ) + close_check + update + @real.reverse_each_port(&block) + end + + alias reverse_each reverse_each_port + + # old #each_mail returns Port + #def each_mail( &block ) + # each_port do |port| + # yield Mail.new(port) + # end + #end + + def each_new_port( mtime = nil ) + close_check + update + @real.each_new_port(mtime) {|p| yield p } + end + + def new_port + close_check + @real.new_port + end + + private + + def close_check + @closed and raise ArgumentError, 'accessing already closed mbox' + end + + def update + return if FileTest.zero?(@filename) + return if @updated and File.mtime(@filename) < @updated + w = nil + port = nil + time = nil + UNIXMbox.lock(@filename) {|f| + begin + f.each do |line| + if /\AFrom / === line + w.close if w + File.utime time, time, port.filename if time + + port = @real.new_port + w = port.wopen + time = fromline2time(line) + else + w.print line if w + end + end + ensure + if w and not w.closed? + w.close + File.utime time, time, port.filename if time + end + end + f.truncate(0) unless @readonly + @updated = Time.now + } + end + + def fromline2time( line ) + m = /\AFrom \S+ \w+ (\w+) (\d+) (\d+):(\d+):(\d+) (\d+)/.match(line) \ + or return nil + Time.local(m[6].to_i, m[1], m[2].to_i, m[3].to_i, m[4].to_i, m[5].to_i) + end + + end # UNIXMbox + + MboxLoader = UNIXMbox + + + class Maildir + + extend Mutex_m + + PORT_CLASS = MaildirPort + + @seq = 0 + def Maildir.unique_number + synchronize { + @seq += 1 + return @seq + } + end + + def initialize( dir = nil ) + @dirname = dir || ENV['MAILDIR'] + raise ArgumentError, "not directory: #{@dirname}"\ + unless FileTest.directory? @dirname + @new = "#{@dirname}/new" + @tmp = "#{@dirname}/tmp" + @cur = "#{@dirname}/cur" + end + + def directory + @dirname + end + + def inspect + "#<#{self.class} #{@dirname}>" + end + + def close + end + + def each_port + mail_files(@cur).each do |path| + yield PORT_CLASS.new(path) + end + end + + alias each each_port + + def reverse_each_port + mail_files(@cur).reverse_each do |path| + yield PORT_CLASS.new(path) + end + end + + alias reverse_each reverse_each_port + + def new_port + fname = nil + tmpfname = nil + newfname = nil + + begin + fname = "#{Time.now.to_i}.#{$$}_#{Maildir.unique_number}.#{Socket.gethostname}" + + tmpfname = "#{@tmp}/#{fname}" + newfname = "#{@new}/#{fname}" + end while FileTest.exist? tmpfname + + if block_given? + File.open(tmpfname, 'w') {|f| yield f } + File.rename tmpfname, newfname + PORT_CLASS.new(newfname) + else + File.open(tmpfname, 'w') {|f| f.write "\n\n" } + PORT_CLASS.new(tmpfname) + end + end + + def each_new_port + mail_files(@new).each do |path| + dest = @cur + '/' + File.basename(path) + File.rename path, dest + yield PORT_CLASS.new(dest) + end + + check_tmp + end + + TOO_OLD = 60 * 60 * 36 # 36 hour + + def check_tmp + old = Time.now.to_i - TOO_OLD + + each_filename(@tmp) do |full, fname| + if FileTest.file? full and + File.stat(full).mtime.to_i < old + File.unlink full + end + end + end + + private + + def mail_files( dir ) + Dir.entries(dir)\ + .select {|s| s[0] != ?. }\ + .sort_by {|s| s.slice(/\A\d+/).to_i }\ + .map {|s| "#{dir}/#{s}" }\ + .select {|path| FileTest.file? path } + end + + def each_filename( dir ) + Dir.foreach(dir) do |fname| + path = "#{dir}/#{fname}" + if fname[0] != ?. and FileTest.file? path + yield path, fname + end + end + end + + end # Maildir + + MaildirLoader = Maildir + +end # module TMail +require 'tmail/mailbox' +# +# net.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'nkf' + + +module TMail + + class Mail + + def send_to( smtp ) + do_send_to(smtp) do + ready_to_send + end + end + + def send_text_to( smtp ) + do_send_to(smtp) do + ready_to_send + mime_encode + end + end + + def do_send_to( smtp ) + from = from_address or raise ArgumentError, 'no from address' + (dests = destinations).empty? and raise ArgumentError, 'no receipient' + yield + send_to_0 smtp, from, dests + end + private :do_send_to + + def send_to_0( smtp, from, to ) + smtp.ready(from, to) do |f| + encoded "\r\n", 'j', f, '' + end + end + + def ready_to_send + delete_no_send_fields + add_message_id + add_date + end + + NOSEND_FIELDS = %w( + received + bcc + ) + + def delete_no_send_fields + NOSEND_FIELDS.each do |nm| + delete nm + end + delete_if {|n,v| v.empty? } + end + + def add_message_id( fqdn = nil ) + self.message_id = ::TMail::new_message_id(fqdn) + end + + def add_date + self.date = Time.now + end + + def mime_encode + if parts.empty? + mime_encode_singlepart + else + mime_encode_multipart true + end + end + + def mime_encode_singlepart + self.mime_version = '1.0' + b = body + if NKF.guess(b) != NKF::BINARY + mime_encode_text b + else + mime_encode_binary b + end + end + + def mime_encode_text( body ) + self.body = NKF.nkf('-j -m0', body) + self.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'} + self.encoding = '7bit' + end + + def mime_encode_binary( body ) + self.body = [body].pack('m') + self.set_content_type 'application', 'octet-stream' + self.encoding = 'Base64' + end + + def mime_encode_multipart( top = true ) + self.mime_version = '1.0' if top + self.set_content_type 'multipart', 'mixed' + e = encoding(nil) + if e and not /\A(?:7bit|8bit|binary)\z/i === e + raise ArgumentError, + 'using C.T.Encoding with multipart mail is not permitted' + end + end + + def create_empty_mail + self.class.new(StringPort.new(''), @config) + end + + def create_reply + setup_reply create_empty_mail() + end + + def setup_reply( m ) + if tmp = reply_addresses(nil) + m.to_addrs = tmp + end + + mid = message_id(nil) + tmp = references(nil) || [] + tmp.push mid if mid + m.in_reply_to = [mid] if mid + m.references = tmp unless tmp.empty? + m.subject = 'Re: ' + subject('').sub(/\A(?:\s*re:)+/i, '') + + m + end + + def create_forward + setup_forward create_empty_mail() + end + + def setup_forward( mail ) + m = Mail.new(StringPort.new('')) + m.body = decoded + m.set_content_type 'message', 'rfc822' + m.encoding = encoding('7bit') + mail.parts.push m + end + + end + + + class DeleteFields + + NOSEND_FIELDS = %w( + received + bcc + ) + + def initialize( nosend = nil, delempty = true ) + @no_send_fields = nosend || NOSEND_FIELDS.dup + @delete_empty_fields = delempty + end + + attr :no_send_fields + attr :delete_empty_fields, true + + def exec( mail ) + @no_send_fields.each do |nm| + delete nm + end + delete_if {|n,v| v.empty? } if @delete_empty_fields + end + + end + + + class AddMessageId + + def initialize( fqdn = nil ) + @fqdn = fqdn + end + + attr :fqdn, true + + def exec( mail ) + mail.message_id = ::TMail::new_msgid(@fqdn) + end + + end + + + class AddDate + + def exec( mail ) + mail.date = Time.now + end + + end + + + class MimeEncodeAuto + + def initialize( s = nil, m = nil ) + @singlepart_composer = s || MimeEncodeSingle.new + @multipart_composer = m || MimeEncodeMulti.new + end + + attr :singlepart_composer + attr :multipart_composer + + def exec( mail ) + if mail._builtin_multipart? + then @multipart_composer + else @singlepart_composer end.exec mail + end + + end + + + class MimeEncodeSingle + + def exec( mail ) + mail.mime_version = '1.0' + b = mail.body + if NKF.guess(b) != NKF::BINARY + on_text b + else + on_binary b + end + end + + def on_text( body ) + mail.body = NKF.nkf('-j -m0', body) + mail.set_content_type 'text', 'plain', {'charset' => 'iso-2022-jp'} + mail.encoding = '7bit' + end + + def on_binary( body ) + mail.body = [body].pack('m') + mail.set_content_type 'application', 'octet-stream' + mail.encoding = 'Base64' + end + + end + + + class MimeEncodeMulti + + def exec( mail, top = true ) + mail.mime_version = '1.0' if top + mail.set_content_type 'multipart', 'mixed' + e = encoding(nil) + if e and not /\A(?:7bit|8bit|binary)\z/i === e + raise ArgumentError, + 'using C.T.Encoding with multipart mail is not permitted' + end + mail.parts.each do |m| + exec m, false if m._builtin_multipart? + end + end + + end + +end # module TMail +# +# obsolete.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +module TMail + + # mail.rb + class Mail + alias include? key? + alias has_key? key? + + def values + ret = [] + each_field {|v| ret.push v } + ret + end + + def value?( val ) + HeaderField === val or return false + + [ @header[val.name.downcase] ].flatten.include? val + end + + alias has_value? value? + end + + + # facade.rb + class Mail + def from_addr( default = nil ) + addr, = from_addrs(nil) + addr || default + end + + def from_address( default = nil ) + if a = from_addr(nil) + a.spec + else + default + end + end + + alias from_address= from_addrs= + + def from_phrase( default = nil ) + if a = from_addr(nil) + a.phrase + else + default + end + end + + alias msgid message_id + alias msgid= message_id= + + alias each_dest each_destination + end + + + # address.rb + class Address + alias route routes + alias addr spec + + def spec=( str ) + @local, @domain = str.split(/@/,2).map {|s| s.split(/\./) } + end + + alias addr= spec= + alias address= spec= + end + + + # mbox.rb + class MhMailbox + alias new_mail new_port + alias each_mail each_port + alias each_newmail each_new_port + end + class UNIXMbox + alias new_mail new_port + alias each_mail each_port + alias each_newmail each_new_port + end + class Maildir + alias new_mail new_port + alias each_mail each_port + alias each_newmail each_new_port + end + + + # utils.rb + extend TextUtils + + class << self + alias msgid? message_id? + alias boundary new_boundary + alias msgid new_message_id + alias new_msgid new_message_id + end + + def Mail.boundary + ::TMail.new_boundary + end + + def Mail.msgid + ::TMail.new_message_id + end + +end # module TMail +# +# DO NOT MODIFY!!!! +# This file is automatically generated by racc 1.4.3 +# from racc grammer file "parser.y". +# +# +# parser.rb: generated by racc (runtime embedded) +# + +###### racc/parser.rb + +unless $".index 'racc/parser.rb' +$".push 'racc/parser.rb' + +self.class.module_eval <<'..end /home/aamine/lib/ruby/racc/parser.rb modeval..idb76f2e220d', '/home/aamine/lib/ruby/racc/parser.rb', 1 +# +# parser.rb +# +# Copyright (c) 1999-2003 Minero Aoki <aamine@loveruby.net> +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# +# As a special exception, when this code is copied by Racc +# into a Racc output file, you may use that output file +# without restriction. +# +# $Id: parser.rb,v 1.1.1.1 2004/10/14 11:59:58 webster132 Exp $ +# + +unless defined? NotImplementedError + NotImplementedError = NotImplementError +end + + +module Racc + class ParseError < StandardError; end +end +unless defined?(::ParseError) + ParseError = Racc::ParseError +end + + +module Racc + + unless defined? Racc_No_Extentions + Racc_No_Extentions = false + end + + class Parser + + Racc_Runtime_Version = '1.4.3' + Racc_Runtime_Revision = '$Revision: 1.1.1.1 $'.split(/\s+/)[1] + + Racc_Runtime_Core_Version_R = '1.4.3' + Racc_Runtime_Core_Revision_R = '$Revision: 1.1.1.1 $'.split(/\s+/)[1] + begin + require 'racc/cparse' + # Racc_Runtime_Core_Version_C = (defined in extention) + Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split(/\s+/)[2] + unless new.respond_to?(:_racc_do_parse_c, true) + raise LoadError, 'old cparse.so' + end + if Racc_No_Extentions + raise LoadError, 'selecting ruby version of racc runtime core' + end + + Racc_Main_Parsing_Routine = :_racc_do_parse_c + Racc_YY_Parse_Method = :_racc_yyparse_c + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C + Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C + Racc_Runtime_Type = 'c' + rescue LoadError + Racc_Main_Parsing_Routine = :_racc_do_parse_rb + Racc_YY_Parse_Method = :_racc_yyparse_rb + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R + Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R + Racc_Runtime_Type = 'ruby' + end + + def self.racc_runtime_type + Racc_Runtime_Type + end + + private + + def _racc_setup + @yydebug = false unless self.class::Racc_debug_parser + @yydebug = false unless defined? @yydebug + if @yydebug + @racc_debug_out = $stderr unless defined? @racc_debug_out + @racc_debug_out ||= $stderr + end + arg = self.class::Racc_arg + arg[13] = true if arg.size < 14 + arg + end + + def _racc_init_sysvars + @racc_state = [0] + @racc_tstack = [] + @racc_vstack = [] + + @racc_t = nil + @racc_val = nil + + @racc_read_next = true + + @racc_user_yyerror = false + @racc_error_status = 0 + end + + + ### + ### do_parse + ### + + def do_parse + __send__ Racc_Main_Parsing_Routine, _racc_setup(), false + end + + def next_token + raise NotImplementedError, "#{self.class}\#next_token is not defined" + end + + def _racc_do_parse_rb( arg, in_debug ) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + + _racc_init_sysvars + tok = act = i = nil + nerr = 0 + + catch(:racc_end_parse) { + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token() + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + racc_read_token(@racc_t, tok, @racc_val) if @yydebug + @racc_read_next = false + end + end + i += @racc_t + if i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + ; + else + act = action_default[@racc_state[-1]] + end + else + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + end + end + } + end + + + ### + ### yyparse + ### + + def yyparse( recv, mid ) + __send__ Racc_YY_Parse_Method, recv, mid, _racc_setup(), true + end + + def _racc_yyparse_rb( recv, mid, arg, c_debug ) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + + _racc_init_sysvars + tok = nil + act = nil + i = nil + nerr = 0 + + + catch(:racc_end_parse) { + until i = action_pointer[@racc_state[-1]] + while act = _racc_evalact(action_default[@racc_state[-1]], arg) + end + end + + recv.__send__(mid) do |tok, val| +# $stderr.puts "rd: tok=#{tok}, val=#{val}" + unless tok + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + @racc_val = val + @racc_read_next = false + + i += @racc_t + if i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + ; +# $stderr.puts "01: act=#{act}" + else + act = action_default[@racc_state[-1]] +# $stderr.puts "02: act=#{act}" +# $stderr.puts "curstate=#{@racc_state[-1]}" + end + + while act = _racc_evalact(act, arg) + end + + while not (i = action_pointer[@racc_state[-1]]) or + not @racc_read_next or + @racc_t == 0 # $ + if i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + ; +# $stderr.puts "03: act=#{act}" + else +# $stderr.puts "04: act=#{act}" + act = action_default[@racc_state[-1]] + end + + while act = _racc_evalact(act, arg) + end + end + end + } + end + + + ### + ### common + ### + + def _racc_evalact( act, arg ) +# $stderr.puts "ea: act=#{act}" + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg +nerr = 0 # tmp + + if act > 0 and act < shift_n + # + # shift + # + + if @racc_error_status > 0 + @racc_error_status -= 1 unless @racc_t == 1 # error token + end + + @racc_vstack.push @racc_val + @racc_state.push act + @racc_read_next = true + + if @yydebug + @racc_tstack.push @racc_t + racc_shift @racc_t, @racc_tstack, @racc_vstack + end + + elsif act < 0 and act > -reduce_n + # + # reduce + # + + code = catch(:racc_jump) { + @racc_state.push _racc_do_reduce(arg, act) + false + } + if code + case code + when 1 # yyerror + @racc_user_yyerror = true # user_yyerror + return -reduce_n + when 2 # yyaccept + return shift_n + else + raise RuntimeError, '[Racc Bug] unknown jump code' + end + end + + elsif act == shift_n + # + # accept + # + + racc_accept if @yydebug + throw :racc_end_parse, @racc_vstack[0] + + elsif act == -reduce_n + # + # error + # + + case @racc_error_status + when 0 + unless arg[21] # user_yyerror + nerr += 1 + on_error @racc_t, @racc_val, @racc_vstack + end + when 3 + if @racc_t == 0 # is $ + throw :racc_end_parse, nil + end + @racc_read_next = true + end + @racc_user_yyerror = false + @racc_error_status = 3 + + while true + if i = action_pointer[@racc_state[-1]] + i += 1 # error token + if i >= 0 and + (act = action_table[i]) and + action_check[i] == @racc_state[-1] + break + end + end + + throw :racc_end_parse, nil if @racc_state.size < 2 + @racc_state.pop + @racc_vstack.pop + if @yydebug + @racc_tstack.pop + racc_e_pop @racc_state, @racc_tstack, @racc_vstack + end + end + + return act + + else + raise RuntimeError, "[Racc Bug] unknown action #{act.inspect}" + end + + racc_next_state(@racc_state[-1], @racc_state) if @yydebug + + nil + end + + def _racc_do_reduce( arg, act ) + action_table, action_check, action_default, action_pointer, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, token_table, shift_n, + reduce_n, use_result, * = arg + state = @racc_state + vstack = @racc_vstack + tstack = @racc_tstack + + i = act * -3 + len = reduce_table[i] + reduce_to = reduce_table[i+1] + method_id = reduce_table[i+2] + void_array = [] + + tmp_t = tstack[-len, len] if @yydebug + tmp_v = vstack[-len, len] + tstack[-len, len] = void_array if @yydebug + vstack[-len, len] = void_array + state[-len, len] = void_array + + # tstack must be updated AFTER method call + if use_result + vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) + else + vstack.push __send__(method_id, tmp_v, vstack) + end + tstack.push reduce_to + + racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug + + k1 = reduce_to - nt_base + if i = goto_pointer[k1] + i += state[-1] + if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 + return curstate + end + end + goto_default[k1] + end + + def on_error( t, val, vstack ) + raise ParseError, sprintf("\nparse error on value %s (%s)", + val.inspect, token_to_str(t) || '?') + end + + def yyerror + throw :racc_jump, 1 + end + + def yyaccept + throw :racc_jump, 2 + end + + def yyerrok + @racc_error_status = 0 + end + + + # for debugging output + + def racc_read_token( t, tok, val ) + @racc_debug_out.print 'read ' + @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' + @racc_debug_out.puts val.inspect + @racc_debug_out.puts + end + + def racc_shift( tok, tstack, vstack ) + @racc_debug_out.puts "shift #{racc_token2str tok}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_reduce( toks, sim, tstack, vstack ) + out = @racc_debug_out + out.print 'reduce ' + if toks.empty? + out.print ' <none>' + else + toks.each {|t| out.print ' ', racc_token2str(t) } + end + out.puts " --> #{racc_token2str(sim)}" + + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_accept + @racc_debug_out.puts 'accept' + @racc_debug_out.puts + end + + def racc_e_pop( state, tstack, vstack ) + @racc_debug_out.puts 'error recovering mode: pop token' + racc_print_states state + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_next_state( curstate, state ) + @racc_debug_out.puts "goto #{curstate}" + racc_print_states state + @racc_debug_out.puts + end + + def racc_print_stacks( t, v ) + out = @racc_debug_out + out.print ' [' + t.each_index do |i| + out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' + end + out.puts ' ]' + end + + def racc_print_states( s ) + out = @racc_debug_out + out.print ' [' + s.each {|st| out.print ' ', st } + out.puts ' ]' + end + + def racc_token2str( tok ) + self.class::Racc_token_to_s_table[tok] or + raise RuntimeError, "[Racc Bug] can't convert token #{tok} to string" + end + + def token_to_str( t ) + self.class::Racc_token_to_s_table[t] + end + + end + +end +..end /home/aamine/lib/ruby/racc/parser.rb modeval..idb76f2e220d +end # end of racc/parser.rb + + +# +# parser.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/scanner' +require 'tmail/utils' + + +module TMail + + class Parser < Racc::Parser + +module_eval <<'..end parser.y modeval..id43721faf1c', 'parser.y', 331 + + include TextUtils + + def self.parse( ident, str, cmt = nil ) + new.parse(ident, str, cmt) + end + + MAILP_DEBUG = false + + def initialize + self.debug = MAILP_DEBUG + end + + def debug=( flag ) + @yydebug = flag && Racc_debug_parser + @scanner_debug = flag + end + + def debug + @yydebug + end + + def parse( ident, str, comments = nil ) + @scanner = Scanner.new(str, ident, comments) + @scanner.debug = @scanner_debug + @first = [ident, ident] + result = yyparse(self, :parse_in) + comments.map! {|c| to_kcode(c) } if comments + result + end + + private + + def parse_in( &block ) + yield @first + @scanner.scan(&block) + end + + def on_error( t, val, vstack ) + raise SyntaxError, "parse error on token #{racc_token2str t}" + end + +..end parser.y modeval..id43721faf1c + +##### racc 1.4.3 generates ### + +racc_reduce_table = [ + 0, 0, :racc_error, + 2, 35, :_reduce_1, + 2, 35, :_reduce_2, + 2, 35, :_reduce_3, + 2, 35, :_reduce_4, + 2, 35, :_reduce_5, + 2, 35, :_reduce_6, + 2, 35, :_reduce_7, + 2, 35, :_reduce_8, + 2, 35, :_reduce_9, + 2, 35, :_reduce_10, + 2, 35, :_reduce_11, + 2, 35, :_reduce_12, + 6, 36, :_reduce_13, + 0, 48, :_reduce_none, + 2, 48, :_reduce_none, + 3, 49, :_reduce_16, + 5, 49, :_reduce_17, + 1, 50, :_reduce_18, + 7, 37, :_reduce_19, + 0, 51, :_reduce_none, + 2, 51, :_reduce_21, + 0, 52, :_reduce_none, + 2, 52, :_reduce_23, + 1, 58, :_reduce_24, + 3, 58, :_reduce_25, + 2, 58, :_reduce_26, + 0, 53, :_reduce_none, + 2, 53, :_reduce_28, + 0, 54, :_reduce_29, + 3, 54, :_reduce_30, + 0, 55, :_reduce_none, + 2, 55, :_reduce_32, + 2, 55, :_reduce_33, + 0, 56, :_reduce_none, + 2, 56, :_reduce_35, + 1, 61, :_reduce_36, + 1, 61, :_reduce_37, + 0, 57, :_reduce_none, + 2, 57, :_reduce_39, + 1, 38, :_reduce_none, + 1, 38, :_reduce_none, + 3, 38, :_reduce_none, + 1, 46, :_reduce_none, + 1, 46, :_reduce_none, + 1, 46, :_reduce_none, + 1, 39, :_reduce_none, + 2, 39, :_reduce_47, + 1, 64, :_reduce_48, + 3, 64, :_reduce_49, + 1, 68, :_reduce_none, + 1, 68, :_reduce_none, + 1, 69, :_reduce_52, + 3, 69, :_reduce_53, + 1, 47, :_reduce_none, + 1, 47, :_reduce_none, + 2, 47, :_reduce_56, + 2, 67, :_reduce_none, + 3, 65, :_reduce_58, + 2, 65, :_reduce_59, + 1, 70, :_reduce_60, + 2, 70, :_reduce_61, + 4, 62, :_reduce_62, + 3, 62, :_reduce_63, + 2, 72, :_reduce_none, + 2, 73, :_reduce_65, + 4, 73, :_reduce_66, + 3, 63, :_reduce_67, + 1, 63, :_reduce_68, + 1, 74, :_reduce_none, + 2, 74, :_reduce_70, + 1, 71, :_reduce_71, + 3, 71, :_reduce_72, + 1, 59, :_reduce_73, + 3, 59, :_reduce_74, + 1, 76, :_reduce_75, + 2, 76, :_reduce_76, + 1, 75, :_reduce_none, + 1, 75, :_reduce_none, + 1, 75, :_reduce_none, + 1, 77, :_reduce_none, + 1, 77, :_reduce_none, + 1, 77, :_reduce_none, + 1, 66, :_reduce_none, + 2, 66, :_reduce_none, + 3, 60, :_reduce_85, + 1, 40, :_reduce_86, + 3, 40, :_reduce_87, + 1, 79, :_reduce_none, + 2, 79, :_reduce_89, + 1, 41, :_reduce_90, + 2, 41, :_reduce_91, + 3, 42, :_reduce_92, + 5, 43, :_reduce_93, + 3, 43, :_reduce_94, + 0, 80, :_reduce_95, + 5, 80, :_reduce_96, + 1, 82, :_reduce_none, + 1, 82, :_reduce_none, + 1, 44, :_reduce_99, + 3, 45, :_reduce_100, + 0, 81, :_reduce_none, + 1, 81, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none, + 1, 78, :_reduce_none ] + +racc_reduce_n = 110 + +racc_shift_n = 168 + +racc_action_table = [ + -70, -69, 23, 25, 146, 147, 29, 31, 105, 106, + 16, 17, 20, 22, 136, 27, -70, -69, 32, 101, + -70, -69, 154, 100, 113, 115, -70, -69, -70, 109, + 75, 23, 25, 101, 155, 29, 31, 142, 143, 16, + 17, 20, 22, 107, 27, 23, 25, 32, 98, 29, + 31, 96, 94, 16, 17, 20, 22, 78, 27, 23, + 25, 32, 112, 29, 31, 74, 91, 16, 17, 20, + 22, 88, 117, 92, 81, 32, 23, 25, 80, 123, + 29, 31, 100, 125, 16, 17, 20, 22, 126, 23, + 25, 109, 32, 29, 31, 91, 128, 16, 17, 20, + 22, 129, 27, 23, 25, 32, 101, 29, 31, 101, + 130, 16, 17, 20, 22, 79, 52, 23, 25, 32, + 78, 29, 31, 133, 78, 16, 17, 20, 22, 77, + 23, 25, 75, 32, 29, 31, 65, 62, 16, 17, + 20, 22, 139, 23, 25, 101, 32, 29, 31, 60, + 100, 16, 17, 20, 22, 44, 27, 101, 148, 32, + 23, 25, 120, 149, 29, 31, 152, 153, 16, 17, + 20, 22, 42, 27, 157, 159, 32, 23, 25, 120, + 40, 29, 31, 15, 164, 16, 17, 20, 22, 40, + 27, 23, 25, 32, 68, 29, 31, 166, 167, 16, + 17, 20, 22, nil, 27, 23, 25, 32, nil, 29, + 31, 74, nil, 16, 17, 20, 22, nil, 23, 25, + nil, 32, 29, 31, nil, nil, 16, 17, 20, 22, + nil, 23, 25, nil, 32, 29, 31, nil, nil, 16, + 17, 20, 22, nil, 23, 25, nil, 32, 29, 31, + nil, nil, 16, 17, 20, 22, nil, 23, 25, nil, + 32, 29, 31, nil, nil, 16, 17, 20, 22, nil, + 27, 23, 25, 32, nil, 29, 31, nil, nil, 16, + 17, 20, 22, nil, 23, 25, nil, 32, 29, 31, + nil, nil, 16, 17, 20, 22, nil, 23, 25, nil, + 32, 29, 31, nil, nil, 16, 17, 20, 22, nil, + 84, 25, nil, 32, 29, 31, nil, 87, 16, 17, + 20, 22, 4, 6, 7, 8, 9, 10, 11, 12, + 13, 1, 2, 3, 84, 25, nil, nil, 29, 31, + nil, 87, 16, 17, 20, 22, 84, 25, nil, nil, + 29, 31, nil, 87, 16, 17, 20, 22, 84, 25, + nil, nil, 29, 31, nil, 87, 16, 17, 20, 22, + 84, 25, nil, nil, 29, 31, nil, 87, 16, 17, + 20, 22, 84, 25, nil, nil, 29, 31, nil, 87, + 16, 17, 20, 22, 84, 25, nil, nil, 29, 31, + nil, 87, 16, 17, 20, 22 ] + +racc_action_check = [ + 75, 28, 68, 68, 136, 136, 68, 68, 72, 72, + 68, 68, 68, 68, 126, 68, 75, 28, 68, 67, + 75, 28, 143, 66, 86, 86, 75, 28, 75, 75, + 28, 3, 3, 86, 143, 3, 3, 134, 134, 3, + 3, 3, 3, 73, 3, 152, 152, 3, 62, 152, + 152, 60, 56, 152, 152, 152, 152, 51, 152, 52, + 52, 152, 80, 52, 52, 52, 50, 52, 52, 52, + 52, 45, 89, 52, 42, 52, 71, 71, 41, 96, + 71, 71, 97, 98, 71, 71, 71, 71, 100, 7, + 7, 101, 71, 7, 7, 102, 104, 7, 7, 7, + 7, 105, 7, 8, 8, 7, 108, 8, 8, 111, + 112, 8, 8, 8, 8, 40, 8, 9, 9, 8, + 36, 9, 9, 117, 121, 9, 9, 9, 9, 33, + 10, 10, 70, 9, 10, 10, 13, 12, 10, 10, + 10, 10, 130, 2, 2, 131, 10, 2, 2, 11, + 135, 2, 2, 2, 2, 6, 2, 138, 139, 2, + 90, 90, 90, 140, 90, 90, 141, 142, 90, 90, + 90, 90, 5, 90, 148, 151, 90, 127, 127, 127, + 4, 127, 127, 1, 157, 127, 127, 127, 127, 159, + 127, 26, 26, 127, 26, 26, 26, 163, 164, 26, + 26, 26, 26, nil, 26, 27, 27, 26, nil, 27, + 27, 27, nil, 27, 27, 27, 27, nil, 155, 155, + nil, 27, 155, 155, nil, nil, 155, 155, 155, 155, + nil, 122, 122, nil, 155, 122, 122, nil, nil, 122, + 122, 122, 122, nil, 76, 76, nil, 122, 76, 76, + nil, nil, 76, 76, 76, 76, nil, 38, 38, nil, + 76, 38, 38, nil, nil, 38, 38, 38, 38, nil, + 38, 55, 55, 38, nil, 55, 55, nil, nil, 55, + 55, 55, 55, nil, 94, 94, nil, 55, 94, 94, + nil, nil, 94, 94, 94, 94, nil, 59, 59, nil, + 94, 59, 59, nil, nil, 59, 59, 59, 59, nil, + 114, 114, nil, 59, 114, 114, nil, 114, 114, 114, + 114, 114, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 77, 77, nil, nil, 77, 77, + nil, 77, 77, 77, 77, 77, 44, 44, nil, nil, + 44, 44, nil, 44, 44, 44, 44, 44, 113, 113, + nil, nil, 113, 113, nil, 113, 113, 113, 113, 113, + 88, 88, nil, nil, 88, 88, nil, 88, 88, 88, + 88, 88, 74, 74, nil, nil, 74, 74, nil, 74, + 74, 74, 74, 74, 129, 129, nil, nil, 129, 129, + nil, 129, 129, 129, 129, 129 ] + +racc_action_pointer = [ + 320, 152, 129, 17, 165, 172, 137, 75, 89, 103, + 116, 135, 106, 105, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, 177, 191, 1, nil, + nil, nil, nil, 109, nil, nil, 94, nil, 243, nil, + 99, 64, 74, nil, 332, 52, nil, nil, nil, nil, + 50, 31, 45, nil, nil, 257, 36, nil, nil, 283, + 22, nil, 16, nil, nil, nil, -3, -10, -12, nil, + 103, 62, -8, 15, 368, 0, 230, 320, nil, nil, + 47, nil, nil, nil, nil, nil, 4, nil, 356, 50, + 146, nil, nil, nil, 270, nil, 65, 56, 52, nil, + 57, 62, 79, nil, 68, 81, nil, nil, 77, nil, + nil, 80, 96, 344, 296, nil, nil, 108, nil, nil, + nil, 98, 217, nil, nil, nil, -19, 163, nil, 380, + 128, 116, nil, nil, 14, 124, -26, nil, 128, 141, + 148, 141, 152, 7, nil, nil, nil, nil, 160, nil, + nil, 149, 31, nil, nil, 204, nil, 167, nil, 174, + nil, nil, nil, 169, 184, nil, nil, nil ] + +racc_action_default = [ + -110, -110, -110, -110, -14, -110, -20, -110, -110, -110, + -110, -110, -110, -110, -10, -95, -106, -107, -77, -44, + -108, -11, -109, -79, -43, -103, -110, -110, -60, -104, + -55, -105, -78, -68, -54, -71, -45, -12, -110, -1, + -110, -110, -110, -2, -110, -22, -51, -48, -50, -3, + -40, -41, -110, -46, -4, -86, -5, -88, -6, -90, + -110, -7, -95, -8, -9, -99, -101, -61, -59, -56, + -69, -110, -110, -110, -110, -75, -110, -110, -57, -15, + -110, 168, -73, -80, -82, -21, -24, -81, -110, -27, + -110, -83, -47, -89, -110, -91, -110, -101, -110, -100, + -102, -75, -58, -52, -110, -110, -64, -63, -65, -76, + -72, -67, -110, -110, -110, -26, -23, -110, -29, -49, + -84, -42, -87, -92, -94, -95, -110, -110, -62, -110, + -110, -25, -74, -28, -31, -101, -110, -53, -66, -110, + -110, -34, -110, -110, -93, -96, -98, -97, -110, -18, + -13, -38, -110, -30, -33, -110, -32, -16, -19, -14, + -35, -36, -37, -110, -110, -39, -85, -17 ] + +racc_goto_table = [ + 39, 67, 70, 73, 24, 37, 69, 66, 36, 38, + 57, 59, 55, 67, 108, 83, 90, 111, 69, 99, + 85, 49, 53, 76, 158, 134, 141, 70, 73, 151, + 118, 89, 45, 156, 160, 150, 140, 21, 14, 19, + 119, 102, 64, 63, 61, 83, 70, 104, 83, 58, + 124, 132, 56, 131, 97, 54, 93, 43, 5, 83, + 95, 145, 76, nil, 116, 76, nil, nil, 127, 138, + 103, nil, nil, nil, 38, nil, nil, 110, nil, nil, + nil, nil, nil, nil, 83, 83, nil, nil, 144, nil, + nil, nil, nil, nil, nil, 57, 121, 122, nil, nil, + 83, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 135, nil, nil, + nil, nil, nil, 93, nil, nil, nil, 70, 162, 137, + 70, 163, 161, 38, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 165 ] + +racc_goto_check = [ + 2, 37, 37, 29, 13, 13, 28, 46, 31, 36, + 41, 41, 45, 37, 25, 44, 32, 25, 28, 47, + 24, 4, 4, 42, 23, 20, 21, 37, 29, 22, + 19, 18, 17, 26, 27, 16, 15, 12, 11, 33, + 34, 35, 10, 9, 8, 44, 37, 29, 44, 7, + 47, 43, 6, 25, 46, 5, 41, 3, 1, 44, + 41, 48, 42, nil, 24, 42, nil, nil, 32, 25, + 13, nil, nil, nil, 36, nil, nil, 41, nil, nil, + nil, nil, nil, nil, 44, 44, nil, nil, 47, nil, + nil, nil, nil, nil, nil, 41, 31, 45, nil, nil, + 44, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, 46, nil, nil, + nil, nil, nil, 41, nil, nil, nil, 37, 29, 13, + 37, 29, 28, 36, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 2 ] + +racc_goto_pointer = [ + nil, 58, -4, 51, 14, 47, 43, 39, 33, 31, + 29, 37, 35, 2, nil, -94, -105, 26, -14, -59, + -93, -108, -112, -127, -24, -60, -110, -118, -20, -24, + nil, 6, -34, 37, -50, -27, 6, -25, nil, nil, + nil, 1, -5, -63, -29, 3, -8, -47, -75 ] + +racc_goto_default = [ + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, 48, 41, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, 86, nil, nil, 30, 34, + 50, 51, nil, 46, 47, nil, 26, 28, 71, 72, + 33, 35, 114, 82, 18, nil, nil, nil, nil ] + +racc_token_table = { + false => 0, + Object.new => 1, + :DATETIME => 2, + :RECEIVED => 3, + :MADDRESS => 4, + :RETPATH => 5, + :KEYWORDS => 6, + :ENCRYPTED => 7, + :MIMEVERSION => 8, + :CTYPE => 9, + :CENCODING => 10, + :CDISPOSITION => 11, + :ADDRESS => 12, + :MAILBOX => 13, + :DIGIT => 14, + :ATOM => 15, + "," => 16, + ":" => 17, + :FROM => 18, + :BY => 19, + "@" => 20, + :DOMLIT => 21, + :VIA => 22, + :WITH => 23, + :ID => 24, + :FOR => 25, + ";" => 26, + "<" => 27, + ">" => 28, + "." => 29, + :QUOTED => 30, + :TOKEN => 31, + "/" => 32, + "=" => 33 } + +racc_use_result_var = false + +racc_nt_base = 34 + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] + +Racc_token_to_s_table = [ +'$end', +'error', +'DATETIME', +'RECEIVED', +'MADDRESS', +'RETPATH', +'KEYWORDS', +'ENCRYPTED', +'MIMEVERSION', +'CTYPE', +'CENCODING', +'CDISPOSITION', +'ADDRESS', +'MAILBOX', +'DIGIT', +'ATOM', +'","', +'":"', +'FROM', +'BY', +'"@"', +'DOMLIT', +'VIA', +'WITH', +'ID', +'FOR', +'";"', +'"<"', +'">"', +'"."', +'QUOTED', +'TOKEN', +'"/"', +'"="', +'$start', +'content', +'datetime', +'received', +'addrs_TOP', +'retpath', +'keys', +'enc', +'version', +'ctype', +'cencode', +'cdisp', +'addr_TOP', +'mbox', +'day', +'hour', +'zone', +'from', +'by', +'via', +'with', +'id', +'for', +'received_datetime', +'received_domain', +'domain', +'msgid', +'received_addrspec', +'routeaddr', +'spec', +'addrs', +'group_bare', +'commas', +'group', +'addr', +'mboxes', +'addr_phrase', +'local_head', +'routes', +'at_domains', +'local', +'word', +'dots', +'domword', +'atom', +'phrase', +'params', +'opt_semicolon', +'value'] + +Racc_debug_parser = false + +##### racc system variables end ##### + + # reduce 0 omitted + +module_eval <<'.,.,', 'parser.y', 16 + def _reduce_1( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 17 + def _reduce_2( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 18 + def _reduce_3( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 19 + def _reduce_4( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 20 + def _reduce_5( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 21 + def _reduce_6( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 22 + def _reduce_7( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 23 + def _reduce_8( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 24 + def _reduce_9( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 25 + def _reduce_10( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 26 + def _reduce_11( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 27 + def _reduce_12( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 33 + def _reduce_13( val, _values) + t = Time.gm(val[3].to_i, val[2], val[1].to_i, 0, 0, 0) + (t + val[4] - val[5]).localtime + end +.,., + + # reduce 14 omitted + + # reduce 15 omitted + +module_eval <<'.,.,', 'parser.y', 42 + def _reduce_16( val, _values) + (val[0].to_i * 60 * 60) + + (val[2].to_i * 60) + end +.,., + +module_eval <<'.,.,', 'parser.y', 47 + def _reduce_17( val, _values) + (val[0].to_i * 60 * 60) + + (val[2].to_i * 60) + + (val[4].to_i) + end +.,., + +module_eval <<'.,.,', 'parser.y', 54 + def _reduce_18( val, _values) + timezone_string_to_unixtime(val[0]) + end +.,., + +module_eval <<'.,.,', 'parser.y', 59 + def _reduce_19( val, _values) + val + end +.,., + + # reduce 20 omitted + +module_eval <<'.,.,', 'parser.y', 65 + def _reduce_21( val, _values) + val[1] + end +.,., + + # reduce 22 omitted + +module_eval <<'.,.,', 'parser.y', 71 + def _reduce_23( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 77 + def _reduce_24( val, _values) + join_domain(val[0]) + end +.,., + +module_eval <<'.,.,', 'parser.y', 81 + def _reduce_25( val, _values) + join_domain(val[2]) + end +.,., + +module_eval <<'.,.,', 'parser.y', 85 + def _reduce_26( val, _values) + join_domain(val[0]) + end +.,., + + # reduce 27 omitted + +module_eval <<'.,.,', 'parser.y', 91 + def _reduce_28( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 96 + def _reduce_29( val, _values) + [] + end +.,., + +module_eval <<'.,.,', 'parser.y', 100 + def _reduce_30( val, _values) + val[0].push val[2] + val[0] + end +.,., + + # reduce 31 omitted + +module_eval <<'.,.,', 'parser.y', 107 + def _reduce_32( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 111 + def _reduce_33( val, _values) + val[1] + end +.,., + + # reduce 34 omitted + +module_eval <<'.,.,', 'parser.y', 117 + def _reduce_35( val, _values) + val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 123 + def _reduce_36( val, _values) + val[0].spec + end +.,., + +module_eval <<'.,.,', 'parser.y', 127 + def _reduce_37( val, _values) + val[0].spec + end +.,., + + # reduce 38 omitted + +module_eval <<'.,.,', 'parser.y', 134 + def _reduce_39( val, _values) + val[1] + end +.,., + + # reduce 40 omitted + + # reduce 41 omitted + + # reduce 42 omitted + + # reduce 43 omitted + + # reduce 44 omitted + + # reduce 45 omitted + + # reduce 46 omitted + +module_eval <<'.,.,', 'parser.y', 146 + def _reduce_47( val, _values) + [ Address.new(nil, nil) ] + end +.,., + +module_eval <<'.,.,', 'parser.y', 148 + def _reduce_48( val, _values) + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 149 + def _reduce_49( val, _values) + val[0].push val[2]; val[0] + end +.,., + + # reduce 50 omitted + + # reduce 51 omitted + +module_eval <<'.,.,', 'parser.y', 156 + def _reduce_52( val, _values) + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 160 + def _reduce_53( val, _values) + val[0].push val[2] + val[0] + end +.,., + + # reduce 54 omitted + + # reduce 55 omitted + +module_eval <<'.,.,', 'parser.y', 168 + def _reduce_56( val, _values) + val[1].phrase = Decoder.decode(val[0]) + val[1] + end +.,., + + # reduce 57 omitted + +module_eval <<'.,.,', 'parser.y', 176 + def _reduce_58( val, _values) + AddressGroup.new(val[0], val[2]) + end +.,., + +module_eval <<'.,.,', 'parser.y', 178 + def _reduce_59( val, _values) + AddressGroup.new(val[0], []) + end +.,., + +module_eval <<'.,.,', 'parser.y', 181 + def _reduce_60( val, _values) + val[0].join('.') + end +.,., + +module_eval <<'.,.,', 'parser.y', 182 + def _reduce_61( val, _values) + val[0] << ' ' << val[1].join('.') + end +.,., + +module_eval <<'.,.,', 'parser.y', 186 + def _reduce_62( val, _values) + val[2].routes.replace val[1] + val[2] + end +.,., + +module_eval <<'.,.,', 'parser.y', 191 + def _reduce_63( val, _values) + val[1] + end +.,., + + # reduce 64 omitted + +module_eval <<'.,.,', 'parser.y', 196 + def _reduce_65( val, _values) + [ val[1].join('.') ] + end +.,., + +module_eval <<'.,.,', 'parser.y', 197 + def _reduce_66( val, _values) + val[0].push val[3].join('.'); val[0] + end +.,., + +module_eval <<'.,.,', 'parser.y', 199 + def _reduce_67( val, _values) + Address.new( val[0], val[2] ) + end +.,., + +module_eval <<'.,.,', 'parser.y', 200 + def _reduce_68( val, _values) + Address.new( val[0], nil ) + end +.,., + + # reduce 69 omitted + +module_eval <<'.,.,', 'parser.y', 203 + def _reduce_70( val, _values) + val[0].push ''; val[0] + end +.,., + +module_eval <<'.,.,', 'parser.y', 206 + def _reduce_71( val, _values) + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 209 + def _reduce_72( val, _values) + val[1].times do + val[0].push '' + end + val[0].push val[2] + val[0] + end +.,., + +module_eval <<'.,.,', 'parser.y', 217 + def _reduce_73( val, _values) + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 220 + def _reduce_74( val, _values) + val[1].times do + val[0].push '' + end + val[0].push val[2] + val[0] + end +.,., + +module_eval <<'.,.,', 'parser.y', 227 + def _reduce_75( val, _values) + 0 + end +.,., + +module_eval <<'.,.,', 'parser.y', 228 + def _reduce_76( val, _values) + 1 + end +.,., + + # reduce 77 omitted + + # reduce 78 omitted + + # reduce 79 omitted + + # reduce 80 omitted + + # reduce 81 omitted + + # reduce 82 omitted + + # reduce 83 omitted + + # reduce 84 omitted + +module_eval <<'.,.,', 'parser.y', 243 + def _reduce_85( val, _values) + val[1] = val[1].spec + val.join('') + end +.,., + +module_eval <<'.,.,', 'parser.y', 247 + def _reduce_86( val, _values) + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 248 + def _reduce_87( val, _values) + val[0].push val[2]; val[0] + end +.,., + + # reduce 88 omitted + +module_eval <<'.,.,', 'parser.y', 251 + def _reduce_89( val, _values) + val[0] << ' ' << val[1] + end +.,., + +module_eval <<'.,.,', 'parser.y', 255 + def _reduce_90( val, _values) + val.push nil + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 260 + def _reduce_91( val, _values) + val + end +.,., + +module_eval <<'.,.,', 'parser.y', 265 + def _reduce_92( val, _values) + [ val[0].to_i, val[2].to_i ] + end +.,., + +module_eval <<'.,.,', 'parser.y', 270 + def _reduce_93( val, _values) + [ val[0].downcase, val[2].downcase, decode_params(val[3]) ] + end +.,., + +module_eval <<'.,.,', 'parser.y', 274 + def _reduce_94( val, _values) + [ val[0].downcase, nil, decode_params(val[1]) ] + end +.,., + +module_eval <<'.,.,', 'parser.y', 279 + def _reduce_95( val, _values) + {} + end +.,., + +module_eval <<'.,.,', 'parser.y', 283 + def _reduce_96( val, _values) + val[0][ val[2].downcase ] = val[4] + val[0] + end +.,., + + # reduce 97 omitted + + # reduce 98 omitted + +module_eval <<'.,.,', 'parser.y', 292 + def _reduce_99( val, _values) + val[0].downcase + end +.,., + +module_eval <<'.,.,', 'parser.y', 297 + def _reduce_100( val, _values) + [ val[0].downcase, decode_params(val[1]) ] + end +.,., + + # reduce 101 omitted + + # reduce 102 omitted + + # reduce 103 omitted + + # reduce 104 omitted + + # reduce 105 omitted + + # reduce 106 omitted + + # reduce 107 omitted + + # reduce 108 omitted + + # reduce 109 omitted + + def _reduce_none( val, _values) + val[0] + end + + end # class Parser + +end # module TMail +# +# port.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/stringio' + + +module TMail + + class Port + def reproducible? + false + end + end + + + ### + ### FilePort + ### + + class FilePort < Port + + def initialize( fname ) + @filename = File.expand_path(fname) + super() + end + + attr_reader :filename + + alias ident filename + + def ==( other ) + other.respond_to?(:filename) and @filename == other.filename + end + + alias eql? == + + def hash + @filename.hash + end + + def inspect + "#<#{self.class}:#{@filename}>" + end + + def reproducible? + true + end + + def size + File.size @filename + end + + + def ropen( &block ) + File.open(@filename, &block) + end + + def wopen( &block ) + File.open(@filename, 'w', &block) + end + + def aopen( &block ) + File.open(@filename, 'a', &block) + end + + + def read_all + ropen {|f| + return f.read + } + end + + + def remove + File.unlink @filename + end + + def move_to( port ) + begin + File.link @filename, port.filename + rescue Errno::EXDEV + copy_to port + end + File.unlink @filename + end + + alias mv move_to + + def copy_to( port ) + if FilePort === port + copy_file @filename, port.filename + else + File.open(@filename) {|r| + port.wopen {|w| + while s = r.sysread(4096) + w.write << s + end + } } + end + end + + alias cp copy_to + + private + + # from fileutils.rb + def copy_file( src, dest ) + st = r = w = nil + + File.open(src, 'rb') {|r| + File.open(dest, 'wb') {|w| + st = r.stat + begin + while true + w.write r.sysread(st.blksize) + end + rescue EOFError + end + } } + end + + end + + + module MailFlags + + def seen=( b ) + set_status 'S', b + end + + def seen? + get_status 'S' + end + + def replied=( b ) + set_status 'R', b + end + + def replied? + get_status 'R' + end + + def flagged=( b ) + set_status 'F', b + end + + def flagged? + get_status 'F' + end + + private + + def procinfostr( str, tag, true_p ) + a = str.upcase.split(//) + a.push true_p ? tag : nil + a.delete tag unless true_p + a.compact.sort.join('').squeeze + end + + end + + + class MhPort < FilePort + + include MailFlags + + private + + def set_status( tag, flag ) + begin + tmpfile = @filename + '.tmailtmp.' + $$.to_s + File.open(tmpfile, 'w') {|f| + write_status f, tag, flag + } + File.unlink @filename + File.link tmpfile, @filename + ensure + File.unlink tmpfile + end + end + + def write_status( f, tag, flag ) + stat = '' + File.open(@filename) {|r| + while line = r.gets + if line.strip.empty? + break + elsif m = /\AX-TMail-Status:/i.match(line) + stat = m.post_match.strip + else + f.print line + end + end + + s = procinfostr(stat, tag, flag) + f.puts 'X-TMail-Status: ' + s unless s.empty? + f.puts + + while s = r.read(2048) + f.write s + end + } + end + + def get_status( tag ) + File.foreach(@filename) {|line| + return false if line.strip.empty? + if m = /\AX-TMail-Status:/i.match(line) + return m.post_match.strip.include?(tag[0]) + end + } + false + end + + end + + + class MaildirPort < FilePort + + def move_to_new + new = replace_dir(@filename, 'new') + File.rename @filename, new + @filename = new + end + + def move_to_cur + new = replace_dir(@filename, 'cur') + File.rename @filename, new + @filename = new + end + + def replace_dir( path, dir ) + "#{File.dirname File.dirname(path)}/#{dir}/#{File.basename path}" + end + private :replace_dir + + + include MailFlags + + private + + MAIL_FILE = /\A(\d+\.[\d_]+\.[^:]+)(?:\:(\d),(\w+)?)?\z/ + + def set_status( tag, flag ) + if m = MAIL_FILE.match(File.basename(@filename)) + s, uniq, type, info, = m.to_a + return if type and type != '2' # do not change anything + newname = File.dirname(@filename) + '/' + + uniq + ':2,' + procinfostr(info.to_s, tag, flag) + else + newname = @filename + ':2,' + tag + end + + File.link @filename, newname + File.unlink @filename + @filename = newname + end + + def get_status( tag ) + m = MAIL_FILE.match(File.basename(@filename)) or return false + m[2] == '2' and m[3].to_s.include?(tag[0]) + end + + end + + + ### + ### StringPort + ### + + class StringPort < Port + + def initialize( str = '' ) + @buffer = str + super() + end + + def string + @buffer + end + + def to_s + @buffer.dup + end + + alias read_all to_s + + def size + @buffer.size + end + + def ==( other ) + StringPort === other and @buffer.equal? other.string + end + + alias eql? == + + def hash + @buffer.object_id.hash + end + + def inspect + "#<#{self.class}:id=#{sprintf '0x%x', @buffer.object_id}>" + end + + def reproducible? + true + end + + def ropen( &block ) + @buffer or raise Errno::ENOENT, "#{inspect} is already removed" + StringInput.open(@buffer, &block) + end + + def wopen( &block ) + @buffer = '' + StringOutput.new(@buffer, &block) + end + + def aopen( &block ) + @buffer ||= '' + StringOutput.new(@buffer, &block) + end + + def remove + @buffer = nil + end + + alias rm remove + + def copy_to( port ) + port.wopen {|f| + f.write @buffer + } + end + + alias cp copy_to + + def move_to( port ) + if StringPort === port + str = @buffer + port.instance_eval { @buffer = str } + else + copy_to port + end + remove + end + + end + +end # module TMail +module TMail + class Mail + def subject(to_charset = 'utf-8') + Unquoter.unquote_and_convert_to(quoted_subject, to_charset) + end + + def unquoted_body(to_charset = 'utf-8') + from_charset = sub_header("content-type", "charset") + case (content_transfer_encoding || "7bit").downcase + when "quoted-printable" + Unquoter.unquote_quoted_printable_and_convert_to(quoted_body, + to_charset, from_charset, true) + when "base64" + Unquoter.unquote_base64_and_convert_to(quoted_body, to_charset, + from_charset) + when "7bit", "8bit" + Unquoter.convert_to(quoted_body, to_charset, from_charset) + when "binary" + quoted_body + else + quoted_body + end + end + + def body(to_charset = 'utf-8', &block) + attachment_presenter = block || Proc.new { |file_name| "Attachment: #{file_name}\n" } + + if multipart? + parts.collect { |part| + header = part["content-type"] + + if part.multipart? + part.body(to_charset, &attachment_presenter) + elsif header.nil? + "" + elsif !attachment?(part) + part.unquoted_body(to_charset) + else + attachment_presenter.call(header["name"] || "(unnamed)") + end + }.join + else + unquoted_body(to_charset) + end + end + end + + class Unquoter + class << self + def unquote_and_convert_to(text, to_charset, from_charset = "iso-8859-1", preserve_underscores=false) + return "" if text.nil? + if text =~ /^=\?(.*?)\?(.)\?(.*)\?=$/ + from_charset = $1 + quoting_method = $2 + text = $3 + case quoting_method.upcase + when "Q" then + unquote_quoted_printable_and_convert_to(text, to_charset, from_charset, preserve_underscores) + when "B" then + unquote_base64_and_convert_to(text, to_charset, from_charset) + else + raise "unknown quoting method #{quoting_method.inspect}" + end + else + convert_to(text, to_charset, from_charset) + end + end + + def unquote_quoted_printable_and_convert_to(text, to, from, preserve_underscores=false) + text = text.gsub(/_/, " ") unless preserve_underscores + convert_to(text.unpack("M*").first, to, from) + end + + def unquote_base64_and_convert_to(text, to, from) + convert_to(Base64.decode(text).first, to, from) + end + + begin + require 'iconv' + def convert_to(text, to, from) + return text unless to && from + text ? Iconv.iconv(to, from, text).first : "" + rescue Iconv::IllegalSequence, Errno::EINVAL + # the 'from' parameter specifies a charset other than what the text + # actually is...not much we can do in this case but just return the + # unconverted text. + # + # Ditto if either parameter represents an unknown charset, like + # X-UNKNOWN. + text + end + rescue LoadError + # Not providing quoting support + def convert_to(text, to, from) + warn "Action Mailer: iconv not loaded; ignoring conversion from #{from} to #{to} (#{__FILE__}:#{__LINE__})" + text + end + end + end + end +end + +if __FILE__ == $0 + require 'test/unit' + + class TC_Unquoter < Test::Unit::TestCase + def test_unquote_quoted_printable + a ="=?ISO-8859-1?Q?[166417]_Bekr=E6ftelse_fra_Rejsefeber?=" + b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8') + assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b + end + + def test_unquote_base64 + a ="=?ISO-8859-1?B?WzE2NjQxN10gQmVrcuZmdGVsc2UgZnJhIFJlanNlZmViZXI=?=" + b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8') + assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b + end + + def test_unquote_without_charset + a ="[166417]_Bekr=E6ftelse_fra_Rejsefeber" + b = TMail::Unquoter.unquote_and_convert_to(a, 'utf-8') + assert_equal "[166417]_Bekr=E6ftelse_fra_Rejsefeber", b + end + end +end +# +# scanner.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/utils' + +module TMail + require 'tmail/scanner_r.rb' + begin + raise LoadError, 'Turn off Ruby extention by user choice' if ENV['NORUBYEXT'] + require 'tmail/scanner_c.so' + Scanner = Scanner_C + rescue LoadError + Scanner = Scanner_R + end +end +# +# scanner_r.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +require 'tmail/config' + + +module TMail + + class Scanner_R + + Version = '0.10.7' + Version.freeze + + MIME_HEADERS = { + :CTYPE => true, + :CENCODING => true, + :CDISPOSITION => true + } + + alnum = 'a-zA-Z0-9' + atomsyms = %q[ _#!$%&`'*+-{|}~^@/=? ].strip + tokensyms = %q[ _#!$%&`'*+-{|}~^@. ].strip + + atomchars = alnum + Regexp.quote(atomsyms) + tokenchars = alnum + Regexp.quote(tokensyms) + iso2022str = '\e(?!\(B)..(?:[^\e]+|\e(?!\(B)..)*\e\(B' + + eucstr = '(?:[\xa1-\xfe][\xa1-\xfe])+' + sjisstr = '(?:[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc])+' + utf8str = '(?:[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf][\x80-\xbf])+' + + quoted_with_iso2022 = /\A(?:[^\\\e"]+|#{iso2022str})+/n + domlit_with_iso2022 = /\A(?:[^\\\e\]]+|#{iso2022str})+/n + comment_with_iso2022 = /\A(?:[^\\\e()]+|#{iso2022str})+/n + + quoted_without_iso2022 = /\A[^\\"]+/n + domlit_without_iso2022 = /\A[^\\\]]+/n + comment_without_iso2022 = /\A[^\\()]+/n + + PATTERN_TABLE = {} + PATTERN_TABLE['EUC'] = + [ + /\A(?:[#{atomchars}]+|#{iso2022str}|#{eucstr})+/n, + /\A(?:[#{tokenchars}]+|#{iso2022str}|#{eucstr})+/n, + quoted_with_iso2022, + domlit_with_iso2022, + comment_with_iso2022 + ] + PATTERN_TABLE['SJIS'] = + [ + /\A(?:[#{atomchars}]+|#{iso2022str}|#{sjisstr})+/n, + /\A(?:[#{tokenchars}]+|#{iso2022str}|#{sjisstr})+/n, + quoted_with_iso2022, + domlit_with_iso2022, + comment_with_iso2022 + ] + PATTERN_TABLE['UTF8'] = + [ + /\A(?:[#{atomchars}]+|#{utf8str})+/n, + /\A(?:[#{tokenchars}]+|#{utf8str})+/n, + quoted_without_iso2022, + domlit_without_iso2022, + comment_without_iso2022 + ] + PATTERN_TABLE['NONE'] = + [ + /\A[#{atomchars}]+/n, + /\A[#{tokenchars}]+/n, + quoted_without_iso2022, + domlit_without_iso2022, + comment_without_iso2022 + ] + + + def initialize( str, scantype, comments ) + init_scanner str + @comments = comments || [] + @debug = false + + # fix scanner mode + @received = (scantype == :RECEIVED) + @is_mime_header = MIME_HEADERS[scantype] + + atom, token, @quoted_re, @domlit_re, @comment_re = PATTERN_TABLE[$KCODE] + @word_re = (MIME_HEADERS[scantype] ? token : atom) + end + + attr_accessor :debug + + def scan( &block ) + if @debug + scan_main do |arr| + s, v = arr + printf "%7d %-10s %s\n", + rest_size(), + s.respond_to?(:id2name) ? s.id2name : s.inspect, + v.inspect + yield arr + end + else + scan_main(&block) + end + end + + private + + RECV_TOKEN = { + 'from' => :FROM, + 'by' => :BY, + 'via' => :VIA, + 'with' => :WITH, + 'id' => :ID, + 'for' => :FOR + } + + def scan_main + until eof? + if skip(/\A[\n\r\t ]+/n) # LWSP + break if eof? + end + + if s = readstr(@word_re) + if @is_mime_header + yield :TOKEN, s + else + # atom + if /\A\d+\z/ === s + yield :DIGIT, s + elsif @received + yield RECV_TOKEN[s.downcase] || :ATOM, s + else + yield :ATOM, s + end + end + + elsif skip(/\A"/) + yield :QUOTED, scan_quoted_word() + + elsif skip(/\A\[/) + yield :DOMLIT, scan_domain_literal() + + elsif skip(/\A\(/) + @comments.push scan_comment() + + else + c = readchar() + yield c, c + end + end + + yield false, '$' + end + + def scan_quoted_word + scan_qstr(@quoted_re, /\A"/, 'quoted-word') + end + + def scan_domain_literal + '[' + scan_qstr(@domlit_re, /\A\]/, 'domain-literal') + ']' + end + + def scan_qstr( pattern, terminal, type ) + result = '' + until eof? + if s = readstr(pattern) then result << s + elsif skip(terminal) then return result + elsif skip(/\A\\/) then result << readchar() + else + raise "TMail FATAL: not match in #{type}" + end + end + scan_error! "found unterminated #{type}" + end + + def scan_comment + result = '' + nest = 1 + content = @comment_re + + until eof? + if s = readstr(content) then result << s + elsif skip(/\A\)/) then nest -= 1 + return result if nest == 0 + result << ')' + elsif skip(/\A\(/) then nest += 1 + result << '(' + elsif skip(/\A\\/) then result << readchar() + else + raise 'TMail FATAL: not match in comment' + end + end + scan_error! 'found unterminated comment' + end + + # string scanner + + def init_scanner( str ) + @src = str + end + + def eof? + @src.empty? + end + + def rest_size + @src.size + end + + def readstr( re ) + if m = re.match(@src) + @src = m.post_match + m[0] + else + nil + end + end + + def readchar + readstr(/\A./) + end + + def skip( re ) + if m = re.match(@src) + @src = m.post_match + true + else + false + end + end + + def scan_error!( msg ) + raise SyntaxError, msg + end + + end + +end # module TMail +# +# stringio.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +class StringInput#:nodoc: + + include Enumerable + + class << self + + def new( str ) + if block_given? + begin + f = super + yield f + ensure + f.close if f + end + else + super + end + end + + alias open new + + end + + def initialize( str ) + @src = str + @pos = 0 + @closed = false + @lineno = 0 + end + + attr_reader :lineno + + def string + @src + end + + def inspect + "#<#{self.class}:#{@closed ? 'closed' : 'open'},src=#{@src[0,30].inspect}>" + end + + def close + stream_check! + @pos = nil + @closed = true + end + + def closed? + @closed + end + + def pos + stream_check! + [@pos, @src.size].min + end + + alias tell pos + + def seek( offset, whence = IO::SEEK_SET ) + stream_check! + case whence + when IO::SEEK_SET + @pos = offset + when IO::SEEK_CUR + @pos += offset + when IO::SEEK_END + @pos = @src.size - offset + else + raise ArgumentError, "unknown seek flag: #{whence}" + end + @pos = 0 if @pos < 0 + @pos = [@pos, @src.size + 1].min + offset + end + + def rewind + stream_check! + @pos = 0 + end + + def eof? + stream_check! + @pos > @src.size + end + + def each( &block ) + stream_check! + begin + @src.each(&block) + ensure + @pos = 0 + end + end + + def gets + stream_check! + if idx = @src.index(?\n, @pos) + idx += 1 # "\n".size + line = @src[ @pos ... idx ] + @pos = idx + @pos += 1 if @pos == @src.size + else + line = @src[ @pos .. -1 ] + @pos = @src.size + 1 + end + @lineno += 1 + + line + end + + def getc + stream_check! + ch = @src[@pos] + @pos += 1 + @pos += 1 if @pos == @src.size + ch + end + + def read( len = nil ) + stream_check! + return read_all unless len + str = @src[@pos, len] + @pos += len + @pos += 1 if @pos == @src.size + str + end + + alias sysread read + + def read_all + stream_check! + return nil if eof? + rest = @src[@pos ... @src.size] + @pos = @src.size + 1 + rest + end + + def stream_check! + @closed and raise IOError, 'closed stream' + end + +end + + +class StringOutput#:nodoc: + + class << self + + def new( str = '' ) + if block_given? + begin + f = super + yield f + ensure + f.close if f + end + else + super + end + end + + alias open new + + end + + def initialize( str = '' ) + @dest = str + @closed = false + end + + def close + @closed = true + end + + def closed? + @closed + end + + def string + @dest + end + + alias value string + alias to_str string + + def size + @dest.size + end + + alias pos size + + def inspect + "#<#{self.class}:#{@dest ? 'open' : 'closed'},#{id}>" + end + + def print( *args ) + stream_check! + raise ArgumentError, 'wrong # of argument (0 for >1)' if args.empty? + args.each do |s| + raise ArgumentError, 'nil not allowed' if s.nil? + @dest << s.to_s + end + nil + end + + def puts( *args ) + stream_check! + args.each do |str| + @dest << (s = str.to_s) + @dest << "\n" unless s[-1] == ?\n + end + @dest << "\n" if args.empty? + nil + end + + def putc( ch ) + stream_check! + @dest << ch.chr + nil + end + + def printf( *args ) + stream_check! + @dest << sprintf(*args) + nil + end + + def write( str ) + stream_check! + s = str.to_s + @dest << s + s.size + end + + alias syswrite write + + def <<( str ) + stream_check! + @dest << str.to_s + self + end + + private + + def stream_check! + @closed and raise IOError, 'closed stream' + end + +end +require 'tmail' +# +# utils.rb +# +#-- +# Copyright (c) 1998-2003 Minero Aoki <aamine@loveruby.net> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. +#++ + +module TMail + + class SyntaxError < StandardError; end + + + def TMail.new_boundary + 'mimepart_' + random_tag + end + + def TMail.new_message_id( fqdn = nil ) + fqdn ||= ::Socket.gethostname + "<#{random_tag()}@#{fqdn}.tmail>" + end + + def TMail.random_tag + @uniq += 1 + t = Time.now + sprintf('%x%x_%x%x%d%x', + t.to_i, t.tv_usec, + $$, Thread.current.object_id, @uniq, rand(255)) + end + private_class_method :random_tag + + @uniq = 0 + + + module TextUtils + + aspecial = '()<>[]:;.\\,"' + tspecial = '()<>[];:\\,"/?=' + lwsp = " \t\r\n" + control = '\x00-\x1f\x7f-\xff' + + ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n + PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n + TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n + CONTROL_CHAR = /[#{control}]/n + + def atom_safe?( str ) + not ATOM_UNSAFE === str + end + + def quote_atom( str ) + (ATOM_UNSAFE === str) ? dquote(str) : str + end + + def quote_phrase( str ) + (PHRASE_UNSAFE === str) ? dquote(str) : str + end + + def token_safe?( str ) + not TOKEN_UNSAFE === str + end + + def quote_token( str ) + (TOKEN_UNSAFE === str) ? dquote(str) : str + end + + def dquote( str ) + '"' + str.gsub(/["\\]/n) {|s| '\\' + s } + '"' + end + private :dquote + + + def join_domain( arr ) + arr.map {|i| + if /\A\[.*\]\z/ === i + i + else + quote_atom(i) + end + }.join('.') + end + + + ZONESTR_TABLE = { + 'jst' => 9 * 60, + 'eet' => 2 * 60, + 'bst' => 1 * 60, + 'met' => 1 * 60, + 'gmt' => 0, + 'utc' => 0, + 'ut' => 0, + 'nst' => -(3 * 60 + 30), + 'ast' => -4 * 60, + 'edt' => -4 * 60, + 'est' => -5 * 60, + 'cdt' => -5 * 60, + 'cst' => -6 * 60, + 'mdt' => -6 * 60, + 'mst' => -7 * 60, + 'pdt' => -7 * 60, + 'pst' => -8 * 60, + 'a' => -1 * 60, + 'b' => -2 * 60, + 'c' => -3 * 60, + 'd' => -4 * 60, + 'e' => -5 * 60, + 'f' => -6 * 60, + 'g' => -7 * 60, + 'h' => -8 * 60, + 'i' => -9 * 60, + # j not use + 'k' => -10 * 60, + 'l' => -11 * 60, + 'm' => -12 * 60, + 'n' => 1 * 60, + 'o' => 2 * 60, + 'p' => 3 * 60, + 'q' => 4 * 60, + 'r' => 5 * 60, + 's' => 6 * 60, + 't' => 7 * 60, + 'u' => 8 * 60, + 'v' => 9 * 60, + 'w' => 10 * 60, + 'x' => 11 * 60, + 'y' => 12 * 60, + 'z' => 0 * 60 + } + + def timezone_string_to_unixtime( str ) + if m = /([\+\-])(\d\d?)(\d\d)/.match(str) + sec = (m[2].to_i * 60 + m[3].to_i) * 60 + m[1] == '-' ? -sec : sec + else + min = ZONESTR_TABLE[str.downcase] or + raise SyntaxError, "wrong timezone format '#{str}'" + min * 60 + end + end + + + WDAY = %w( Sun Mon Tue Wed Thu Fri Sat TMailBUG ) + MONTH = %w( TMailBUG Jan Feb Mar Apr May Jun + Jul Aug Sep Oct Nov Dec TMailBUG ) + + def time2str( tm ) + # [ruby-list:7928] + gmt = Time.at(tm.to_i) + gmt.gmtime + offset = tm.to_i - Time.local(*gmt.to_a[0,6].reverse).to_i + + # DO NOT USE strftime: setlocale() breaks it + sprintf '%s, %s %s %d %02d:%02d:%02d %+.2d%.2d', + WDAY[tm.wday], tm.mday, MONTH[tm.month], + tm.year, tm.hour, tm.min, tm.sec, + *(offset / 60).divmod(60) + end + + + MESSAGE_ID = /<[^\@>]+\@[^>\@]+>/ + + def message_id?( str ) + MESSAGE_ID === str + end + + + MIME_ENCODED = /=\?[^\s?=]+\?[QB]\?[^\s?=]+\?=/i + + def mime_encoded?( str ) + MIME_ENCODED === str + end + + + def decode_params( hash ) + new = Hash.new + encoded = nil + hash.each do |key, value| + if m = /\*(?:(\d+)\*)?\z/.match(key) + ((encoded ||= {})[m.pre_match] ||= [])[(m[1] || 0).to_i] = value + else + new[key] = to_kcode(value) + end + end + if encoded + encoded.each do |key, strings| + new[key] = decode_RFC2231(strings.join('')) + end + end + + new + end + + NKF_FLAGS = { + 'EUC' => '-e -m', + 'SJIS' => '-s -m' + } + + def to_kcode( str ) + flag = NKF_FLAGS[$KCODE] or return str + NKF.nkf(flag, str) + end + + RFC2231_ENCODED = /\A(?:iso-2022-jp|euc-jp|shift_jis|us-ascii)?'[a-z]*'/in + + def decode_RFC2231( str ) + m = RFC2231_ENCODED.match(str) or return str + begin + NKF.nkf(NKF_FLAGS[$KCODE], + m.post_match.gsub(/%[\da-f]{2}/in) {|s| s[1,2].hex.chr }) + rescue + m.post_match.gsub(/%[\da-f]{2}/in, "") + end + end + + end + +end +require 'tmail/info' +require 'tmail/mail' +require 'tmail/mailbox' +module ActionMailer + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 2 + TINY = 5 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end +#-- +# Copyright (c) 2004 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +begin + require 'action_controller' +rescue LoadError + begin + require File.dirname(__FILE__) + '/../../actionpack/lib/action_controller' + rescue LoadError + require 'rubygems' + require_gem 'actionpack', '>= 1.9.1' + end +end + +$:.unshift(File.dirname(__FILE__) + "/action_mailer/vendor/") + +require 'action_mailer/base' +require 'action_mailer/helpers' +require 'action_mailer/mail_helper' +require 'action_mailer/quoting' +require 'tmail' +require 'net/smtp' + +ActionMailer::Base.class_eval do + include ActionMailer::Quoting + include ActionMailer::Helpers + + helper MailHelper +end + +silence_warnings { TMail::Encoder.const_set("MAX_LINE_LEN", 200) }module TestHelper + def test_format(text) + "<em><strong><small>#{text}</small></strong></em>" + end +end +$:.unshift(File.dirname(__FILE__) + "/../lib/") +$:.unshift File.dirname(__FILE__) + "/fixtures/helpers" + +require 'test/unit' +require 'action_mailer' + +module MailerHelper + def person_name + "Mr. Joe Person" + end +end + +class HelperMailer < ActionMailer::Base + helper MailerHelper + helper :test + + def use_helper(recipient) + recipients recipient + subject "using helpers" + from "tester@example.com" + end + + def use_test_helper(recipient) + recipients recipient + subject "using helpers" + from "tester@example.com" + self.body = { :text => "emphasize me!" } + end + + def use_mail_helper(recipient) + recipients recipient + subject "using mailing helpers" + from "tester@example.com" + self.body = { :text => + "But soft! What light through yonder window breaks? It is the east, " + + "and Juliet is the sun. Arise, fair sun, and kill the envious moon, " + + "which is sick and pale with grief that thou, her maid, art far more " + + "fair than she. Be not her maid, for she is envious! Her vestal " + + "livery is but sick and green, and none but fools do wear it. Cast " + + "it off!" + } + end + + def use_helper_method(recipient) + recipients recipient + subject "using helpers" + from "tester@example.com" + self.body = { :text => "emphasize me!" } + end + + private + + def name_of_the_mailer_class + self.class.name + end + helper_method :name_of_the_mailer_class +end + +HelperMailer.template_root = File.dirname(__FILE__) + "/fixtures" + +class MailerHelperTest < Test::Unit::TestCase + def new_mail( charset="utf-8" ) + mail = TMail::Mail.new + mail.set_content_type "text", "plain", { "charset" => charset } if charset + mail + end + + def setup + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + + @recipient = 'test@localhost' + end + + def test_use_helper + mail = HelperMailer.create_use_helper(@recipient) + assert_match %r{Mr. Joe Person}, mail.encoded + end + + def test_use_test_helper + mail = HelperMailer.create_use_test_helper(@recipient) + assert_match %r{<em><strong><small>emphasize me!}, mail.encoded + end + + def test_use_helper_method + mail = HelperMailer.create_use_helper_method(@recipient) + assert_match %r{HelperMailer}, mail.encoded + end + + def test_use_mail_helper + mail = HelperMailer.create_use_mail_helper(@recipient) + assert_match %r{ But soft!}, mail.encoded + assert_match %r{east, and\n Juliet}, mail.encoded + end +end + +$:.unshift(File.dirname(__FILE__) + "/../lib/") + +require 'test/unit' +require 'action_mailer' + +class RenderMailer < ActionMailer::Base + def inline_template(recipient) + recipients recipient + subject "using helpers" + from "tester@example.com" + body render(:inline => "Hello, <%= @world %>", :body => { :world => "Earth" }) + end + + def file_template(recipient) + recipients recipient + subject "using helpers" + from "tester@example.com" + body render(:file => "signed_up", :body => { :recipient => recipient }) + end + + def initialize_defaults(method_name) + super + mailer_name "test_mailer" + end +end + +RenderMailer.template_root = File.dirname(__FILE__) + "/fixtures" + +class RenderHelperTest < Test::Unit::TestCase + def setup + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + + @recipient = 'test@localhost' + end + + def test_inline_template + mail = RenderMailer.create_inline_template(@recipient) + assert_equal "Hello, Earth", mail.body.strip + end + + def test_file_template + mail = RenderMailer.create_file_template(@recipient) + assert_equal "Hello there, \n\nMr. test@localhost", mail.body.strip + end +end + +$:.unshift(File.dirname(__FILE__) + "/../lib/") + +require 'test/unit' +require 'action_mailer' + +class MockSMTP + def self.deliveries + @@deliveries + end + + def initialize + @@deliveries = [] + end + + def sendmail(mail, from, to) + @@deliveries << [mail, from, to] + end +end + +class Net::SMTP + def self.start(*args) + yield MockSMTP.new + end +end + +class FunkyPathMailer < ActionMailer::Base + self.template_root = "#{File.dirname(__FILE__)}/fixtures/path.with.dots" + + def multipart_with_template_path_with_dots(recipient) + recipients recipient + subject "Have a lovely picture" + from "Chad Fowler <chad@chadfowler.com>" + attachment :content_type => "image/jpeg", + :body => "not really a jpeg, we're only testing, after all" + end + + def template_path + "#{File.dirname(__FILE__)}/fixtures/path.with.dots" + end +end + +class TestMailer < ActionMailer::Base + + def signed_up(recipient) + @recipients = recipient + @subject = "[Signed up] Welcome #{recipient}" + @from = "system@loudthinking.com" + @sent_on = Time.local(2004, 12, 12) + @body["recipient"] = recipient + end + + def cancelled_account(recipient) + self.recipients = recipient + self.subject = "[Cancelled] Goodbye #{recipient}" + self.from = "system@loudthinking.com" + self.sent_on = Time.local(2004, 12, 12) + self.body = "Goodbye, Mr. #{recipient}" + end + + def cc_bcc(recipient) + recipients recipient + subject "testing bcc/cc" + from "system@loudthinking.com" + sent_on Time.local(2004, 12, 12) + cc "nobody@loudthinking.com" + bcc "root@loudthinking.com" + body "Nothing to see here." + end + + def iso_charset(recipient) + @recipients = recipient + @subject = "testing isø charsets" + @from = "system@loudthinking.com" + @sent_on = Time.local 2004, 12, 12 + @cc = "nobody@loudthinking.com" + @bcc = "root@loudthinking.com" + @body = "Nothing to see here." + @charset = "iso-8859-1" + end + + def unencoded_subject(recipient) + @recipients = recipient + @subject = "testing unencoded subject" + @from = "system@loudthinking.com" + @sent_on = Time.local 2004, 12, 12 + @cc = "nobody@loudthinking.com" + @bcc = "root@loudthinking.com" + @body = "Nothing to see here." + end + + def extended_headers(recipient) + @recipients = recipient + @subject = "testing extended headers" + @from = "Grytøyr <stian1@example.net>" + @sent_on = Time.local 2004, 12, 12 + @cc = "Grytøyr <stian2@example.net>" + @bcc = "Grytøyr <stian3@example.net>" + @body = "Nothing to see here." + @charset = "iso-8859-1" + end + + def utf8_body(recipient) + @recipients = recipient + @subject = "testing utf-8 body" + @from = "Foo áëô îü <extended@example.net>" + @sent_on = Time.local 2004, 12, 12 + @cc = "Foo áëô îü <extended@example.net>" + @bcc = "Foo áëô îü <extended@example.net>" + @body = "åœö blah" + @charset = "utf-8" + end + + def multipart_with_mime_version(recipient) + recipients recipient + subject "multipart with mime_version" + from "test@example.com" + sent_on Time.local(2004, 12, 12) + mime_version "1.1" + content_type "multipart/alternative" + + part "text/plain" do |p| + p.body = "blah" + end + + part "text/html" do |p| + p.body = "<b>blah</b>" + end + end + + def multipart_with_utf8_subject(recipient) + recipients recipient + subject "Foo áëô îü" + from "test@example.com" + charset "utf-8" + + part "text/plain" do |p| + p.body = "blah" + end + + part "text/html" do |p| + p.body = "<b>blah</b>" + end + end + + def explicitly_multipart_example(recipient, ct=nil) + recipients recipient + subject "multipart example" + from "test@example.com" + sent_on Time.local(2004, 12, 12) + body "plain text default" + content_type ct if ct + + part "text/html" do |p| + p.charset = "iso-8859-1" + p.body = "blah" + end + + attachment :content_type => "image/jpeg", :filename => "foo.jpg", + :body => "123456789" + end + + def implicitly_multipart_example(recipient, cs = nil, order = nil) + @recipients = recipient + @subject = "multipart example" + @from = "test@example.com" + @sent_on = Time.local 2004, 12, 12 + @body = { "recipient" => recipient } + @charset = cs if cs + @implicit_parts_order = order if order + end + + def implicitly_multipart_with_utf8 + recipients "no.one@nowhere.test" + subject "Foo áëô îü" + from "some.one@somewhere.test" + template "implicitly_multipart_example" + body ({ "recipient" => "no.one@nowhere.test" }) + end + + def html_mail(recipient) + recipients recipient + subject "html mail" + from "test@example.com" + body "<em>Emphasize</em> <strong>this</strong>" + content_type "text/html" + end + + def html_mail_with_underscores(recipient) + subject "html mail with underscores" + body %{<a href="http://google.com" target="_blank">_Google</a>} + end + + def custom_template(recipient) + recipients recipient + subject "[Signed up] Welcome #{recipient}" + from "system@loudthinking.com" + sent_on Time.local(2004, 12, 12) + template "signed_up" + + body["recipient"] = recipient + end + + def various_newlines(recipient) + recipients recipient + subject "various newlines" + from "test@example.com" + body "line #1\nline #2\rline #3\r\nline #4\r\r" + + "line #5\n\nline#6\r\n\r\nline #7" + end + + def various_newlines_multipart(recipient) + recipients recipient + subject "various newlines multipart" + from "test@example.com" + content_type "multipart/alternative" + part :content_type => "text/plain", :body => "line #1\nline #2\rline #3\r\nline #4\r\r" + part :content_type => "text/html", :body => "<p>line #1</p>\n<p>line #2</p>\r<p>line #3</p>\r\n<p>line #4</p>\r\r" + end + + def nested_multipart(recipient) + recipients recipient + subject "nested multipart" + from "test@example.com" + content_type "multipart/mixed" + part :content_type => "multipart/alternative", :content_disposition => "inline" do |p| + p.part :content_type => "text/plain", :body => "test text\nline #2" + p.part :content_type => "text/html", :body => "<b>test</b> HTML<br/>\nline #2" + end + attachment :content_type => "application/octet-stream",:filename => "test.txt", :body => "test abcdefghijklmnopqstuvwxyz" + end + + def attachment_with_custom_header(recipient) + recipients recipient + subject "custom header in attachment" + from "test@example.com" + content_type "multipart/related" + part :content_type => "text/html", :body => 'yo' + attachment :content_type => "image/jpeg",:filename => "test.jpeg", :body => "i am not a real picture", :headers => { 'Content-ID' => '<test@test.com>' } + end + + def unnamed_attachment(recipient) + recipients recipient + subject "nested multipart" + from "test@example.com" + content_type "multipart/mixed" + part :content_type => "text/plain", :body => "hullo" + attachment :content_type => "application/octet-stream", :body => "test abcdefghijklmnopqstuvwxyz" + end + + def headers_with_nonalpha_chars(recipient) + recipients recipient + subject "nonalpha chars" + from "One: Two <test@example.com>" + cc "Three: Four <test@example.com>" + bcc "Five: Six <test@example.com>" + body "testing" + end + + def custom_content_type_attributes + recipients "no.one@nowhere.test" + subject "custom content types" + from "some.one@somewhere.test" + content_type "text/plain; format=flowed" + body "testing" + end + + class <<self + attr_accessor :received_body + end + + def receive(mail) + self.class.received_body = mail.body + end +end + +TestMailer.template_root = File.dirname(__FILE__) + "/fixtures" + +class ActionMailerTest < Test::Unit::TestCase + include ActionMailer::Quoting + + def encode( text, charset="utf-8" ) + quoted_printable( text, charset ) + end + + def new_mail( charset="utf-8" ) + mail = TMail::Mail.new + if charset + mail.set_content_type "text", "plain", { "charset" => charset } + end + mail + end + + def setup + ActionMailer::Base.delivery_method = :test + ActionMailer::Base.perform_deliveries = true + ActionMailer::Base.deliveries = [] + + @recipient = 'test@localhost' + end + + def test_nested_parts + created = nil + assert_nothing_raised { created = TestMailer.create_nested_multipart(@recipient)} + assert_equal 2,created.parts.size + assert_equal 2,created.parts.first.parts.size + + assert_equal "multipart/mixed", created.content_type + assert_equal "multipart/alternative", created.parts.first.content_type + assert_equal "text/plain", created.parts.first.parts.first.content_type + assert_equal "text/html", created.parts.first.parts[1].content_type + assert_equal "application/octet-stream", created.parts[1].content_type + end + + def test_attachment_with_custom_header + created = nil + assert_nothing_raised { created = TestMailer.create_attachment_with_custom_header(@recipient)} + assert_equal "<test@test.com>", created.parts[1].header['content-id'].to_s + end + + def test_signed_up + expected = new_mail + expected.to = @recipient + expected.subject = "[Signed up] Welcome #{@recipient}" + expected.body = "Hello there, \n\nMr. #{@recipient}" + expected.from = "system@loudthinking.com" + expected.date = Time.local(2004, 12, 12) + expected.mime_version = nil + + created = nil + assert_nothing_raised { created = TestMailer.create_signed_up(@recipient) } + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised { TestMailer.deliver_signed_up(@recipient) } + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_custom_template + expected = new_mail + expected.to = @recipient + expected.subject = "[Signed up] Welcome #{@recipient}" + expected.body = "Hello there, \n\nMr. #{@recipient}" + expected.from = "system@loudthinking.com" + expected.date = Time.local(2004, 12, 12) + + created = nil + assert_nothing_raised { created = TestMailer.create_custom_template(@recipient) } + assert_not_nil created + assert_equal expected.encoded, created.encoded + end + + def test_cancelled_account + expected = new_mail + expected.to = @recipient + expected.subject = "[Cancelled] Goodbye #{@recipient}" + expected.body = "Goodbye, Mr. #{@recipient}" + expected.from = "system@loudthinking.com" + expected.date = Time.local(2004, 12, 12) + + created = nil + assert_nothing_raised { created = TestMailer.create_cancelled_account(@recipient) } + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised { TestMailer.deliver_cancelled_account(@recipient) } + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_cc_bcc + expected = new_mail + expected.to = @recipient + expected.subject = "testing bcc/cc" + expected.body = "Nothing to see here." + expected.from = "system@loudthinking.com" + expected.cc = "nobody@loudthinking.com" + expected.bcc = "root@loudthinking.com" + expected.date = Time.local 2004, 12, 12 + + created = nil + assert_nothing_raised do + created = TestMailer.create_cc_bcc @recipient + end + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_cc_bcc @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_iso_charset + expected = new_mail( "iso-8859-1" ) + expected.to = @recipient + expected.subject = encode "testing isø charsets", "iso-8859-1" + expected.body = "Nothing to see here." + expected.from = "system@loudthinking.com" + expected.cc = "nobody@loudthinking.com" + expected.bcc = "root@loudthinking.com" + expected.date = Time.local 2004, 12, 12 + + created = nil + assert_nothing_raised do + created = TestMailer.create_iso_charset @recipient + end + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_iso_charset @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_unencoded_subject + expected = new_mail + expected.to = @recipient + expected.subject = "testing unencoded subject" + expected.body = "Nothing to see here." + expected.from = "system@loudthinking.com" + expected.cc = "nobody@loudthinking.com" + expected.bcc = "root@loudthinking.com" + expected.date = Time.local 2004, 12, 12 + + created = nil + assert_nothing_raised do + created = TestMailer.create_unencoded_subject @recipient + end + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_unencoded_subject @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_instances_are_nil + assert_nil ActionMailer::Base.new + assert_nil TestMailer.new + end + + def test_deliveries_array + assert_not_nil ActionMailer::Base.deliveries + assert_equal 0, ActionMailer::Base.deliveries.size + TestMailer.deliver_signed_up(@recipient) + assert_equal 1, ActionMailer::Base.deliveries.size + assert_not_nil ActionMailer::Base.deliveries.first + end + + def test_perform_deliveries_flag + ActionMailer::Base.perform_deliveries = false + TestMailer.deliver_signed_up(@recipient) + assert_equal 0, ActionMailer::Base.deliveries.size + ActionMailer::Base.perform_deliveries = true + TestMailer.deliver_signed_up(@recipient) + assert_equal 1, ActionMailer::Base.deliveries.size + end + + def test_unquote_quoted_printable_subject + msg = <<EOF +From: me@example.com +Subject: =?utf-8?Q?testing_testing_=D6=A4?= +Content-Type: text/plain; charset=iso-8859-1 + +The body +EOF + mail = TMail::Mail.parse(msg) + assert_equal "testing testing \326\244", mail.subject + assert_equal "=?utf-8?Q?testing_testing_=D6=A4?=", mail.quoted_subject + end + + def test_unquote_7bit_subject + msg = <<EOF +From: me@example.com +Subject: this == working? +Content-Type: text/plain; charset=iso-8859-1 + +The body +EOF + mail = TMail::Mail.parse(msg) + assert_equal "this == working?", mail.subject + assert_equal "this == working?", mail.quoted_subject + end + + def test_unquote_7bit_body + msg = <<EOF +From: me@example.com +Subject: subject +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 7bit + +The=3Dbody +EOF + mail = TMail::Mail.parse(msg) + assert_equal "The=3Dbody", mail.body.strip + assert_equal "The=3Dbody", mail.quoted_body.strip + end + + def test_unquote_quoted_printable_body + msg = <<EOF +From: me@example.com +Subject: subject +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: quoted-printable + +The=3Dbody +EOF + mail = TMail::Mail.parse(msg) + assert_equal "The=body", mail.body.strip + assert_equal "The=3Dbody", mail.quoted_body.strip + end + + def test_unquote_base64_body + msg = <<EOF +From: me@example.com +Subject: subject +Content-Type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: base64 + +VGhlIGJvZHk= +EOF + mail = TMail::Mail.parse(msg) + assert_equal "The body", mail.body.strip + assert_equal "VGhlIGJvZHk=", mail.quoted_body.strip + end + + def test_extended_headers + @recipient = "Grytøyr <test@localhost>" + + expected = new_mail "iso-8859-1" + expected.to = quote_address_if_necessary @recipient, "iso-8859-1" + expected.subject = "testing extended headers" + expected.body = "Nothing to see here." + expected.from = quote_address_if_necessary "Grytøyr <stian1@example.net>", "iso-8859-1" + expected.cc = quote_address_if_necessary "Grytøyr <stian2@example.net>", "iso-8859-1" + expected.bcc = quote_address_if_necessary "Grytøyr <stian3@example.net>", "iso-8859-1" + expected.date = Time.local 2004, 12, 12 + + created = nil + assert_nothing_raised do + created = TestMailer.create_extended_headers @recipient + end + + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_extended_headers @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_utf8_body_is_not_quoted + @recipient = "Foo áëô îü <extended@example.net>" + expected = new_mail "utf-8" + expected.to = quote_address_if_necessary @recipient, "utf-8" + expected.subject = "testing utf-8 body" + expected.body = "åœö blah" + expected.from = quote_address_if_necessary @recipient, "utf-8" + expected.cc = quote_address_if_necessary @recipient, "utf-8" + expected.bcc = quote_address_if_necessary @recipient, "utf-8" + expected.date = Time.local 2004, 12, 12 + + created = TestMailer.create_utf8_body @recipient + assert_match(/åœö blah/, created.encoded) + end + + def test_multiple_utf8_recipients + @recipient = ["\"Foo áëô îü\" <extended@example.net>", "\"Example Recipient\" <me@example.com>"] + expected = new_mail "utf-8" + expected.to = quote_address_if_necessary @recipient, "utf-8" + expected.subject = "testing utf-8 body" + expected.body = "åœö blah" + expected.from = quote_address_if_necessary @recipient.first, "utf-8" + expected.cc = quote_address_if_necessary @recipient, "utf-8" + expected.bcc = quote_address_if_necessary @recipient, "utf-8" + expected.date = Time.local 2004, 12, 12 + + created = TestMailer.create_utf8_body @recipient + assert_match(/\nFrom: =\?utf-8\?Q\?Foo_.*?\?= <extended@example.net>\r/, created.encoded) + assert_match(/\nTo: =\?utf-8\?Q\?Foo_.*?\?= <extended@example.net>, Example Recipient <me/, created.encoded) + end + + def test_receive_decodes_base64_encoded_mail + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email") + TestMailer.receive(fixture) + assert_match(/Jamis/, TestMailer.received_body) + end + + def test_receive_attachments + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email2") + mail = TMail::Mail.parse(fixture) + attachment = mail.attachments.last + assert_equal "smime.p7s", attachment.original_filename + assert_equal "application/pkcs7-signature", attachment.content_type + end + + def test_decode_attachment_without_charset + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email3") + mail = TMail::Mail.parse(fixture) + attachment = mail.attachments.last + assert_equal 1026, attachment.read.length + end + + def test_attachment_using_content_location + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email12") + mail = TMail::Mail.parse(fixture) + assert_equal 1, mail.attachments.length + assert_equal "Photo25.jpg", mail.attachments.first.original_filename + end + + def test_attachment_with_text_type + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email13") + mail = TMail::Mail.parse(fixture) + assert mail.has_attachments? + assert_equal 1, mail.attachments.length + assert_equal "hello.rb", mail.attachments.first.original_filename + end + + def test_decode_part_without_content_type + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email4") + mail = TMail::Mail.parse(fixture) + assert_nothing_raised { mail.body } + end + + def test_decode_message_without_content_type + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email5") + mail = TMail::Mail.parse(fixture) + assert_nothing_raised { mail.body } + end + + def test_decode_message_with_incorrect_charset + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email6") + mail = TMail::Mail.parse(fixture) + assert_nothing_raised { mail.body } + end + + def test_multipart_with_mime_version + mail = TestMailer.create_multipart_with_mime_version(@recipient) + assert_equal "1.1", mail.mime_version + end + + def test_multipart_with_utf8_subject + mail = TestMailer.create_multipart_with_utf8_subject(@recipient) + assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded) + end + + def test_implicitly_multipart_with_utf8 + mail = TestMailer.create_implicitly_multipart_with_utf8 + assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded) + end + + def test_explicitly_multipart_messages + mail = TestMailer.create_explicitly_multipart_example(@recipient) + assert_equal 3, mail.parts.length + assert_nil mail.content_type + assert_equal "text/plain", mail.parts[0].content_type + + assert_equal "text/html", mail.parts[1].content_type + assert_equal "iso-8859-1", mail.parts[1].sub_header("content-type", "charset") + assert_equal "inline", mail.parts[1].content_disposition + + assert_equal "image/jpeg", mail.parts[2].content_type + assert_equal "attachment", mail.parts[2].content_disposition + assert_equal "foo.jpg", mail.parts[2].sub_header("content-disposition", "filename") + assert_equal "foo.jpg", mail.parts[2].sub_header("content-type", "name") + assert_nil mail.parts[2].sub_header("content-type", "charset") + end + + def test_explicitly_multipart_with_content_type + mail = TestMailer.create_explicitly_multipart_example(@recipient, "multipart/alternative") + assert_equal 3, mail.parts.length + assert_equal "multipart/alternative", mail.content_type + end + + def test_explicitly_multipart_with_invalid_content_type + mail = TestMailer.create_explicitly_multipart_example(@recipient, "text/xml") + assert_equal 3, mail.parts.length + assert_nil mail.content_type + end + + def test_implicitly_multipart_messages + mail = TestMailer.create_implicitly_multipart_example(@recipient) + assert_equal 3, mail.parts.length + assert_equal "1.0", mail.mime_version + assert_equal "multipart/alternative", mail.content_type + assert_equal "text/yaml", mail.parts[0].content_type + assert_equal "utf-8", mail.parts[0].sub_header("content-type", "charset") + assert_equal "text/plain", mail.parts[1].content_type + assert_equal "utf-8", mail.parts[1].sub_header("content-type", "charset") + assert_equal "text/html", mail.parts[2].content_type + assert_equal "utf-8", mail.parts[2].sub_header("content-type", "charset") + end + + def test_implicitly_multipart_messages_with_custom_order + mail = TestMailer.create_implicitly_multipart_example(@recipient, nil, ["text/yaml", "text/plain"]) + assert_equal 3, mail.parts.length + assert_equal "text/html", mail.parts[0].content_type + assert_equal "text/plain", mail.parts[1].content_type + assert_equal "text/yaml", mail.parts[2].content_type + end + + def test_implicitly_multipart_messages_with_charset + mail = TestMailer.create_implicitly_multipart_example(@recipient, 'iso-8859-1') + + assert_equal "multipart/alternative", mail.header['content-type'].body + + assert_equal 'iso-8859-1', mail.parts[0].sub_header("content-type", "charset") + assert_equal 'iso-8859-1', mail.parts[1].sub_header("content-type", "charset") + assert_equal 'iso-8859-1', mail.parts[2].sub_header("content-type", "charset") + end + + def test_html_mail + mail = TestMailer.create_html_mail(@recipient) + assert_equal "text/html", mail.content_type + end + + def test_html_mail_with_underscores + mail = TestMailer.create_html_mail_with_underscores(@recipient) + assert_equal %{<a href="http://google.com" target="_blank">_Google</a>}, mail.body + end + + def test_various_newlines + mail = TestMailer.create_various_newlines(@recipient) + assert_equal("line #1\nline #2\nline #3\nline #4\n\n" + + "line #5\n\nline#6\n\nline #7", mail.body) + end + + def test_various_newlines_multipart + mail = TestMailer.create_various_newlines_multipart(@recipient) + assert_equal "line #1\nline #2\nline #3\nline #4\n\n", mail.parts[0].body + assert_equal "<p>line #1</p>\n<p>line #2</p>\n<p>line #3</p>\n<p>line #4</p>\n\n", mail.parts[1].body + end + + def test_headers_removed_on_smtp_delivery + ActionMailer::Base.delivery_method = :smtp + TestMailer.deliver_cc_bcc(@recipient) + assert MockSMTP.deliveries[0][2].include?("root@loudthinking.com") + assert MockSMTP.deliveries[0][2].include?("nobody@loudthinking.com") + assert MockSMTP.deliveries[0][2].include?(@recipient) + assert_match %r{^Cc: nobody@loudthinking.com}, MockSMTP.deliveries[0][0] + assert_match %r{^To: #{@recipient}}, MockSMTP.deliveries[0][0] + assert_no_match %r{^Bcc: root@loudthinking.com}, MockSMTP.deliveries[0][0] + end + + def test_recursive_multipart_processing + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email7") + mail = TMail::Mail.parse(fixture) + assert_equal "This is the first part.\n\nAttachment: test.rb\nAttachment: test.pdf\n\n\nAttachment: smime.p7s\n", mail.body + end + + def test_decode_encoded_attachment_filename + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email8") + mail = TMail::Mail.parse(fixture) + attachment = mail.attachments.last + assert_equal "01QuienTeDijat.Pitbull.mp3", attachment.original_filename + end + + def test_wrong_mail_header + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email9") + assert_raise(TMail::SyntaxError) { TMail::Mail.parse(fixture) } + end + + def test_decode_message_with_unknown_charset + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email10") + mail = TMail::Mail.parse(fixture) + assert_nothing_raised { mail.body } + end + + def test_decode_message_with_unquoted_atchar_in_header + fixture = File.read(File.dirname(__FILE__) + "/fixtures/raw_email11") + mail = TMail::Mail.parse(fixture) + assert_not_nil mail.from + end + + def test_empty_header_values_omitted + result = TestMailer.create_unnamed_attachment(@recipient).encoded + assert_match %r{Content-Type: application/octet-stream[^;]}, result + assert_match %r{Content-Disposition: attachment[^;]}, result + end + + def test_headers_with_nonalpha_chars + mail = TestMailer.create_headers_with_nonalpha_chars(@recipient) + assert !mail.from_addrs.empty? + assert !mail.cc_addrs.empty? + assert !mail.bcc_addrs.empty? + assert_match(/:/, mail.from_addrs.to_s) + assert_match(/:/, mail.cc_addrs.to_s) + assert_match(/:/, mail.bcc_addrs.to_s) + end + + def test_deliver_with_mail_object + mail = TestMailer.create_headers_with_nonalpha_chars(@recipient) + assert_nothing_raised { TestMailer.deliver(mail) } + assert_equal 1, TestMailer.deliveries.length + end + + def test_multipart_with_template_path_with_dots + mail = FunkyPathMailer.create_multipart_with_template_path_with_dots(@recipient) + assert_equal 2, mail.parts.length + end + + def test_custom_content_type_attributes + mail = TestMailer.create_custom_content_type_attributes + assert_match %r{format=flowed}, mail['content-type'].to_s + assert_match %r{charset=utf-8}, mail['content-type'].to_s + end +end + +class InheritableTemplateRootTest < Test::Unit::TestCase + def test_attr + expected = "#{File.dirname(__FILE__)}/fixtures/path.with.dots" + assert_equal expected, FunkyPathMailer.template_root + + sub = Class.new(FunkyPathMailer) + sub.template_root = 'test/path' + + assert_equal 'test/path', sub.template_root + assert_equal expected, FunkyPathMailer.template_root + end +end +$:.unshift(File.dirname(__FILE__) + "/../lib/") +$:.unshift(File.dirname(__FILE__) + "/../lib/action_mailer/vendor") + +require 'test/unit' +require 'tmail' +require 'tempfile' + +class QuotingTest < Test::Unit::TestCase + def test_quote_multibyte_chars + original = "\303\246 \303\270 and \303\245" + + result = execute_in_sandbox(<<-CODE) + $:.unshift(File.dirname(__FILE__) + "/../lib/") + $KCODE = 'u' + require 'jcode' + require 'action_mailer/quoting' + include ActionMailer::Quoting + quoted_printable(#{original.inspect}, "UTF-8") + CODE + + unquoted = TMail::Unquoter.unquote_and_convert_to(result, nil) + assert_equal unquoted, original + end + + private + + # This whole thing *could* be much simpler, but I don't think Tempfile, + # popen and others exist on all platforms (like Windows). + def execute_in_sandbox(code) + test_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.rb" + res_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.out" + + File.open(test_name, "w+") do |file| + file.write(<<-CODE) + block = Proc.new do + #{code} + end + puts block.call + CODE + end + + system("ruby #{test_name} > #{res_name}") or raise "could not run test in sandbox" + File.read(res_name) + ensure + File.delete(test_name) rescue nil + File.delete(res_name) rescue nil + end +end +$:.unshift(File.dirname(__FILE__) + "/../lib/") +$:.unshift File.dirname(__FILE__) + "/fixtures/helpers" + +require 'test/unit' +require 'action_mailer' + +class TMailMailTest < Test::Unit::TestCase + def test_body + m = TMail::Mail.new + expected = 'something_with_underscores' + m.encoding = 'quoted-printable' + quoted_body = [expected].pack('*M') + m.body = quoted_body + assert_equal "something_with_underscores=\n", m.quoted_body + assert_equal expected, m.body + end +end +$:.unshift(File.dirname(__FILE__) + "/../lib") + +require "action_controller" +require "action_controller/test_process" + +Person = Struct.new("Person", :id, :name, :email_address, :phone_number) + +class AddressBookService + attr_reader :people + + def initialize() @people = [] end + def create_person(data) people.unshift(Person.new(next_person_id, data["name"], data["email_address"], data["phone_number"])) end + def find_person(topic_id) people.select { |person| person.id == person.to_i }.first end + def next_person_id() people.first.id + 1 end +end + +class AddressBookController < ActionController::Base + layout "address_book/layout" + + before_filter :initialize_session_storage + + # Could also have used a proc + # before_filter proc { |c| c.instance_variable_set("@address_book", c.session["address_book"] ||= AddressBookService.new) } + + def index + @title = "Address Book" + @people = @address_book.people + end + + def person + @person = @address_book.find_person(@params["id"]) + end + + def create_person + @address_book.create_person(@params["person"]) + redirect_to :action => "index" + end + + private + def initialize_session_storage + @address_book = @session["address_book"] ||= AddressBookService.new + end +end + +ActionController::Base.template_root = File.dirname(__FILE__) +# ActionController::Base.logger = Logger.new("debug.log") # Remove first comment to turn on logging in current dir + +begin + AddressBookController.process_cgi(CGI.new) if $0 == __FILE__ +rescue => e + CGI.new.out { "#{e.class}: #{e.message}" } +end$:.unshift(File.dirname(__FILE__) + "/../lib") + +require "action_controller" +require 'action_controller/test_process' + +Person = Struct.new("Person", :name, :address, :age) + +class BenchmarkController < ActionController::Base + def message + render_text "hello world" + end + + def list + @people = [ Person.new("David"), Person.new("Mary") ] + render_template "hello: <% for person in @people %>Name: <%= person.name %><% end %>" + end + + def form_helper + @person = Person.new "david", "hyacintvej", 24 + render_template( + "<% person = Person.new 'Mary', 'hyacintvej', 22 %> " + + "change the name <%= text_field 'person', 'name' %> and <%= text_field 'person', 'address' %> and <%= text_field 'person', 'age' %>" + ) + end +end + +#ActionController::Base.template_root = File.dirname(__FILE__) + +require "benchmark" + +RUNS = ARGV[0] ? ARGV[0].to_i : 50 + +require "profile" if ARGV[1] + +runtime = Benchmark.measure { + RUNS.times { BenchmarkController.process_test(ActionController::TestRequest.new({ "action" => "list" })) } +} + +puts "List: #{RUNS / runtime.real}" + + +runtime = Benchmark.measure { + RUNS.times { BenchmarkController.process_test(ActionController::TestRequest.new({ "action" => "message" })) } +} + +puts "Message: #{RUNS / runtime.real}" + +runtime = Benchmark.measure { + RUNS.times { BenchmarkController.process_test(ActionController::TestRequest.new({ "action" => "form_helper" })) } +} + +puts "Form helper: #{RUNS / runtime.real}" +require 'rbconfig' +require 'find' +require 'ftools' + +include Config + +# this was adapted from rdoc's install.rb by ways of Log4r + +$sitedir = CONFIG["sitelibdir"] +unless $sitedir + version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"] + $libdir = File.join(CONFIG["libdir"], "ruby", version) + $sitedir = $:.find {|x| x =~ /site_ruby/ } + if !$sitedir + $sitedir = File.join($libdir, "site_ruby") + elsif $sitedir !~ Regexp.quote(version) + $sitedir = File.join($sitedir, version) + end +end + +# the acual gruntwork +Dir.chdir("lib") + +Find.find("action_controller", "action_controller.rb", "action_view", "action_view.rb") { |f| + if f[-3..-1] == ".rb" + File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true) + else + File::makedirs(File.join($sitedir, *f.split(/\//))) + end +}require 'test/unit' +require 'test/unit/assertions' +require 'rexml/document' +require File.dirname(__FILE__) + "/vendor/html-scanner/html/document" + +module Test #:nodoc: + module Unit #:nodoc: + # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions + # can be used against. These collections are: + # + # * assigns: Instance variables assigned in the action that are available for the view. + # * session: Objects being saved in the session. + # * flash: The flash objects currently in the session. + # * cookies: Cookies being sent to the user on this request. + # + # These collections can be used just like any other hash: + # + # assert_not_nil assigns(:person) # makes sure that a @person instance variable was set + # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave" + # assert flash.empty? # makes sure that there's nothing in the flash + # + # For historic reasons, the assigns hash uses string-based keys. So assigns[:person] won't work, but assigns["person"] will. To + # appease our yearning for symbols, though, an alternative accessor has been deviced using a method call instead of index referencing. + # So assigns(:person) will work just like assigns["person"], but again, assigns[:person] will not work. + # + # On top of the collections, you have the complete url that a given action redirected to available in redirect_to_url. + # + # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another + # action call which can then be asserted against. + # + # == Manipulating the request collections + # + # The collections described above link to the response, so you can test if what the actions were expected to do happened. But + # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions + # and cookies, though. For sessions, you just do: + # + # @request.session[:key] = "value" + # + # For cookies, you need to manually create the cookie, like this: + # + # @request.cookies["key"] = CGI::Cookie.new("key", "value") + # + # == Testing named routes + # + # If you're using named routes, they can be easily tested using the original named routes methods straight in the test case. + # Example: + # + # assert_redirected_to page_url(:title => 'foo') + module Assertions + # Asserts that the response is one of the following types: + # + # * <tt>:success</tt>: Status code was 200 + # * <tt>:redirect</tt>: Status code was in the 300-399 range + # * <tt>:missing</tt>: Status code was 404 + # * <tt>:error</tt>: Status code was in the 500-599 range + # + # You can also pass an explicit status code number as the type, like assert_response(501) + def assert_response(type, message = nil) + clean_backtrace do + if [ :success, :missing, :redirect, :error ].include?(type) && @response.send("#{type}?") + assert_block("") { true } # to count the assertion + elsif type.is_a?(Fixnum) && @response.response_code == type + assert_block("") { true } # to count the assertion + else + assert_block(build_message(message, "Expected response to be a <?>, but was <?>", type, @response.response_code)) { false } + end + end + end + + # Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, + # such that assert_redirected_to(:controller => "weblog") will also match the redirection of + # redirect_to(:controller => "weblog", :action => "show") and so on. + def assert_redirected_to(options = {}, message=nil) + clean_backtrace do + assert_response(:redirect, message) + + if options.is_a?(String) + msg = build_message(message, "expected a redirect to <?>, found one to <?>", options, @response.redirect_url) + url_regexp = %r{^(\w+://.*?(/|$|\?))(.*)$} + eurl, epath, url, path = [options, @response.redirect_url].collect do |url| + u, p = (url_regexp =~ url) ? [$1, $3] : [nil, url] + [u, (p[0..0] == '/') ? p : '/' + p] + end.flatten + + assert_equal(eurl, url, msg) if eurl && url + assert_equal(epath, path, msg) if epath && path + else + @response_diff = options.diff(@response.redirected_to) if options.is_a?(Hash) && @response.redirected_to.is_a?(Hash) + msg = build_message(message, "response is not a redirection to all of the options supplied (redirection is <?>)#{', difference: <?>' if @response_diff}", + @response.redirected_to || @response.redirect_url, @response_diff) + + assert_block(msg) do + if options.is_a?(Symbol) + @response.redirected_to == options + else + options.keys.all? do |k| + if k == :controller then options[k] == ActionController::Routing.controller_relative_to(@response.redirected_to[k], @controller.class.controller_path) + else options[k] == (@response.redirected_to[k].respond_to?(:to_param) ? @response.redirected_to[k].to_param : @response.redirected_to[k] unless @response.redirected_to[k].nil?) + end + end + end + end + end + end + end + + # Asserts that the request was rendered with the appropriate template file. + def assert_template(expected = nil, message=nil) + clean_backtrace do + rendered = expected ? @response.rendered_file(!expected.include?('/')) : @response.rendered_file + msg = build_message(message, "expecting <?> but rendering with <?>", expected, rendered) + assert_block(msg) do + if expected.nil? + !@response.rendered_with_file? + else + expected == rendered + end + end + end + end + + # Asserts that the routing of the given path was handled correctly and that the parsed options match. + def assert_recognizes(expected_options, path, extras={}, message=nil) + clean_backtrace do + path = "/#{path}" unless path[0..0] == '/' + # Load routes.rb if it hasn't been loaded. + ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? + + # Assume given controller + request = ActionController::TestRequest.new({}, {}, nil) + request.path = path + ActionController::Routing::Routes.recognize!(request) + + expected_options = expected_options.clone + extras.each_key { |key| expected_options.delete key } unless extras.nil? + + expected_options.stringify_keys! + msg = build_message(message, "The recognized options <?> did not match <?>", + request.path_parameters, expected_options) + assert_block(msg) { request.path_parameters == expected_options } + end + end + + # Asserts that the provided options can be used to generate the provided path. + def assert_generates(expected_path, options, defaults={}, extras = {}, message=nil) + clean_backtrace do + expected_path = "/#{expected_path}" unless expected_path[0] == ?/ + # Load routes.rb if it hasn't been loaded. + ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? + + generated_path, extra_keys = ActionController::Routing::Routes.generate(options, extras) + found_extras = options.reject {|k, v| ! extra_keys.include? k} + + msg = build_message(message, "found extras <?>, not <?>", found_extras, extras) + assert_block(msg) { found_extras == extras } + + msg = build_message(message, "The generated path <?> did not match <?>", generated_path, + expected_path) + assert_block(msg) { expected_path == generated_path } + end + end + + # Asserts that path and options match both ways; in other words, the URL generated from + # options is the same as path, and also that the options recognized from path are the same as options + def assert_routing(path, options, defaults={}, extras={}, message=nil) + assert_recognizes(options, path, extras, message) + + controller, default_controller = options[:controller], defaults[:controller] + if controller && controller.include?(?/) && default_controller && default_controller.include?(?/) + options[:controller] = "/#{controller}" + end + + assert_generates(path, options, defaults, extras, message) + end + + # Asserts that there is a tag/node/element in the body of the response + # that meets all of the given conditions. The +conditions+ parameter must + # be a hash of any of the following keys (all are optional): + # + # * <tt>:tag</tt>: the node type must match the corresponding value + # * <tt>:attributes</tt>: a hash. The node's attributes must match the + # corresponding values in the hash. + # * <tt>:parent</tt>: a hash. The node's parent must match the + # corresponding hash. + # * <tt>:child</tt>: a hash. At least one of the node's immediate children + # must meet the criteria described by the hash. + # * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must + # meet the criteria described by the hash. + # * <tt>:descendant</tt>: a hash. At least one of the node's descendants + # must meet the criteria described by the hash. + # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must + # meet the criteria described by the hash. + # * <tt>:after</tt>: a hash. The node must be after any sibling meeting + # the criteria described by the hash, and at least one sibling must match. + # * <tt>:before</tt>: a hash. The node must be before any sibling meeting + # the criteria described by the hash, and at least one sibling must match. + # * <tt>:children</tt>: a hash, for counting children of a node. Accepts + # the keys: + # * <tt>:count</tt>: either a number or a range which must equal (or + # include) the number of children that match. + # * <tt>:less_than</tt>: the number of matching children must be less + # than this number. + # * <tt>:greater_than</tt>: the number of matching children must be + # greater than this number. + # * <tt>:only</tt>: another hash consisting of the keys to use + # to match on the children, and only matching children will be + # counted. + # * <tt>:content</tt>: the textual content of the node must match the + # given value. This will not match HTML tags in the body of a + # tag--only text. + # + # Conditions are matched using the following algorithm: + # + # * if the condition is a string, it must be a substring of the value. + # * if the condition is a regexp, it must match the value. + # * if the condition is a number, the value must match number.to_s. + # * if the condition is +true+, the value must not be +nil+. + # * if the condition is +false+ or +nil+, the value must be +nil+. + # + # Usage: + # + # # assert that there is a "span" tag + # assert_tag :tag => "span" + # + # # assert that there is a "span" tag with id="x" + # assert_tag :tag => "span", :attributes => { :id => "x" } + # + # # assert that there is a "span" tag using the short-hand + # assert_tag :span + # + # # assert that there is a "span" tag with id="x" using the short-hand + # assert_tag :span, :attributes => { :id => "x" } + # + # # assert that there is a "span" inside of a "div" + # assert_tag :tag => "span", :parent => { :tag => "div" } + # + # # assert that there is a "span" somewhere inside a table + # assert_tag :tag => "span", :ancestor => { :tag => "table" } + # + # # assert that there is a "span" with at least one "em" child + # assert_tag :tag => "span", :child => { :tag => "em" } + # + # # assert that there is a "span" containing a (possibly nested) + # # "strong" tag. + # assert_tag :tag => "span", :descendant => { :tag => "strong" } + # + # # assert that there is a "span" containing between 2 and 4 "em" tags + # # as immediate children + # assert_tag :tag => "span", + # :children => { :count => 2..4, :only => { :tag => "em" } } + # + # # get funky: assert that there is a "div", with an "ul" ancestor + # # and an "li" parent (with "class" = "enum"), and containing a + # # "span" descendant that contains text matching /hello world/ + # assert_tag :tag => "div", + # :ancestor => { :tag => "ul" }, + # :parent => { :tag => "li", + # :attributes => { :class => "enum" } }, + # :descendant => { :tag => "span", + # :child => /hello world/ } + # + # <strong>Please note</strong: #assert_tag and #assert_no_tag only work + # with well-formed XHTML. They recognize a few tags as implicitly self-closing + # (like br and hr and such) but will not work correctly with tags + # that allow optional closing tags (p, li, td). <em>You must explicitly + # close all of your tags to use these assertions.</em> + def assert_tag(*opts) + clean_backtrace do + opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first + tag = find_tag(opts) + assert tag, "expected tag, but no tag found matching #{opts.inspect} in:\n#{@response.body.inspect}" + end + end + + # Identical to #assert_tag, but asserts that a matching tag does _not_ + # exist. (See #assert_tag for a full discussion of the syntax.) + def assert_no_tag(*opts) + clean_backtrace do + opts = opts.size > 1 ? opts.last.merge({ :tag => opts.first.to_s }) : opts.first + tag = find_tag(opts) + assert !tag, "expected no tag, but found tag matching #{opts.inspect} in:\n#{@response.body.inspect}" + end + end + + # test 2 html strings to be equivalent, i.e. identical up to reordering of attributes + def assert_dom_equal(expected, actual, message="") + clean_backtrace do + expected_dom = HTML::Document.new(expected).root + actual_dom = HTML::Document.new(actual).root + full_message = build_message(message, "<?> expected to be == to\n<?>.", expected_dom.to_s, actual_dom.to_s) + assert_block(full_message) { expected_dom == actual_dom } + end + end + + # negated form of +assert_dom_equivalent+ + def assert_dom_not_equal(expected, actual, message="") + clean_backtrace do + expected_dom = HTML::Document.new(expected).root + actual_dom = HTML::Document.new(actual).root + full_message = build_message(message, "<?> expected to be != to\n<?>.", expected_dom.to_s, actual_dom.to_s) + assert_block(full_message) { expected_dom != actual_dom } + end + end + + # ensures that the passed record is valid by active record standards. returns the error messages if not + def assert_valid(record) + clean_backtrace do + assert record.valid?, record.errors.full_messages.join("\n") + end + end + + def clean_backtrace(&block) + yield + rescue AssertionFailedError => e + path = File.expand_path(__FILE__) + raise AssertionFailedError, e.message, e.backtrace.reject { |line| File.expand_path(line) =~ /#{path}/ } + end + end + end +end +require 'action_controller/mime_type' +require 'action_controller/request' +require 'action_controller/response' +require 'action_controller/routing' +require 'action_controller/code_generation' +require 'action_controller/url_rewriter' +require 'drb' +require 'set' + +module ActionController #:nodoc: + class ActionControllerError < StandardError #:nodoc: + end + class SessionRestoreError < ActionControllerError #:nodoc: + end + class MissingTemplate < ActionControllerError #:nodoc: + end + class RoutingError < ActionControllerError #:nodoc: + attr_reader :failures + def initialize(message, failures=[]) + super(message) + @failures = failures + end + end + class UnknownController < ActionControllerError #:nodoc: + end + class UnknownAction < ActionControllerError #:nodoc: + end + class MissingFile < ActionControllerError #:nodoc: + end + class SessionOverflowError < ActionControllerError #:nodoc: + DEFAULT_MESSAGE = 'Your session data is larger than the data column in which it is to be stored. You must increase the size of your data column if you intend to store large data.' + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + class DoubleRenderError < ActionControllerError #:nodoc: + DEFAULT_MESSAGE = "Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and only once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\". Finally, note that to cause a before filter to halt execution of the rest of the filter chain, the filter must return false, explicitly, so \"render(...) and return false\"." + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + class RedirectBackError < ActionControllerError #:nodoc: + DEFAULT_MESSAGE = 'No HTTP_REFERER was set in the request to this action, so redirect_to :back could not be called successfully. If this is a test, make sure to specify @request.env["HTTP_REFERER"].' + + def initialize(message = nil) + super(message || DEFAULT_MESSAGE) + end + end + + # Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed + # on request and then either render a template or redirect to another action. An action is defined as a public method + # on the controller, which will automatically be made accessible to the web-server through Rails Routes. + # + # A sample controller could look like this: + # + # class GuestBookController < ActionController::Base + # def index + # @entries = Entry.find(:all) + # end + # + # def sign + # Entry.create(params[:entry]) + # redirect_to :action => "index" + # end + # end + # + # Actions, by default, render a template in the <tt>app/views</tt> directory corresponding to the name of the controller and action + # after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the + # template <tt>app/views/guestbook/index.rhtml</tt> by default after populating the <tt>@entries</tt> instance variable. + # + # Unlike index, the sign action will not render a template. After performing its main purpose (creating a + # new entry in the guest book), it initiates a redirect instead. This redirect works by returning an external + # "302 Moved" HTTP response that takes the user to the index action. + # + # The index and sign represent the two basic action archetypes used in Action Controllers. Get-and-show and do-and-redirect. + # Most actions are variations of these themes. + # + # == Requests + # + # Requests are processed by the Action Controller framework by extracting the value of the "action" key in the request parameters. + # This value should hold the name of the action to be performed. Once the action has been identified, the remaining + # request parameters, the session (if one is available), and the full request with all the http headers are made available to + # the action through instance variables. Then the action is performed. + # + # The full request object is available with the request accessor and is primarily used to query for http headers. These queries + # are made by accessing the environment hash, like this: + # + # def server_ip + # location = request.env["SERVER_ADDR"] + # render :text => "This server hosted at #{location}" + # end + # + # == Parameters + # + # All request parameters, whether they come from a GET or POST request, or from the URL, are available through the params method + # which returns a hash. For example, an action that was performed through <tt>/weblog/list?category=All&limit=5</tt> will include + # <tt>{ "category" => "All", "limit" => 5 }</tt> in params. + # + # It's also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as: + # + # <input type="text" name="post[name]" value="david"> + # <input type="text" name="post[address]" value="hyacintvej"> + # + # A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>. + # If the address input had been named "post[address][street]", the params would have included + # <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting. + # + # == Sessions + # + # Sessions allows you to store objects in between requests. This is useful for objects that are not yet ready to be persisted, + # such as a Signup object constructed in a multi-paged process, or objects that don't change much and are needed all the time, such + # as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it's likely + # they could be changed unknowingly. It's usually too much work to keep it all synchronized -- something databases already excel at. + # + # You can place objects in the session by using the <tt>session</tt> method, which accesses a hash: + # + # session[:person] = Person.authenticate(user_name, password) + # + # And retrieved again through the same hash: + # + # Hello #{session[:person]} + # + # For removing objects from the session, you can either assign a single key to nil, like <tt>session[:person] = nil</tt>, or you can + # remove the entire session with reset_session. + # + # By default, sessions are stored on the file system in <tt>RAILS_ROOT/tmp/sessions</tt>. Any object can be placed in the session + # (as long as it can be Marshalled). But remember that 1000 active sessions each storing a 50kb object could lead to a 50MB store on the filesystem. + # In other words, think carefully about size and caching before resorting to the use of the session on the filesystem. + # + # An alternative to storing sessions on disk is to use ActiveRecordStore to store sessions in your database, which can solve problems + # caused by storing sessions in the file system and may speed up your application. To use ActiveRecordStore, uncomment the line: + # + # config.action_controller.session_store = :active_record_store + # + # in your <tt>environment.rb</tt> and run <tt>rake db:sessions:create</tt>. + # + # == Responses + # + # Each action results in a response, which holds the headers and document to be sent to the user's browser. The actual response + # object is generated automatically through the use of renders and redirects and requires no user intervention. + # + # == Renders + # + # Action Controller sends content to the user by using one of five rendering methods. The most versatile and common is the rendering + # of a template. Included in the Action Pack is the Action View, which enables rendering of ERb templates. It's automatically configured. + # The controller passes objects to the view by assigning instance variables: + # + # def show + # @post = Post.find(params[:id]) + # end + # + # Which are then automatically available to the view: + # + # Title: <%= @post.title %> + # + # You don't have to rely on the automated rendering. Especially actions that could result in the rendering of different templates will use + # the manual rendering methods: + # + # def search + # @results = Search.find(params[:query]) + # case @results + # when 0 then render :action => "no_results" + # when 1 then render :action => "show" + # when 2..10 then render :action => "show_many" + # end + # end + # + # Read more about writing ERb and Builder templates in link:classes/ActionView/Base.html. + # + # == Redirects + # + # Redirects are used to move from one action to another. For example, after a <tt>create</tt> action, which stores a blog entry to a database, + # we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself), we're going to reuse (and redirect to) + # a <tt>show</tt> action that we'll assume has already been created. The code might look like this: + # + # def create + # @entry = Entry.new(params[:entry]) + # if @entry.save + # # The entry was saved correctly, redirect to show + # redirect_to :action => 'show', :id => @entry.id + # else + # # things didn't go so well, do something else + # end + # end + # + # In this case, after saving our new entry to the database, the user is redirected to the <tt>show</tt> method which is then executed. + # + # == Calling multiple redirects or renders + # + # An action should conclude with a single render or redirect. Attempting to try to do either again will result in a DoubleRenderError: + # + # def do_something + # redirect_to :action => "elsewhere" + # render :action => "overthere" # raises DoubleRenderError + # end + # + # If you need to redirect on the condition of something, then be sure to add "and return" to halt execution. + # + # def do_something + # redirect_to(:action => "elsewhere") and return if monkeys.nil? + # render :action => "overthere" # won't be called unless monkeys is nil + # end + # + class Base + DEFAULT_RENDER_STATUS_CODE = "200 OK" + + include Reloadable::Subclasses + + # Determines whether the view has access to controller internals @request, @response, @session, and @template. + # By default, it does. + @@view_controller_internals = true + cattr_accessor :view_controller_internals + + # Protected instance variable cache + @@protected_variables_cache = nil + cattr_accessor :protected_variables_cache + + # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets, + # and images to a dedicated asset server away from the main web server. Example: + # ActionController::Base.asset_host = "http://assets.example.com" + @@asset_host = "" + cattr_accessor :asset_host + + # All requests are considered local by default, so everyone will be exposed to detailed debugging screens on errors. + # When the application is ready to go public, this should be set to false, and the protected method <tt>local_request?</tt> + # should instead be implemented in the controller to determine when debugging screens should be shown. + @@consider_all_requests_local = true + cattr_accessor :consider_all_requests_local + + # Enable or disable the collection of failure information for RoutingErrors. + # This information can be extremely useful when tweaking custom routes, but is + # pointless once routes have been tested and verified. + @@debug_routes = true + cattr_accessor :debug_routes + + # Controls whether the application is thread-safe, so multi-threaded servers like WEBrick know whether to apply a mutex + # around the performance of each action. Action Pack and Active Record are by default thread-safe, but many applications + # may not be. Turned off by default. + @@allow_concurrency = false + cattr_accessor :allow_concurrency + + # Modern REST web services often need to submit complex data to the web application. + # The param_parsers hash lets you register handlers wich will process the http body and add parameters to the + # <tt>params</tt> hash. These handlers are invoked for post and put requests. + # + # By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instanciated + # in the <tt>params</tt>. This allows XML requests to mask themselves as regular form submissions, so you can have one + # action serve both regular forms and web service requests. + # + # Example of doing your own parser for a custom content type: + # + # ActionController::Base.param_parsers[Mime::Type.lookup('application/atom+xml')] = Proc.new do |data| + # node = REXML::Document.new(post) + # { node.root.name => node.root } + # end + # + # Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the + # root node for such requests. The new default is to keep the root, such that "<r><name>David</name></r>" results + # in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can + # re-register XmlSimple as application/xml handler ike this: + # + # ActionController::Base.param_parsers[Mime::XML] = + # Proc.new { |data| XmlSimple.xml_in(data, 'ForceArray' => false) } + # + # A YAML parser is also available and can be turned on with: + # + # ActionController::Base.param_parsers[Mime::YAML] = :yaml + @@param_parsers = { Mime::XML => :xml_simple } + cattr_accessor :param_parsers + + # Template root determines the base from which template references will be made. So a call to render("test/template") + # will be converted to "#{template_root}/test/template.rhtml". + class_inheritable_accessor :template_root + + # The logger is used for generating information on the action run-time (including benchmarking) if available. + # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. + cattr_accessor :logger + + # Determines which template class should be used by ActionController. + cattr_accessor :template_class + + # Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates. + cattr_accessor :ignore_missing_templates + + # Holds the request object that's primarily used to get environment variables through access like + # <tt>request.env["REQUEST_URI"]</tt>. + attr_accessor :request + + # Holds a hash of all the GET, POST, and Url parameters passed to the action. Accessed like <tt>params["post_id"]</tt> + # to get the post_id. No type casts are made, so all values are returned as strings. + attr_accessor :params + + # Holds the response object that's primarily used to set additional HTTP headers through access like + # <tt>response.headers["Cache-Control"] = "no-cache"</tt>. Can also be used to access the final body HTML after a template + # has been rendered through response.body -- useful for <tt>after_filter</tt>s that wants to manipulate the output, + # such as a OutputCompressionFilter. + attr_accessor :response + + # Holds a hash of objects in the session. Accessed like <tt>session[:person]</tt> to get the object tied to the "person" + # key. The session will hold any type of object as values, but the key should be a string or symbol. + attr_accessor :session + + # Holds a hash of header names and values. Accessed like <tt>headers["Cache-Control"]</tt> to get the value of the Cache-Control + # directive. Values should always be specified as strings. + attr_accessor :headers + + # Holds the hash of variables that are passed on to the template class to be made available to the view. This hash + # is generated by taking a snapshot of all the instance variables in the current scope just before a template is rendered. + attr_accessor :assigns + + # Returns the name of the action this controller is processing. + attr_accessor :action_name + + class << self + # Factory for the standard create, process loop where the controller is discarded after processing. + def process(request, response) #:nodoc: + new.process(request, response) + end + + # Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController". + def controller_class_name + @controller_class_name ||= name.demodulize + end + + # Converts the class name from something like "OneModule::TwoModule::NeatController" to "neat". + def controller_name + @controller_name ||= controller_class_name.sub(/Controller$/, '').underscore + end + + # Converts the class name from something like "OneModule::TwoModule::NeatController" to "one_module/two_module/neat". + def controller_path + @controller_path ||= name.gsub(/Controller$/, '').underscore + end + + # Return an array containing the names of public methods that have been marked hidden from the action processor. + # By default, all methods defined in ActionController::Base and included modules are hidden. + # More methods can be hidden using <tt>hide_actions</tt>. + def hidden_actions + write_inheritable_attribute(:hidden_actions, ActionController::Base.public_instance_methods) unless read_inheritable_attribute(:hidden_actions) + read_inheritable_attribute(:hidden_actions) + end + + # Hide each of the given methods from being callable as actions. + def hide_action(*names) + write_inheritable_attribute(:hidden_actions, hidden_actions | names.collect { |n| n.to_s }) + end + + # Replace sensitive paramater data from the request log. + # Filters paramaters that have any of the arguments as a substring. + # Looks in all subhashes of the param hash for keys to filter. + # If a block is given, each key and value of the paramater hash and all + # subhashes is passed to it, the value or key + # can be replaced using String#replace or similar method. + # + # Examples: + # filter_parameter_logging + # => Does nothing, just slows the logging process down + # + # filter_parameter_logging :password + # => replaces the value to all keys matching /password/i with "[FILTERED]" + # + # filter_parameter_logging :foo, "bar" + # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]" + # + # filter_parameter_logging { |k,v| v.reverse! if k =~ /secret/i } + # => reverses the value to all keys matching /secret/i + # + # filter_parameter_logging(:foo, "bar") { |k,v| v.reverse! if k =~ /secret/i } + # => reverses the value to all keys matching /secret/i, and + # replaces the value to all keys matching /foo|bar/i with "[FILTERED]" + def filter_parameter_logging(*filter_words, &block) + parameter_filter = Regexp.new(filter_words.collect{ |s| s.to_s }.join('|'), true) if filter_words.length > 0 + + define_method(:filter_parameters) do |unfiltered_parameters| + filtered_parameters = {} + + unfiltered_parameters.each do |key, value| + if key =~ parameter_filter + filtered_parameters[key] = '[FILTERED]' + elsif value.is_a?(Hash) + filtered_parameters[key] = filter_parameters(value) + elsif block_given? + key, value = key.dup, value.dup + yield key, value + filtered_parameters[key] = value + else + filtered_parameters[key] = value + end + end + + filtered_parameters + end + end + end + + public + # Extracts the action_name from the request parameters and performs that action. + def process(request, response, method = :perform_action, *arguments) #:nodoc: + initialize_template_class(response) + assign_shortcuts(request, response) + initialize_current_url + assign_names + forget_variables_added_to_assigns + + log_processing + send(method, *arguments) + + response + ensure + process_cleanup + end + + # Returns a URL that has been rewritten according to the options hash and the defined Routes. + # (For doing a complete redirect, use redirect_to). + #  + # <tt>url_for</tt> is used to: + #  + # All keys given to url_for are forwarded to the Route module, save for the following: + # * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example, + # <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt> + # will produce "/posts/show/10#comments". + # * <tt>:only_path</tt> -- if true, returns the absolute URL (omitting the protocol, host name, and port) + # * <tt>:trailing_slash</tt> -- if true, adds a trailing slash, as in "/archive/2005/". Note that this + # is currently not recommended since it breaks caching. + # * <tt>:host</tt> -- overrides the default (current) host if provided + # * <tt>:protocol</tt> -- overrides the default (current) protocol if provided + # + # The URL is generated from the remaining keys in the hash. A URL contains two key parts: the <base> and a query string. + # Routes composes a query string as the key/value pairs not included in the <base>. + # + # The default Routes setup supports a typical Rails path of "controller/action/id" where action and id are optional, with + # action defaulting to 'index' when not given. Here are some typical url_for statements and their corresponding URLs: + #  + # url_for :controller => 'posts', :action => 'recent' # => 'proto://host.com/posts/recent' + # url_for :controller => 'posts', :action => 'index' # => 'proto://host.com/posts' + # url_for :controller => 'posts', :action => 'show', :id => 10 # => 'proto://host.com/posts/show/10' + # + # When generating a new URL, missing values may be filled in from the current request's parameters. For example, + # <tt>url_for :action => 'some_action'</tt> will retain the current controller, as expected. This behavior extends to + # other parameters, including <tt>:controller</tt>, <tt>:id</tt>, and any other parameters that are placed into a Route's + # path. + #  + # The URL helpers such as <tt>url_for</tt> have a limited form of memory: when generating a new URL, they can look for + # missing values in the current request's parameters. Routes attempts to guess when a value should and should not be + # taken from the defaults. There are a few simple rules on how this is performed: + # + # * If the controller name begins with a slash, no defaults are used: <tt>url_for :controller => '/home'</tt> + # * If the controller changes, the action will default to index unless provided + # + # The final rule is applied while the URL is being generated and is best illustrated by an example. Let us consider the + # route given by <tt>map.connect 'people/:last/:first/:action', :action => 'bio', :controller => 'people'</tt>. + # + # Suppose that the current URL is "people/hh/david/contacts". Let's consider a few different cases of URLs which are generated + # from this page. + # + # * <tt>url_for :action => 'bio'</tt> -- During the generation of this URL, default values will be used for the first and + # last components, and the action shall change. The generated URL will be, "people/hh/david/bio". + # * <tt>url_for :first => 'davids-little-brother'</tt> This generates the URL 'people/hh/davids-little-brother' -- note + # that this URL leaves out the assumed action of 'bio'. + # + # However, you might ask why the action from the current request, 'contacts', isn't carried over into the new URL. The + # answer has to do with the order in which the parameters appear in the generated path. In a nutshell, since the + # value that appears in the slot for <tt>:first</tt> is not equal to default value for <tt>:first</tt> we stop using + # defaults. On it's own, this rule can account for much of the typical Rails URL behavior. + #  + # Although a convienence, defaults can occasionaly get in your way. In some cases a default persists longer than desired. + # The default may be cleared by adding <tt>:name => nil</tt> to <tt>url_for</tt>'s options. + # This is often required when writing form helpers, since the defaults in play may vary greatly depending upon where the + # helper is used from. The following line will redirect to PostController's default action, regardless of the page it is + # displayed on: + # + # url_for :controller => 'posts', :action => nil + # + # If you explicitly want to create a URL that's almost the same as the current URL, you can do so using the + # :overwrite_params options. Say for your posts you have different views for showing and printing them. + # Then, in the show view, you get the URL for the print view like this + # + # url_for :overwrite_params => { :action => 'print' } + # + # This takes the current URL as is and only exchanges the action. In contrast, <tt>url_for :action => 'print'</tt> + # would have slashed-off the path components after the changed action. + def url_for(options = {}, *parameters_for_method_reference) #:doc: + case options + when String then options + when Symbol then send(options, *parameters_for_method_reference) + when Hash then @url.rewrite(rewrite_options(options)) + end + end + + # Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController". + def controller_class_name + self.class.controller_class_name + end + + # Converts the class name from something like "OneModule::TwoModule::NeatController" to "neat". + def controller_name + self.class.controller_name + end + + def session_enabled? + request.session_options[:disabled] != false + end + + protected + # Renders the content that will be returned to the browser as the response body. + # + # === Rendering an action + # + # Action rendering is the most common form and the type used automatically by Action Controller when nothing else is + # specified. By default, actions are rendered within the current layout (if one exists). + # + # # Renders the template for the action "goal" within the current controller + # render :action => "goal" + # + # # Renders the template for the action "short_goal" within the current controller, + # # but without the current active layout + # render :action => "short_goal", :layout => false + # + # # Renders the template for the action "long_goal" within the current controller, + # # but with a custom layout + # render :action => "long_goal", :layout => "spectacular" + # + # _Deprecation_ _notice_: This used to have the signatures <tt>render_action("action", status = 200)</tt>, + # <tt>render_without_layout("controller/action", status = 200)</tt>, and + # <tt>render_with_layout("controller/action", status = 200, layout)</tt>. + # + # === Rendering partials + # + # Partial rendering is most commonly used together with Ajax calls that only update one or a few elements on a page + # without reloading. Rendering of partials from the controller makes it possible to use the same partial template in + # both the full-page rendering (by calling it from within the template) and when sub-page updates happen (from the + # controller action responding to Ajax calls). By default, the current layout is not used. + # + # # Renders the partial located at app/views/controller/_win.r(html|xml) + # render :partial => "win" + # + # # Renders the partial with a status code of 500 (internal error) + # render :partial => "broken", :status => 500 + # + # # Renders the same partial but also makes a local variable available to it + # render :partial => "win", :locals => { :name => "david" } + # + # # Renders a collection of the same partial by making each element of @wins available through + # # the local variable "win" as it builds the complete response + # render :partial => "win", :collection => @wins + # + # # Renders the same collection of partials, but also renders the win_divider partial in between + # # each win partial. + # render :partial => "win", :collection => @wins, :spacer_template => "win_divider" + # + # _Deprecation_ _notice_: This used to have the signatures + # <tt>render_partial(partial_path = default_template_name, object = nil, local_assigns = {})</tt> and + # <tt>render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = {})</tt>. + # + # === Rendering a template + # + # Template rendering works just like action rendering except that it takes a path relative to the template root. + # The current layout is automatically applied. + # + # # Renders the template located in [TEMPLATE_ROOT]/weblog/show.r(html|xml) (in Rails, app/views/weblog/show.rhtml) + # render :template => "weblog/show" + # + # === Rendering a file + # + # File rendering works just like action rendering except that it takes a filesystem path. By default, the path + # is assumed to be absolute, and the current layout is not applied. + # + # # Renders the template located at the absolute filesystem path + # render :file => "/path/to/some/template.rhtml" + # render :file => "c:/path/to/some/template.rhtml" + # + # # Renders a template within the current layout, and with a 404 status code + # render :file => "/path/to/some/template.rhtml", :layout => true, :status => 404 + # render :file => "c:/path/to/some/template.rhtml", :layout => true, :status => 404 + # + # # Renders a template relative to the template root and chooses the proper file extension + # render :file => "some/template", :use_full_path => true + # + # _Deprecation_ _notice_: This used to have the signature <tt>render_file(path, status = 200)</tt> + # + # === Rendering text + # + # Rendering of text is usually used for tests or for rendering prepared content, such as a cache. By default, text + # rendering is not done within the active layout. + # + # # Renders the clear text "hello world" with status code 200 + # render :text => "hello world!" + # + # # Renders the clear text "Explosion!" with status code 500 + # render :text => "Explosion!", :status => 500 + # + # # Renders the clear text "Hi there!" within the current active layout (if one exists) + # render :text => "Explosion!", :layout => true + # + # # Renders the clear text "Hi there!" within the layout + # # placed in "app/views/layouts/special.r(html|xml)" + # render :text => "Explosion!", :layout => "special" + # + # _Deprecation_ _notice_: This used to have the signature <tt>render_text("text", status = 200)</tt> + # + # === Rendering an inline template + # + # Rendering of an inline template works as a cross between text and action rendering where the source for the template + # is supplied inline, like text, but its interpreted with ERb or Builder, like action. By default, ERb is used for rendering + # and the current layout is not used. + # + # # Renders "hello, hello, hello, again" + # render :inline => "<%= 'hello, ' * 3 + 'again' %>" + # + # # Renders "<p>Good seeing you!</p>" using Builder + # render :inline => "xml.p { 'Good seeing you!' }", :type => :rxml + # + # # Renders "hello david" + # render :inline => "<%= 'hello ' + name %>", :locals => { :name => "david" } + # + # _Deprecation_ _notice_: This used to have the signature <tt>render_template(template, status = 200, type = :rhtml)</tt> + # + # === Rendering inline JavaScriptGenerator page updates + # + # In addition to rendering JavaScriptGenerator page updates with Ajax in RJS templates (see ActionView::Base for details), + # you can also pass the <tt>:update</tt> parameter to +render+, along with a block, to render page updates inline. + # + # render :update do |page| + # page.replace_html 'user_list', :partial => 'user', :collection => @users + # page.visual_effect :highlight, 'user_list' + # end + # + # === Rendering nothing + # + # Rendering nothing is often convenient in combination with Ajax calls that perform their effect client-side or + # when you just want to communicate a status code. Due to a bug in Safari, nothing actually means a single space. + # + # # Renders an empty response with status code 200 + # render :nothing => true + # + # # Renders an empty response with status code 401 (access denied) + # render :nothing => true, :status => 401 + def render(options = nil, deprecated_status = nil, &block) #:doc: + raise DoubleRenderError, "Can only render or redirect once per action" if performed? + + # Backwards compatibility + unless options.is_a?(Hash) + if options == :update + options = {:update => true} + else + return render_file(options || default_template_name, deprecated_status, true) + end + end + + if content_type = options[:content_type] + headers["Content-Type"] = content_type + end + + if text = options[:text] + render_text(text, options[:status]) + + else + if file = options[:file] + render_file(file, options[:status], options[:use_full_path], options[:locals] || {}) + + elsif template = options[:template] + render_file(template, options[:status], true) + + elsif inline = options[:inline] + render_template(inline, options[:status], options[:type], options[:locals] || {}) + + elsif action_name = options[:action] + render_action(action_name, options[:status], options[:layout]) + + elsif xml = options[:xml] + render_xml(xml, options[:status]) + + elsif partial = options[:partial] + partial = default_template_name if partial == true + if collection = options[:collection] + render_partial_collection(partial, collection, options[:spacer_template], options[:locals], options[:status]) + else + render_partial(partial, ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals], options[:status]) + end + + elsif options[:update] + add_variables_to_assigns + @template.send :evaluate_assigns + + generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block) + render_javascript(generator.to_s) + + elsif options[:nothing] + # Safari doesn't pass the headers of the return if the response is zero length + render_text(" ", options[:status]) + + else + render_file(default_template_name, options[:status], true) + + end + end + end + + # Renders according to the same rules as <tt>render</tt>, but returns the result in a string instead + # of sending it as the response body to the browser. + def render_to_string(options = nil, &block) #:doc: + result = render(options, &block) + + erase_render_results + forget_variables_added_to_assigns + reset_variables_added_to_assigns + + result + end + + def render_action(action_name, status = nil, with_layout = true) #:nodoc: + template = default_template_name(action_name.to_s) + if with_layout && !template_exempt_from_layout?(template) + render_with_layout(template, status) + else + render_without_layout(template, status) + end + end + + def render_file(template_path, status = nil, use_full_path = false, locals = {}) #:nodoc: + add_variables_to_assigns + assert_existence_of_template_file(template_path) if use_full_path + logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger + render_text(@template.render_file(template_path, use_full_path, locals), status) + end + + def render_template(template, status = nil, type = :rhtml, local_assigns = {}) #:nodoc: + add_variables_to_assigns + render_text(@template.render_template(type, template, nil, local_assigns), status) + end + + def render_text(text = nil, status = nil) #:nodoc: + @performed_render = true + @response.headers['Status'] = (status || DEFAULT_RENDER_STATUS_CODE).to_s + @response.body = text + end + + def render_javascript(javascript, status = nil) #:nodoc: + @response.headers['Content-Type'] = 'text/javascript; charset=UTF-8' + render_text(javascript, status) + end + + def render_xml(xml, status = nil) #:nodoc: + @response.headers['Content-Type'] = 'application/xml' + render_text(xml, status) + end + + def render_nothing(status = nil) #:nodoc: + render_text(' ', status) + end + + def render_partial(partial_path = default_template_name, object = nil, local_assigns = nil, status = nil) #:nodoc: + add_variables_to_assigns + render_text(@template.render_partial(partial_path, object, local_assigns), status) + end + + def render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = nil, status = nil) #:nodoc: + add_variables_to_assigns + render_text(@template.render_partial_collection(partial_name, collection, partial_spacer_template, local_assigns), status) + end + + def render_with_layout(template_name = default_template_name, status = nil, layout = nil) #:nodoc: + render_with_a_layout(template_name, status, layout) + end + + def render_without_layout(template_name = default_template_name, status = nil) #:nodoc: + render_with_no_layout(template_name, status) + end + + + # Clears the rendered results, allowing for another render to be performed. + def erase_render_results #:nodoc: + @response.body = nil + @performed_render = false + end + + # Clears the redirected results from the headers, resets the status to 200 and returns + # the URL that was used to redirect or nil if there was no redirected URL + # Note that +redirect_to+ will change the body of the response to indicate a redirection. + # The response body is not reset here, see +erase_render_results+ + def erase_redirect_results #:nodoc: + @performed_redirect = false + response.redirected_to = nil + response.redirected_to_method_params = nil + response.headers['Status'] = DEFAULT_RENDER_STATUS_CODE + response.headers.delete('location') + end + + # Erase both render and redirect results + def erase_results #:nodoc: + erase_render_results + erase_redirect_results + end + + def rewrite_options(options) #:nodoc: + if defaults = default_url_options(options) + defaults.merge(options) + else + options + end + end + + # Overwrite to implement a number of default options that all url_for-based methods will use. The default options should come in + # the form of a hash, just like the one you would use for url_for directly. Example: + # + # def default_url_options(options) + # { :project => @project.active? ? @project.url_name : "unknown" } + # end + # + # As you can infer from the example, this is mostly useful for situations where you want to centralize dynamic decisions about the + # urls as they stem from the business domain. Please note that any individual url_for call can always override the defaults set + # by this method. + def default_url_options(options) #:doc: + end + + # Redirects the browser to the target specified in +options+. This parameter can take one of three forms: + # + # * <tt>Hash</tt>: The URL will be generated by calling url_for with the +options+. + # * <tt>String starting with protocol:// (like http://)</tt>: Is passed straight through as the target for redirection. + # * <tt>String not containing a protocol</tt>: The current protocol and host is prepended to the string. + # * <tt>:back</tt>: Back to the page that issued the request. Useful for forms that are triggered from multiple places. + # Short-hand for redirect_to(request.env["HTTP_REFERER"]) + # + # Examples: + # redirect_to :action => "show", :id => 5 + # redirect_to "http://www.rubyonrails.org" + # redirect_to "/images/screenshot.jpg" + # redirect_to :back + # + # The redirection happens as a "302 Moved" header. + # + # When using <tt>redirect_to :back</tt>, if there is no referrer, + # RedirectBackError will be raised. You may specify some fallback + # behavior for this case by rescueing RedirectBackError. + def redirect_to(options = {}, *parameters_for_method_reference) #:doc: + case options + when %r{^\w+://.*} + raise DoubleRenderError if performed? + logger.info("Redirected to #{options}") if logger + response.redirect(options) + response.redirected_to = options + @performed_redirect = true + + when String + redirect_to(request.protocol + request.host_with_port + options) + + when :back + request.env["HTTP_REFERER"] ? redirect_to(request.env["HTTP_REFERER"]) : raise(RedirectBackError) + + else + if parameters_for_method_reference.empty? + redirect_to(url_for(options)) + response.redirected_to = options + else + redirect_to(url_for(options, *parameters_for_method_reference)) + response.redirected_to, response.redirected_to_method_params = options, parameters_for_method_reference + end + end + end + + # Sets a HTTP 1.1 Cache-Control header. Defaults to issuing a "private" instruction, so that + # intermediate caches shouldn't cache the response. + # + # Examples: + # expires_in 20.minutes + # expires_in 3.hours, :private => false + # expires in 3.hours, 'max-stale' => 5.hours, :private => nil, :public => true + # + # This method will overwrite an existing Cache-Control header. + # See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. + def expires_in(seconds, options = {}) #:doc: + cache_options = { 'max-age' => seconds, 'private' => true }.symbolize_keys.merge!(options.symbolize_keys) + cache_options.delete_if { |k,v| v.nil? or v == false } + cache_control = cache_options.map{ |k,v| v == true ? k.to_s : "#{k.to_s}=#{v.to_s}"} + @response.headers["Cache-Control"] = cache_control.join(', ') + end + + # Sets a HTTP 1.1 Cache-Control header of "no-cache" so no caching should occur by the browser or + # intermediate caches (like caching proxy servers). + def expires_now #:doc: + @response.headers["Cache-Control"] = "no-cache" + end + + # Resets the session by clearing out all the objects stored within and initializing a new session object. + def reset_session #:doc: + @request.reset_session + @session = @request.session + @response.session = @session + end + + private + def self.view_class + @view_class ||= + # create a new class based on the default template class and include helper methods + returning Class.new(ActionView::Base) do |view_class| + view_class.send(:include, master_helper_module) + end + end + + def self.view_root + @view_root ||= template_root + end + + def initialize_template_class(response) + raise "You must assign a template class through ActionController.template_class= before processing a request" unless @@template_class + + response.template = self.class.view_class.new(self.class.view_root, {}, self) + response.redirected_to = nil + @performed_render = @performed_redirect = false + end + + def assign_shortcuts(request, response) + @request, @params, @cookies = request, request.parameters, request.cookies + + @response = response + @response.session = request.session + + @session = @response.session + @template = @response.template + @assigns = @response.template.assigns + + @headers = @response.headers + end + + def initialize_current_url + @url = UrlRewriter.new(@request, @params.clone()) + end + + def log_processing + if logger + logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]" + logger.info " Session ID: #{@session.session_id}" if @session and @session.respond_to?(:session_id) + logger.info " Parameters: #{respond_to?(:filter_parameters) ? filter_parameters(@params).inspect : @params.inspect}" + end + end + + def perform_action + if self.class.action_methods.include?(action_name) || self.class.action_methods.include?('method_missing') + send(action_name) + render unless performed? + elsif template_exists? && template_public? + render + else + raise UnknownAction, "No action responded to #{action_name}", caller + end + end + + def performed? + @performed_render || @performed_redirect + end + + def assign_names + @action_name = (params['action'] || 'index') + end + + def action_methods + self.class.action_methods + end + + def self.action_methods + @action_methods ||= Set.new(public_instance_methods - hidden_actions) + end + + def add_variables_to_assigns + unless @variables_added + add_instance_variables_to_assigns + add_class_variables_to_assigns if view_controller_internals + @variables_added = true + end + end + + def forget_variables_added_to_assigns + @variables_added = nil + end + + def reset_variables_added_to_assigns + @template.instance_variable_set("@assigns_added", nil) + end + + def add_instance_variables_to_assigns + @@protected_variables_cache ||= protected_instance_variables.inject({}) { |h, k| h[k] = true; h } + instance_variables.each do |var| + next if @@protected_variables_cache.include?(var) + @assigns[var[1..-1]] = instance_variable_get(var) + end + end + + def add_class_variables_to_assigns + %w( template_root logger template_class ignore_missing_templates ).each do |cvar| + @assigns[cvar] = self.send(cvar) + end + end + + def protected_instance_variables + if view_controller_internals + [ "@assigns", "@performed_redirect", "@performed_render" ] + else + [ "@assigns", "@performed_redirect", "@performed_render", "@request", "@response", "@session", "@cookies", "@template", "@request_origin", "@parent_controller" ] + end + end + + def request_origin + # this *needs* to be cached! + # otherwise you'd get different results if calling it more than once + @request_origin ||= "#{@request.remote_ip} at #{Time.now.to_s(:db)}" + end + + def complete_request_uri + "#{@request.protocol}#{@request.host}#{@request.request_uri}" + end + + def close_session + @session.close unless @session.nil? || Hash === @session + end + + def template_exists?(template_name = default_template_name) + @template.file_exists?(template_name) + end + + def template_public?(template_name = default_template_name) + @template.file_public?(template_name) + end + + def template_exempt_from_layout?(template_name = default_template_name) + template_name =~ /\.rjs$/ || (@template.pick_template_extension(template_name) == :rjs rescue false) + end + + def assert_existence_of_template_file(template_name) + unless template_exists?(template_name) || ignore_missing_templates + full_template_path = @template.send(:full_template_path, template_name, 'rhtml') + template_type = (template_name =~ /layouts/i) ? 'layout' : 'template' + raise(MissingTemplate, "Missing #{template_type} #{full_template_path}") + end + end + + def default_template_name(action_name = self.action_name) + if action_name + action_name = action_name.to_s + if action_name.include?('/') && template_path_includes_controller?(action_name) + action_name = strip_out_controller(action_name) + end + end + "#{self.class.controller_path}/#{action_name}" + end + + def strip_out_controller(path) + path.split('/', 2).last + end + + def template_path_includes_controller?(path) + self.class.controller_path.split('/')[-1] == path.split('/')[0] + end + + def process_cleanup + close_session + end + end +end +require 'benchmark' + +module ActionController #:nodoc: + # The benchmarking module times the performance of actions and reports to the logger. If the Active Record + # package has been included, a separate timing section for database calls will be added as well. + module Benchmarking #:nodoc: + def self.included(base) + base.extend(ClassMethods) + + base.class_eval do + alias_method :perform_action_without_benchmark, :perform_action + alias_method :perform_action, :perform_action_with_benchmark + + alias_method :render_without_benchmark, :render + alias_method :render, :render_with_benchmark + end + end + + module ClassMethods + # Log and benchmark the workings of a single block and silence whatever logging that may have happened inside it + # (unless <tt>use_silence</tt> is set to false). + # + # The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it + # easy to include benchmarking statements in production software that will remain inexpensive because the benchmark + # will only be conducted if the log level is low enough. + def benchmark(title, log_level = Logger::DEBUG, use_silence = true) + if logger && logger.level == log_level + result = nil + seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield } + logger.add(log_level, "#{title} (#{'%.5f' % seconds})") + result + else + yield + end + end + + # Silences the logger for the duration of the block. + def silence + old_logger_level, logger.level = logger.level, Logger::ERROR if logger + yield + ensure + logger.level = old_logger_level if logger + end + end + + def render_with_benchmark(options = nil, deprecated_status = nil, &block) + unless logger + render_without_benchmark(options, deprecated_status, &block) + else + db_runtime = ActiveRecord::Base.connection.reset_runtime if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? + + render_output = nil + @rendering_runtime = Benchmark::measure{ render_output = render_without_benchmark(options, deprecated_status, &block) }.real + + if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? + @db_rt_before_render = db_runtime + @db_rt_after_render = ActiveRecord::Base.connection.reset_runtime + @rendering_runtime -= @db_rt_after_render + end + + render_output + end + end + + def perform_action_with_benchmark + unless logger + perform_action_without_benchmark + else + runtime = [Benchmark::measure{ perform_action_without_benchmark }.real, 0.0001].max + log_message = "Completed in #{sprintf("%.5f", runtime)} (#{(1 / runtime).floor} reqs/sec)" + log_message << rendering_runtime(runtime) if @rendering_runtime + log_message << active_record_runtime(runtime) if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected? + log_message << " | #{headers["Status"]}" + log_message << " [#{complete_request_uri rescue "unknown"}]" + logger.info(log_message) + end + end + + private + def rendering_runtime(runtime) + " | Rendering: #{sprintf("%.5f", @rendering_runtime)} (#{sprintf("%d", (@rendering_runtime * 100) / runtime)}%)" + end + + def active_record_runtime(runtime) + db_runtime = ActiveRecord::Base.connection.reset_runtime + db_runtime += @db_rt_before_render if @db_rt_before_render + db_runtime += @db_rt_after_render if @db_rt_after_render + db_percentage = (db_runtime * 100) / runtime + " | DB: #{sprintf("%.5f", db_runtime)} (#{sprintf("%d", db_percentage)}%)" + end + end +end +require 'fileutils' + +module ActionController #:nodoc: + # Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls + # around for subsequent requests. Action Controller affords you three approaches in varying levels of granularity: Page, Action, Fragment. + # + # You can read more about each approach and the sweeping assistance by clicking the modules below. + # + # Note: To turn off all caching and sweeping, set Base.perform_caching = false. + module Caching + def self.included(base) #:nodoc: + base.send(:include, Pages, Actions, Fragments, Sweeping) + + base.class_eval do + @@perform_caching = true + cattr_accessor :perform_caching + end + end + + # Page caching is an approach to caching where the entire action output of is stored as a HTML file that the web server + # can serve without going through the Action Pack. This can be as much as 100 times faster than going through the process of dynamically + # generating the content. Unfortunately, this incredible speed-up is only available to stateless pages where all visitors + # are treated the same. Content management systems -- including weblogs and wikis -- have many pages that are a great fit + # for this approach, but account-based systems where people log in and manipulate their own data are often less likely candidates. + # + # Specifying which actions to cache is done through the <tt>caches</tt> class method: + # + # class WeblogController < ActionController::Base + # caches_page :show, :new + # end + # + # This will generate cache files such as weblog/show/5 and weblog/new, which match the URLs used to trigger the dynamic + # generation. This is how the web server is able pick up a cache file when it exists and otherwise let the request pass on to + # the Action Pack to generate it. + # + # Expiration of the cache is handled by deleting the cached file, which results in a lazy regeneration approach where the cache + # is not restored before another hit is made against it. The API for doing so mimics the options from url_for and friends: + # + # class WeblogController < ActionController::Base + # def update + # List.update(params[:list][:id], params[:list]) + # expire_page :action => "show", :id => params[:list][:id] + # redirect_to :action => "show", :id => params[:list][:id] + # end + # end + # + # Additionally, you can expire caches using Sweepers that act on changes in the model to determine when a cache is supposed to be + # expired. + # + # == Setting the cache directory + # + # The cache directory should be the document root for the web server and is set using Base.page_cache_directory = "/document/root". + # For Rails, this directory has already been set to RAILS_ROOT + "/public". + # + # == Setting the cache extension + # + # By default, the cache extension is .html, which makes it easy for the cached files to be picked up by the web server. If you want + # something else, like .php or .shtml, just set Base.page_cache_extension. + module Pages + def self.included(base) #:nodoc: + base.extend(ClassMethods) + base.class_eval do + @@page_cache_directory = defined?(RAILS_ROOT) ? "#{RAILS_ROOT}/public" : "" + cattr_accessor :page_cache_directory + + @@page_cache_extension = '.html' + cattr_accessor :page_cache_extension + end + end + + module ClassMethods + # Expires the page that was cached with the +path+ as a key. Example: + # expire_page "/lists/show" + def expire_page(path) + return unless perform_caching + + benchmark "Expired page: #{page_cache_file(path)}" do + File.delete(page_cache_path(path)) if File.exists?(page_cache_path(path)) + end + end + + # Manually cache the +content+ in the key determined by +path+. Example: + # cache_page "I'm the cached content", "/lists/show" + def cache_page(content, path) + return unless perform_caching + + benchmark "Cached page: #{page_cache_file(path)}" do + FileUtils.makedirs(File.dirname(page_cache_path(path))) + File.open(page_cache_path(path), "wb+") { |f| f.write(content) } + end + end + + # Caches the +actions+ using the page-caching approach that'll store the cache in a path within the page_cache_directory that + # matches the triggering url. + def caches_page(*actions) + return unless perform_caching + actions.each do |action| + class_eval "after_filter { |c| c.cache_page if c.action_name == '#{action}' }" + end + end + + private + def page_cache_file(path) + name = ((path.empty? || path == "/") ? "/index" : URI.unescape(path)) + name << page_cache_extension unless (name.split('/').last || name).include? '.' + return name + end + + def page_cache_path(path) + page_cache_directory + page_cache_file(path) + end + end + + # Expires the page that was cached with the +options+ as a key. Example: + # expire_page :controller => "lists", :action => "show" + def expire_page(options = {}) + return unless perform_caching + if options[:action].is_a?(Array) + options[:action].dup.each do |action| + self.class.expire_page(url_for(options.merge({ :only_path => true, :skip_relative_url_root => true, :action => action }))) + end + else + self.class.expire_page(url_for(options.merge({ :only_path => true, :skip_relative_url_root => true }))) + end + end + + # Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of @response.body is used + # If no options are provided, the current +options+ for this action is used. Example: + # cache_page "I'm the cached content", :controller => "lists", :action => "show" + def cache_page(content = nil, options = {}) + return unless perform_caching && caching_allowed + self.class.cache_page(content || @response.body, url_for(options.merge({ :only_path => true, :skip_relative_url_root => true }))) + end + + private + def caching_allowed + !@request.post? && @response.headers['Status'] && @response.headers['Status'].to_i < 400 + end + end + + # Action caching is similar to page caching by the fact that the entire output of the response is cached, but unlike page caching, + # every request still goes through the Action Pack. The key benefit of this is that filters are run before the cache is served, which + # allows for authentication and other restrictions on whether someone is allowed to see the cache. Example: + # + # class ListsController < ApplicationController + # before_filter :authenticate, :except => :public + # caches_page :public + # caches_action :show, :feed + # end + # + # In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the + # show and feed action are to be shielded behind the authenticate filter, so we need to implement those as action caches. + # + # Action caching internally uses the fragment caching and an around filter to do the job. The fragment cache is named according to both + # the current host and the path. So a page that is accessed at http://david.somewhere.com/lists/show/1 will result in a fragment named + # "david.somewhere.com/lists/show/1". This allows the cacher to differentiate between "david.somewhere.com/lists/" and + # "jamis.somewhere.com/lists/" -- which is a helpful way of assisting the subdomain-as-account-key pattern. + module Actions + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + base.send(:attr_accessor, :rendered_action_cache) + end + + module ClassMethods #:nodoc: + def caches_action(*actions) + return unless perform_caching + around_filter(ActionCacheFilter.new(*actions)) + end + end + + def expire_action(options = {}) + return unless perform_caching + if options[:action].is_a?(Array) + options[:action].dup.each do |action| + expire_fragment(url_for(options.merge({ :action => action })).split("://").last) + end + else + expire_fragment(url_for(options).split("://").last) + end + end + + class ActionCacheFilter #:nodoc: + def initialize(*actions) + @actions = actions + end + + def before(controller) + return unless @actions.include?(controller.action_name.intern) + if cache = controller.read_fragment(controller.url_for.split("://").last) + controller.rendered_action_cache = true + controller.send(:render_text, cache) + false + end + end + + def after(controller) + return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache + controller.write_fragment(controller.url_for.split("://").last, controller.response.body) + end + end + end + + # Fragment caching is used for caching various blocks within templates without caching the entire action as a whole. This is useful when + # certain elements of an action change frequently or depend on complicated state while other parts rarely change or can be shared amongst multiple + # parties. The caching is doing using the cache helper available in the Action View. A template with caching might look something like: + # + # <b>Hello <%= @name %></b> + # <% cache do %> + # All the topics in the system: + # <%= render_collection_of_partials "topic", Topic.find_all %> + # <% end %> + # + # This cache will bind to the name of action that called it. So you would be able to invalidate it using + # <tt>expire_fragment(:controller => "topics", :action => "list")</tt> -- if that was the controller/action used. This is not too helpful + # if you need to cache multiple fragments per action or if the action itself is cached using <tt>caches_action</tt>. So instead we should + # qualify the name of the action used with something like: + # + # <% cache(:action => "list", :action_suffix => "all_topics") do %> + # + # That would result in a name such as "/topics/list/all_topics", which wouldn't conflict with any action cache and neither with another + # fragment using a different suffix. Note that the URL doesn't have to really exist or be callable. We're just using the url_for system + # to generate unique cache names that we can refer to later for expirations. The expiration call for this example would be + # <tt>expire_fragment(:controller => "topics", :action => "list", :action_suffix => "all_topics")</tt>. + # + # == Fragment stores + # + # In order to use the fragment caching, you need to designate where the caches should be stored. This is done by assigning a fragment store + # of which there are four different kinds: + # + # * FileStore: Keeps the fragments on disk in the +cache_path+, which works well for all types of environments and shares the fragments for + # all the web server processes running off the same application directory. + # * MemoryStore: Keeps the fragments in memory, which is fine for WEBrick and for FCGI (if you don't care that each FCGI process holds its + # own fragment store). It's not suitable for CGI as the process is thrown away at the end of each request. It can potentially also take + # up a lot of memory since each process keeps all the caches in memory. + # * DRbStore: Keeps the fragments in the memory of a separate, shared DRb process. This works for all environments and only keeps one cache + # around for all processes, but requires that you run and manage a separate DRb process. + # * MemCacheStore: Works like DRbStore, but uses Danga's MemCache instead. + # Requires the ruby-memcache library: gem install ruby-memcache. + # + # Configuration examples (MemoryStore is the default): + # + # ActionController::Base.fragment_cache_store = :memory_store + # ActionController::Base.fragment_cache_store = :file_store, "/path/to/cache/directory" + # ActionController::Base.fragment_cache_store = :drb_store, "druby://localhost:9192" + # ActionController::Base.fragment_cache_store = :mem_cache_store, "localhost" + # ActionController::Base.fragment_cache_store = MyOwnStore.new("parameter") + module Fragments + def self.append_features(base) #:nodoc: + super + base.class_eval do + @@fragment_cache_store = MemoryStore.new + cattr_reader :fragment_cache_store + + def self.fragment_cache_store=(store_option) + store, *parameters = *([ store_option ].flatten) + @@fragment_cache_store = if store.is_a?(Symbol) + store_class_name = (store == :drb_store ? "DRbStore" : store.to_s.camelize) + store_class = ActionController::Caching::Fragments.const_get(store_class_name) + store_class.new(*parameters) + else + store + end + end + end + end + + def fragment_cache_key(name) + name.is_a?(Hash) ? url_for(name).split("://").last : name + end + + # Called by CacheHelper#cache + def cache_erb_fragment(block, name = {}, options = nil) + unless perform_caching then block.call; return end + + buffer = eval("_erbout", block.binding) + + if cache = read_fragment(name, options) + buffer.concat(cache) + else + pos = buffer.length + block.call + write_fragment(name, buffer[pos..-1], options) + end + end + + def write_fragment(name, content, options = nil) + return unless perform_caching + + key = fragment_cache_key(name) + self.class.benchmark "Cached fragment: #{key}" do + fragment_cache_store.write(key, content, options) + end + content + end + + def read_fragment(name, options = nil) + return unless perform_caching + + key = fragment_cache_key(name) + self.class.benchmark "Fragment read: #{key}" do + fragment_cache_store.read(key, options) + end + end + + # Name can take one of three forms: + # * String: This would normally take the form of a path like "pages/45/notes" + # * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 } + # * Regexp: Will destroy all the matched fragments, example: %r{pages/\d*/notes} Ensure you do not specify start and finish in the regex (^$) because the actual filename matched looks like ./cache/filename/path.cache + def expire_fragment(name, options = nil) + return unless perform_caching + + key = fragment_cache_key(name) + + if key.is_a?(Regexp) + self.class.benchmark "Expired fragments matching: #{key.source}" do + fragment_cache_store.delete_matched(key, options) + end + else + self.class.benchmark "Expired fragment: #{key}" do + fragment_cache_store.delete(key, options) + end + end + end + + # Deprecated -- just call expire_fragment with a regular expression + def expire_matched_fragments(matcher = /.*/, options = nil) #:nodoc: + expire_fragment(matcher, options) + end + + + class UnthreadedMemoryStore #:nodoc: + def initialize #:nodoc: + @data = {} + end + + def read(name, options=nil) #:nodoc: + @data[name] + end + + def write(name, value, options=nil) #:nodoc: + @data[name] = value + end + + def delete(name, options=nil) #:nodoc: + @data.delete(name) + end + + def delete_matched(matcher, options=nil) #:nodoc: + @data.delete_if { |k,v| k =~ matcher } + end + end + + module ThreadSafety #:nodoc: + def read(name, options=nil) #:nodoc: + @mutex.synchronize { super } + end + + def write(name, value, options=nil) #:nodoc: + @mutex.synchronize { super } + end + + def delete(name, options=nil) #:nodoc: + @mutex.synchronize { super } + end + + def delete_matched(matcher, options=nil) #:nodoc: + @mutex.synchronize { super } + end + end + + class MemoryStore < UnthreadedMemoryStore #:nodoc: + def initialize #:nodoc: + super + if ActionController::Base.allow_concurrency + @mutex = Mutex.new + MemoryStore.send(:include, ThreadSafety) + end + end + end + + class DRbStore < MemoryStore #:nodoc: + attr_reader :address + + def initialize(address = 'druby://localhost:9192') + super() + @address = address + @data = DRbObject.new(nil, address) + end + end + + class MemCacheStore < MemoryStore #:nodoc: + attr_reader :addresses + + def initialize(*addresses) + super() + addresses = addresses.flatten + addresses = ["localhost"] if addresses.empty? + @addresses = addresses + @data = MemCache.new(*addresses) + end + end + + class UnthreadedFileStore #:nodoc: + attr_reader :cache_path + + def initialize(cache_path) + @cache_path = cache_path + end + + def write(name, value, options = nil) #:nodoc: + ensure_cache_path(File.dirname(real_file_path(name))) + File.open(real_file_path(name), "wb+") { |f| f.write(value) } + rescue => e + Base.logger.error "Couldn't create cache directory: #{name} (#{e.message})" if Base.logger + end + + def read(name, options = nil) #:nodoc: + File.open(real_file_path(name), 'rb') { |f| f.read } rescue nil + end + + def delete(name, options) #:nodoc: + File.delete(real_file_path(name)) + rescue SystemCallError => e + # If there's no cache, then there's nothing to complain about + end + + def delete_matched(matcher, options) #:nodoc: + search_dir(@cache_path) do |f| + if f =~ matcher + begin + File.delete(f) + rescue Object => e + # If there's no cache, then there's nothing to complain about + end + end + end + end + + private + def real_file_path(name) + '%s/%s.cache' % [@cache_path, name.gsub('?', '.').gsub(':', '.')] + end + + def ensure_cache_path(path) + FileUtils.makedirs(path) unless File.exists?(path) + end + + def search_dir(dir, &callback) + Dir.foreach(dir) do |d| + next if d == "." || d == ".." + name = File.join(dir, d) + if File.directory?(name) + search_dir(name, &callback) + else + callback.call name + end + end + end + end + + class FileStore < UnthreadedFileStore #:nodoc: + def initialize(cache_path) + super(cache_path) + if ActionController::Base.allow_concurrency + @mutex = Mutex.new + FileStore.send(:include, ThreadSafety) + end + end + end + end + + # Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change. + # They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example: + # + # class ListSweeper < ActionController::Caching::Sweeper + # observe List, Item + # + # def after_save(record) + # list = record.is_a?(List) ? record : record.list + # expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id) + # expire_action(:controller => "lists", :action => "all") + # list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key) } + # end + # end + # + # The sweeper is assigned in the controllers that wish to have its job performed using the <tt>cache_sweeper</tt> class method: + # + # class ListsController < ApplicationController + # caches_action :index, :show, :public, :feed + # cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ] + # end + # + # In the example above, four actions are cached and three actions are responsible for expiring those caches. + module Sweeping + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + end + + module ClassMethods #:nodoc: + def cache_sweeper(*sweepers) + return unless perform_caching + configuration = sweepers.last.is_a?(Hash) ? sweepers.pop : {} + sweepers.each do |sweeper| + observer(sweeper) + + sweeper_instance = Object.const_get(Inflector.classify(sweeper)).instance + + if sweeper_instance.is_a?(Sweeper) + around_filter(sweeper_instance, :only => configuration[:only]) + else + after_filter(sweeper_instance, :only => configuration[:only]) + end + end + end + end + end + + if defined?(ActiveRecord) and defined?(ActiveRecord::Observer) + class Sweeper < ActiveRecord::Observer #:nodoc: + attr_accessor :controller + + # ActiveRecord::Observer will mark this class as reloadable even though it should not be. + # However, subclasses of ActionController::Caching::Sweeper should be Reloadable + include Reloadable::Subclasses + + def before(controller) + self.controller = controller + callback(:before) + end + + def after(controller) + callback(:after) + # Clean up, so that the controller can be collected after this request + self.controller = nil + end + + private + def callback(timing) + controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}" + action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}" + + send(controller_callback_method_name) if respond_to?(controller_callback_method_name) + send(action_callback_method_name) if respond_to?(action_callback_method_name) + end + + def method_missing(method, *arguments) + return if @controller.nil? + @controller.send(method, *arguments) + end + end + end + end +end +require 'cgi' +require 'cgi/session' +require 'cgi/session/pstore' +require 'action_controller/cgi_ext/cgi_methods' + +# Wrapper around the CGIMethods that have been secluded to allow testing without +# an instantiated CGI object +class CGI #:nodoc: + class << self + alias :escapeHTML_fail_on_nil :escapeHTML + + def escapeHTML(string) + escapeHTML_fail_on_nil(string) unless string.nil? + end + end + + # Returns a parameter hash including values from both the request (POST/GET) + # and the query string with the latter taking precedence. + def parameters + request_parameters.update(query_parameters) + end + + def query_parameters + CGIMethods.parse_query_parameters(query_string) + end + + def request_parameters + CGIMethods.parse_request_parameters(params, env_table) + end + + def redirect(where) + header({ + "Status" => "302 Moved", + "location" => "#{where}" + }) + end + + def session(parameters = nil) + parameters = {} if parameters.nil? + parameters['database_manager'] = CGI::Session::PStore + CGI::Session.new(self, parameters) + end +end +require 'cgi' +require 'action_controller/vendor/xml_simple' +require 'action_controller/vendor/xml_node' + +# Static methods for parsing the query and request parameters that can be used in +# a CGI extension class or testing in isolation. +class CGIMethods #:nodoc: + public + # Returns a hash with the pairs from the query string. The implicit hash construction that is done in + # parse_request_params is not done here. + def CGIMethods.parse_query_parameters(query_string) + parsed_params = {} + + query_string.split(/[&;]/).each { |p| + # Ignore repeated delimiters. + next if p.empty? + + k, v = p.split('=',2) + v = nil if (v && v.empty?) + + k = CGI.unescape(k) if k + v = CGI.unescape(v) if v + + unless k.include?(?[) + parsed_params[k] = v + else + keys = split_key(k) + last_key = keys.pop + last_key = keys.pop if (use_array = last_key.empty?) + parent = keys.inject(parsed_params) {|h, k| h[k] ||= {}} + + if use_array then (parent[last_key] ||= []) << v + else parent[last_key] = v + end + end + } + + parsed_params + end + + # Returns the request (POST/GET) parameters in a parsed form where pairs such as "customer[address][street]" / + # "Somewhere cool!" are translated into a full hash hierarchy, like + # { "customer" => { "address" => { "street" => "Somewhere cool!" } } } + def CGIMethods.parse_request_parameters(params) + parsed_params = {} + + for key, value in params + value = [value] if key =~ /.*\[\]$/ + unless key.include?('[') + # much faster to test for the most common case first (GET) + # and avoid the call to build_deep_hash + parsed_params[key] = get_typed_value(value[0]) + else + build_deep_hash(get_typed_value(value[0]), parsed_params, get_levels(key)) + end + end + + parsed_params + end + + def self.parse_formatted_request_parameters(mime_type, raw_post_data) + params = case strategy = ActionController::Base.param_parsers[mime_type] + when Proc + strategy.call(raw_post_data) + when :xml_simple + raw_post_data.blank? ? nil : + typecast_xml_value(XmlSimple.xml_in(raw_post_data, + 'forcearray' => false, + 'forcecontent' => true, + 'keeproot' => true, + 'contentkey' => '__content__')) + when :yaml + YAML.load(raw_post_data) + when :xml_node + node = XmlNode.from_xml(raw_post_data) + { node.node_name => node } + end + + dasherize_keys(params || {}) + rescue Object => e + { "exception" => "#{e.message} (#{e.class})", "backtrace" => e.backtrace, + "raw_post_data" => raw_post_data, "format" => mime_type } + end + + def self.typecast_xml_value(value) + case value + when Hash + if value.has_key?("__content__") + content = translate_xml_entities(value["__content__"]) + case value["type"] + when "integer" then content.to_i + when "boolean" then content == "true" + when "datetime" then Time.parse(content) + when "date" then Date.parse(content) + else content + end + else + value.empty? ? nil : value.inject({}) do |h,(k,v)| + h[k] = typecast_xml_value(v) + h + end + end + when Array + value.map! { |i| typecast_xml_value(i) } + case value.length + when 0 then nil + when 1 then value.first + else value + end + else + raise "can't typecast #{value.inspect}" + end + end + + private + + def self.translate_xml_entities(value) + value.gsub(/</, "<"). + gsub(/>/, ">"). + gsub(/"/, '"'). + gsub(/'/, "'"). + gsub(/&/, "&") + end + + def self.dasherize_keys(params) + case params.class.to_s + when "Hash" + params.inject({}) do |h,(k,v)| + h[k.to_s.tr("-", "_")] = dasherize_keys(v) + h + end + when "Array" + params.map { |v| dasherize_keys(v) } + else + params + end + end + + # Splits the given key into several pieces. Example keys are 'name', 'person[name]', + # 'person[name][first]', and 'people[]'. In each instance, an Array instance is returned. + # 'person[name][first]' produces ['person', 'name', 'first']; 'people[]' produces ['people', ''] + def CGIMethods.split_key(key) + if /^([^\[]+)((?:\[[^\]]*\])+)$/ =~ key + keys = [$1] + + keys.concat($2[1..-2].split('][')) + keys << '' if key[-2..-1] == '[]' # Have to add it since split will drop empty strings + + keys + else + [key] + end + end + + def CGIMethods.get_typed_value(value) + # test most frequent case first + if value.is_a?(String) + value + elsif value.respond_to?(:content_type) && ! value.content_type.blank? + # Uploaded file + unless value.respond_to?(:full_original_filename) + class << value + alias_method :full_original_filename, :original_filename + + # Take the basename of the upload's original filename. + # This handles the full Windows paths given by Internet Explorer + # (and perhaps other broken user agents) without affecting + # those which give the lone filename. + # The Windows regexp is adapted from Perl's File::Basename. + def original_filename + if md = /^(?:.*[:\\\/])?(.*)/m.match(full_original_filename) + md.captures.first + else + File.basename full_original_filename + end + end + end + end + + # Return the same value after overriding original_filename. + value + + elsif value.respond_to?(:read) + # Value as part of a multipart request + value.read + elsif value.class == Array + value.collect { |v| CGIMethods.get_typed_value(v) } + else + # other value (neither string nor a multipart request) + value.to_s + end + end + + PARAMS_HASH_RE = /^([^\[]+)(\[.*\])?(.)?.*$/ + def CGIMethods.get_levels(key) + all, main, bracketed, trailing = PARAMS_HASH_RE.match(key).to_a + if main.nil? + [] + elsif trailing + [key] + elsif bracketed + [main] + bracketed.slice(1...-1).split('][') + else + [main] + end + end + + def CGIMethods.build_deep_hash(value, hash, levels) + if levels.length == 0 + value + elsif hash.nil? + { levels.first => CGIMethods.build_deep_hash(value, nil, levels[1..-1]) } + else + hash.update({ levels.first => CGIMethods.build_deep_hash(value, hash[levels.first], levels[1..-1]) }) + end + end +end +CGI.module_eval { remove_const "Cookie" } + +class CGI #:nodoc: + # This is a cookie class that fixes the performance problems with the default one that ships with 1.8.1 and below. + # It replaces the inheritance on SimpleDelegator with DelegateClass(Array) following the suggestion from Matz on + # http://groups.google.com/groups?th=e3a4e68ba042f842&seekm=c3sioe%241qvm%241%40news.cybercity.dk#link14 + class Cookie < DelegateClass(Array) + # Create a new CGI::Cookie object. + # + # The contents of the cookie can be specified as a +name+ and one + # or more +value+ arguments. Alternatively, the contents can + # be specified as a single hash argument. The possible keywords of + # this hash are as follows: + # + # name:: the name of the cookie. Required. + # value:: the cookie's value or list of values. + # path:: the path for which this cookie applies. Defaults to the + # base directory of the CGI script. + # domain:: the domain for which this cookie applies. + # expires:: the time at which this cookie expires, as a +Time+ object. + # secure:: whether this cookie is a secure cookie or not (default to + # false). Secure cookies are only transmitted to HTTPS + # servers. + # + # These keywords correspond to attributes of the cookie object. + def initialize(name = '', *value) + if name.kind_of?(String) + @name = name + @value = Array(value) + @domain = nil + @expires = nil + @secure = false + @path = nil + else + @name = name['name'] + @value = Array(name['value']) + @domain = name['domain'] + @expires = name['expires'] + @secure = name['secure'] || false + @path = name['path'] + end + + unless @name + raise ArgumentError, "`name' required" + end + + # simple support for IE + unless @path + %r|^(.*/)|.match(ENV['SCRIPT_NAME']) + @path = ($1 or '') + end + + super(@value) + end + + def __setobj__(obj) + @_dc_obj = obj + end + + attr_accessor("name", "value", "path", "domain", "expires") + attr_reader("secure") + + # Set whether the Cookie is a secure cookie or not. + # + # +val+ must be a boolean. + def secure=(val) + @secure = val if val == true or val == false + @secure + end + + # Convert the Cookie to its string representation. + def to_s + buf = "" + buf << @name << '=' + + if @value.kind_of?(String) + buf << CGI::escape(@value) + else + buf << @value.collect{|v| CGI::escape(v) }.join("&") + end + + if @domain + buf << '; domain=' << @domain + end + + if @path + buf << '; path=' << @path + end + + if @expires + buf << '; expires=' << CGI::rfc1123_date(@expires) + end + + if @secure == true + buf << '; secure' + end + + buf + end + + # Parse a raw cookie string into a hash of cookie-name=>Cookie + # pairs. + # + # cookies = CGI::Cookie::parse("raw_cookie_string") + # # { "name1" => cookie1, "name2" => cookie2, ... } + # + def self.parse(raw_cookie) + cookies = Hash.new([]) + + if raw_cookie + raw_cookie.split(/; ?/).each do |pairs| + name, values = pairs.split('=',2) + next unless name and values + name = CGI::unescape(name) + values = values.split('&').collect!{|v| CGI::unescape(v) } + unless cookies.has_key?(name) + cookies[name] = new(name, *values) + end + end + end + + cookies + end + end # class Cookie +end +class CGI #:nodoc: + # Add @request.env['RAW_POST_DATA'] for the vegans. + module QueryExtension + # Initialize the data from the query. + # + # Handles multipart forms (in particular, forms that involve file uploads). + # Reads query parameters in the @params field, and cookies into @cookies. + def initialize_query() + @cookies = CGI::Cookie::parse(env_table['HTTP_COOKIE'] || env_table['COOKIE']) + + #fix some strange request environments + if method = env_table['REQUEST_METHOD'] + method = method.to_s.downcase.intern + else + method = :get + end + + if method == :post && (boundary = multipart_form_boundary) + @multipart = true + @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH'])) + else + @multipart = false + @params = CGI::parse(read_query_params(method) || "") + end + end + + private + unless defined?(MULTIPART_FORM_BOUNDARY_RE) + MULTIPART_FORM_BOUNDARY_RE = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n #" + end + + def multipart_form_boundary + MULTIPART_FORM_BOUNDARY_RE.match(env_table['CONTENT_TYPE']).to_a.pop + end + + if defined? MOD_RUBY + def read_params_from_query + Apache::request.args || '' + end + else + def read_params_from_query + # fixes CGI querystring parsing for lighttpd + env_qs = env_table['QUERY_STRING'] + if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank? + uri.split('?', 2)[1] || '' + else + env_qs + end + end + end + + def read_params_from_post + stdinput.binmode if stdinput.respond_to?(:binmode) + content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) || '' + # fix for Safari Ajax postings that always append \000 + content.chop! if content[-1] == 0 + content.gsub! /&_=$/, '' + env_table['RAW_POST_DATA'] = content.freeze + end + + def read_query_params(method) + case method + when :get + read_params_from_query + when :post, :put + read_params_from_post + when :cmd + read_from_cmdline + else # when :head, :delete, :options + read_params_from_query + end + end + end # module QueryExtension +end +require 'action_controller/cgi_ext/cgi_ext' +require 'action_controller/cgi_ext/cookie_performance_fix' +require 'action_controller/cgi_ext/raw_post_data_fix' + +module ActionController #:nodoc: + class Base + # Process a request extracted from an CGI object and return a response. Pass false as <tt>session_options</tt> to disable + # sessions (large performance increase if sessions are not needed). The <tt>session_options</tt> are the same as for CGI::Session: + # + # * <tt>:database_manager</tt> - standard options are CGI::Session::FileStore, CGI::Session::MemoryStore, and CGI::Session::PStore + # (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in + # lib/action_controller/session. + # * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'. + # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter + # of the request, or automatically generated for a new session. + # * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently + # exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set, + # an ArgumentError is raised. + # * <tt>:session_expires</tt> - the time the current session expires, as a +Time+ object. If not set, the session will continue + # indefinitely. + # * <tt>:session_domain</tt> - the hostname domain for which this session is valid. If not set, defaults to the hostname of the + # server. + # * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS. + # * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script. + def self.process_cgi(cgi = CGI.new, session_options = {}) + new.process_cgi(cgi, session_options) + end + + def process_cgi(cgi, session_options = {}) #:nodoc: + process(CgiRequest.new(cgi, session_options), CgiResponse.new(cgi)).out + end + end + + class CgiRequest < AbstractRequest #:nodoc: + attr_accessor :cgi, :session_options + + DEFAULT_SESSION_OPTIONS = { + :database_manager => CGI::Session::PStore, + :prefix => "ruby_sess.", + :session_path => "/" + } unless const_defined?(:DEFAULT_SESSION_OPTIONS) + + def initialize(cgi, session_options = {}) + @cgi = cgi + @session_options = session_options + @env = @cgi.send(:env_table) + super() + end + + def query_string + if (qs = @cgi.query_string) && !qs.empty? + qs + elsif uri = @env['REQUEST_URI'] + parts = uri.split('?') + parts.shift + parts.join('?') + else + @env['QUERY_STRING'] || '' + end + end + + def query_parameters + (qs = self.query_string).empty? ? {} : CGIMethods.parse_query_parameters(qs) + end + + def request_parameters + @request_parameters ||= + if ActionController::Base.param_parsers.has_key?(content_type) + CGIMethods.parse_formatted_request_parameters(content_type, @env['RAW_POST_DATA']) + else + CGIMethods.parse_request_parameters(@cgi.params) + end + end + + def cookies + @cgi.cookies.freeze + end + + def host_with_port + if forwarded = env["HTTP_X_FORWARDED_HOST"] + forwarded.split(/,\s?/).last + elsif http_host = env['HTTP_HOST'] + http_host + elsif server_name = env['SERVER_NAME'] + server_name + else + "#{env['SERVER_ADDR']}:#{env['SERVER_PORT']}" + end + end + + def host + host_with_port[/^[^:]+/] + end + + def port + if host_with_port =~ /:(\d+)$/ + $1.to_i + else + standard_port + end + end + + def session + unless @session + if @session_options == false + @session = Hash.new + else + stale_session_check! do + if session_options_with_string_keys['new_session'] == true + @session = new_session + else + @session = CGI::Session.new(@cgi, session_options_with_string_keys) + end + @session['__valid_session'] + end + end + end + @session + end + + def reset_session + @session.delete if CGI::Session === @session + @session = new_session + end + + def method_missing(method_id, *arguments) + @cgi.send(method_id, *arguments) rescue super + end + + private + # Delete an old session if it exists then create a new one. + def new_session + if @session_options == false + Hash.new + else + CGI::Session.new(@cgi, session_options_with_string_keys.merge("new_session" => false)).delete rescue nil + CGI::Session.new(@cgi, session_options_with_string_keys.merge("new_session" => true)) + end + end + + def stale_session_check! + yield + rescue ArgumentError => argument_error + if argument_error.message =~ %r{undefined class/module (\w+)} + begin + Module.const_missing($1) + rescue LoadError, NameError => const_error + raise ActionController::SessionRestoreError, <<end_msg +Session contains objects whose class definition isn\'t available. +Remember to require the classes for all objects kept in the session. +(Original exception: #{const_error.message} [#{const_error.class}]) +end_msg + end + + retry + else + raise + end + end + + def session_options_with_string_keys + @session_options_with_string_keys ||= DEFAULT_SESSION_OPTIONS.merge(@session_options).inject({}) { |options, (k,v)| options[k.to_s] = v; options } + end + end + + class CgiResponse < AbstractResponse #:nodoc: + def initialize(cgi) + @cgi = cgi + super() + end + + def out(output = $stdout) + convert_content_type!(@headers) + output.binmode if output.respond_to?(:binmode) + output.sync = false if output.respond_to?(:sync=) + + begin + output.write(@cgi.header(@headers)) + + if @cgi.send(:env_table)['REQUEST_METHOD'] == 'HEAD' + return + elsif @body.respond_to?(:call) + @body.call(self, output) + else + output.write(@body) + end + + output.flush if output.respond_to?(:flush) + rescue Errno::EPIPE => e + # lost connection to the FCGI process -- ignore the output, then + end + end + + private + def convert_content_type!(headers) + if header = headers.delete("Content-Type") + headers["type"] = header + end + if header = headers.delete("Content-type") + headers["type"] = header + end + if header = headers.delete("content-type") + headers["type"] = header + end + end + end +end +module ActionController + module CodeGeneration #:nodoc: + class GenerationError < StandardError #:nodoc: + end + + class Source #:nodoc: + attr_reader :lines, :indentation_level + IndentationString = ' ' + def initialize + @lines, @indentation_level = [], 0 + end + def line(line) + @lines << (IndentationString * @indentation_level + line) + end + alias :<< :line + + def indent + @indentation_level += 1 + yield + ensure + @indentation_level -= 1 + end + + def to_s() lines.join("\n") end + end + + class CodeGenerator #:nodoc: + attr_accessor :source, :locals + def initialize(source = nil) + @locals = [] + @source = source || Source.new + end + + BeginKeywords = %w(if unless begin until while def).collect {|kw| kw.to_sym} + ResumeKeywords = %w(elsif else rescue).collect {|kw| kw.to_sym} + Keywords = BeginKeywords + ResumeKeywords + + def method_missing(keyword, *text) + if Keywords.include? keyword + if ResumeKeywords.include? keyword + raise GenerationError, "Can only resume with #{keyword} immediately after an end" unless source.lines.last =~ /^\s*end\s*$/ + source.lines.pop # Remove the 'end' + end + + line "#{keyword} #{text.join ' '}" + begin source.indent { yield(self.dup) } + ensure line 'end' + end + else + super(keyword, *text) + end + end + + def line(*args) self.source.line(*args) end + alias :<< :line + def indent(*args, &block) source(*args, &block) end + def to_s() source.to_s end + + def share_locals_with(other) + other.locals = self.locals = (other.locals | locals) + end + + FieldsToDuplicate = [:locals] + def dup + copy = self.class.new(source) + self.class::FieldsToDuplicate.each do |sym| + value = self.send(sym) + value = value.dup unless value.nil? || value.is_a?(Numeric) + copy.send("#{sym}=", value) + end + return copy + end + end + + class RecognitionGenerator < CodeGenerator #:nodoc: + Attributes = [:after, :before, :current, :results, :constants, :depth, :move_ahead, :finish_statement] + attr_accessor(*Attributes) + FieldsToDuplicate = CodeGenerator::FieldsToDuplicate + Attributes + + def initialize(*args) + super(*args) + @after, @before = [], [] + @current = nil + @results, @constants = {}, {} + @depth = 0 + @move_ahead = nil + @finish_statement = Proc.new {|hash_expr| hash_expr} + end + + def if_next_matches(string, &block) + test = Routing.test_condition(next_segment(true), string) + self.if(test, &block) + end + + def move_forward(places = 1) + dup = self.dup + dup.depth += 1 + dup.move_ahead = places + yield dup + end + + def next_segment(assign_inline = false, default = nil) + if locals.include?(segment_name) + code = segment_name + else + code = "#{segment_name} = #{path_name}[#{index_name}]" + if assign_inline + code = "(#{code})" + else + line(code) + code = segment_name + end + + locals << segment_name + end + code = "(#{code} || #{default.inspect})" if default + + return code.to_s + end + + def segment_name() "segment#{depth}".to_sym end + def path_name() :path end + def index_name + move_ahead, @move_ahead = @move_ahead, nil + move_ahead ? "index += #{move_ahead}" : 'index' + end + + def continue + dup = self.dup + dup.before << dup.current + dup.current = dup.after.shift + dup.go + end + + def go + if current then current.write_recognition(self) + else self.finish + end + end + + def result(key, expression, delay = false) + unless delay + line "#{key}_value = #{expression}" + expression = "#{key}_value" + end + results[key] = expression + end + def constant_result(key, object) + constants[key] = object + end + + def finish(ensure_traversal_finished = true) + pairs = [] + (results.keys + constants.keys).uniq.each do |key| + pairs << "#{key.to_s.inspect} => #{results[key] ? results[key] : constants[key].inspect}" + end + hash_expr = "{#{pairs.join(', ')}}" + + statement = finish_statement.call(hash_expr) + if ensure_traversal_finished then self.if("! #{next_segment(true)}") {|gp| gp << statement} + else self << statement + end + end + end + + class GenerationGenerator < CodeGenerator #:nodoc: + Attributes = [:after, :before, :current, :segments] + attr_accessor(*Attributes) + FieldsToDuplicate = CodeGenerator::FieldsToDuplicate + Attributes + + def initialize(*args) + super(*args) + @after, @before = [], [] + @current = nil + @segments = [] + end + + def hash_name() 'hash' end + def local_name(key) "#{key}_value" end + + def hash_value(key, assign = true, default = nil) + if locals.include?(local_name(key)) then code = local_name(key) + else + code = "hash[#{key.to_sym.inspect}]" + if assign + code = "(#{local_name(key)} = #{code})" + locals << local_name(key) + end + end + code = "(#{code} || (#{default.inspect}))" if default + return code + end + + def expire_for_keys(*keys) + return if keys.empty? + conds = keys.collect {|key| "expire_on[#{key.to_sym.inspect}]"} + line "not_expired, #{hash_name} = false, options if not_expired && #{conds.join(' && ')}" + end + + def add_segment(*segments) + d = dup + d.segments.concat segments + yield d + end + + def go + if current then current.write_generation(self) + else self.finish + end + end + + def continue + d = dup + d.before << d.current + d.current = d.after.shift + d.go + end + + def finish + line %("/#{segments.join('/')}") + end + + def check_conditions(conditions) + tests = [] + generator = nil + conditions.each do |key, condition| + tests << (generator || self).hash_value(key, true) if condition.is_a? Regexp + tests << Routing.test_condition((generator || self).hash_value(key, false), condition) + generator = self.dup unless generator + end + return tests.join(' && ') + end + end + end +end +module ActionController #:nodoc: + # Components allow you to call other actions for their rendered response while executing another action. You can either delegate + # the entire response rendering or you can mix a partial response in with your other content. + # + # class WeblogController < ActionController::Base + # # Performs a method and then lets hello_world output its render + # def delegate_action + # do_other_stuff_before_hello_world + # render_component :controller => "greeter", :action => "hello_world", :params => { :person => "david" } + # end + # end + # + # class GreeterController < ActionController::Base + # def hello_world + # render :text => "#{params[:person]} says, Hello World!" + # end + # end + # + # The same can be done in a view to do a partial rendering: + # + # Let's see a greeting: + # <%= render_component :controller => "greeter", :action => "hello_world" %> + # + # It is also possible to specify the controller as a class constant, bypassing the inflector + # code to compute the controller class at runtime: + # + # <%= render_component :controller => GreeterController, :action => "hello_world" %> + # + # == When to use components + # + # Components should be used with care. They're significantly slower than simply splitting reusable parts into partials and + # conceptually more complicated. Don't use components as a way of separating concerns inside a single application. Instead, + # reserve components to those rare cases where you truly have reusable view and controller elements that can be employed + # across many applications at once. + # + # So to repeat: Components are a special-purpose approach that can often be replaced with better use of partials and filters. + module Components + def self.included(base) #:nodoc: + base.send :include, InstanceMethods + base.extend(ClassMethods) + + base.helper do + def render_component(options) + @controller.send(:render_component_as_string, options) + end + end + + # If this controller was instantiated to process a component request, + # +parent_controller+ points to the instantiator of this controller. + base.send :attr_accessor, :parent_controller + + base.class_eval do + alias_method :process_cleanup_without_components, :process_cleanup + alias_method :process_cleanup, :process_cleanup_with_components + + alias_method :set_session_options_without_components, :set_session_options + alias_method :set_session_options, :set_session_options_with_components + + alias_method :flash_without_components, :flash + alias_method :flash, :flash_with_components + + alias_method :component_request?, :parent_controller + end + end + + module ClassMethods + # Track parent controller to identify component requests + def process_with_components(request, response, parent_controller = nil) #:nodoc: + controller = new + controller.parent_controller = parent_controller + controller.process(request, response) + end + + # Set the template root to be one directory behind the root dir of the controller. Examples: + # /code/weblog/components/admin/users_controller.rb with Admin::UsersController + # will use /code/weblog/components as template root + # and find templates in /code/weblog/components/admin/users/ + # + # /code/weblog/components/admin/parties/users_controller.rb with Admin::Parties::UsersController + # will also use /code/weblog/components as template root + # and find templates in /code/weblog/components/admin/parties/users/ + def uses_component_template_root + path_of_calling_controller = File.dirname(caller[0].split(/:\d+:/).first) + path_of_controller_root = path_of_calling_controller.sub(/#{controller_path.split("/")[0..-2]}$/, "") # " (for ruby-mode) + + self.template_root = path_of_controller_root + end + end + + module InstanceMethods + # Extracts the action_name from the request parameters and performs that action. + def process_with_components(request, response, method = :perform_action, *arguments) #:nodoc: + flash.discard if component_request? + process_without_components(request, response, method, *arguments) + end + + protected + # Renders the component specified as the response for the current method + def render_component(options) #:doc: + component_logging(options) do + render_text(component_response(options, true).body, response.headers["Status"]) + end + end + + # Returns the component response as a string + def render_component_as_string(options) #:doc: + component_logging(options) do + response = component_response(options, false) + + if redirected = response.redirected_to + render_component_as_string(redirected) + else + response.body + end + end + end + + def flash_with_components(refresh = false) #:nodoc: + if @flash.nil? || refresh + @flash = + if @parent_controller + @parent_controller.flash + else + flash_without_components + end + end + + @flash + end + + private + def component_response(options, reuse_response) + klass = component_class(options) + request = request_for_component(klass.controller_name, options) + response = reuse_response ? @response : @response.dup + + klass.process_with_components(request, response, self) + end + + # determine the controller class for the component request + def component_class(options) + if controller = options[:controller] + controller.is_a?(Class) ? controller : "#{controller.camelize}Controller".constantize + else + self.class + end + end + + # Create a new request object based on the current request. + # The new request inherits the session from the current request, + # bypassing any session options set for the component controller's class + def request_for_component(controller_name, options) + request = @request.dup + request.session = @request.session + + request.instance_variable_set( + :@parameters, + (options[:params] || {}).with_indifferent_access.update( + "controller" => controller_name, "action" => options[:action], "id" => options[:id] + ) + ) + + request + end + + def component_logging(options) + if logger + logger.info "Start rendering component (#{options.inspect}): " + result = yield + logger.info "\n\nEnd of component rendering" + result + else + yield + end + end + + def set_session_options_with_components(request) + set_session_options_without_components(request) unless component_request? + end + + def process_cleanup_with_components + process_cleanup_without_components unless component_request? + end + end + end +end +module ActionController #:nodoc: + # Cookies are read and written through ActionController#cookies. The cookies being read are what were received along with the request, + # the cookies being written are what will be sent out with the response. Cookies are read by value (so you won't get the cookie object + # itself back -- just the value it holds). Examples for writing: + # + # cookies[:user_name] = "david" # => Will set a simple session cookie + # cookies[:login] = { :value => "XJ-122", :expires => Time.now + 360} # => Will set a cookie that expires in 1 hour + # + # Examples for reading: + # + # cookies[:user_name] # => "david" + # cookies.size # => 2 + # + # Example for deleting: + # + # cookies.delete :user_name + # + # All the option symbols for setting cookies are: + # + # * <tt>value</tt> - the cookie's value or list of values (as an array). + # * <tt>path</tt> - the path for which this cookie applies. Defaults to the root of the application. + # * <tt>domain</tt> - the domain for which this cookie applies. + # * <tt>expires</tt> - the time at which this cookie expires, as a +Time+ object. + # * <tt>secure</tt> - whether this cookie is a secure cookie or not (default to false). + # Secure cookies are only transmitted to HTTPS servers. + module Cookies + protected + # Returns the cookie container, which operates as described above. + def cookies + CookieJar.new(self) + end + + # Deprecated cookie writer method + def cookie(*options) + @response.headers["cookie"] << CGI::Cookie.new(*options) + end + end + + class CookieJar < Hash #:nodoc: + def initialize(controller) + @controller, @cookies = controller, controller.instance_variable_get("@cookies") + super() + update(@cookies) + end + + # Returns the value of the cookie by +name+ -- or nil if no such cookie exists. You set new cookies using either the cookie method + # or cookies[]= (for simple name/value cookies without options). + def [](name) + @cookies[name.to_s].value.first if @cookies[name.to_s] && @cookies[name.to_s].respond_to?(:value) + end + + def []=(name, options) + if options.is_a?(Hash) + options = options.inject({}) { |options, pair| options[pair.first.to_s] = pair.last; options } + options["name"] = name.to_s + else + options = { "name" => name.to_s, "value" => options } + end + + set_cookie(options) + end + + # Removes the cookie on the client machine by setting the value to an empty string + # and setting its expiration date into the past + def delete(name) + set_cookie("name" => name.to_s, "value" => "", "expires" => Time.at(0)) + end + + private + def set_cookie(options) #:doc: + options["path"] = "/" unless options["path"] + cookie = CGI::Cookie.new(options) + @controller.logger.info "Cookie set: #{cookie}" unless @controller.logger.nil? + @controller.response.headers["cookie"] << cookie + end + end +end +module ActionController #:nodoc: + module Dependencies #:nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # Dependencies control what classes are needed for the controller to run its course. This is an alternative to doing explicit + # +require+ statements that bring a number of benefits. It's more succinct, communicates what type of dependency we're talking about, + # can trigger special behavior (as in the case of +observer+), and enables Rails to be clever about reloading in cached environments + # like FCGI. Example: + # + # class ApplicationController < ActionController::Base + # model :account, :company, :person, :project, :category + # helper :access_control + # service :notifications, :billings + # observer :project_change_observer + # end + # + # Please note that a controller like ApplicationController will automatically attempt to require_dependency on a model of its + # singuralized name and a helper of its name. If nothing is found, no error is raised. This is especially useful for concrete + # controllers like PostController: + # + # class PostController < ApplicationController + # # model :post (already required) + # # helper :post (already required) + # end + # + # Also note, that if the models follow the pattern of just 1 class per file in the form of MyClass => my_class.rb, then these + # classes don't have to be required as Active Support will auto-require them. + module ClassMethods #:nodoc: + # Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar + # backend for modelling entity classes. + def model(*models) + require_dependencies(:model, models) + depend_on(:model, models) + end + + # Specifies a variable number of services that this controller depends on. Services are normally singletons or factories, like + # Action Mailer service or a Payment Gateway service. + def service(*services) + require_dependencies(:service, services) + depend_on(:service, services) + end + + # Specifies a variable number of observers that are to govern when this controller is handling actions. The observers will + # automatically have .instance called on them to make them active on assignment. + def observer(*observers) + require_dependencies(:observer, observers) + depend_on(:observer, observers) + instantiate_observers(observers) + end + + # Returns an array of symbols that specify the dependencies on a given layer. For the example at the top, calling + # <tt>ApplicationController.dependencies_on(:model)</tt> would return <tt>[:account, :company, :person, :project, :category]</tt> + def dependencies_on(layer) + read_inheritable_attribute("#{layer}_dependencies") + end + + def depend_on(layer, dependencies) #:nodoc: + write_inheritable_array("#{layer}_dependencies", dependencies) + end + + private + def instantiate_observers(observers) + observers.flatten.each { |observer| Object.const_get(Inflector.classify(observer.to_s)).instance } + end + + def require_dependencies(layer, dependencies) + dependencies.flatten.each do |dependency| + begin + require_dependency(dependency.to_s) + rescue LoadError => e + raise LoadError.new("Missing #{layer} #{dependency}.rb").copy_blame!(e) + rescue Object => exception + exception.blame_file! "=> #{layer} #{dependency}.rb" + raise + end + end + end + end + end +end +require 'test/unit' +require 'test/unit/assertions' +require 'rexml/document' + +module Test #:nodoc: + module Unit #:nodoc: + module Assertions + def assert_success(message=nil) #:nodoc: + assert_response(:success, message) + end + + def assert_redirect(message=nil) #:nodoc: + assert_response(:redirect, message) + end + + def assert_rendered_file(expected=nil, message=nil) #:nodoc: + assert_template(expected, message) + end + + # ensure that the session has an object with the specified name + def assert_session_has(key=nil, message=nil) #:nodoc: + msg = build_message(message, "<?> is not in the session <?>", key, @response.session) + assert_block(msg) { @response.has_session_object?(key) } + end + + # ensure that the session has no object with the specified name + def assert_session_has_no(key=nil, message=nil) #:nodoc: + msg = build_message(message, "<?> is in the session <?>", key, @response.session) + assert_block(msg) { !@response.has_session_object?(key) } + end + + def assert_session_equal(expected = nil, key = nil, message = nil) #:nodoc: + msg = build_message(message, "<?> expected in session['?'] but was <?>", expected, key, @response.session[key]) + assert_block(msg) { expected == @response.session[key] } + end + + # -- cookie assertions --------------------------------------------------- + + def assert_no_cookie(key = nil, message = nil) #:nodoc: + actual = @response.cookies[key] + msg = build_message(message, "<?> not expected in cookies['?']", actual, key) + assert_block(msg) { actual.nil? or actual.empty? } + end + + def assert_cookie_equal(expected = nil, key = nil, message = nil) #:nodoc: + actual = @response.cookies[key] + actual = actual.first if actual + msg = build_message(message, "<?> expected in cookies['?'] but was <?>", expected, key, actual) + assert_block(msg) { expected == actual } + end + + # -- flash assertions --------------------------------------------------- + + # ensure that the flash has an object with the specified name + def assert_flash_has(key=nil, message=nil) #:nodoc: + msg = build_message(message, "<?> is not in the flash <?>", key, @response.flash) + assert_block(msg) { @response.has_flash_object?(key) } + end + + # ensure that the flash has no object with the specified name + def assert_flash_has_no(key=nil, message=nil) #:nodoc: + msg = build_message(message, "<?> is in the flash <?>", key, @response.flash) + assert_block(msg) { !@response.has_flash_object?(key) } + end + + # ensure the flash exists + def assert_flash_exists(message=nil) #:nodoc: + msg = build_message(message, "the flash does not exist <?>", @response.session['flash'] ) + assert_block(msg) { @response.has_flash? } + end + + # ensure the flash does not exist + def assert_flash_not_exists(message=nil) #:nodoc: + msg = build_message(message, "the flash exists <?>", @response.flash) + assert_block(msg) { !@response.has_flash? } + end + + # ensure the flash is empty but existent + def assert_flash_empty(message=nil) #:nodoc: + msg = build_message(message, "the flash is not empty <?>", @response.flash) + assert_block(msg) { !@response.has_flash_with_contents? } + end + + # ensure the flash is not empty + def assert_flash_not_empty(message=nil) #:nodoc: + msg = build_message(message, "the flash is empty") + assert_block(msg) { @response.has_flash_with_contents? } + end + + def assert_flash_equal(expected = nil, key = nil, message = nil) #:nodoc: + msg = build_message(message, "<?> expected in flash['?'] but was <?>", expected, key, @response.flash[key]) + assert_block(msg) { expected == @response.flash[key] } + end + + + # ensure our redirection url is an exact match + def assert_redirect_url(url=nil, message=nil) #:nodoc: + assert_redirect(message) + msg = build_message(message, "<?> is not the redirected location <?>", url, @response.redirect_url) + assert_block(msg) { @response.redirect_url == url } + end + + # ensure our redirection url matches a pattern + def assert_redirect_url_match(pattern=nil, message=nil) #:nodoc: + assert_redirect(message) + msg = build_message(message, "<?> was not found in the location: <?>", pattern, @response.redirect_url) + assert_block(msg) { @response.redirect_url_match?(pattern) } + end + + + # -- template assertions ------------------------------------------------ + + # ensure that a template object with the given name exists + def assert_template_has(key=nil, message=nil) #:nodoc: + msg = build_message(message, "<?> is not a template object", key ) + assert_block(msg) { @response.has_template_object?(key) } + end + + # ensure that a template object with the given name does not exist + def assert_template_has_no(key=nil,message=nil) #:nodoc: + msg = build_message(message, "<?> is a template object <?>", key, @response.template_objects[key]) + assert_block(msg) { !@response.has_template_object?(key) } + end + + # ensures that the object assigned to the template on +key+ is equal to +expected+ object. + def assert_template_equal(expected = nil, key = nil, message = nil) #:nodoc: + msg = build_message(message, "<?> expected in assigns['?'] but was <?>", expected, key, @response.template.assigns[key.to_s]) + assert_block(msg) { expected == @response.template.assigns[key.to_s] } + end + alias_method :assert_assigned_equal, :assert_template_equal + + # Asserts that the template returns the +expected+ string or array based on the XPath +expression+. + # This will only work if the template rendered a valid XML document. + def assert_template_xpath_match(expression=nil, expected=nil, message=nil) #:nodoc: + xml, matches = REXML::Document.new(@response.body), [] + xml.elements.each(expression) { |e| matches << e.text } + if matches.empty? then + msg = build_message(message, "<?> not found in document", expression) + flunk(msg) + return + elsif matches.length < 2 then + matches = matches.first + end + + msg = build_message(message, "<?> found <?>, not <?>", expression, matches, expected) + assert_block(msg) { matches == expected } + end + + # Assert the template object with the given name is an Active Record descendant and is valid. + def assert_valid_record(key = nil, message = nil) #:nodoc: + record = find_record_in_template(key) + msg = build_message(message, "Active Record is invalid <?>)", record.errors.full_messages) + assert_block(msg) { record.valid? } + end + + # Assert the template object with the given name is an Active Record descendant and is invalid. + def assert_invalid_record(key = nil, message = nil) #:nodoc: + record = find_record_in_template(key) + msg = build_message(message, "Active Record is valid)") + assert_block(msg) { !record.valid? } + end + + # Assert the template object with the given name is an Active Record descendant and the specified column(s) are valid. + def assert_valid_column_on_record(key = nil, columns = "", message = nil) #:nodoc: + record = find_record_in_template(key) + record.send(:validate) + + cols = glue_columns(columns) + cols.delete_if { |col| !record.errors.invalid?(col) } + msg = build_message(message, "Active Record has invalid columns <?>)", cols.join(",") ) + assert_block(msg) { cols.empty? } + end + + # Assert the template object with the given name is an Active Record descendant and the specified column(s) are invalid. + def assert_invalid_column_on_record(key = nil, columns = "", message = nil) #:nodoc: + record = find_record_in_template(key) + record.send(:validate) + + cols = glue_columns(columns) + cols.delete_if { |col| record.errors.invalid?(col) } + msg = build_message(message, "Active Record has valid columns <?>)", cols.join(",") ) + assert_block(msg) { cols.empty? } + end + + private + def glue_columns(columns) + cols = [] + cols << columns if columns.class == String + cols += columns if columns.class == Array + cols + end + + def find_record_in_template(key = nil) + assert_template_has(key) + record = @response.template_objects[key] + + assert_not_nil(record) + assert_kind_of ActiveRecord::Base, record + + return record + end + end + end +endmodule ActionController + class Base + protected + # Deprecated in favor of calling redirect_to directly with the path. + def redirect_to_path(path) #:nodoc: + redirect_to(path) + end + + # Deprecated in favor of calling redirect_to directly with the url. If the resource has moved permanently, it's possible to pass + # true as the second parameter and the browser will get "301 Moved Permanently" instead of "302 Found". This can also be done through + # just setting the headers["Status"] to "301 Moved Permanently" before using the redirect_to. + def redirect_to_url(url, permanently = false) #:nodoc: + headers["Status"] = "301 Moved Permanently" if permanently + redirect_to(url) + end + end +end +module ActionController + class AbstractRequest + # Determine whether the body of a HTTP call is URL-encoded (default) + # or matches one of the registered param_parsers. + # + # For backward compatibility, the post format is extracted from the + # X-Post-Data-Format HTTP header if present. + def post_format + case content_type.to_s + when 'application/xml' + :xml + when 'application/x-yaml' + :yaml + else + :url_encoded + end + end + + # Is this a POST request formatted as XML or YAML? + def formatted_post? + post? && (post_format == :yaml || post_format == :xml) + end + + # Is this a POST request formatted as XML? + def xml_post? + post? && post_format == :xml + end + + # Is this a POST request formatted as YAML? + def yaml_post? + post? && post_format == :yaml + end + end +end +module ActionController #:nodoc: + module Filters #:nodoc: + def self.included(base) + base.extend(ClassMethods) + base.send(:include, ActionController::Filters::InstanceMethods) + end + + # Filters enable controllers to run shared pre and post processing code for its actions. These filters can be used to do + # authentication, caching, or auditing before the intended action is performed. Or to do localization or output + # compression after the action has been performed. + # + # Filters have access to the request, response, and all the instance variables set by other filters in the chain + # or by the action (in the case of after filters). Additionally, it's possible for a pre-processing <tt>before_filter</tt> + # to halt the processing before the intended action is processed by returning false or performing a redirect or render. + # This is especially useful for filters like authentication where you're not interested in allowing the action to be + # performed if the proper credentials are not in order. + # + # == Filter inheritance + # + # Controller inheritance hierarchies share filters downwards, but subclasses can also add new filters without + # affecting the superclass. For example: + # + # class BankController < ActionController::Base + # before_filter :audit + # + # private + # def audit + # # record the action and parameters in an audit log + # end + # end + # + # class VaultController < BankController + # before_filter :verify_credentials + # + # private + # def verify_credentials + # # make sure the user is allowed into the vault + # end + # end + # + # Now any actions performed on the BankController will have the audit method called before. On the VaultController, + # first the audit method is called, then the verify_credentials method. If the audit method returns false, then + # verify_credentials and the intended action are never called. + # + # == Filter types + # + # A filter can take one of three forms: method reference (symbol), external class, or inline method (proc). The first + # is the most common and works by referencing a protected or private method somewhere in the inheritance hierarchy of + # the controller by use of a symbol. In the bank example above, both BankController and VaultController use this form. + # + # Using an external class makes for more easily reused generic filters, such as output compression. External filter classes + # are implemented by having a static +filter+ method on any class and then passing this class to the filter method. Example: + # + # class OutputCompressionFilter + # def self.filter(controller) + # controller.response.body = compress(controller.response.body) + # end + # end + # + # class NewspaperController < ActionController::Base + # after_filter OutputCompressionFilter + # end + # + # The filter method is passed the controller instance and is hence granted access to all aspects of the controller and can + # manipulate them as it sees fit. + # + # The inline method (using a proc) can be used to quickly do something small that doesn't require a lot of explanation. + # Or just as a quick test. It works like this: + # + # class WeblogController < ActionController::Base + # before_filter { |controller| false if controller.params["stop_action"] } + # end + # + # As you can see, the block expects to be passed the controller after it has assigned the request to the internal variables. + # This means that the block has access to both the request and response objects complete with convenience methods for params, + # session, template, and assigns. Note: The inline method doesn't strictly have to be a block; any object that responds to call + # and returns 1 or -1 on arity will do (such as a Proc or an Method object). + # + # == Filter chain ordering + # + # Using <tt>before_filter</tt> and <tt>after_filter</tt> appends the specified filters to the existing chain. That's usually + # just fine, but some times you care more about the order in which the filters are executed. When that's the case, you + # can use <tt>prepend_before_filter</tt> and <tt>prepend_after_filter</tt>. Filters added by these methods will be put at the + # beginning of their respective chain and executed before the rest. For example: + # + # class ShoppingController + # before_filter :verify_open_shop + # + # class CheckoutController + # prepend_before_filter :ensure_items_in_cart, :ensure_items_in_stock + # + # The filter chain for the CheckoutController is now <tt>:ensure_items_in_cart, :ensure_items_in_stock,</tt> + # <tt>:verify_open_shop</tt>. So if either of the ensure filters return false, we'll never get around to see if the shop + # is open or not. + # + # You may pass multiple filter arguments of each type as well as a filter block. + # If a block is given, it is treated as the last argument. + # + # == Around filters + # + # In addition to the individual before and after filters, it's also possible to specify that a single object should handle + # both the before and after call. That's especially useful when you need to keep state active between the before and after, + # such as the example of a benchmark filter below: + # + # class WeblogController < ActionController::Base + # around_filter BenchmarkingFilter.new + # + # # Before this action is performed, BenchmarkingFilter#before(controller) is executed + # def index + # end + # # After this action has been performed, BenchmarkingFilter#after(controller) is executed + # end + # + # class BenchmarkingFilter + # def initialize + # @runtime + # end + # + # def before + # start_timer + # end + # + # def after + # stop_timer + # report_result + # end + # end + # + # == Filter chain skipping + # + # Some times its convenient to specify a filter chain in a superclass that'll hold true for the majority of the + # subclasses, but not necessarily all of them. The subclasses that behave in exception can then specify which filters + # they would like to be relieved of. Examples + # + # class ApplicationController < ActionController::Base + # before_filter :authenticate + # end + # + # class WeblogController < ApplicationController + # # will run the :authenticate filter + # end + # + # class SignupController < ApplicationController + # # will not run the :authenticate filter + # skip_before_filter :authenticate + # end + # + # == Filter conditions + # + # Filters can be limited to run for only specific actions. This can be expressed either by listing the actions to + # exclude or the actions to include when executing the filter. Available conditions are +:only+ or +:except+, both + # of which accept an arbitrary number of method references. For example: + # + # class Journal < ActionController::Base + # # only require authentication if the current action is edit or delete + # before_filter :authorize, :only => [ :edit, :delete ] + # + # private + # def authorize + # # redirect to login unless authenticated + # end + # end + # + # When setting conditions on inline method (proc) filters the condition must come first and be placed in parentheses. + # + # class UserPreferences < ActionController::Base + # before_filter(:except => :new) { # some proc ... } + # # ... + # end + # + module ClassMethods + # The passed <tt>filters</tt> will be appended to the array of filters that's run _before_ actions + # on this controller are performed. + def append_before_filter(*filters, &block) + conditions = extract_conditions!(filters) + filters << block if block_given? + add_action_conditions(filters, conditions) + append_filter_to_chain('before', filters) + end + + # The passed <tt>filters</tt> will be prepended to the array of filters that's run _before_ actions + # on this controller are performed. + def prepend_before_filter(*filters, &block) + conditions = extract_conditions!(filters) + filters << block if block_given? + add_action_conditions(filters, conditions) + prepend_filter_to_chain('before', filters) + end + + # Short-hand for append_before_filter since that's the most common of the two. + alias :before_filter :append_before_filter + + # The passed <tt>filters</tt> will be appended to the array of filters that's run _after_ actions + # on this controller are performed. + def append_after_filter(*filters, &block) + conditions = extract_conditions!(filters) + filters << block if block_given? + add_action_conditions(filters, conditions) + append_filter_to_chain('after', filters) + end + + # The passed <tt>filters</tt> will be prepended to the array of filters that's run _after_ actions + # on this controller are performed. + def prepend_after_filter(*filters, &block) + conditions = extract_conditions!(filters) + filters << block if block_given? + add_action_conditions(filters, conditions) + prepend_filter_to_chain("after", filters) + end + + # Short-hand for append_after_filter since that's the most common of the two. + alias :after_filter :append_after_filter + + # The passed <tt>filters</tt> will have their +before+ method appended to the array of filters that's run both before actions + # on this controller are performed and have their +after+ method prepended to the after actions. The filter objects must all + # respond to both +before+ and +after+. So if you do append_around_filter A.new, B.new, the callstack will look like: + # + # B#before + # A#before + # A#after + # B#after + def append_around_filter(*filters) + conditions = extract_conditions!(filters) + for filter in filters.flatten + ensure_filter_responds_to_before_and_after(filter) + append_before_filter(conditions || {}) { |c| filter.before(c) } + prepend_after_filter(conditions || {}) { |c| filter.after(c) } + end + end + + # The passed <tt>filters</tt> will have their +before+ method prepended to the array of filters that's run both before actions + # on this controller are performed and have their +after+ method appended to the after actions. The filter objects must all + # respond to both +before+ and +after+. So if you do prepend_around_filter A.new, B.new, the callstack will look like: + # + # A#before + # B#before + # B#after + # A#after + def prepend_around_filter(*filters) + for filter in filters.flatten + ensure_filter_responds_to_before_and_after(filter) + prepend_before_filter { |c| filter.before(c) } + append_after_filter { |c| filter.after(c) } + end + end + + # Short-hand for append_around_filter since that's the most common of the two. + alias :around_filter :append_around_filter + + # Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference + # filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out + # of many sub-controllers need a different hierarchy. + # + # You can control the actions to skip the filter for with the <tt>:only</tt> and <tt>:except</tt> options, + # just like when you apply the filters. + def skip_before_filter(*filters) + if conditions = extract_conditions!(filters) + remove_contradicting_conditions!(filters, conditions) + conditions[:only], conditions[:except] = conditions[:except], conditions[:only] + add_action_conditions(filters, conditions) + else + for filter in filters.flatten + write_inheritable_attribute("before_filters", read_inheritable_attribute("before_filters") - [ filter ]) + end + end + end + + # Removes the specified filters from the +after+ filter chain. Note that this only works for skipping method-reference + # filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out + # of many sub-controllers need a different hierarchy. + # + # You can control the actions to skip the filter for with the <tt>:only</tt> and <tt>:except</tt> options, + # just like when you apply the filters. + def skip_after_filter(*filters) + if conditions = extract_conditions!(filters) + remove_contradicting_conditions!(filters, conditions) + conditions[:only], conditions[:except] = conditions[:except], conditions[:only] + add_action_conditions(filters, conditions) + else + for filter in filters.flatten + write_inheritable_attribute("after_filters", read_inheritable_attribute("after_filters") - [ filter ]) + end + end + end + + # Returns all the before filters for this class and all its ancestors. + def before_filters #:nodoc: + @before_filters ||= read_inheritable_attribute("before_filters") || [] + end + + # Returns all the after filters for this class and all its ancestors. + def after_filters #:nodoc: + @after_filters ||= read_inheritable_attribute("after_filters") || [] + end + + # Returns a mapping between filters and the actions that may run them. + def included_actions #:nodoc: + @included_actions ||= read_inheritable_attribute("included_actions") || {} + end + + # Returns a mapping between filters and actions that may not run them. + def excluded_actions #:nodoc: + @excluded_actions ||= read_inheritable_attribute("excluded_actions") || {} + end + + private + def append_filter_to_chain(condition, filters) + write_inheritable_array("#{condition}_filters", filters) + end + + def prepend_filter_to_chain(condition, filters) + old_filters = read_inheritable_attribute("#{condition}_filters") || [] + write_inheritable_attribute("#{condition}_filters", filters + old_filters) + end + + def ensure_filter_responds_to_before_and_after(filter) + unless filter.respond_to?(:before) && filter.respond_to?(:after) + raise ActionControllerError, "Filter object must respond to both before and after" + end + end + + def extract_conditions!(filters) + return nil unless filters.last.is_a? Hash + filters.pop + end + + def add_action_conditions(filters, conditions) + return unless conditions + included, excluded = conditions[:only], conditions[:except] + write_inheritable_hash('included_actions', condition_hash(filters, included)) && return if included + write_inheritable_hash('excluded_actions', condition_hash(filters, excluded)) if excluded + end + + def condition_hash(filters, *actions) + filters.inject({}) {|hash, filter| hash.merge(filter => actions.flatten.map {|action| action.to_s})} + end + + def remove_contradicting_conditions!(filters, conditions) + return unless conditions[:only] + filters.each do |filter| + next unless included_actions_for_filter = (read_inheritable_attribute('included_actions') || {})[filter] + [*conditions[:only]].each do |conditional_action| + conditional_action = conditional_action.to_s + included_actions_for_filter.delete(conditional_action) if included_actions_for_filter.include?(conditional_action) + end + end + end + end + + module InstanceMethods # :nodoc: + def self.included(base) + base.class_eval do + alias_method :perform_action_without_filters, :perform_action + alias_method :perform_action, :perform_action_with_filters + + alias_method :process_without_filters, :process + alias_method :process, :process_with_filters + + alias_method :process_cleanup_without_filters, :process_cleanup + alias_method :process_cleanup, :process_cleanup_with_filters + end + end + + def perform_action_with_filters + before_action_result = before_action + + unless before_action_result == false || performed? + perform_action_without_filters + after_action + end + + @before_filter_chain_aborted = (before_action_result == false) + end + + def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc: + @before_filter_chain_aborted = false + process_without_filters(request, response, method, *arguments) + end + + # Calls all the defined before-filter filters, which are added by using "before_filter :method". + # If any of the filters return false, no more filters will be executed and the action is aborted. + def before_action #:doc: + call_filters(self.class.before_filters) + end + + # Calls all the defined after-filter filters, which are added by using "after_filter :method". + # If any of the filters return false, no more filters will be executed. + def after_action #:doc: + call_filters(self.class.after_filters) + end + + private + def call_filters(filters) + filters.each do |filter| + next if action_exempted?(filter) + + filter_result = case + when filter.is_a?(Symbol) + self.send(filter) + when filter_block?(filter) + filter.call(self) + when filter_class?(filter) + filter.filter(self) + else + raise( + ActionControllerError, + 'Filters need to be either a symbol, proc/method, or class implementing a static filter method' + ) + end + + if filter_result == false + logger.info "Filter chain halted as [#{filter}] returned false" if logger + return false + end + end + end + + def filter_block?(filter) + filter.respond_to?('call') && (filter.arity == 1 || filter.arity == -1) + end + + def filter_class?(filter) + filter.respond_to?('filter') + end + + def action_exempted?(filter) + case + when ia = self.class.included_actions[filter] + !ia.include?(action_name) + when ea = self.class.excluded_actions[filter] + ea.include?(action_name) + end + end + + def process_cleanup_with_filters + if @before_filter_chain_aborted + close_session + else + process_cleanup_without_filters + end + end + end + end +end +module ActionController #:nodoc: + # The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed + # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create action + # that sets <tt>flash[:notice] = "Successfully created"</tt> before redirecting to a display action that can then expose + # the flash to its template. Actually, that exposure is automatically done. Example: + # + # class WeblogController < ActionController::Base + # def create + # # save post + # flash[:notice] = "Successfully created post" + # redirect_to :action => "display", :params => { :id => post.id } + # end + # + # def display + # # doesn't need to assign the flash notice to the template, that's done automatically + # end + # end + # + # display.rhtml + # <% if @flash[:notice] %><div class="notice"><%= @flash[:notice] %></div><% end %> + # + # This example just places a string in the flash, but you can put any object in there. And of course, you can put as many + # as you like at a time too. Just remember: They'll be gone by the time the next action has been performed. + # + # See docs on the FlashHash class for more details about the flash. + module Flash + def self.included(base) + base.send :include, InstanceMethods + + base.class_eval do + alias_method :assign_shortcuts_without_flash, :assign_shortcuts + alias_method :assign_shortcuts, :assign_shortcuts_with_flash + + alias_method :process_cleanup_without_flash, :process_cleanup + alias_method :process_cleanup, :process_cleanup_with_flash + end + end + + + class FlashNow #:nodoc: + def initialize(flash) + @flash = flash + end + + def []=(k, v) + @flash[k] = v + @flash.discard(k) + v + end + + def [](k) + @flash[k] + end + end + + class FlashHash < Hash + def initialize #:nodoc: + super + @used = {} + end + + def []=(k, v) #:nodoc: + keep(k) + super + end + + def update(h) #:nodoc: + h.keys.each{ |k| discard(k) } + super + end + + alias :merge! :update + + def replace(h) #:nodoc: + @used = {} + super + end + + # Sets a flash that will not be available to the next action, only to the current. + # + # flash.now[:message] = "Hello current action" + # + # This method enables you to use the flash as a central messaging system in your app. + # When you need to pass an object to the next action, you use the standard flash assign (<tt>[]=</tt>). + # When you need to pass an object to the current action, you use <tt>now</tt>, and your object will + # vanish when the current action is done. + # + # Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>. + def now + FlashNow.new self + end + + # Keeps either the entire current flash or a specific flash entry available for the next action: + # + # flash.keep # keeps the entire flash + # flash.keep(:notice) # keeps only the "notice" entry, the rest of the flash is discarded + def keep(k=nil) + use(k, false) + end + + # Marks the entire flash or a single flash entry to be discarded by the end of the current action + # + # flash.keep # keep entire flash available for the next action + # flash.discard(:warning) # discard the "warning" entry (it'll still be available for the current action) + def discard(k=nil) + use(k) + end + + # Mark for removal entries that were kept, and delete unkept ones. + # + # This method is called automatically by filters, so you generally don't need to care about it. + def sweep #:nodoc: + keys.each do |k| + unless @used[k] + use(k) + else + delete(k) + @used.delete(k) + end + end + (@used.keys - keys).each{|k| @used.delete k } # clean up after keys that could have been left over by calling reject! or shift on the flash + end + + private + # Used internally by the <tt>keep</tt> and <tt>discard</tt> methods + # use() # marks the entire flash as used + # use('msg') # marks the "msg" entry as used + # use(nil, false) # marks the entire flash as unused (keeps it around for one more action) + # use('msg', false) # marks the "msg" entry as unused (keeps it around for one more action) + def use(k=nil, v=true) + unless k.nil? + @used[k] = v + else + keys.each{|key| use key, v } + end + end + end + + module InstanceMethods #:nodoc: + def assign_shortcuts_with_flash(request, response) #:nodoc: + assign_shortcuts_without_flash(request, response) + flash(:refresh) + end + + def process_cleanup_with_flash + flash.sweep if @session + process_cleanup_without_flash + end + + protected + # Access the contents of the flash. Use <tt>flash["notice"]</tt> to read a notice you put there or + # <tt>flash["notice"] = "hello"</tt> to put a new one. + # Note that if sessions are disabled only flash.now will work. + def flash(refresh = false) #:doc: + if @flash.nil? || refresh + @flash = + if @session.is_a?(Hash) + # @session is a Hash, if sessions are disabled + # we don't put the flash in the session in this case + FlashHash.new + else + # otherwise, @session is a CGI::Session or a TestSession + # so make sure it gets retrieved from/saved to session storage after request processing + @session["flash"] ||= FlashHash.new + end + end + + @flash + end + + # deprecated. use <tt>flash.keep</tt> instead + def keep_flash #:doc: + warn 'keep_flash is deprecated; use flash.keep instead.' + flash.keep + end + end + end +endmodule ActionController #:nodoc: + module Helpers #:nodoc: + def self.append_features(base) + super + + # Initialize the base module to aggregate its helpers. + base.class_inheritable_accessor :master_helper_module + base.master_helper_module = Module.new + + # Extend base with class methods to declare helpers. + base.extend(ClassMethods) + + base.class_eval do + # Wrap inherited to create a new master helper module for subclasses. + class << self + alias_method :inherited_without_helper, :inherited + alias_method :inherited, :inherited_with_helper + end + end + end + + # The template helpers serve to relieve the templates from including the same inline code again and again. It's a + # set of standardized methods for working with forms (FormHelper), dates (DateHelper), texts (TextHelper), and + # Active Records (ActiveRecordHelper) that's available to all templates by default. + # + # It's also really easy to make your own helpers and it's much encouraged to keep the template files free + # from complicated logic. It's even encouraged to bundle common compositions of methods from other helpers + # (often the common helpers) as they're used by the specific application. + # + # module MyHelper + # def hello_world() "hello world" end + # end + # + # MyHelper can now be included in a controller, like this: + # + # class MyController < ActionController::Base + # helper :my_helper + # end + # + # ...and, same as above, used in any template rendered from MyController, like this: + # + # Let's hear what the helper has to say: <tt><%= hello_world %></tt> + module ClassMethods + # Makes all the (instance) methods in the helper module available to templates rendered through this controller. + # See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules + # available to the templates. + def add_template_helper(helper_module) #:nodoc: + master_helper_module.send(:include, helper_module) + end + + # Declare a helper: + # helper :foo + # requires 'foo_helper' and includes FooHelper in the template class. + # helper FooHelper + # includes FooHelper in the template class. + # helper { def foo() "#{bar} is the very best" end } + # evaluates the block in the template class, adding method #foo. + # helper(:three, BlindHelper) { def mice() 'mice' end } + # does all three. + def helper(*args, &block) + args.flatten.each do |arg| + case arg + when Module + add_template_helper(arg) + when String, Symbol + file_name = arg.to_s.underscore + '_helper' + class_name = file_name.camelize + + begin + require_dependency(file_name) + rescue LoadError => load_error + requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1] + msg = (requiree == file_name) ? "Missing helper file helpers/#{file_name}.rb" : "Can't load file: #{requiree}" + raise LoadError.new(msg).copy_blame!(load_error) + end + + add_template_helper(class_name.constantize) + else + raise ArgumentError, 'helper expects String, Symbol, or Module argument' + end + end + + # Evaluate block in template class if given. + master_helper_module.module_eval(&block) if block_given? + end + + # Declare a controller method as a helper. For example, + # helper_method :link_to + # def link_to(name, options) ... end + # makes the link_to controller method available in the view. + def helper_method(*methods) + methods.flatten.each do |method| + master_helper_module.module_eval <<-end_eval + def #{method}(*args, &block) + controller.send(%(#{method}), *args, &block) + end + end_eval + end + end + + # Declare a controller attribute as a helper. For example, + # helper_attr :name + # attr_accessor :name + # makes the name and name= controller methods available in the view. + # The is a convenience wrapper for helper_method. + def helper_attr(*attrs) + attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") } + end + + private + def default_helper_module! + module_name = name.sub(/Controller$|$/, 'Helper') + module_path = module_name.split('::').map { |m| m.underscore }.join('/') + require_dependency module_path + helper module_name.constantize + rescue LoadError + logger.debug("#{name}: missing default helper path #{module_path}") if logger + rescue NameError + logger.debug("#{name}: missing default helper module #{module_name}") if logger + end + + def inherited_with_helper(child) + inherited_without_helper(child) + begin + child.master_helper_module = Module.new + child.master_helper_module.send :include, master_helper_module + child.send :default_helper_module! + rescue MissingSourceFile => e + raise unless e.is_missing?("helpers/#{child.controller_path}_helper") + end + end + end + end +end +require 'dispatcher' +require 'stringio' +require 'uri' + +module ActionController + module Integration #:nodoc: + # An integration Session instance represents a set of requests and responses + # performed sequentially by some virtual user. Becase you can instantiate + # multiple sessions and run them side-by-side, you can also mimic (to some + # limited extent) multiple simultaneous users interacting with your system. + # + # Typically, you will instantiate a new session using IntegrationTest#open_session, + # rather than instantiating Integration::Session directly. + class Session + include Test::Unit::Assertions + include ActionController::TestProcess + + # The integer HTTP status code of the last request. + attr_reader :status + + # The status message that accompanied the status code of the last request. + attr_reader :status_message + + # The URI of the last request. + attr_reader :path + + # The hostname used in the last request. + attr_accessor :host + + # The remote_addr used in the last request. + attr_accessor :remote_addr + + # The Accept header to send. + attr_accessor :accept + + # A map of the cookies returned by the last response, and which will be + # sent with the next request. + attr_reader :cookies + + # A map of the headers returned by the last response. + attr_reader :headers + + # A reference to the controller instance used by the last request. + attr_reader :controller + + # A reference to the request instance used by the last request. + attr_reader :request + + # A reference to the response instance used by the last request. + attr_reader :response + + # Create an initialize a new Session instance. + def initialize + reset! + end + + # Resets the instance. This can be used to reset the state information + # in an existing session instance, so it can be used from a clean-slate + # condition. + # + # session.reset! + def reset! + @status = @path = @headers = nil + @result = @status_message = nil + @https = false + @cookies = {} + @controller = @request = @response = nil + + self.host = "www.example.com" + self.remote_addr = "127.0.0.1" + self.accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" + + unless @named_routes_configured + # install the named routes in this session instance. + klass = class<<self; self; end + Routing::NamedRoutes.install(klass) + + # the helpers are made protected by default--we make them public for + # easier access during testing and troubleshooting. + klass.send(:public, *Routing::NamedRoutes::Helpers) + @named_routes_configured = true + end + end + + # Specify whether or not the session should mimic a secure HTTPS request. + # + # session.https! + # session.https!(false) + def https!(flag=true) + @https = flag + end + + # Return +true+ if the session is mimicing a secure HTTPS request. + # + # if session.https? + # ... + # end + def https? + @https + end + + # Set the host name to use in the next request. + # + # session.host! "www.example.com" + def host!(name) + @host = name + end + + # Follow a single redirect response. If the last response was not a + # redirect, an exception will be raised. Otherwise, the redirect is + # performed on the location header. + def follow_redirect! + raise "not a redirect! #{@status} #{@status_message}" unless redirect? + get(interpret_uri(headers["location"].first)) + status + end + + # Performs a GET request, following any subsequent redirect. Note that + # the redirects are followed until the response is not a redirect--this + # means you may run into an infinite loop if your redirect loops back to + # itself. + def get_via_redirect(path, args={}) + get path, args + follow_redirect! while redirect? + status + end + + # Performs a POST request, following any subsequent redirect. This is + # vulnerable to infinite loops, the same as #get_via_redirect. + def post_via_redirect(path, args={}) + post path, args + follow_redirect! while redirect? + status + end + + # Returns +true+ if the last response was a redirect. + def redirect? + status/100 == 3 + end + + # Performs a GET request with the given parameters. The parameters may + # be +nil+, a Hash, or a string that is appropriately encoded + # (application/x-www-form-urlencoded or multipart/form-data). The headers + # should be a hash. The keys will automatically be upcased, with the + # prefix 'HTTP_' added if needed. + def get(path, parameters=nil, headers=nil) + process :get, path, parameters, headers + end + + # Performs a POST request with the given parameters. The parameters may + # be +nil+, a Hash, or a string that is appropriately encoded + # (application/x-www-form-urlencoded or multipart/form-data). The headers + # should be a hash. The keys will automatically be upcased, with the + # prefix 'HTTP_' added if needed. + def post(path, parameters=nil, headers=nil) + process :post, path, parameters, headers + end + + # Performs an XMLHttpRequest request with the given parameters, mimicing + # the request environment created by the Prototype library. The parameters + # may be +nil+, a Hash, or a string that is appropriately encoded + # (application/x-www-form-urlencoded or multipart/form-data). The headers + # should be a hash. The keys will automatically be upcased, with the + # prefix 'HTTP_' added if needed. + def xml_http_request(path, parameters=nil, headers=nil) + headers = (headers || {}).merge("X-Requested-With" => "XMLHttpRequest") + post(path, parameters, headers) + end + + # Returns the URL for the given options, according to the rules specified + # in the application's routes. + def url_for(options) + controller ? controller.url_for(options) : generic_url_rewriter.rewrite(options) + end + + private + + class MockCGI < CGI #:nodoc: + attr_accessor :stdinput, :stdoutput, :env_table + + def initialize(env, input=nil) + self.env_table = env + self.stdinput = StringIO.new(input || "") + self.stdoutput = StringIO.new + + super() + end + end + + # Tailors the session based on the given URI, setting the HTTPS value + # and the hostname. + def interpret_uri(path) + location = URI.parse(path) + https! URI::HTTPS === location if location.scheme + host! location.host if location.host + location.query ? "#{location.path}?#{location.query}" : location.path + end + + # Performs the actual request. + def process(method, path, parameters=nil, headers=nil) + data = requestify(parameters) + path = interpret_uri(path) if path =~ %r{://} + path = "/#{path}" unless path[0] == ?/ + @path = path + env = {} + + if method == :get + env["QUERY_STRING"] = data + data = nil + end + + env.update( + "REQUEST_METHOD" => method.to_s.upcase, + "REQUEST_URI" => path, + "HTTP_HOST" => host, + "REMOTE_ADDR" => remote_addr, + "SERVER_PORT" => (https? ? "443" : "80"), + "CONTENT_TYPE" => "application/x-www-form-urlencoded", + "CONTENT_LENGTH" => data ? data.length.to_s : nil, + "HTTP_COOKIE" => encode_cookies, + "HTTPS" => https? ? "on" : "off", + "HTTP_ACCEPT" => accept + ) + + (headers || {}).each do |key, value| + key = key.to_s.upcase.gsub(/-/, "_") + key = "HTTP_#{key}" unless env.has_key?(key) || env =~ /^X|HTTP/ + env[key] = value + end + + unless ActionController::Base.respond_to?(:clear_last_instantiation!) + ActionController::Base.send(:include, ControllerCapture) + end + + ActionController::Base.clear_last_instantiation! + + cgi = MockCGI.new(env, data) + Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, cgi.stdoutput) + @result = cgi.stdoutput.string + + @controller = ActionController::Base.last_instantiation + @request = @controller.request + @response = @controller.response + + # Decorate the response with the standard behavior of the TestResponse + # so that things like assert_response can be used in integration + # tests. + @response.extend(TestResponseBehavior) + + parse_result + return status + end + + # Parses the result of the response and extracts the various values, + # like cookies, status, headers, etc. + def parse_result + headers, result_body = @result.split(/\r\n\r\n/, 2) + + @headers = Hash.new { |h,k| h[k] = [] } + headers.each_line do |line| + key, value = line.strip.split(/:\s*/, 2) + @headers[key.downcase] << value + end + + (@headers['set-cookie'] || [] ).each do |string| + name, value = string.match(/^(.*?)=(.*?);/)[1,2] + @cookies[name] = value + end + + @status, @status_message = @headers["status"].first.split(/ /) + @status = @status.to_i + end + + # Encode the cookies hash in a format suitable for passing to a + # request. + def encode_cookies + cookies.inject("") do |string, (name, value)| + string << "#{name}=#{value}; " + end + end + + # Get a temporarly URL writer object + def generic_url_rewriter + cgi = MockCGI.new('REQUEST_METHOD' => "GET", + 'QUERY_STRING' => "", + "REQUEST_URI" => "/", + "HTTP_HOST" => host, + "SERVER_PORT" => https? ? "443" : "80", + "HTTPS" => https? ? "on" : "off") + ActionController::UrlRewriter.new(ActionController::CgiRequest.new(cgi), {}) + end + + def name_with_prefix(prefix, name) + prefix ? "#{prefix}[#{name}]" : name.to_s + end + + # Convert the given parameters to a request string. The parameters may + # be a string, +nil+, or a Hash. + def requestify(parameters, prefix=nil) + if Hash === parameters + return nil if parameters.empty? + parameters.map { |k,v| requestify(v, name_with_prefix(prefix, k)) }.join("&") + elsif Array === parameters + parameters.map { |v| requestify(v, name_with_prefix(prefix, "")) }.join("&") + elsif prefix.nil? + parameters + else + "#{CGI.escape(prefix)}=#{CGI.escape(parameters.to_s)}" + end + end + + end + + # A module used to extend ActionController::Base, so that integration tests + # can capture the controller used to satisfy a request. + module ControllerCapture #:nodoc: + def self.included(base) + base.extend(ClassMethods) + base.class_eval do + class <<self + alias_method :new_without_capture, :new + alias_method :new, :new_with_capture + end + end + end + + module ClassMethods #:nodoc: + mattr_accessor :last_instantiation + + def clear_last_instantiation! + self.last_instantiation = nil + end + + def new_with_capture(*args) + self.last_instantiation ||= new_without_capture(*args) + end + end + end + end + + # An IntegrationTest is one that spans multiple controllers and actions, + # tying them all together to ensure they work together as expected. It tests + # more completely than either unit or functional tests do, exercising the + # entire stack, from the dispatcher to the database. + # + # At its simplest, you simply extend IntegrationTest and write your tests + # using the get/post methods: + # + # require "#{File.dirname(__FILE__)}/test_helper" + # + # class ExampleTest < ActionController::IntegrationTest + # fixtures :people + # + # def test_login + # # get the login page + # get "/login" + # assert_equal 200, status + # + # # post the login and follow through to the home page + # post "/login", :username => people(:jamis).username, + # :password => people(:jamis).password + # follow_redirect! + # assert_equal 200, status + # assert_equal "/home", path + # end + # end + # + # However, you can also have multiple session instances open per test, and + # even extend those instances with assertions and methods to create a very + # powerful testing DSL that is specific for your application. You can even + # reference any named routes you happen to have defined! + # + # require "#{File.dirname(__FILE__)}/test_helper" + # + # class AdvancedTest < ActionController::IntegrationTest + # fixtures :people, :rooms + # + # def test_login_and_speak + # jamis, david = login(:jamis), login(:david) + # room = rooms(:office) + # + # jamis.enter(room) + # jamis.speak(room, "anybody home?") + # + # david.enter(room) + # david.speak(room, "hello!") + # end + # + # private + # + # module CustomAssertions + # def enter(room) + # # reference a named route, for maximum internal consistency! + # get(room_url(:id => room.id)) + # assert(...) + # ... + # end + # + # def speak(room, message) + # xml_http_request "/say/#{room.id}", :message => message + # assert(...) + # ... + # end + # end + # + # def login(who) + # open_session do |sess| + # sess.extend(CustomAssertions) + # who = people(who) + # sess.post "/login", :username => who.username, + # :password => who.password + # assert(...) + # end + # end + # end + class IntegrationTest < Test::Unit::TestCase + # Work around a bug in test/unit caused by the default test being named + # as a symbol (:default_test), which causes regex test filters + # (like "ruby test.rb -n /foo/") to fail because =~ doesn't work on + # symbols. + def initialize(name) #:nodoc: + super(name.to_s) + end + + # Work around test/unit's requirement that every subclass of TestCase have + # at least one test method. Note that this implementation extends to all + # subclasses, as well, so subclasses of IntegrationTest may also exist + # without any test methods. + def run(*args) #:nodoc: + return if @method_name == "default_test" + super + end + + # Because of how use_instantiated_fixtures and use_transactional_fixtures + # are defined, we need to treat them as special cases. Otherwise, users + # would potentially have to set their values for both Test::Unit::TestCase + # ActionController::IntegrationTest, since by the time the value is set on + # TestCase, IntegrationTest has already been defined and cannot inherit + # changes to those variables. So, we make those two attributes copy-on-write. + + class << self + def use_transactional_fixtures=(flag) #:nodoc: + @_use_transactional_fixtures = true + @use_transactional_fixtures = flag + end + + def use_instantiated_fixtures=(flag) #:nodoc: + @_use_instantiated_fixtures = true + @use_instantiated_fixtures = flag + end + + def use_transactional_fixtures #:nodoc: + @_use_transactional_fixtures ? + @use_transactional_fixtures : + superclass.use_transactional_fixtures + end + + def use_instantiated_fixtures #:nodoc: + @_use_instantiated_fixtures ? + @use_instantiated_fixtures : + superclass.use_instantiated_fixtures + end + end + + # Reset the current session. This is useful for testing multiple sessions + # in a single test case. + def reset! + @integration_session = open_session + end + + %w(get post cookies assigns xml_http_request).each do |method| + define_method(method) do |*args| + reset! unless @integration_session + returning @integration_session.send(method, *args) do + copy_session_variables! + end + end + end + + # Open a new session instance. If a block is given, the new session is + # yielded to the block before being returned. + # + # session = open_session do |sess| + # sess.extend(CustomAssertions) + # end + # + # By default, a single session is automatically created for you, but you + # can use this method to open multiple sessions that ought to be tested + # simultaneously. + def open_session + session = Integration::Session.new + + # delegate the fixture accessors back to the test instance + extras = Module.new { attr_accessor :delegate, :test_result } + self.class.fixture_table_names.each do |table_name| + name = table_name.tr(".", "_") + next unless respond_to?(name) + extras.send(:define_method, name) { |*args| delegate.send(name, *args) } + end + + # delegate add_assertion to the test case + extras.send(:define_method, :add_assertion) { test_result.add_assertion } + session.extend(extras) + session.delegate = self + session.test_result = @_result + + yield session if block_given? + session + end + + # Copy the instance variables from the current session instance into the + # test instance. + def copy_session_variables! #:nodoc: + return unless @integration_session + %w(controller response request).each do |var| + instance_variable_set("@#{var}", @integration_session.send(var)) + end + end + + # Delegate unhandled messages to the current session instance. + def method_missing(sym, *args, &block) + reset! unless @integration_session + returning @integration_session.send(sym, *args, &block) do + copy_session_variables! + end + end + end +end +module ActionController #:nodoc: + module Layout #:nodoc: + def self.included(base) + base.extend(ClassMethods) + base.class_eval do + alias_method :render_with_no_layout, :render + alias_method :render, :render_with_a_layout + + class << self + alias_method :inherited_without_layout, :inherited + alias_method :inherited, :inherited_with_layout + end + end + end + + # Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in + # repeated setups. The inclusion pattern has pages that look like this: + # + # <%= render "shared/header" %> + # Hello World + # <%= render "shared/footer" %> + # + # This approach is a decent way of keeping common structures isolated from the changing content, but it's verbose + # and if you ever want to change the structure of these two includes, you'll have to change all the templates. + # + # With layouts, you can flip it around and have the common structure know where to insert changing content. This means + # that the header and footer are only mentioned in one place, like this: + # + # <!-- The header part of this layout --> + # <%= yield %> + # <!-- The footer part of this layout --> + # + # And then you have content pages that look like this: + # + # hello world + # + # Not a word about common structures. At rendering time, the content page is computed and then inserted in the layout, + # like this: + # + # <!-- The header part of this layout --> + # hello world + # <!-- The footer part of this layout --> + # + # == Accessing shared variables + # + # Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with + # references that won't materialize before rendering time: + # + # <h1><%= @page_title %></h1> + # <%= yield %> + # + # ...and content pages that fulfill these references _at_ rendering time: + # + # <% @page_title = "Welcome" %> + # Off-world colonies offers you a chance to start a new life + # + # The result after rendering is: + # + # <h1>Welcome</h1> + # Off-world colonies offers you a chance to start a new life + # + # == Automatic layout assignment + # + # If there is a template in <tt>app/views/layouts/</tt> with the same name as the current controller then it will be automatically + # set as that controller's layout unless explicitly told otherwise. Say you have a WeblogController, for example. If a template named + # <tt>app/views/layouts/weblog.rhtml</tt> or <tt>app/views/layouts/weblog.rxml</tt> exists then it will be automatically set as + # the layout for your WeblogController. You can create a layout with the name <tt>application.rhtml</tt> or <tt>application.rxml</tt> + # and this will be set as the default controller if there is no layout with the same name as the current controller and there is + # no layout explicitly assigned with the +layout+ method. Nested controllers use the same folder structure for automatic layout. + # assignment. So an Admin::WeblogController will look for a template named <tt>app/views/layouts/admin/weblog.rhtml</tt>. + # Setting a layout explicitly will always override the automatic behaviour for the controller where the layout is set. + # Explicitly setting the layout in a parent class, though, will not override the child class's layout assignement if the child + # class has a layout with the same name. + # + # == Inheritance for layouts + # + # Layouts are shared downwards in the inheritance hierarchy, but not upwards. Examples: + # + # class BankController < ActionController::Base + # layout "bank_standard" + # + # class InformationController < BankController + # + # class VaultController < BankController + # layout :access_level_layout + # + # class EmployeeController < BankController + # layout nil + # + # The InformationController uses "bank_standard" inherited from the BankController, the VaultController overwrites + # and picks the layout dynamically, and the EmployeeController doesn't want to use a layout at all. + # + # == Types of layouts + # + # Layouts are basically just regular templates, but the name of this template needs not be specified statically. Sometimes + # you want to alternate layouts depending on runtime information, such as whether someone is logged in or not. This can + # be done either by specifying a method reference as a symbol or using an inline method (as a proc). + # + # The method reference is the preferred approach to variable layouts and is used like this: + # + # class WeblogController < ActionController::Base + # layout :writers_and_readers + # + # def index + # # fetching posts + # end + # + # private + # def writers_and_readers + # logged_in? ? "writer_layout" : "reader_layout" + # end + # + # Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing + # is logged in or not. + # + # If you want to use an inline method, such as a proc, do something like this: + # + # class WeblogController < ActionController::Base + # layout proc{ |controller| controller.logged_in? ? "writer_layout" : "reader_layout" } + # + # Of course, the most common way of specifying a layout is still just as a plain template name: + # + # class WeblogController < ActionController::Base + # layout "weblog_standard" + # + # If no directory is specified for the template name, the template will by default by looked for in +app/views/layouts/+. + # + # == Conditional layouts + # + # If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering + # a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The + # <tt>:only</tt> and <tt>:except</tt> options can be passed to the layout call. For example: + # + # class WeblogController < ActionController::Base + # layout "weblog_standard", :except => :rss + # + # # ... + # + # end + # + # This will assign "weblog_standard" as the WeblogController's layout except for the +rss+ action, which will not wrap a layout + # around the rendered view. + # + # Both the <tt>:only</tt> and <tt>:except</tt> condition can accept an arbitrary number of method references, so + # #<tt>:except => [ :rss, :text_only ]</tt> is valid, as is <tt>:except => :rss</tt>. + # + # == Using a different layout in the action render call + # + # If most of your actions use the same layout, it makes perfect sense to define a controller-wide layout as described above. + # Some times you'll have exceptions, though, where one action wants to use a different layout than the rest of the controller. + # This is possible using the <tt>render</tt> method. It's just a bit more manual work as you'll have to supply fully + # qualified template and layout names as this example shows: + # + # class WeblogController < ActionController::Base + # def help + # render :action => "help/index", :layout => "help" + # end + # end + # + # As you can see, you pass the template as the first parameter, the status code as the second ("200" is OK), and the layout + # as the third. + # + # NOTE: The old notation for rendering the view from a layout was to expose the magic <tt>@content_for_layout</tt> instance + # variable. The preferred notation now is to use <tt>yield</tt>, as documented above. + module ClassMethods + # If a layout is specified, all rendered actions will have their result rendered + # when the layout<tt>yield</tt>'s. This layout can itself depend on instance variables assigned during action + # performance and have access to them as any normal template would. + def layout(template_name, conditions = {}) + add_layout_conditions(conditions) + write_inheritable_attribute "layout", template_name + end + + def layout_conditions #:nodoc: + @layout_conditions ||= read_inheritable_attribute("layout_conditions") + end + + def default_layout #:nodoc: + @default_layout ||= read_inheritable_attribute("layout") + end + + private + def inherited_with_layout(child) + inherited_without_layout(child) + child.send :include, Reloadable + layout_match = child.name.underscore.sub(/_controller$/, '').sub(/^controllers\//, '') + child.layout(layout_match) unless layout_list.grep(%r{layouts/#{layout_match}\.[a-z][0-9a-z]*$}).empty? + end + + def layout_list + Dir.glob("#{template_root}/layouts/**/*") + end + + def add_layout_conditions(conditions) + write_inheritable_hash "layout_conditions", normalize_conditions(conditions) + end + + def normalize_conditions(conditions) + conditions.inject({}) {|hash, (key, value)| hash.merge(key => [value].flatten.map {|action| action.to_s})} + end + + def layout_directory_exists_cache + @@layout_directory_exists_cache ||= Hash.new do |h, dirname| + h[dirname] = File.directory? dirname + end + end + end + + # Returns the name of the active layout. If the layout was specified as a method reference (through a symbol), this method + # is called and the return value is used. Likewise if the layout was specified as an inline method (through a proc or method + # object). If the layout was defined without a directory, layouts is assumed. So <tt>layout "weblog/standard"</tt> will return + # weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard. + def active_layout(passed_layout = nil) + layout = passed_layout || self.class.default_layout + + active_layout = case layout + when String then layout + when Symbol then send(layout) + when Proc then layout.call(self) + end + + # Explicitly passed layout names with slashes are looked up relative to the template root, + # but auto-discovered layouts derived from a nested controller will contain a slash, though be relative + # to the 'layouts' directory so we have to check the file system to infer which case the layout name came from. + if active_layout + if active_layout.include?('/') && ! layout_directory?(active_layout) + active_layout + else + "layouts/#{active_layout}" + end + end + end + + def render_with_a_layout(options = nil, deprecated_status = nil, deprecated_layout = nil, &block) #:nodoc: + template_with_options = options.is_a?(Hash) + + if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options, deprecated_layout)) + options = options.merge :layout => false if template_with_options + logger.info("Rendering #{options} within #{layout}") if logger + + if template_with_options + content_for_layout = render_with_no_layout(options, &block) + deprecated_status = options[:status] || deprecated_status + else + content_for_layout = render_with_no_layout(options, deprecated_status, &block) + end + + erase_render_results + add_variables_to_assigns + @template.instance_variable_set("@content_for_layout", content_for_layout) + render_text(@template.render_file(layout, true), deprecated_status) + else + render_with_no_layout(options, deprecated_status, &block) + end + end + + private + + def apply_layout?(template_with_options, options) + return false if options == :update + template_with_options ? candidate_for_layout?(options) : !template_exempt_from_layout? + end + + def candidate_for_layout?(options) + (options.has_key?(:layout) && options[:layout] != false) || + options.values_at(:text, :xml, :file, :inline, :partial, :nothing).compact.empty? && + !template_exempt_from_layout?(default_template_name(options[:action] || options[:template])) + end + + def pick_layout(template_with_options, options, deprecated_layout) + if deprecated_layout + deprecated_layout + elsif template_with_options + case layout = options[:layout] + when FalseClass + nil + when NilClass, TrueClass + active_layout if action_has_layout? + else + active_layout(layout) + end + else + active_layout if action_has_layout? + end + end + + def action_has_layout? + if conditions = self.class.layout_conditions + case + when only = conditions[:only] + only.include?(action_name) + when except = conditions[:except] + !except.include?(action_name) + else + true + end + else + true + end + end + + # Does a layout directory for this class exist? + # we cache this info in a class level hash + def layout_directory?(layout_name) + template_path = File.join(self.class.view_root, 'layouts', layout_name) + dirname = File.dirname(template_path) + self.class.send(:layout_directory_exists_cache)[dirname] + end + end +end +module ActionController + # Macros are class-level calls that add pre-defined actions to the controller based on the parameters passed in. + # Currently, they're used to bridge the JavaScript macros, like autocompletion and in-place editing, with the controller + # backing. + module Macros + module AutoComplete #:nodoc: + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + end + + # Example: + # + # # Controller + # class BlogController < ApplicationController + # auto_complete_for :post, :title + # end + # + # # View + # <%= text_field_with_auto_complete :post, title %> + # + # By default, auto_complete_for limits the results to 10 entries, + # and sorts by the given field. + # + # auto_complete_for takes a third parameter, an options hash to + # the find method used to search for the records: + # + # auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC' + # + # For help on defining text input fields with autocompletion, + # see ActionView::Helpers::JavaScriptHelper. + # + # For more examples, see script.aculo.us: + # * http://script.aculo.us/demos/ajax/autocompleter + # * http://script.aculo.us/demos/ajax/autocompleter_customized + module ClassMethods + def auto_complete_for(object, method, options = {}) + define_method("auto_complete_for_#{object}_#{method}") do + find_options = { + :conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ], + :order => "#{method} ASC", + :limit => 10 }.merge!(options) + + @items = object.to_s.camelize.constantize.find(:all, find_options) + + render :inline => "<%= auto_complete_result @items, '#{method}' %>" + end + end + end + end + end +endmodule ActionController + module Macros + module InPlaceEditing #:nodoc: + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + end + + # Example: + # + # # Controller + # class BlogController < ApplicationController + # in_place_edit_for :post, :title + # end + # + # # View + # <%= in_place_editor_field :post, 'title' %> + # + # For help on defining an in place editor in the browser, + # see ActionView::Helpers::JavaScriptHelper. + module ClassMethods + def in_place_edit_for(object, attribute, options = {}) + define_method("set_#{object}_#{attribute}") do + @item = object.to_s.camelize.constantize.find(params[:id]) + @item.update_attribute(attribute, params[:value]) + render :text => @item.send(attribute) + end + end + end + end + end +end +module ActionController #:nodoc: + module MimeResponds #:nodoc: + def self.included(base) + base.send(:include, ActionController::MimeResponds::InstanceMethods) + end + + module InstanceMethods + # Without web-service support, an action which collects the data for displaying a list of people + # might look something like this: + # + # def list + # @people = Person.find(:all) + # end + # + # Here's the same action, with web-service support baked in: + # + # def list + # @people = Person.find(:all) + # + # respond_to do |wants| + # wants.html + # wants.xml { render :xml => @people.to_xml } + # end + # end + # + # What that says is, "if the client wants HTML in response to this action, just respond as we + # would have before, but if the client wants XML, return them the list of people in XML format." + # (Rails determines the desired response format from the HTTP Accept header submitted by the client.) + # + # Supposing you have an action that adds a new person, optionally creating their company + # (by name) if it does not already exist, without web-services, it might look like this: + # + # def add + # @company = Company.find_or_create_by_name(params[:company][:name]) + # @person = @company.people.create(params[:person]) + # + # redirect_to(person_list_url) + # end + # + # Here's the same action, with web-service support baked in: + # + # def add + # company = params[:person].delete(:company) + # @company = Company.find_or_create_by_name(company[:name]) + # @person = @company.people.create(params[:person]) + # + # respond_to do |wants| + # wants.html { redirect_to(person_list_url) } + # wants.js + # wants.xml { render :xml => @person.to_xml(:include => @company) } + # end + # end + # + # If the client wants HTML, we just redirect them back to the person list. If they want Javascript + # (wants.js), then it is an RJS request and we render the RJS template associated with this action. + # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also + # include the person’s company in the rendered XML, so you get something like this: + # + # <person> + # <id>...</id> + # ... + # <company> + # <id>...</id> + # <name>...</name> + # ... + # </company> + # </person> + # + # Note, however, the extra bit at the top of that action: + # + # company = params[:person].delete(:company) + # @company = Company.find_or_create_by_name(company[:name]) + # + # This is because the incoming XML document (if a web-service request is in process) can only contain a + # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded): + # + # person[name]=...&person[company][name]=...&... + # + # And, like this (xml-encoded): + # + # <person> + # <name>...</name> + # <company> + # <name>...</name> + # </company> + # </person> + # + # In other words, we make the request so that it operates on a single entity—a person. Then, in the action, + # we extract the company data from the request, find or create the company, and then create the new person + # with the remaining data. + # + # Note that you can define your own XML parameter parser which would allow you to describe multiple entities + # in a single request (i.e., by wrapping them all in a single root note), but if you just go with the flow + # and accept Rails' defaults, life will be much easier. + # + # If you need to use a MIME type which isn't supported by default, you can register your own handlers in + # environment.rb as follows. + # + # Mime::Type.register "image/jpg", :jpg + # + def respond_to(*types, &block) + raise ArgumentError, "respond_to takes either types or a block, never bot" unless types.any? ^ block + block ||= lambda { |responder| types.each { |type| responder.send(type) } } + responder = Responder.new(block.binding) + block.call(responder) + responder.respond + end + end + + class Responder #:nodoc: + DEFAULT_BLOCKS = { + :html => 'Proc.new { render }', + :js => 'Proc.new { render :action => "#{action_name}.rjs" }', + :xml => 'Proc.new { render :action => "#{action_name}.rxml" }' + } + + def initialize(block_binding) + @block_binding = block_binding + @mime_type_priority = eval("request.accepts", block_binding) + @order = [] + @responses = {} + end + + def custom(mime_type, &block) + mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s) + + @order << mime_type + + if block_given? + @responses[mime_type] = block + else + @responses[mime_type] = eval(DEFAULT_BLOCKS[mime_type.to_sym], @block_binding) + end + end + + for mime_type in %w( all html js xml rss atom yaml ) + eval <<-EOT + def #{mime_type}(&block) + custom(Mime::#{mime_type.upcase}, &block) + end + EOT + end + + def any(*args, &block) + args.each { |type| send(type, &block) } + end + + def respond + for priority in @mime_type_priority + if priority == Mime::ALL + @responses[@order.first].call + return + else + if priority === @order + @responses[priority].call + return # mime type match found, be happy and return + end + end + end + + if @order.include?(Mime::ALL) + @responses[Mime::ALL].call + else + eval 'render(:nothing => true, :status => "406 Not Acceptable")', @block_binding + end + end + end + end +end +module Mime + class Type #:nodoc: + # A simple helper class used in parsing the accept header + class AcceptItem #:nodoc: + attr_accessor :order, :name, :q + + def initialize(order, name, q=nil) + @order = order + @name = name.strip + q ||= 0.0 if @name == "*/*" # default "*/*" to end of list + @q = ((q || 1.0).to_f * 100).to_i + end + + def to_s + @name + end + + def <=>(item) + result = item.q <=> q + result = order <=> item.order if result == 0 + result + end + + def ==(item) + name == (item.respond_to?(:name) ? item.name : item) + end + end + + class << self + def lookup(string) + LOOKUP[string] + end + + def parse(accept_header) + # keep track of creation order to keep the subsequent sort stable + index = 0 + list = accept_header.split(/,/). + map! { |i| AcceptItem.new(index += 1, *i.split(/;\s*q=/)) }.sort! + + # Take care of the broken text/xml entry by renaming or deleting it + + text_xml = list.index("text/xml") + app_xml = list.index("application/xml") + + if text_xml && app_xml + # set the q value to the max of the two + list[app_xml].q = [list[text_xml].q, list[app_xml].q].max + + # make sure app_xml is ahead of text_xml in the list + if app_xml > text_xml + list[app_xml], list[text_xml] = list[text_xml], list[app_xml] + app_xml, text_xml = text_xml, app_xml + end + + # delete text_xml from the list + list.delete_at(text_xml) + + elsif text_xml + list[text_xml].name = "application/xml" + end + + # Look for more specific xml-based types and sort them ahead of app/xml + + if app_xml + idx = app_xml + app_xml_type = list[app_xml] + + while(idx < list.length) + type = list[idx] + break if type.q < app_xml_type.q + if type.name =~ /\+xml$/ + list[app_xml], list[idx] = list[idx], list[app_xml] + app_xml = idx + end + idx += 1 + end + end + + list.map! { |i| Mime::Type.lookup(i.name) }.uniq! + list + end + end + + def initialize(string, symbol = nil, synonyms = []) + @symbol, @synonyms = symbol, synonyms + @string = string + end + + def to_s + @string + end + + def to_str + to_s + end + + def to_sym + @symbol || @string.to_sym + end + + def ===(list) + if list.is_a?(Array) + (@synonyms + [ self ]).any? { |synonym| list.include?(synonym) } + else + super + end + end + + def ==(mime_type) + (@synonyms + [ self ]).any? { |synonym| synonym.to_s == mime_type.to_s } if mime_type + end + end + + ALL = Type.new "*/*", :all + HTML = Type.new "text/html", :html, %w( application/xhtml+xml ) + JS = Type.new "text/javascript", :js, %w( application/javascript application/x-javascript ) + XML = Type.new "application/xml", :xml, %w( text/xml application/x-xml ) + RSS = Type.new "application/rss+xml", :rss + ATOM = Type.new "application/atom+xml", :atom + YAML = Type.new "application/x-yaml", :yaml, %w( text/yaml ) + + LOOKUP = Hash.new { |h, k| h[k] = Type.new(k) } + + LOOKUP["*/*"] = ALL + + LOOKUP["text/html"] = HTML + LOOKUP["application/xhtml+xml"] = HTML + + LOOKUP["application/xml"] = XML + LOOKUP["text/xml"] = XML + LOOKUP["application/x-xml"] = XML + + LOOKUP["text/javascript"] = JS + LOOKUP["application/javascript"] = JS + LOOKUP["application/x-javascript"] = JS + + LOOKUP["text/yaml"] = YAML + LOOKUP["application/x-yaml"] = YAML + + LOOKUP["application/rss+xml"] = RSS + LOOKUP["application/atom+xml"] = ATOM +endmodule ActionController + # === Action Pack pagination for Active Record collections + # + # The Pagination module aids in the process of paging large collections of + # Active Record objects. It offers macro-style automatic fetching of your + # model for multiple views, or explicit fetching for single actions. And if + # the magic isn't flexible enough for your needs, you can create your own + # paginators with a minimal amount of code. + # + # The Pagination module can handle as much or as little as you wish. In the + # controller, have it automatically query your model for pagination; or, + # if you prefer, create Paginator objects yourself. + # + # Pagination is included automatically for all controllers. + # + # For help rendering pagination links, see + # ActionView::Helpers::PaginationHelper. + # + # ==== Automatic pagination for every action in a controller + # + # class PersonController < ApplicationController + # model :person + # + # paginate :people, :order => 'last_name, first_name', + # :per_page => 20 + # + # # ... + # end + # + # Each action in this controller now has access to a <tt>@people</tt> + # instance variable, which is an ordered collection of model objects for the + # current page (at most 20, sorted by last name and first name), and a + # <tt>@person_pages</tt> Paginator instance. The current page is determined + # by the <tt>params[:page]</tt> variable. + # + # ==== Pagination for a single action + # + # def list + # @person_pages, @people = + # paginate :people, :order => 'last_name, first_name' + # end + # + # Like the previous example, but explicitly creates <tt>@person_pages</tt> + # and <tt>@people</tt> for a single action, and uses the default of 10 items + # per page. + # + # ==== Custom/"classic" pagination + # + # def list + # @person_pages = Paginator.new self, Person.count, 10, params[:page] + # @people = Person.find :all, :order => 'last_name, first_name', + # :limit => @person_pages.items_per_page, + # :offset => @person_pages.current.offset + # end + # + # Explicitly creates the paginator from the previous example and uses + # Paginator#to_sql to retrieve <tt>@people</tt> from the model. + # + module Pagination + unless const_defined?(:OPTIONS) + # A hash holding options for controllers using macro-style pagination + OPTIONS = Hash.new + + # The default options for pagination + DEFAULT_OPTIONS = { + :class_name => nil, + :singular_name => nil, + :per_page => 10, + :conditions => nil, + :order_by => nil, + :order => nil, + :join => nil, + :joins => nil, + :count => nil, + :include => nil, + :select => nil, + :parameter => 'page' + } + end + + def self.included(base) #:nodoc: + super + base.extend(ClassMethods) + end + + def self.validate_options!(collection_id, options, in_action) #:nodoc: + options.merge!(DEFAULT_OPTIONS) {|key, old, new| old} + + valid_options = DEFAULT_OPTIONS.keys + valid_options << :actions unless in_action + + unknown_option_keys = options.keys - valid_options + raise ActionController::ActionControllerError, + "Unknown options: #{unknown_option_keys.join(', ')}" unless + unknown_option_keys.empty? + + options[:singular_name] ||= Inflector.singularize(collection_id.to_s) + options[:class_name] ||= Inflector.camelize(options[:singular_name]) + end + + # Returns a paginator and a collection of Active Record model instances + # for the paginator's current page. This is designed to be used in a + # single action; to automatically paginate multiple actions, consider + # ClassMethods#paginate. + # + # +options+ are: + # <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by + # singularizing the collection name + # <tt>:class_name</tt>:: the class name to use, if it can't be inferred by + # camelizing the singular name + # <tt>:per_page</tt>:: the maximum number of items to include in a + # single page. Defaults to 10 + # <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and + # Model.count + # <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params) + # <tt>:order_by</tt>:: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params) + # <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params) + # and Model.count + # <tt>:join</tt>:: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params) + # and Model.count + # <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params) + # and Model.count + # <tt>:select</tt>:: :select parameter passed to Model.find(:all, *params) + # + # <tt>:count</tt>:: parameter passed as :select option to Model.count(*params) + # + def paginate(collection_id, options={}) + Pagination.validate_options!(collection_id, options, true) + paginator_and_collection_for(collection_id, options) + end + + # These methods become class methods on any controller + module ClassMethods + # Creates a +before_filter+ which automatically paginates an Active + # Record model for all actions in a controller (or certain actions if + # specified with the <tt>:actions</tt> option). + # + # +options+ are the same as PaginationHelper#paginate, with the addition + # of: + # <tt>:actions</tt>:: an array of actions for which the pagination is + # active. Defaults to +nil+ (i.e., every action) + def paginate(collection_id, options={}) + Pagination.validate_options!(collection_id, options, false) + module_eval do + before_filter :create_paginators_and_retrieve_collections + OPTIONS[self] ||= Hash.new + OPTIONS[self][collection_id] = options + end + end + end + + def create_paginators_and_retrieve_collections #:nodoc: + Pagination::OPTIONS[self.class].each do |collection_id, options| + next unless options[:actions].include? action_name if + options[:actions] + + paginator, collection = + paginator_and_collection_for(collection_id, options) + + paginator_name = "@#{options[:singular_name]}_pages" + self.instance_variable_set(paginator_name, paginator) + + collection_name = "@#{collection_id.to_s}" + self.instance_variable_set(collection_name, collection) + end + end + + # Returns the total number of items in the collection to be paginated for + # the +model+ and given +conditions+. Override this method to implement a + # custom counter. + def count_collection_for_pagination(model, options) + model.count(:conditions => options[:conditions], + :joins => options[:join] || options[:joins], + :include => options[:include], + :select => options[:count]) + end + + # Returns a collection of items for the given +model+ and +options[conditions]+, + # ordered by +options[order]+, for the current page in the given +paginator+. + # Override this method to implement a custom finder. + def find_collection_for_pagination(model, options, paginator) + model.find(:all, :conditions => options[:conditions], + :order => options[:order_by] || options[:order], + :joins => options[:join] || options[:joins], :include => options[:include], + :select => options[:select], :limit => options[:per_page], + :offset => paginator.current.offset) + end + + protected :create_paginators_and_retrieve_collections, + :count_collection_for_pagination, + :find_collection_for_pagination + + def paginator_and_collection_for(collection_id, options) #:nodoc: + klass = options[:class_name].constantize + page = @params[options[:parameter]] + count = count_collection_for_pagination(klass, options) + paginator = Paginator.new(self, count, options[:per_page], page) + collection = find_collection_for_pagination(klass, options, paginator) + + return paginator, collection + end + + private :paginator_and_collection_for + + # A class representing a paginator for an Active Record collection. + class Paginator + include Enumerable + + # Creates a new Paginator on the given +controller+ for a set of items + # of size +item_count+ and having +items_per_page+ items per page. + # Raises ArgumentError if items_per_page is out of bounds (i.e., less + # than or equal to zero). The page CGI parameter for links defaults to + # "page" and can be overridden with +page_parameter+. + def initialize(controller, item_count, items_per_page, current_page=1) + raise ArgumentError, 'must have at least one item per page' if + items_per_page <= 0 + + @controller = controller + @item_count = item_count || 0 + @items_per_page = items_per_page + @pages = {} + + self.current_page = current_page + end + attr_reader :controller, :item_count, :items_per_page + + # Sets the current page number of this paginator. If +page+ is a Page + # object, its +number+ attribute is used as the value; if the page does + # not belong to this Paginator, an ArgumentError is raised. + def current_page=(page) + if page.is_a? Page + raise ArgumentError, 'Page/Paginator mismatch' unless + page.paginator == self + end + page = page.to_i + @current_page_number = has_page_number?(page) ? page : 1 + end + + # Returns a Page object representing this paginator's current page. + def current_page + @current_page ||= self[@current_page_number] + end + alias current :current_page + + # Returns a new Page representing the first page in this paginator. + def first_page + @first_page ||= self[1] + end + alias first :first_page + + # Returns a new Page representing the last page in this paginator. + def last_page + @last_page ||= self[page_count] + end + alias last :last_page + + # Returns the number of pages in this paginator. + def page_count + @page_count ||= @item_count.zero? ? 1 : + (q,r=@item_count.divmod(@items_per_page); r==0? q : q+1) + end + + alias length :page_count + + # Returns true if this paginator contains the page of index +number+. + def has_page_number?(number) + number >= 1 and number <= page_count + end + + # Returns a new Page representing the page with the given index + # +number+. + def [](number) + @pages[number] ||= Page.new(self, number) + end + + # Successively yields all the paginator's pages to the given block. + def each(&block) + page_count.times do |n| + yield self[n+1] + end + end + + # A class representing a single page in a paginator. + class Page + include Comparable + + # Creates a new Page for the given +paginator+ with the index + # +number+. If +number+ is not in the range of valid page numbers or + # is not a number at all, it defaults to 1. + def initialize(paginator, number) + @paginator = paginator + @number = number.to_i + @number = 1 unless @paginator.has_page_number? @number + end + attr_reader :paginator, :number + alias to_i :number + + # Compares two Page objects and returns true when they represent the + # same page (i.e., their paginators are the same and they have the + # same page number). + def ==(page) + return false if page.nil? + @paginator == page.paginator and + @number == page.number + end + + # Compares two Page objects and returns -1 if the left-hand page comes + # before the right-hand page, 0 if the pages are equal, and 1 if the + # left-hand page comes after the right-hand page. Raises ArgumentError + # if the pages do not belong to the same Paginator object. + def <=>(page) + raise ArgumentError unless @paginator == page.paginator + @number <=> page.number + end + + # Returns the item offset for the first item in this page. + def offset + @paginator.items_per_page * (@number - 1) + end + + # Returns the number of the first item displayed. + def first_item + offset + 1 + end + + # Returns the number of the last item displayed. + def last_item + [@paginator.items_per_page * @number, @paginator.item_count].min + end + + # Returns true if this page is the first page in the paginator. + def first? + self == @paginator.first + end + + # Returns true if this page is the last page in the paginator. + def last? + self == @paginator.last + end + + # Returns a new Page object representing the page just before this + # page, or nil if this is the first page. + def previous + if first? then nil else @paginator[@number - 1] end + end + + # Returns a new Page object representing the page just after this + # page, or nil if this is the last page. + def next + if last? then nil else @paginator[@number + 1] end + end + + # Returns a new Window object for this page with the specified + # +padding+. + def window(padding=2) + Window.new(self, padding) + end + + # Returns the limit/offset array for this page. + def to_sql + [@paginator.items_per_page, offset] + end + + def to_param #:nodoc: + @number.to_s + end + end + + # A class for representing ranges around a given page. + class Window + # Creates a new Window object for the given +page+ with the specified + # +padding+. + def initialize(page, padding=2) + @paginator = page.paginator + @page = page + self.padding = padding + end + attr_reader :paginator, :page + + # Sets the window's padding (the number of pages on either side of the + # window page). + def padding=(padding) + @padding = padding < 0 ? 0 : padding + # Find the beginning and end pages of the window + @first = @paginator.has_page_number?(@page.number - @padding) ? + @paginator[@page.number - @padding] : @paginator.first + @last = @paginator.has_page_number?(@page.number + @padding) ? + @paginator[@page.number + @padding] : @paginator.last + end + attr_reader :padding, :first, :last + + # Returns an array of Page objects in the current window. + def pages + (@first.number..@last.number).to_a.collect! {|n| @paginator[n]} + end + alias to_a :pages + end + end + + end +end +module ActionController + # Subclassing AbstractRequest makes these methods available to the request objects used in production and testing, + # CgiRequest and TestRequest + class AbstractRequest + cattr_accessor :relative_url_root + + # Returns the hash of environment variables for this request, + # such as { 'RAILS_ENV' => 'production' }. + attr_reader :env + + # Returns both GET and POST parameters in a single hash. + def parameters + @parameters ||= request_parameters.update(query_parameters).update(path_parameters).with_indifferent_access + end + + # Returns the HTTP request method as a lowercase symbol (:get, for example) + def method + @request_method ||= @env['REQUEST_METHOD'].downcase.to_sym + end + + # Is this a GET request? Equivalent to request.method == :get + def get? + method == :get + end + + # Is this a POST request? Equivalent to request.method == :post + def post? + method == :post + end + + # Is this a PUT request? Equivalent to request.method == :put + def put? + method == :put + end + + # Is this a DELETE request? Equivalent to request.method == :delete + def delete? + method == :delete + end + + # Is this a HEAD request? Equivalent to request.method == :head + def head? + method == :head + end + + # Determine whether the body of a HTTP call is URL-encoded (default) + # or matches one of the registered param_parsers. + # + # For backward compatibility, the post format is extracted from the + # X-Post-Data-Format HTTP header if present. + def content_type + @content_type ||= + begin + content_type = @env['CONTENT_TYPE'].to_s.downcase + + if x_post_format = @env['HTTP_X_POST_DATA_FORMAT'] + case x_post_format.to_s.downcase + when 'yaml' + content_type = 'application/x-yaml' + when 'xml' + content_type = 'application/xml' + end + end + + Mime::Type.lookup(content_type) + end + end + + # Returns the accepted MIME type for the request + def accepts + @accepts ||= + if @env['HTTP_ACCEPT'].to_s.strip.empty? + [ content_type, Mime::ALL ] + else + Mime::Type.parse(@env['HTTP_ACCEPT']) + end + end + + # Returns true if the request's "X-Requested-With" header contains + # "XMLHttpRequest". (The Prototype Javascript library sends this header with + # every Ajax request.) + def xml_http_request? + not /XMLHttpRequest/i.match(@env['HTTP_X_REQUESTED_WITH']).nil? + end + alias xhr? :xml_http_request? + + # Determine originating IP address. REMOTE_ADDR is the standard + # but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or + # HTTP_X_FORWARDED_FOR are set by proxies so check for these before + # falling back to REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma- + # delimited list in the case of multiple chained proxies; the first is + # the originating IP. + def remote_ip + return @env['HTTP_CLIENT_IP'] if @env.include? 'HTTP_CLIENT_IP' + + if @env.include? 'HTTP_X_FORWARDED_FOR' then + remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip| + ip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i + end + + return remote_ips.first.strip unless remote_ips.empty? + end + + @env['REMOTE_ADDR'] + end + + # Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify + # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk". + def domain(tld_length = 1) + return nil if !/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/.match(host).nil? or host.nil? + + host.split('.').last(1 + tld_length).join('.') + end + + # Returns all the subdomains as an array, so ["dev", "www"] would be returned for "dev.www.rubyonrails.org". + # You can specify a different <tt>tld_length</tt>, such as 2 to catch ["www"] instead of ["www", "rubyonrails"] + # in "www.rubyonrails.co.uk". + def subdomains(tld_length = 1) + return [] unless host + parts = host.split('.') + parts[0..-(tld_length+2)] + end + + # Receive the raw post data. + # This is useful for services such as REST, XMLRPC and SOAP + # which communicate over HTTP POST but don't use the traditional parameter format. + def raw_post + @env['RAW_POST_DATA'] + end + + # Returns the request URI correctly, taking into account the idiosyncracies + # of the various servers. + def request_uri + if uri = @env['REQUEST_URI'] + (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri # Remove domain, which webrick puts into the request_uri. + else # REQUEST_URI is blank under IIS - get this from PATH_INFO and SCRIPT_NAME + script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$}) + uri = @env['PATH_INFO'] + uri = uri.sub(/#{script_filename}\//, '') unless script_filename.nil? + unless (env_qs = @env['QUERY_STRING']).nil? || env_qs.empty? + uri << '?' << env_qs + end + uri + end + end + + # Return 'https://' if this is an SSL request and 'http://' otherwise. + def protocol + ssl? ? 'https://' : 'http://' + end + + # Is this an SSL request? + def ssl? + @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https' + end + + # Returns the interpreted path to requested resource after all the installation directory of this application was taken into account + def path + path = (uri = request_uri) ? uri.split('?').first : '' + + # Cut off the path to the installation directory if given + root = relative_url_root + path[0, root.length] = '' if root + path || '' + end + + # Returns the path minus the web server relative installation directory. + # This can be set with the environment variable RAILS_RELATIVE_URL_ROOT. + # It can be automatically extracted for Apache setups. If the server is not + # Apache, this method returns an empty string. + def relative_url_root + @@relative_url_root ||= case + when @env["RAILS_RELATIVE_URL_ROOT"] + @env["RAILS_RELATIVE_URL_ROOT"] + when server_software == 'apache' + @env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)$/, '') + else + '' + end + end + + # Returns the port number of this request as an integer. + def port + @port_as_int ||= @env['SERVER_PORT'].to_i + end + + # Returns the standard port number for this request's protocol + def standard_port + case protocol + when 'https://' then 443 + else 80 + end + end + + # Returns a port suffix like ":8080" if the port number of this request + # is not the default HTTP port 80 or HTTPS port 443. + def port_string + (port == standard_port) ? '' : ":#{port}" + end + + # Returns a host:port string for this request, such as example.com or + # example.com:8080. + def host_with_port + host + port_string + end + + def path_parameters=(parameters) #:nodoc: + @path_parameters = parameters + @symbolized_path_parameters = @parameters = nil + end + + # The same as <tt>path_parameters</tt> with explicitly symbolized keys + def symbolized_path_parameters + @symbolized_path_parameters ||= path_parameters.symbolize_keys + end + + # Returns a hash with the parameters used to form the path of the request + # + # Example: + # + # {:action => 'my_action', :controller => 'my_controller'} + def path_parameters + @path_parameters ||= {} + end + + # Returns the lowercase name of the HTTP server software. + def server_software + (@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil + end + + #-- + # Must be implemented in the concrete request + #++ + def query_parameters #:nodoc: + end + + def request_parameters #:nodoc: + end + + # Returns the host for this request, such as example.com. + def host + end + + def cookies #:nodoc: + end + + def session #:nodoc: + end + + def session=(session) #:nodoc: + @session = session + end + + def reset_session #:nodoc: + end + end +end +module ActionController #:nodoc: + # Actions that fail to perform as expected throw exceptions. These exceptions can either be rescued for the public view + # (with a nice user-friendly explanation) or for the developers view (with tons of debugging information). The developers view + # is already implemented by the Action Controller, but the public view should be tailored to your specific application. So too + # could the decision on whether something is a public or a developer request. + # + # You can tailor the rescuing behavior and appearance by overwriting the following two stub methods. + module Rescue + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + base.class_eval do + alias_method :perform_action_without_rescue, :perform_action + alias_method :perform_action, :perform_action_with_rescue + end + end + + module ClassMethods #:nodoc: + def process_with_exception(request, response, exception) + new.process(request, response, :rescue_action, exception) + end + end + + protected + # Exception handler called when the performance of an action raises an exception. + def rescue_action(exception) + log_error(exception) if logger + erase_results if performed? + + if consider_all_requests_local || local_request? + rescue_action_locally(exception) + else + rescue_action_in_public(exception) + end + end + + # Overwrite to implement custom logging of errors. By default logs as fatal. + def log_error(exception) #:doc: + if ActionView::TemplateError === exception + logger.fatal(exception.to_s) + else + logger.fatal( + "\n\n#{exception.class} (#{exception.message}):\n " + + clean_backtrace(exception).join("\n ") + + "\n\n" + ) + end + end + + # Overwrite to implement public exception handling (for requests answering false to <tt>local_request?</tt>). + def rescue_action_in_public(exception) #:doc: + case exception + when RoutingError, UnknownAction then + render_text(IO.read(File.join(RAILS_ROOT, 'public', '404.html')), "404 Not Found") + else render_text "<html><body><h1>Application error (Rails)</h1></body></html>" + end + end + + # Overwrite to expand the meaning of a local request in order to show local rescues on other occurrences than + # the remote IP being 127.0.0.1. For example, this could include the IP of the developer machine when debugging + # remotely. + def local_request? #:doc: + [@request.remote_addr, @request.remote_ip] == ["127.0.0.1"] * 2 + end + + # Renders a detailed diagnostics screen on action exceptions. + def rescue_action_locally(exception) + add_variables_to_assigns + @template.instance_variable_set("@exception", exception) + @template.instance_variable_set("@rescues_path", File.dirname(__FILE__) + "/templates/rescues/") + @template.send(:assign_variables_from_controller) + + @template.instance_variable_set("@contents", @template.render_file(template_path_for_local_rescue(exception), false)) + + @headers["Content-Type"] = "text/html" + render_file(rescues_path("layout"), response_code_for_rescue(exception)) + end + + private + def perform_action_with_rescue #:nodoc: + begin + perform_action_without_rescue + rescue Object => exception + if defined?(Breakpoint) && @params["BP-RETRY"] + msg = exception.backtrace.first + if md = /^(.+?):(\d+)(?::in `(.+)')?$/.match(msg) then + origin_file, origin_line = md[1], md[2].to_i + + set_trace_func(lambda do |type, file, line, method, context, klass| + if file == origin_file and line == origin_line then + set_trace_func(nil) + @params["BP-RETRY"] = false + + callstack = caller + callstack.slice!(0) if callstack.first["rescue.rb"] + file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures + + message = "Exception at #{file}:#{line}#{" in `#{method}'" if method}." # `´ ( for ruby-mode) + + Breakpoint.handle_breakpoint(context, message, file, line) + end + end) + + retry + end + end + + rescue_action(exception) + end + end + + def rescues_path(template_name) + File.dirname(__FILE__) + "/templates/rescues/#{template_name}.rhtml" + end + + def template_path_for_local_rescue(exception) + rescues_path( + case exception + when MissingTemplate then "missing_template" + when RoutingError then "routing_error" + when UnknownAction then "unknown_action" + when ActionView::TemplateError then "template_error" + else "diagnostics" + end + ) + end + + def response_code_for_rescue(exception) + case exception + when UnknownAction, RoutingError then "404 Page Not Found" + else "500 Internal Error" + end + end + + def clean_backtrace(exception) + exception.backtrace.collect { |line| Object.const_defined?(:RAILS_ROOT) ? line.gsub(RAILS_ROOT, "") : line } + end + end +end +module ActionController + class AbstractResponse #:nodoc: + DEFAULT_HEADERS = { "Cache-Control" => "no-cache" } + attr_accessor :body, :headers, :session, :cookies, :assigns, :template, :redirected_to, :redirected_to_method_params + + def initialize + @body, @headers, @session, @assigns = "", DEFAULT_HEADERS.merge("cookie" => []), [], [] + end + + def redirect(to_url, permanently = false) + @headers["Status"] = "302 Found" unless @headers["Status"] == "301 Moved Permanently" + @headers["location"] = to_url + + @body = "<html><body>You are being <a href=\"#{to_url}\">redirected</a>.</body></html>" + end + end +endmodule ActionController + module Routing #:nodoc: + class << self + def expiry_hash(options, recall) + k = v = nil + expire_on = {} + options.each {|k, v| expire_on[k] = ((rcv = recall[k]) && (rcv != v))} + expire_on + end + + def extract_parameter_value(parameter) #:nodoc: + CGI.escape((parameter.respond_to?(:to_param) ? parameter.to_param : parameter).to_s) + end + def controller_relative_to(controller, previous) + if controller.nil? then previous + elsif controller[0] == ?/ then controller[1..-1] + elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}" + else controller + end + end + + def treat_hash(hash, keys_to_delete = []) + k = v = nil + hash.each do |k, v| + if v then hash[k] = (v.respond_to? :to_param) ? v.to_param.to_s : v.to_s + else + hash.delete k + keys_to_delete << k + end + end + hash + end + + def test_condition(expression, condition) + case condition + when String then "(#{expression} == #{condition.inspect})" + when Regexp then + condition = Regexp.new("^#{condition.source}$") unless /^\^.*\$$/ =~ condition.source + "(#{condition.inspect} =~ #{expression})" + when Array then + conds = condition.collect do |condition| + cond = test_condition(expression, condition) + (cond[0, 1] == '(' && cond[-1, 1] == ')') ? cond : "(#{cond})" + end + "(#{conds.join(' || ')})" + when true then expression + when nil then "! #{expression}" + else + raise ArgumentError, "Valid criteria are strings, regular expressions, true, or nil" + end + end + end + + class Component #:nodoc: + def dynamic?() false end + def optional?() false end + + def key() nil end + + def self.new(string, *args) + return super(string, *args) unless self == Component + case string + when ':controller' then ControllerComponent.new(:controller, *args) + when /^:(\w+)$/ then DynamicComponent.new($1, *args) + when /^\*(\w+)$/ then PathComponent.new($1, *args) + else StaticComponent.new(string, *args) + end + end + end + + class StaticComponent < Component #:nodoc: + attr_reader :value + + def initialize(value) + @value = value + end + + def write_recognition(g) + g.if_next_matches(value) do |gp| + gp.move_forward {|gpp| gpp.continue} + end + end + + def write_generation(g) + g.add_segment(value) {|gp| gp.continue } + end + end + + class DynamicComponent < Component #:nodoc: + attr_reader :key, :default + attr_accessor :condition + + def dynamic?() true end + def optional?() @optional end + + def default=(default) + @optional = true + @default = default + end + + def initialize(key, options = {}) + @key = key.to_sym + @optional = false + default, @condition = options[:default], options[:condition] + self.default = default if options.key?(:default) + end + + def default_check(g) + presence = "#{g.hash_value(key, !! default)}" + if default + "!(#{presence} && #{g.hash_value(key, false)} != #{default.to_s.inspect})" + else + "! #{presence}" + end + end + + def write_generation(g) + wrote_dropout = write_dropout_generation(g) + write_continue_generation(g, wrote_dropout) + end + + def write_dropout_generation(g) + return false unless optional? && g.after.all? {|c| c.optional?} + + check = [default_check(g)] + gp = g.dup # Use another generator to write the conditions after the first && + # We do this to ensure that the generator will not assume x_value is set. It will + # not be set if it follows a false condition -- for example, false && (x = 2) + + check += gp.after.map {|c| c.default_check gp} + gp.if(check.join(' && ')) { gp.finish } # If this condition is met, we stop here + true + end + + def write_continue_generation(g, use_else) + test = Routing.test_condition(g.hash_value(key, true, default), condition || true) + check = (use_else && condition.nil? && default) ? [:else] : [use_else ? :elsif : :if, test] + + g.send(*check) do |gp| + gp.expire_for_keys(key) unless gp.after.empty? + add_segments_to(gp) {|gpp| gpp.continue} + end + end + + def add_segments_to(g) + g.add_segment(%(\#{CGI.escape(#{g.hash_value(key, true, default)})})) {|gp| yield gp} + end + + def recognition_check(g) + test_type = [true, nil].include?(condition) ? :presence : :constraint + + prefix = condition.is_a?(Regexp) ? "#{g.next_segment(true)} && " : '' + check = prefix + Routing.test_condition(g.next_segment(true), condition || true) + + g.if(check) {|gp| yield gp, test_type} + end + + def write_recognition(g) + test_type = nil + recognition_check(g) do |gp, test_type| + assign_result(gp) {|gpp| gpp.continue} + end + + if optional? && g.after.all? {|c| c.optional?} + call = (test_type == :presence) ? [:else] : [:elsif, "! #{g.next_segment(true)}"] + + g.send(*call) do |gp| + assign_default(gp) + gp.after.each {|c| c.assign_default(gp)} + gp.finish(false) + end + end + end + + def assign_result(g, with_default = false) + g.result key, "CGI.unescape(#{g.next_segment(true, with_default ? default : nil)})" + g.move_forward {|gp| yield gp} + end + + def assign_default(g) + g.constant_result key, default unless default.nil? + end + end + + class ControllerComponent < DynamicComponent #:nodoc: + def key() :controller end + + def add_segments_to(g) + g.add_segment(%(\#{#{g.hash_value(key, true, default)}})) {|gp| yield gp} + end + + def recognition_check(g) + g << "controller_result = ::ActionController::Routing::ControllerComponent.traverse_to_controller(#{g.path_name}, #{g.index_name})" + g.if('controller_result') do |gp| + gp << 'controller_value, segments_to_controller = controller_result' + if condition + gp << "controller_path = #{gp.path_name}[#{gp.index_name},segments_to_controller].join('/')" + gp.if(Routing.test_condition("controller_path", condition)) do |gpp| + gpp.move_forward('segments_to_controller') {|gppp| yield gppp, :constraint} + end + else + gp.move_forward('segments_to_controller') {|gpp| yield gpp, :constraint} + end + end + end + + def assign_result(g) + g.result key, 'controller_value' + yield g + end + + def assign_default(g) + ControllerComponent.assign_controller(g, default) + end + + class << self + def assign_controller(g, controller) + expr = "::#{controller.split('/').collect {|c| c.camelize}.join('::')}Controller" + g.result :controller, expr, true + end + + def traverse_to_controller(segments, start_at = 0) + mod = ::Object + length = segments.length + index = start_at + mod_name = controller_name = segment = nil + while index < length + return nil unless /\A[A-Za-z][A-Za-z\d_]*\Z/ =~ (segment = segments[index]) + index += 1 + + mod_name = segment.camelize + controller_name = "#{mod_name}Controller" + path_suffix = File.join(segments[start_at..(index - 1)]) + next_mod = nil + + # If the controller is already present, or if we load it, return it. + if mod.const_defined?(controller_name) || attempt_load(mod, controller_name, path_suffix + "_controller") == :defined + controller = mod.const_get(controller_name) + return nil unless controller.is_a?(Class) && controller.ancestors.include?(ActionController::Base) # it's not really a controller? + return [controller, (index - start_at)] + end + + # No controller? Look for the module + if mod.const_defined? mod_name + next_mod = mod.send(:const_get, mod_name) + next_mod = nil unless next_mod.is_a?(Module) + else + # Try to load a file that defines the module we want. + case attempt_load(mod, mod_name, path_suffix) + when :defined then next_mod = mod.const_get mod_name + when :dir then # We didn't find a file, but there's a dir. + next_mod = Module.new # So create a module for the directory + mod.send :const_set, mod_name, next_mod + else + return nil + end + end + mod = next_mod + + return nil unless mod && mod.is_a?(Module) + end + nil + end + + protected + def safe_load_paths #:nodoc: + if defined?(RAILS_ROOT) + $LOAD_PATH.select do |base| + base = File.expand_path(base) + extended_root = File.expand_path(RAILS_ROOT) + # Exclude all paths that are not nested within app, lib, or components. + base.match(/\A#{Regexp.escape(extended_root)}\/*(app|lib|components)\/[a-z]/) || base =~ %r{rails-[\d.]+/builtin} + end + else + $LOAD_PATH + end + end + + def attempt_load(mod, const_name, path) + has_dir = false + safe_load_paths.each do |load_path| + full_path = File.join(load_path, path) + file_path = full_path + '.rb' + if File.file?(file_path) # Found a .rb file? Load it up + require_dependency(file_path) + return :defined if mod.const_defined? const_name + else + has_dir ||= File.directory?(full_path) + end + end + return (has_dir ? :dir : nil) + end + end + end + + class PathComponent < DynamicComponent #:nodoc: + def optional?() true end + def default() [] end + def condition() nil end + + def default=(value) + raise RoutingError, "All path components have an implicit default of []" unless value == [] + end + + def write_generation(g) + raise RoutingError, 'Path components must occur last' unless g.after.empty? + g.if("#{g.hash_value(key, true)} && ! #{g.hash_value(key, true)}.empty?") do + g << "#{g.hash_value(key, true)} = #{g.hash_value(key, true)}.join('/') unless #{g.hash_value(key, true)}.is_a?(String)" + g.add_segment("\#{CGI.escape_skipping_slashes(#{g.hash_value(key, true)})}") {|gp| gp.finish } + end + g.else { g.finish } + end + + def write_recognition(g) + raise RoutingError, "Path components must occur last" unless g.after.empty? + + start = g.index_name + start = "(#{start})" unless /^\w+$/ =~ start + + value_expr = "#{g.path_name}[#{start}..-1] || []" + g.result key, "ActionController::Routing::PathComponent::Result.new_escaped(#{value_expr})" + g.finish(false) + end + + class Result < ::Array #:nodoc: + def to_s() join '/' end + def self.new_escaped(strings) + new strings.collect {|str| CGI.unescape str} + end + end + end + + class Route #:nodoc: + attr_accessor :components, :known + attr_reader :path, :options, :keys, :defaults + + def initialize(path, options = {}) + @path, @options = path, options + + initialize_components path + defaults, conditions = initialize_hashes options.dup + @defaults = defaults.dup + configure_components(defaults, conditions) + add_default_requirements + initialize_keys + end + + def inspect + "<#{self.class} #{path.inspect}, #{options.inspect[1..-1]}>" + end + + def write_generation(generator = CodeGeneration::GenerationGenerator.new) + generator.before, generator.current, generator.after = [], components.first, (components[1..-1] || []) + + if known.empty? then generator.go + else + # Alter the conditions to allow :action => 'index' to also catch :action => nil + altered_known = known.collect do |k, v| + if k == :action && v== 'index' then [k, [nil, 'index']] + else [k, v] + end + end + generator.if(generator.check_conditions(altered_known)) {|gp| gp.go } + end + + generator + end + + def write_recognition(generator = CodeGeneration::RecognitionGenerator.new) + g = generator.dup + g.share_locals_with generator + g.before, g.current, g.after = [], components.first, (components[1..-1] || []) + + known.each do |key, value| + if key == :controller then ControllerComponent.assign_controller(g, value) + else g.constant_result(key, value) + end + end + + g.go + + generator + end + + def initialize_keys + @keys = (components.collect {|c| c.key} + known.keys).compact + @keys.freeze + end + + def extra_keys(options) + options.keys - @keys + end + + def matches_controller?(controller) + if known[:controller] then known[:controller] == controller + else + c = components.find {|c| c.key == :controller} + return false unless c + return c.condition.nil? || eval(Routing.test_condition('controller', c.condition)) + end + end + + protected + def initialize_components(path) + path = path.split('/') if path.is_a? String + path.shift if path.first.blank? + self.components = path.collect {|str| Component.new str} + end + + def initialize_hashes(options) + path_keys = components.collect {|c| c.key }.compact + self.known = {} + defaults = options.delete(:defaults) || {} + conditions = options.delete(:require) || {} + conditions.update(options.delete(:requirements) || {}) + + options.each do |k, v| + if path_keys.include?(k) then (v.is_a?(Regexp) ? conditions : defaults)[k] = v + else known[k] = v + end + end + [defaults, conditions] + end + + def configure_components(defaults, conditions) + components.each do |component| + if defaults.key?(component.key) then component.default = defaults[component.key] + elsif component.key == :action then component.default = 'index' + elsif component.key == :id then component.default = nil + end + + component.condition = conditions[component.key] if conditions.key?(component.key) + end + end + + def add_default_requirements + component_keys = components.collect {|c| c.key} + known[:action] ||= 'index' unless component_keys.include? :action + end + end + + class RouteSet #:nodoc: + attr_reader :routes, :categories, :controller_to_selector + def initialize + @routes = [] + @generation_methods = Hash.new(:generate_default_path) + end + + def generate(options, request_or_recall_hash = {}) + recall = request_or_recall_hash.is_a?(Hash) ? request_or_recall_hash : request_or_recall_hash.symbolized_path_parameters + use_recall = true + + controller = options[:controller] + options[:action] ||= 'index' if controller + recall_controller = recall[:controller] + if (recall_controller && recall_controller.include?(?/)) || (controller && controller.include?(?/)) + recall = {} if controller && controller[0] == ?/ + options[:controller] = Routing.controller_relative_to(controller, recall_controller) + end + options = recall.dup if options.empty? # XXX move to url_rewriter? + + keys_to_delete = [] + Routing.treat_hash(options, keys_to_delete) + + merged = recall.merge(options) + keys_to_delete.each {|key| merged.delete key} + expire_on = Routing.expiry_hash(options, recall) + + generate_path(merged, options, expire_on) + end + + def generate_path(merged, options, expire_on) + send @generation_methods[merged[:controller]], merged, options, expire_on + end + def generate_default_path(*args) + write_generation + generate_default_path(*args) + end + + def write_generation + method_sources = [] + @generation_methods = Hash.new(:generate_default_path) + categorize_routes.each do |controller, routes| + next unless routes.length < @routes.length + + ivar = controller.gsub('/', '__') + method_name = "generate_path_for_#{ivar}".to_sym + instance_variable_set "@#{ivar}", routes + code = generation_code_for(ivar, method_name).to_s + method_sources << code + + filename = "generated_code/routing/generation_for_controller_#{controller}.rb" + eval(code, nil, filename) + + @generation_methods[controller.to_s] = method_name + @generation_methods[controller.to_sym] = method_name + end + + code = generation_code_for('routes', 'generate_default_path').to_s + eval(code, nil, 'generated_code/routing/generation.rb') + + return (method_sources << code) + end + + def recognize(request) + string_path = request.path + string_path.chomp! if string_path[0] == ?/ + path = string_path.split '/' + path.shift + + hash = recognize_path(path) + return recognition_failed(request) unless hash && hash['controller'] + + controller = hash['controller'] + hash['controller'] = controller.controller_path + request.path_parameters = hash + controller.new + end + alias :recognize! :recognize + + def recognition_failed(request) + raise ActionController::RoutingError, "Recognition failed for #{request.path.inspect}" + end + + def write_recognition + g = generator = CodeGeneration::RecognitionGenerator.new + g.finish_statement = Proc.new {|hash_expr| "return #{hash_expr}"} + + g.def "self.recognize_path(path)" do + each do |route| + g << 'index = 0' + route.write_recognition(g) + end + end + + eval g.to_s, nil, 'generated/routing/recognition.rb' + return g.to_s + end + + def generation_code_for(ivar = 'routes', method_name = nil) + routes = instance_variable_get('@' + ivar) + key_ivar = "@keys_for_#{ivar}" + instance_variable_set(key_ivar, routes.collect {|route| route.keys}) + + g = generator = CodeGeneration::GenerationGenerator.new + g.def "self.#{method_name}(merged, options, expire_on)" do + g << 'unused_count = options.length + 1' + g << "unused_keys = keys = options.keys" + g << 'path = nil' + + routes.each_with_index do |route, index| + g << "new_unused_keys = keys - #{key_ivar}[#{index}]" + g << 'new_path = (' + g.source.indent do + if index.zero? + g << "new_unused_count = new_unused_keys.length" + g << "hash = merged; not_expired = true" + route.write_generation(g.dup) + else + g.if "(new_unused_count = new_unused_keys.length) < unused_count" do |gp| + gp << "hash = merged; not_expired = true" + route.write_generation(gp) + end + end + end + g.source.lines.last << ' )' # Add the closing brace to the end line + g.if 'new_path' do + g << 'return new_path, [] if new_unused_count.zero?' + g << 'path = new_path; unused_keys = new_unused_keys; unused_count = new_unused_count' + end + end + + g << "raise RoutingError, \"No url can be generated for the hash \#{options.inspect}\" unless path" + g << "return path, unused_keys" + end + + return g + end + + def categorize_routes + @categorized_routes = by_controller = Hash.new(self) + + known_controllers.each do |name| + set = by_controller[name] = [] + each do |route| + set << route if route.matches_controller? name + end + end + + @categorized_routes + end + + def known_controllers + @routes.inject([]) do |known, route| + if (controller = route.known[:controller]) + if controller.is_a?(Regexp) + known << controller.source.scan(%r{[\w\d/]+}).select {|word| controller =~ word} + else known << controller + end + end + known + end.uniq + end + + def reload + NamedRoutes.clear + + if defined?(RAILS_ROOT) then load(File.join(RAILS_ROOT, 'config', 'routes.rb')) + else connect(':controller/:action/:id', :action => 'index', :id => nil) + end + + NamedRoutes.install + end + + def connect(*args) + new_route = Route.new(*args) + @routes << new_route + return new_route + end + + def draw + old_routes = @routes + @routes = [] + + begin yield self + rescue + @routes = old_routes + raise + end + write_generation + write_recognition + end + + def empty?() @routes.empty? end + + def each(&block) @routes.each(&block) end + + # Defines a new named route with the provided name and arguments. + # This method need only be used when you wish to use a name that a RouteSet instance + # method exists for, such as categories. + # + # For example, map.categories '/categories', :controller => 'categories' will not work + # due to RouteSet#categories. + def named_route(name, path, hash = {}) + route = connect(path, hash) + NamedRoutes.name_route(route, name) + route + end + + def method_missing(name, *args) + (1..2).include?(args.length) ? named_route(name, *args) : super(name, *args) + end + + def extra_keys(options, recall = {}) + generate(options.dup, recall).last + end + end + + module NamedRoutes #:nodoc: + Helpers = [] + class << self + def clear() Helpers.clear end + + def hash_access_name(name) + "hash_for_#{name}_url" + end + + def url_helper_name(name) + "#{name}_url" + end + + def known_hash_for_route(route) + hash = route.known.symbolize_keys + route.defaults.each do |key, value| + hash[key.to_sym] ||= value if value + end + hash[:controller] = "/#{hash[:controller]}" + + hash + end + + def define_hash_access_method(route, name) + hash = known_hash_for_route(route) + define_method(hash_access_name(name)) do |*args| + args.first ? hash.merge(args.first) : hash + end + end + + def name_route(route, name) + define_hash_access_method(route, name) + + module_eval(%{def #{url_helper_name name}(options = {}) + url_for(#{hash_access_name(name)}.merge(options)) + end}, "generated/routing/named_routes/#{name}.rb") + + protected url_helper_name(name), hash_access_name(name) + + Helpers << url_helper_name(name).to_sym + Helpers << hash_access_name(name).to_sym + Helpers.uniq! + end + + def install(cls = ActionController::Base) + cls.send :include, self + if cls.respond_to? :helper_method + Helpers.each do |helper_name| + cls.send :helper_method, helper_name + end + end + end + end + end + + Routes = RouteSet.new + end +end +module ActionController + module Scaffolding # :nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # Scaffolding is a way to quickly put an Active Record class online by providing a series of standardized actions + # for listing, showing, creating, updating, and destroying objects of the class. These standardized actions come + # with both controller logic and default templates that through introspection already know which fields to display + # and which input types to use. Example: + # + # class WeblogController < ActionController::Base + # scaffold :entry + # end + # + # This tiny piece of code will add all of the following methods to the controller: + # + # class WeblogController < ActionController::Base + # verify :method => :post, :only => [ :destroy, :create, :update ], + # :redirect_to => { :action => :list } + # + # def index + # list + # end + # + # def list + # @entries = Entry.find_all + # render_scaffold "list" + # end + # + # def show + # @entry = Entry.find(params[:id]) + # render_scaffold + # end + # + # def destroy + # Entry.find(params[:id]).destroy + # redirect_to :action => "list" + # end + # + # def new + # @entry = Entry.new + # render_scaffold + # end + # + # def create + # @entry = Entry.new(params[:entry]) + # if @entry.save + # flash[:notice] = "Entry was successfully created" + # redirect_to :action => "list" + # else + # render_scaffold('new') + # end + # end + # + # def edit + # @entry = Entry.find(params[:id]) + # render_scaffold + # end + # + # def update + # @entry = Entry.find(params[:id]) + # @entry.attributes = params[:entry] + # + # if @entry.save + # flash[:notice] = "Entry was successfully updated" + # redirect_to :action => "show", :id => @entry + # else + # render_scaffold('edit') + # end + # end + # end + # + # The <tt>render_scaffold</tt> method will first check to see if you've made your own template (like "weblog/show.rhtml" for + # the show action) and if not, then render the generic template for that action. This gives you the possibility of using the + # scaffold while you're building your specific application. Start out with a totally generic setup, then replace one template + # and one action at a time while relying on the rest of the scaffolded templates and actions. + module ClassMethods + # Adds a swath of generic CRUD actions to the controller. The +model_id+ is automatically converted into a class name unless + # one is specifically provide through <tt>options[:class_name]</tt>. So <tt>scaffold :post</tt> would use Post as the class + # and @post/@posts for the instance variables. + # + # It's possible to use more than one scaffold in a single controller by specifying <tt>options[:suffix] = true</tt>. This will + # make <tt>scaffold :post, :suffix => true</tt> use method names like list_post, show_post, and create_post + # instead of just list, show, and post. If suffix is used, then no index method is added. + def scaffold(model_id, options = {}) + options.assert_valid_keys(:class_name, :suffix) + + singular_name = model_id.to_s + class_name = options[:class_name] || singular_name.camelize + plural_name = singular_name.pluralize + suffix = options[:suffix] ? "_#{singular_name}" : "" + + unless options[:suffix] + module_eval <<-"end_eval", __FILE__, __LINE__ + def index + list + end + end_eval + end + + module_eval <<-"end_eval", __FILE__, __LINE__ + + verify :method => :post, :only => [ :destroy#{suffix}, :create#{suffix}, :update#{suffix} ], + :redirect_to => { :action => :list#{suffix} } + + + def list#{suffix} + @#{singular_name}_pages, @#{plural_name} = paginate :#{plural_name}, :per_page => 10 + render#{suffix}_scaffold "list#{suffix}" + end + + def show#{suffix} + @#{singular_name} = #{class_name}.find(params[:id]) + render#{suffix}_scaffold + end + + def destroy#{suffix} + #{class_name}.find(params[:id]).destroy + redirect_to :action => "list#{suffix}" + end + + def new#{suffix} + @#{singular_name} = #{class_name}.new + render#{suffix}_scaffold + end + + def create#{suffix} + @#{singular_name} = #{class_name}.new(params[:#{singular_name}]) + if @#{singular_name}.save + flash[:notice] = "#{class_name} was successfully created" + redirect_to :action => "list#{suffix}" + else + render#{suffix}_scaffold('new') + end + end + + def edit#{suffix} + @#{singular_name} = #{class_name}.find(params[:id]) + render#{suffix}_scaffold + end + + def update#{suffix} + @#{singular_name} = #{class_name}.find(params[:id]) + @#{singular_name}.attributes = params[:#{singular_name}] + + if @#{singular_name}.save + flash[:notice] = "#{class_name} was successfully updated" + redirect_to :action => "show#{suffix}", :id => @#{singular_name} + else + render#{suffix}_scaffold('edit') + end + end + + private + def render#{suffix}_scaffold(action=nil) + action ||= caller_method_name(caller) + # logger.info ("testing template:" + "\#{self.class.controller_path}/\#{action}") if logger + + if template_exists?("\#{self.class.controller_path}/\#{action}") + render_action(action) + else + @scaffold_class = #{class_name} + @scaffold_singular_name, @scaffold_plural_name = "#{singular_name}", "#{plural_name}" + @scaffold_suffix = "#{suffix}" + add_instance_variables_to_assigns + + @template.instance_variable_set("@content_for_layout", @template.render_file(scaffold_path(action.sub(/#{suffix}$/, "")), false)) + + if !active_layout.nil? + render_file(active_layout, nil, true) + else + render_file(scaffold_path("layout")) + end + end + end + + def scaffold_path(template_name) + File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".rhtml" + end + + def caller_method_name(caller) + caller.first.scan(/`(.*)'/).first.first # ' ruby-mode + end + end_eval + end + end + end +end +require 'cgi' +require 'cgi/session' +require 'digest/md5' +require 'base64' + +class CGI + class Session + # Return this session's underlying Session instance. Useful for the DB-backed session stores. + def model + @dbman.model if @dbman + end + + + # A session store backed by an Active Record class. A default class is + # provided, but any object duck-typing to an Active Record +Session+ class + # with text +session_id+ and +data+ attributes is sufficient. + # + # The default assumes a +sessions+ tables with columns: + # +id+ (numeric primary key), + # +session_id+ (text, or longtext if your session data exceeds 65K), and + # +data+ (text or longtext; careful if your session data exceeds 65KB). + # The +session_id+ column should always be indexed for speedy lookups. + # Session data is marshaled to the +data+ column in Base64 format. + # If the data you write is larger than the column's size limit, + # ActionController::SessionOverflowError will be raised. + # + # You may configure the table name, primary key, and data column. + # For example, at the end of config/environment.rb: + # CGI::Session::ActiveRecordStore::Session.table_name = 'legacy_session_table' + # CGI::Session::ActiveRecordStore::Session.primary_key = 'session_id' + # CGI::Session::ActiveRecordStore::Session.data_column_name = 'legacy_session_data' + # Note that setting the primary key to the session_id frees you from + # having a separate id column if you don't want it. However, you must + # set session.model.id = session.session_id by hand! A before_filter + # on ApplicationController is a good place. + # + # Since the default class is a simple Active Record, you get timestamps + # for free if you add +created_at+ and +updated_at+ datetime columns to + # the +sessions+ table, making periodic session expiration a snap. + # + # You may provide your own session class implementation, whether a + # feature-packed Active Record or a bare-metal high-performance SQL + # store, by setting + # +CGI::Session::ActiveRecordStore.session_class = MySessionClass+ + # You must implement these methods: + # self.find_by_session_id(session_id) + # initialize(hash_of_session_id_and_data) + # attr_reader :session_id + # attr_accessor :data + # save + # destroy + # + # The example SqlBypass class is a generic SQL session store. You may + # use it as a basis for high-performance database-specific stores. + class ActiveRecordStore + # The default Active Record class. + class Session < ActiveRecord::Base + # Customizable data column name. Defaults to 'data'. + cattr_accessor :data_column_name + self.data_column_name = 'data' + + before_save :marshal_data! + before_save :raise_on_session_data_overflow! + + class << self + # Don't try to reload ARStore::Session in dev mode. + def reloadable? #:nodoc: + false + end + + def data_column_size_limit + @data_column_size_limit ||= columns_hash[@@data_column_name].limit + end + + # Hook to set up sessid compatibility. + def find_by_session_id(session_id) + setup_sessid_compatibility! + find_by_session_id(session_id) + end + + def marshal(data) Base64.encode64(Marshal.dump(data)) if data end + def unmarshal(data) Marshal.load(Base64.decode64(data)) if data end + + def create_table! + connection.execute <<-end_sql + CREATE TABLE #{table_name} ( + id INTEGER PRIMARY KEY, + #{connection.quote_column_name('session_id')} TEXT UNIQUE, + #{connection.quote_column_name(@@data_column_name)} TEXT(255) + ) + end_sql + end + + def drop_table! + connection.execute "DROP TABLE #{table_name}" + end + + private + # Compatibility with tables using sessid instead of session_id. + def setup_sessid_compatibility! + # Reset column info since it may be stale. + reset_column_information + if columns_hash['sessid'] + def self.find_by_session_id(*args) + find_by_sessid(*args) + end + + define_method(:session_id) { sessid } + define_method(:session_id=) { |session_id| self.sessid = session_id } + else + def self.find_by_session_id(session_id) + find :first, :conditions => ["session_id #{attribute_condition(session_id)}", session_id] + end + end + end + end + + # Lazy-unmarshal session state. + def data + @data ||= self.class.unmarshal(read_attribute(@@data_column_name)) || {} + end + + # Has the session been loaded yet? + def loaded? + !! @data + end + + private + attr_writer :data + + def marshal_data! + return false if !loaded? + write_attribute(@@data_column_name, self.class.marshal(self.data)) + end + + # Ensures that the data about to be stored in the database is not + # larger than the data storage column. Raises + # ActionController::SessionOverflowError. + def raise_on_session_data_overflow! + return false if !loaded? + limit = self.class.data_column_size_limit + if loaded? and limit and read_attribute(@@data_column_name).size > limit + raise ActionController::SessionOverflowError + end + end + end + + # A barebones session store which duck-types with the default session + # store but bypasses Active Record and issues SQL directly. This is + # an example session model class meant as a basis for your own classes. + # + # The database connection, table name, and session id and data columns + # are configurable class attributes. Marshaling and unmarshaling + # are implemented as class methods that you may override. By default, + # marshaling data is +Base64.encode64(Marshal.dump(data))+ and + # unmarshaling data is +Marshal.load(Base64.decode64(data))+. + # + # This marshaling behavior is intended to store the widest range of + # binary session data in a +text+ column. For higher performance, + # store in a +blob+ column instead and forgo the Base64 encoding. + class SqlBypass + # Use the ActiveRecord::Base.connection by default. + cattr_accessor :connection + + # The table name defaults to 'sessions'. + cattr_accessor :table_name + @@table_name = 'sessions' + + # The session id field defaults to 'session_id'. + cattr_accessor :session_id_column + @@session_id_column = 'session_id' + + # The data field defaults to 'data'. + cattr_accessor :data_column + @@data_column = 'data' + + class << self + + def connection + @@connection ||= ActiveRecord::Base.connection + end + + # Look up a session by id and unmarshal its data if found. + def find_by_session_id(session_id) + if record = @@connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{@@connection.quote(session_id)}") + new(:session_id => session_id, :marshaled_data => record['data']) + end + end + + def marshal(data) Base64.encode64(Marshal.dump(data)) if data end + def unmarshal(data) Marshal.load(Base64.decode64(data)) if data end + + def create_table! + @@connection.execute <<-end_sql + CREATE TABLE #{table_name} ( + id INTEGER PRIMARY KEY, + #{@@connection.quote_column_name(session_id_column)} TEXT UNIQUE, + #{@@connection.quote_column_name(data_column)} TEXT + ) + end_sql + end + + def drop_table! + @@connection.execute "DROP TABLE #{table_name}" + end + end + + attr_reader :session_id + attr_writer :data + + # Look for normal and marshaled data, self.find_by_session_id's way of + # telling us to postpone unmarshaling until the data is requested. + # We need to handle a normal data attribute in case of a new record. + def initialize(attributes) + @session_id, @data, @marshaled_data = attributes[:session_id], attributes[:data], attributes[:marshaled_data] + @new_record = @marshaled_data.nil? + end + + def new_record? + @new_record + end + + # Lazy-unmarshal session state. + def data + unless @data + if @marshaled_data + @data, @marshaled_data = self.class.unmarshal(@marshaled_data) || {}, nil + else + @data = {} + end + end + @data + end + + def loaded? + !! @data + end + + def save + return false if !loaded? + marshaled_data = self.class.marshal(data) + + if @new_record + @new_record = false + @@connection.update <<-end_sql, 'Create session' + INSERT INTO #{@@table_name} ( + #{@@connection.quote_column_name(@@session_id_column)}, + #{@@connection.quote_column_name(@@data_column)} ) + VALUES ( + #{@@connection.quote(session_id)}, + #{@@connection.quote(marshaled_data)} ) + end_sql + else + @@connection.update <<-end_sql, 'Update session' + UPDATE #{@@table_name} + SET #{@@connection.quote_column_name(@@data_column)}=#{@@connection.quote(marshaled_data)} + WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)} + end_sql + end + end + + def destroy + unless @new_record + @@connection.delete <<-end_sql, 'Destroy session' + DELETE FROM #{@@table_name} + WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)} + end_sql + end + end + end + + + # The class used for session storage. Defaults to + # CGI::Session::ActiveRecordStore::Session. + cattr_accessor :session_class + self.session_class = Session + + # Find or instantiate a session given a CGI::Session. + def initialize(session, option = nil) + session_id = session.session_id + unless @session = ActiveRecord::Base.silence { @@session_class.find_by_session_id(session_id) } + unless session.new_session + raise CGI::Session::NoSession, 'uninitialized session' + end + @session = @@session_class.new(:session_id => session_id, :data => {}) + # session saving can be lazy again, because of improved component implementation + # therefore next line gets commented out: + # @session.save + end + end + + # Access the underlying session model. + def model + @session + end + + # Restore session state. The session model handles unmarshaling. + def restore + if @session + @session.data + end + end + + # Save session store. + def update + if @session + ActiveRecord::Base.silence { @session.save } + end + end + + # Save and close the session store. + def close + if @session + update + @session = nil + end + end + + # Delete and close the session store. + def delete + if @session + ActiveRecord::Base.silence { @session.destroy } + @session = nil + end + end + + protected + def logger + ActionController::Base.logger rescue nil + end + end + end +end +#!/usr/local/bin/ruby -w + +# This is a really simple session storage daemon, basically just a hash, +# which is enabled for DRb access. + +require 'drb' + +session_hash = Hash.new +session_hash.instance_eval { @mutex = Mutex.new } + +class <<session_hash + def []=(key, value) + @mutex.synchronize do + super(key, value) + end + end + + def [](key) + @mutex.synchronize do + super(key) + end + end + + def delete(key) + @mutex.synchronize do + super(key) + end + end +end + +DRb.start_service('druby://127.0.0.1:9192', session_hash) +DRb.thread.joinrequire 'cgi' +require 'cgi/session' +require 'drb' + +class CGI #:nodoc:all + class Session + class DRbStore + @@session_data = DRbObject.new(nil, 'druby://localhost:9192') + + def initialize(session, option=nil) + @session_id = session.session_id + end + + def restore + @h = @@session_data[@session_id] || {} + end + + def update + @@session_data[@session_id] = @h + end + + def close + update + end + + def delete + @@session_data.delete(@session_id) + end + end + end +end +# cgi/session/memcached.rb - persistent storage of marshalled session data +# +# == Overview +# +# This file provides the CGI::Session::MemCache class, which builds +# persistence of storage data on top of the MemCache library. See +# cgi/session.rb for more details on session storage managers. +# + +begin + require 'cgi/session' + require 'memcache' + + class CGI + class Session + # MemCache-based session storage class. + # + # This builds upon the top-level MemCache class provided by the + # library file memcache.rb. Session data is marshalled and stored + # in a memcached cache. + class MemCacheStore + def check_id(id) #:nodoc:# + /[^0-9a-zA-Z]+/ =~ id.to_s ? false : true + end + + # Create a new CGI::Session::MemCache instance + # + # This constructor is used internally by CGI::Session. The + # user does not generally need to call it directly. + # + # +session+ is the session for which this instance is being + # created. The session id must only contain alphanumeric + # characters; automatically generated session ids observe + # this requirement. + # + # +options+ is a hash of options for the initializer. The + # following options are recognized: + # + # cache:: an instance of a MemCache client to use as the + # session cache. + # + # expires:: an expiry time value to use for session entries in + # the session cache. +expires+ is interpreted in seconds + # relative to the current time if it’s less than 60*60*24*30 + # (30 days), or as an absolute Unix time (e.g., Time#to_i) if + # greater. If +expires+ is +0+, or not passed on +options+, + # the entry will never expire. + # + # This session's memcache entry will be created if it does + # not exist, or retrieved if it does. + def initialize(session, options = {}) + id = session.session_id + unless check_id(id) + raise ArgumentError, "session_id '%s' is invalid" % id + end + @cache = options['cache'] || MemCache.new('localhost') + @expires = options['expires'] || 0 + @session_key = "session:#{id}" + @session_data = {} + end + + # Restore session state from the session's memcache entry. + # + # Returns the session state as a hash. + def restore + begin + @session_data = @cache[@session_key] || {} + rescue + @session_data = {} + end + end + + # Save session state to the session's memcache entry. + def update + begin + @cache.set(@session_key, @session_data, @expires) + rescue + # Ignore session update failures. + end + end + + # Update and close the session's memcache entry. + def close + update + end + + # Delete the session's memcache entry. + def delete + begin + @cache.delete(@session_key) + rescue + # Ignore session delete failures. + end + @session_data = {} + end + end + end + end +rescue LoadError + # MemCache wasn't available so neither can the store be +end +require 'action_controller/session/drb_store' +require 'action_controller/session/mem_cache_store' +if Object.const_defined?(:ActiveRecord) + require 'action_controller/session/active_record_store' +end + +module ActionController #:nodoc: + module SessionManagement #:nodoc: + def self.included(base) + base.extend(ClassMethods) + + base.send :alias_method, :process_without_session_management_support, :process + base.send :alias_method, :process, :process_with_session_management_support + + base.send :alias_method, :process_cleanup_without_session_management_support, :process_cleanup + base.send :alias_method, :process_cleanup, :process_cleanup_with_session_management_support + end + + module ClassMethods + # Set the session store to be used for keeping the session data between requests. The default is using the + # file system, but you can also specify one of the other included stores (:active_record_store, :drb_store, + # :mem_cache_store, or :memory_store) or use your own class. + def session_store=(store) + ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager] = + store.is_a?(Symbol) ? CGI::Session.const_get(store == :drb_store ? "DRbStore" : store.to_s.camelize) : store + end + + # Returns the session store class currently used. + def session_store + ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS[:database_manager] + end + + # Returns the hash used to configure the session. Example use: + # + # ActionController::Base.session_options[:session_secure] = true # session only available over HTTPS + def session_options + ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS + end + + # Specify how sessions ought to be managed for a subset of the actions on + # the controller. Like filters, you can specify <tt>:only</tt> and + # <tt>:except</tt> clauses to restrict the subset, otherwise options + # apply to all actions on this controller. + # + # The session options are inheritable, as well, so if you specify them in + # a parent controller, they apply to controllers that extend the parent. + # + # Usage: + # + # # turn off session management for all actions. + # session :off + # + # # turn off session management for all actions _except_ foo and bar. + # session :off, :except => %w(foo bar) + # + # # turn off session management for only the foo and bar actions. + # session :off, :only => %w(foo bar) + # + # # the session will only work over HTTPS, but only for the foo action + # session :only => :foo, :session_secure => true + # + # # the session will only be disabled for 'foo', and only if it is + # # requested as a web service + # session :off, :only => :foo, + # :if => Proc.new { |req| req.parameters[:ws] } + # + # All session options described for ActionController::Base.process_cgi + # are valid arguments. + def session(*args) + options = Hash === args.last ? args.pop : {} + + options[:disabled] = true if !args.empty? + options[:only] = [*options[:only]].map { |o| o.to_s } if options[:only] + options[:except] = [*options[:except]].map { |o| o.to_s } if options[:except] + if options[:only] && options[:except] + raise ArgumentError, "only one of either :only or :except are allowed" + end + + write_inheritable_array("session_options", [options]) + end + + def cached_session_options #:nodoc: + @session_options ||= read_inheritable_attribute("session_options") || [] + end + + def session_options_for(request, action) #:nodoc: + if (session_options = cached_session_options).empty? + {} + else + options = {} + + action = action.to_s + session_options.each do |opts| + next if opts[:if] && !opts[:if].call(request) + if opts[:only] && opts[:only].include?(action) + options.merge!(opts) + elsif opts[:except] && !opts[:except].include?(action) + options.merge!(opts) + elsif !opts[:only] && !opts[:except] + options.merge!(opts) + end + end + + if options.empty? then options + else + options.delete :only + options.delete :except + options.delete :if + options[:disabled] ? false : options + end + end + end + end + + def process_with_session_management_support(request, response, method = :perform_action, *arguments) #:nodoc: + set_session_options(request) + process_without_session_management_support(request, response, method, *arguments) + end + + private + def set_session_options(request) + request.session_options = self.class.session_options_for(request, request.parameters["action"] || "index") + end + + def process_cleanup_with_session_management_support + process_cleanup_without_session_management_support + clear_persistent_model_associations + end + + # Clear cached associations in session data so they don't overflow + # the database field. Only applies to ActiveRecordStore since there + # is not a standard way to iterate over session data. + def clear_persistent_model_associations #:doc: + if defined?(@session) && @session.instance_variables.include?('@data') + session_data = @session.instance_variable_get('@data') + + if session_data && session_data.respond_to?(:each_value) + session_data.each_value do |obj| + obj.clear_association_cache if obj.respond_to?(:clear_association_cache) + end + end + end + end + end +end +module ActionController #:nodoc: + # Methods for sending files and streams to the browser instead of rendering. + module Streaming + DEFAULT_SEND_FILE_OPTIONS = { + :type => 'application/octet-stream'.freeze, + :disposition => 'attachment'.freeze, + :stream => true, + :buffer_size => 4096 + }.freeze + + protected + # Sends the file by streaming it 4096 bytes at a time. This way the + # whole file doesn't need to be read into memory at once. This makes + # it feasible to send even large files. + # + # Be careful to sanitize the path parameter if it coming from a web + # page. send_file(params[:path]) allows a malicious user to + # download any file on your server. + # + # Options: + # * <tt>:filename</tt> - suggests a filename for the browser to use. + # Defaults to File.basename(path). + # * <tt>:type</tt> - specifies an HTTP content type. + # Defaults to 'application/octet-stream'. + # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. + # Valid values are 'inline' and 'attachment' (default). + # * <tt>:stream</tt> - whether to send the file to the user agent as it is read (true) + # or to read the entire file before sending (false). Defaults to true. + # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file. + # Defaults to 4096. + # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'. + # + # The default Content-Type and Content-Disposition headers are + # set to download arbitrary binary files in as many browsers as + # possible. IE versions 4, 5, 5.5, and 6 are all known to have + # a variety of quirks (especially when downloading over SSL). + # + # Simple download: + # send_file '/path/to.zip' + # + # Show a JPEG in the browser: + # send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline' + # + # Show a 404 page in the browser: + # send_file '/path/to/404.html, :type => 'text/html; charset=utf-8', :status => 404 + # + # Read about the other Content-* HTTP headers if you'd like to + # provide the user with more information (such as Content-Description). + # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11 + # + # Also be aware that the document may be cached by proxies and browsers. + # The Pragma and Cache-Control headers declare how the file may be cached + # by intermediaries. They default to require clients to validate with + # the server before releasing cached responses. See + # http://www.mnot.net/cache_docs/ for an overview of web caching and + # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 + # for the Cache-Control header spec. + def send_file(path, options = {}) #:doc: + raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path) + + options[:length] ||= File.size(path) + options[:filename] ||= File.basename(path) + send_file_headers! options + + @performed_render = false + + if options[:stream] + render :status => options[:status], :text => Proc.new { |response, output| + logger.info "Streaming file #{path}" unless logger.nil? + len = options[:buffer_size] || 4096 + File.open(path, 'rb') do |file| + if output.respond_to?(:syswrite) + begin + while true + output.syswrite(file.sysread(len)) + end + rescue EOFError + end + else + while buf = file.read(len) + output.write(buf) + end + end + end + } + else + logger.info "Sending file #{path}" unless logger.nil? + File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read } + end + end + + # Send binary data to the user as a file download. May set content type, apparent file name, + # and specify whether to show data inline or download as an attachment. + # + # Options: + # * <tt>:filename</tt> - Suggests a filename for the browser to use. + # * <tt>:type</tt> - specifies an HTTP content type. + # Defaults to 'application/octet-stream'. + # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded. + # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'. + # Valid values are 'inline' and 'attachment' (default). + # + # Generic data download: + # send_data buffer + # + # Download a dynamically-generated tarball: + # send_data generate_tgz('dir'), :filename => 'dir.tgz' + # + # Display an image Active Record in the browser: + # send_data image.data, :type => image.content_type, :disposition => 'inline' + # + # See +send_file+ for more information on HTTP Content-* headers and caching. + def send_data(data, options = {}) #:doc: + logger.info "Sending data #{options[:filename]}" unless logger.nil? + send_file_headers! options.merge(:length => data.size) + @performed_render = false + render :status => options[:status], :text => data + end + + private + def send_file_headers!(options) + options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options)) + [:length, :type, :disposition].each do |arg| + raise ArgumentError, ":#{arg} option required" if options[arg].nil? + end + + disposition = options[:disposition].dup || 'attachment' + + disposition <<= %(; filename="#{options[:filename]}") if options[:filename] + + @headers.update( + 'Content-Length' => options[:length], + 'Content-Type' => options[:type].strip, # fixes a problem with extra '\r' with some browsers + 'Content-Disposition' => disposition, + 'Content-Transfer-Encoding' => 'binary' + ) + + # Fix a problem with IE 6.0 on opening downloaded files: + # If Cache-Control: no-cache is set (which Rails does by default), + # IE removes the file it just downloaded from its cache immediately + # after it displays the "open/save" dialog, which means that if you + # hit "open" the file isn't there anymore when the application that + # is called for handling the download is run, so let's workaround that + @headers['Cache-Control'] = 'private' if @headers['Cache-Control'] == 'no-cache' + end + end +end +require File.dirname(__FILE__) + '/assertions' +require File.dirname(__FILE__) + '/deprecated_assertions' + +module ActionController #:nodoc: + class Base + # Process a test request called with a +TestRequest+ object. + def self.process_test(request) + new.process_test(request) + end + + def process_test(request) #:nodoc: + process(request, TestResponse.new) + end + + def process_with_test(*args) + returning process_without_test(*args) do + add_variables_to_assigns + end + end + + alias_method :process_without_test, :process + alias_method :process, :process_with_test + end + + class TestRequest < AbstractRequest #:nodoc: + attr_accessor :cookies, :session_options + attr_accessor :query_parameters, :request_parameters, :path, :session, :env + attr_accessor :host + + def initialize(query_parameters = nil, request_parameters = nil, session = nil) + @query_parameters = query_parameters || {} + @request_parameters = request_parameters || {} + @session = session || TestSession.new + + initialize_containers + initialize_default_values + + super() + end + + def reset_session + @session = {} + end + + def raw_post + if raw_post = env['RAW_POST_DATA'] + raw_post + else + params = self.request_parameters.dup + %w(controller action only_path).each do |k| + params.delete(k) + params.delete(k.to_sym) + end + + params.map { |k,v| [ CGI.escape(k.to_s), CGI.escape(v.to_s) ].join('=') }.sort.join('&') + end + end + + def port=(number) + @env["SERVER_PORT"] = number.to_i + @port_as_int = nil + end + + def action=(action_name) + @query_parameters.update({ "action" => action_name }) + @parameters = nil + end + + # Used to check AbstractRequest's request_uri functionality. + # Disables the use of @path and @request_uri so superclass can handle those. + def set_REQUEST_URI(value) + @env["REQUEST_URI"] = value + @request_uri = nil + @path = nil + end + + def request_uri=(uri) + @request_uri = uri + @path = uri.split("?").first + end + + def remote_addr=(addr) + @env['REMOTE_ADDR'] = addr + end + + def remote_addr + @env['REMOTE_ADDR'] + end + + def request_uri + @request_uri || super() + end + + def path + @path || super() + end + + def assign_parameters(controller_path, action, parameters) + parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action) + extra_keys = ActionController::Routing::Routes.extra_keys(parameters) + non_path_parameters = get? ? query_parameters : request_parameters + parameters.each do |key, value| + if value.is_a? Fixnum + value = value.to_s + elsif value.is_a? Array + value = ActionController::Routing::PathComponent::Result.new(value) + end + + if extra_keys.include?(key.to_sym) + non_path_parameters[key] = value + else + path_parameters[key.to_s] = value + end + end + end + + def recycle! + self.request_parameters = {} + self.query_parameters = {} + self.path_parameters = {} + @request_method, @accepts, @content_type = nil, nil, nil + end + + private + def initialize_containers + @env, @cookies = {}, {} + end + + def initialize_default_values + @host = "test.host" + @request_uri = "/" + self.remote_addr = "0.0.0.0" + @env["SERVER_PORT"] = 80 + @env['REQUEST_METHOD'] = "GET" + end + end + + # A refactoring of TestResponse to allow the same behavior to be applied + # to the "real" CgiResponse class in integration tests. + module TestResponseBehavior #:nodoc: + # the response code of the request + def response_code + headers['Status'][0,3].to_i rescue 0 + end + + # returns a String to ensure compatibility with Net::HTTPResponse + def code + headers['Status'].to_s.split(' ')[0] + end + + def message + headers['Status'].to_s.split(' ',2)[1] + end + + # was the response successful? + def success? + response_code == 200 + end + + # was the URL not found? + def missing? + response_code == 404 + end + + # were we redirected? + def redirect? + (300..399).include?(response_code) + end + + # was there a server-side error? + def error? + (500..599).include?(response_code) + end + + alias_method :server_error?, :error? + + # returns the redirection location or nil + def redirect_url + redirect? ? headers['location'] : nil + end + + # does the redirect location match this regexp pattern? + def redirect_url_match?( pattern ) + return false if redirect_url.nil? + p = Regexp.new(pattern) if pattern.class == String + p = pattern if pattern.class == Regexp + return false if p.nil? + p.match(redirect_url) != nil + end + + # returns the template path of the file which was used to + # render this response (or nil) + def rendered_file(with_controller=false) + unless template.first_render.nil? + unless with_controller + template.first_render + else + template.first_render.split('/').last || template.first_render + end + end + end + + # was this template rendered by a file? + def rendered_with_file? + !rendered_file.nil? + end + + # a shortcut to the flash (or an empty hash if no flash.. hey! that rhymes!) + def flash + session['flash'] || {} + end + + # do we have a flash? + def has_flash? + !session['flash'].empty? + end + + # do we have a flash that has contents? + def has_flash_with_contents? + !flash.empty? + end + + # does the specified flash object exist? + def has_flash_object?(name=nil) + !flash[name].nil? + end + + # does the specified object exist in the session? + def has_session_object?(name=nil) + !session[name].nil? + end + + # a shortcut to the template.assigns + def template_objects + template.assigns || {} + end + + # does the specified template object exist? + def has_template_object?(name=nil) + !template_objects[name].nil? + end + + # Returns the response cookies, converted to a Hash of (name => CGI::Cookie) pairs + # Example: + # + # assert_equal ['AuthorOfNewPage'], r.cookies['author'].value + def cookies + headers['cookie'].inject({}) { |hash, cookie| hash[cookie.name] = cookie; hash } + end + + # Returns binary content (downloadable file), converted to a String + def binary_content + raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc) + require 'stringio' + + sio = StringIO.new + + begin + $stdout = sio + body.call + ensure + $stdout = STDOUT + end + + sio.rewind + sio.read + end + end + + class TestResponse < AbstractResponse #:nodoc: + include TestResponseBehavior + end + + class TestSession #:nodoc: + def initialize(attributes = {}) + @attributes = attributes + end + + def [](key) + @attributes[key] + end + + def []=(key, value) + @attributes[key] = value + end + + def session_id + "" + end + + def update() end + def close() end + def delete() @attributes = {} end + end + + # Essentially generates a modified Tempfile object similar to the object + # you'd get from the standard library CGI module in a multipart + # request. This means you can use an ActionController::TestUploadedFile + # object in the params of a test request in order to simulate + # a file upload. + # + # Usage example, within a functional test: + # post :change_avatar, :avatar => ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/spongebob.png', 'image/png') + class TestUploadedFile + # The filename, *not* including the path, of the "uploaded" file + attr_reader :original_filename + + # The content type of the "uploaded" file + attr_reader :content_type + + def initialize(path, content_type = 'text/plain') + raise "file does not exist" unless File.exist?(path) + @content_type = content_type + @original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 } + @tempfile = Tempfile.new(@original_filename) + FileUtils.copy_file(path, @tempfile.path) + end + + def path #:nodoc: + @tempfile.path + end + + alias local_path path + + def method_missing(method_name, *args, &block) #:nodoc: + @tempfile.send(method_name, *args, &block) + end + end + + module TestProcess + def self.included(base) + # execute the request simulating a specific http method and set/volley the response + %w( get post put delete head ).each do |method| + base.class_eval <<-EOV, __FILE__, __LINE__ + def #{method}(action, parameters = nil, session = nil, flash = nil) + @request.env['REQUEST_METHOD'] = "#{method.upcase}" if @request + process(action, parameters, session, flash) + end + EOV + end + end + + # execute the request and set/volley the response + def process(action, parameters = nil, session = nil, flash = nil) + # Sanity check for required instance variables so we can give an + # understandable error message. + %w(controller request response).each do |iv_name| + raise "@#{iv_name} is nil: make sure you set it in your test's setup method." if instance_variable_get("@#{iv_name}").nil? + end + + @request.recycle! + + @html_document = nil + @request.env['REQUEST_METHOD'] ||= "GET" + @request.action = action.to_s + + parameters ||= {} + @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters) + + @request.session = ActionController::TestSession.new(session) unless session.nil? + @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash + build_request_uri(action, parameters) + @controller.process(@request, @response) + end + + def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil) + @request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' + @request.env['HTTP_ACCEPT'] = 'text/javascript, text/html, application/xml, text/xml, */*' + returning self.send(request_method, action, parameters, session, flash) do + @request.env.delete 'HTTP_X_REQUESTED_WITH' + @request.env.delete 'HTTP_ACCEPT' + end + end + alias xhr :xml_http_request + + def follow_redirect + if @response.redirected_to[:controller] + raise "Can't follow redirects outside of current controller (#{@response.redirected_to[:controller]})" + end + + get(@response.redirected_to.delete(:action), @response.redirected_to.stringify_keys) + end + + def assigns(key = nil) + if key.nil? + @response.template.assigns + else + @response.template.assigns[key.to_s] + end + end + + def session + @response.session + end + + def flash + @response.flash + end + + def cookies + @response.cookies + end + + def redirect_to_url + @response.redirect_url + end + + def build_request_uri(action, parameters) + unless @request.env['REQUEST_URI'] + options = @controller.send(:rewrite_options, parameters) + options.update(:only_path => true, :action => action) + + url = ActionController::UrlRewriter.new(@request, parameters) + @request.set_REQUEST_URI(url.rewrite(options)) + end + end + + def html_document + @html_document ||= HTML::Document.new(@response.body) + end + + def find_tag(conditions) + html_document.find(conditions) + end + + def find_all_tag(conditions) + html_document.find_all(conditions) + end + + def method_missing(selector, *args) + return @controller.send(selector, *args) if ActionController::Routing::NamedRoutes::Helpers.include?(selector) + return super + end + + # Shortcut for ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + path, type). Example: + # post :change_avatar, :avatar => fixture_file_upload('/files/spongebob.png', 'image/png') + def fixture_file_upload(path, mime_type = nil) + ActionController::TestUploadedFile.new( + Test::Unit::TestCase.respond_to?(:fixture_path) ? Test::Unit::TestCase.fixture_path + path : path, + mime_type + ) + end + + # A helper to make it easier to test different route configurations. + # This method temporarily replaces ActionController::Routing::Routes + # with a new RouteSet instance. + # + # The new instance is yielded to the passed block. Typically the block + # will create some routes using map.draw { map.connect ... }: + # + # with_routing do |set| + # set.draw { set.connect ':controller/:id/:action' } + # assert_equal( + # ['/content/10/show', {}], + # set.generate(:controller => 'content', :id => 10, :action => 'show') + # ) + # end + # + def with_routing + real_routes = ActionController::Routing::Routes + ActionController::Routing.send :remove_const, :Routes + + temporary_routes = ActionController::Routing::RouteSet.new + ActionController::Routing.send :const_set, :Routes, temporary_routes + + yield temporary_routes + ensure + if ActionController::Routing.const_defined? :Routes + ActionController::Routing.send(:remove_const, :Routes) + end + ActionController::Routing.const_set(:Routes, real_routes) if real_routes + end + end +end + +module Test + module Unit + class TestCase #:nodoc: + include ActionController::TestProcess + end + end +end +module ActionController + # Rewrites URLs for Base.redirect_to and Base.url_for in the controller. + + class UrlRewriter #:nodoc: + RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :trailing_slash, :skip_relative_url_root] + def initialize(request, parameters) + @request, @parameters = request, parameters + end + + def rewrite(options = {}) + rewrite_url(rewrite_path(options), options) + end + + def to_str + "#{@request.protocol}, #{@request.host_with_port}, #{@request.path}, #{@parameters[:controller]}, #{@parameters[:action]}, #{@request.parameters.inspect}" + end + + alias_method :to_s, :to_str + + private + def rewrite_url(path, options) + rewritten_url = "" + unless options[:only_path] + rewritten_url << (options[:protocol] || @request.protocol) + rewritten_url << (options[:host] || @request.host_with_port) + end + + rewritten_url << @request.relative_url_root.to_s unless options[:skip_relative_url_root] + rewritten_url << path + rewritten_url << '/' if options[:trailing_slash] + rewritten_url << "##{options[:anchor]}" if options[:anchor] + + rewritten_url + end + + def rewrite_path(options) + options = options.symbolize_keys + options.update(options[:params].symbolize_keys) if options[:params] + if (overwrite = options.delete(:overwrite_params)) + options.update(@parameters.symbolize_keys) + options.update(overwrite) + end + RESERVED_OPTIONS.each {|k| options.delete k} + path, extra_keys = Routing::Routes.generate(options.dup, @request) # Warning: Routes will mutate and violate the options hash + + path << build_query_string(options, extra_keys) unless extra_keys.empty? + + path + end + + # Returns a query string with escaped keys and values from the passed hash. If the passed hash contains an "id" it'll + # be added as a path element instead of a regular parameter pair. + def build_query_string(hash, only_keys = nil) + elements = [] + query_string = "" + + only_keys ||= hash.keys + + only_keys.each do |key| + value = hash[key] + key = CGI.escape key.to_s + if value.class == Array + key << '[]' + else + value = [ value ] + end + value.each { |val| elements << "#{key}=#{Routing.extract_parameter_value(val)}" } + end + + query_string << ("?" + elements.join("&")) unless elements.empty? + query_string + end + end +end +require File.dirname(__FILE__) + '/tokenizer' +require File.dirname(__FILE__) + '/node' + +module HTML #:nodoc: + + # A top-level HTMl document. You give it a body of text, and it will parse that + # text into a tree of nodes. + class Document #:nodoc: + + # The root of the parsed document. + attr_reader :root + + # Create a new Document from the given text. + def initialize(text, strict=false, xml=false) + tokenizer = Tokenizer.new(text) + @root = Node.new(nil) + node_stack = [ @root ] + while token = tokenizer.next + node = Node.parse(node_stack.last, tokenizer.line, tokenizer.position, token) + + node_stack.last.children << node unless node.tag? && node.closing == :close + if node.tag? + if node_stack.length > 1 && node.closing == :close + if node_stack.last.name == node.name + node_stack.pop + else + open_start = node_stack.last.position - 20 + open_start = 0 if open_start < 0 + close_start = node.position - 20 + close_start = 0 if close_start < 0 + msg = <<EOF.strip +ignoring attempt to close #{node_stack.last.name} with #{node.name} + opened at byte #{node_stack.last.position}, line #{node_stack.last.line} + closed at byte #{node.position}, line #{node.line} + attributes at open: #{node_stack.last.attributes.inspect} + text around open: #{text[open_start,40].inspect} + text around close: #{text[close_start,40].inspect} +EOF + strict ? raise(msg) : warn(msg) + end + elsif !node.childless?(xml) && node.closing != :close + node_stack.push node + end + end + end + end + + # Search the tree for (and return) the first node that matches the given + # conditions. The conditions are interpreted differently for different node + # types, see HTML::Text#find and HTML::Tag#find. + def find(conditions) + @root.find(conditions) + end + + # Search the tree for (and return) all nodes that match the given + # conditions. The conditions are interpreted differently for different node + # types, see HTML::Text#find and HTML::Tag#find. + def find_all(conditions) + @root.find_all(conditions) + end + + end + +end +require 'strscan' + +module HTML #:nodoc: + + class Conditions < Hash #:nodoc: + def initialize(hash) + super() + hash = { :content => hash } unless Hash === hash + hash = keys_to_symbols(hash) + hash.each do |k,v| + case k + when :tag, :content then + # keys are valid, and require no further processing + when :attributes then + hash[k] = keys_to_strings(v) + when :parent, :child, :ancestor, :descendant, :sibling, :before, + :after + hash[k] = Conditions.new(v) + when :children + hash[k] = v = keys_to_symbols(v) + v.each do |k,v2| + case k + when :count, :greater_than, :less_than + # keys are valid, and require no further processing + when :only + v[k] = Conditions.new(v2) + else + raise "illegal key #{k.inspect} => #{v2.inspect}" + end + end + else + raise "illegal key #{k.inspect} => #{v.inspect}" + end + end + update hash + end + + private + + def keys_to_strings(hash) + hash.keys.inject({}) do |h,k| + h[k.to_s] = hash[k] + h + end + end + + def keys_to_symbols(hash) + hash.keys.inject({}) do |h,k| + raise "illegal key #{k.inspect}" unless k.respond_to?(:to_sym) + h[k.to_sym] = hash[k] + h + end + end + end + + # The base class of all nodes, textual and otherwise, in an HTML document. + class Node #:nodoc: + # The array of children of this node. Not all nodes have children. + attr_reader :children + + # The parent node of this node. All nodes have a parent, except for the + # root node. + attr_reader :parent + + # The line number of the input where this node was begun + attr_reader :line + + # The byte position in the input where this node was begun + attr_reader :position + + # Create a new node as a child of the given parent. + def initialize(parent, line=0, pos=0) + @parent = parent + @children = [] + @line, @position = line, pos + end + + # Return a textual representation of the node. + def to_s + s = "" + @children.each { |child| s << child.to_s } + s + end + + # Return false (subclasses must override this to provide specific matching + # behavior.) +conditions+ may be of any type. + def match(conditions) + false + end + + # Search the children of this node for the first node for which #find + # returns non +nil+. Returns the result of the #find call that succeeded. + def find(conditions) + conditions = validate_conditions(conditions) + + @children.each do |child| + node = child.find(conditions) + return node if node + end + nil + end + + # Search for all nodes that match the given conditions, and return them + # as an array. + def find_all(conditions) + conditions = validate_conditions(conditions) + + matches = [] + matches << self if match(conditions) + @children.each do |child| + matches.concat child.find_all(conditions) + end + matches + end + + # Returns +false+. Subclasses may override this if they define a kind of + # tag. + def tag? + false + end + + def validate_conditions(conditions) + Conditions === conditions ? conditions : Conditions.new(conditions) + end + + def ==(node) + return false unless self.class == node.class && children.size == node.children.size + + equivalent = true + + children.size.times do |i| + equivalent &&= children[i] == node.children[i] + end + + equivalent + end + + class <<self + def parse(parent, line, pos, content, strict=true) + if content !~ /^<\S/ + Text.new(parent, line, pos, content) + else + scanner = StringScanner.new(content) + + unless scanner.skip(/</) + if strict + raise "expected <" + else + return Text.new(parent, line, pos, content) + end + end + + if scanner.skip(/!\[CDATA\[/) + scanner.scan_until(/\]\]>/) + return CDATA.new(parent, line, pos, scanner.pre_match) + end + + closing = ( scanner.scan(/\//) ? :close : nil ) + return Text.new(parent, line, pos, content) unless name = scanner.scan(/[\w:]+/) + name.downcase! + + unless closing + scanner.skip(/\s*/) + attributes = {} + while attr = scanner.scan(/[-\w:]+/) + value = true + if scanner.scan(/\s*=\s*/) + if delim = scanner.scan(/['"]/) + value = "" + while text = scanner.scan(/[^#{delim}\\]+|./) + case text + when "\\" then + value << text + value << scanner.getch + when delim + break + else value << text + end + end + else + value = scanner.scan(/[^\s>\/]+/) + end + end + attributes[attr.downcase] = value + scanner.skip(/\s*/) + end + + closing = ( scanner.scan(/\//) ? :self : nil ) + end + + unless scanner.scan(/\s*>/) + if strict + raise "expected > (got #{scanner.rest.inspect} for #{content}, #{attributes.inspect})" + else + # throw away all text until we find what we're looking for + scanner.skip_until(/>/) or scanner.terminate + end + end + + Tag.new(parent, line, pos, name, attributes, closing) + end + end + end + end + + # A node that represents text, rather than markup. + class Text < Node #:nodoc: + + attr_reader :content + + # Creates a new text node as a child of the given parent, with the given + # content. + def initialize(parent, line, pos, content) + super(parent, line, pos) + @content = content + end + + # Returns the content of this node. + def to_s + @content + end + + # Returns +self+ if this node meets the given conditions. Text nodes support + # conditions of the following kinds: + # + # * if +conditions+ is a string, it must be a substring of the node's + # content + # * if +conditions+ is a regular expression, it must match the node's + # content + # * if +conditions+ is a hash, it must contain a <tt>:content</tt> key that + # is either a string or a regexp, and which is interpreted as described + # above. + def find(conditions) + match(conditions) && self + end + + # Returns non-+nil+ if this node meets the given conditions, or +nil+ + # otherwise. See the discussion of #find for the valid conditions. + def match(conditions) + case conditions + when String + @content.index(conditions) + when Regexp + @content =~ conditions + when Hash + conditions = validate_conditions(conditions) + + # Text nodes only have :content, :parent, :ancestor + unless (conditions.keys - [:content, :parent, :ancestor]).empty? + return false + end + + match(conditions[:content]) + else + nil + end + end + + def ==(node) + return false unless super + content == node.content + end + end + + # A CDATA node is simply a text node with a specialized way of displaying + # itself. + class CDATA < Text #:nodoc: + def to_s + "<![CDATA[#{super}]>" + end + end + + # A Tag is any node that represents markup. It may be an opening tag, a + # closing tag, or a self-closing tag. It has a name, and may have a hash of + # attributes. + class Tag < Node #:nodoc: + + # Either +nil+, <tt>:close</tt>, or <tt>:self</tt> + attr_reader :closing + + # Either +nil+, or a hash of attributes for this node. + attr_reader :attributes + + # The name of this tag. + attr_reader :name + + # Create a new node as a child of the given parent, using the given content + # to describe the node. It will be parsed and the node name, attributes and + # closing status extracted. + def initialize(parent, line, pos, name, attributes, closing) + super(parent, line, pos) + @name = name + @attributes = attributes + @closing = closing + end + + # A convenience for obtaining an attribute of the node. Returns +nil+ if + # the node has no attributes. + def [](attr) + @attributes ? @attributes[attr] : nil + end + + # Returns non-+nil+ if this tag can contain child nodes. + def childless?(xml = false) + return false if xml && @closing.nil? + !@closing.nil? || + @name =~ /^(img|br|hr|link|meta|area|base|basefont| + col|frame|input|isindex|param)$/ox + end + + # Returns a textual representation of the node + def to_s + if @closing == :close + "</#{@name}>" + else + s = "<#{@name}" + @attributes.each do |k,v| + s << " #{k}" + s << "='#{v.gsub(/'/,"\\\\'")}'" if String === v + end + s << " /" if @closing == :self + s << ">" + @children.each { |child| s << child.to_s } + s << "</#{@name}>" if @closing != :self && !@children.empty? + s + end + end + + # If either the node or any of its children meet the given conditions, the + # matching node is returned. Otherwise, +nil+ is returned. (See the + # description of the valid conditions in the +match+ method.) + def find(conditions) + match(conditions) && self || super + end + + # Returns +true+, indicating that this node represents an HTML tag. + def tag? + true + end + + # Returns +true+ if the node meets any of the given conditions. The + # +conditions+ parameter must be a hash of any of the following keys + # (all are optional): + # + # * <tt>:tag</tt>: the node name must match the corresponding value + # * <tt>:attributes</tt>: a hash. The node's values must match the + # corresponding values in the hash. + # * <tt>:parent</tt>: a hash. The node's parent must match the + # corresponding hash. + # * <tt>:child</tt>: a hash. At least one of the node's immediate children + # must meet the criteria described by the hash. + # * <tt>:ancestor</tt>: a hash. At least one of the node's ancestors must + # meet the criteria described by the hash. + # * <tt>:descendant</tt>: a hash. At least one of the node's descendants + # must meet the criteria described by the hash. + # * <tt>:sibling</tt>: a hash. At least one of the node's siblings must + # meet the criteria described by the hash. + # * <tt>:after</tt>: a hash. The node must be after any sibling meeting + # the criteria described by the hash, and at least one sibling must match. + # * <tt>:before</tt>: a hash. The node must be before any sibling meeting + # the criteria described by the hash, and at least one sibling must match. + # * <tt>:children</tt>: a hash, for counting children of a node. Accepts the + # keys: + # ** <tt>:count</tt>: either a number or a range which must equal (or + # include) the number of children that match. + # ** <tt>:less_than</tt>: the number of matching children must be less than + # this number. + # ** <tt>:greater_than</tt>: the number of matching children must be + # greater than this number. + # ** <tt>:only</tt>: another hash consisting of the keys to use + # to match on the children, and only matching children will be + # counted. + # + # Conditions are matched using the following algorithm: + # + # * if the condition is a string, it must be a substring of the value. + # * if the condition is a regexp, it must match the value. + # * if the condition is a number, the value must match number.to_s. + # * if the condition is +true+, the value must not be +nil+. + # * if the condition is +false+ or +nil+, the value must be +nil+. + # + # Usage: + # + # # test if the node is a "span" tag + # node.match :tag => "span" + # + # # test if the node's parent is a "div" + # node.match :parent => { :tag => "div" } + # + # # test if any of the node's ancestors are "table" tags + # node.match :ancestor => { :tag => "table" } + # + # # test if any of the node's immediate children are "em" tags + # node.match :child => { :tag => "em" } + # + # # test if any of the node's descendants are "strong" tags + # node.match :descendant => { :tag => "strong" } + # + # # test if the node has between 2 and 4 span tags as immediate children + # node.match :children => { :count => 2..4, :only => { :tag => "span" } } + # + # # get funky: test to see if the node is a "div", has a "ul" ancestor + # # and an "li" parent (with "class" = "enum"), and whether or not it has + # # a "span" descendant that contains # text matching /hello world/: + # node.match :tag => "div", + # :ancestor => { :tag => "ul" }, + # :parent => { :tag => "li", + # :attributes => { :class => "enum" } }, + # :descendant => { :tag => "span", + # :child => /hello world/ } + def match(conditions) + conditions = validate_conditions(conditions) + + # check content of child nodes + if conditions[:content] + if children.empty? + return false unless match_condition("", conditions[:content]) + else + return false unless children.find { |child| child.match(conditions[:content]) } + end + end + + # test the name + return false unless match_condition(@name, conditions[:tag]) if conditions[:tag] + + # test attributes + (conditions[:attributes] || {}).each do |key, value| + return false unless match_condition(self[key], value) + end + + # test parent + return false unless parent.match(conditions[:parent]) if conditions[:parent] + + # test children + return false unless children.find { |child| child.match(conditions[:child]) } if conditions[:child] + + # test ancestors + if conditions[:ancestor] + return false unless catch :found do + p = self + throw :found, true if p.match(conditions[:ancestor]) while p = p.parent + end + end + + # test descendants + if conditions[:descendant] + return false unless children.find do |child| + # test the child + child.match(conditions[:descendant]) || + # test the child's descendants + child.match(:descendant => conditions[:descendant]) + end + end + + # count children + if opts = conditions[:children] + matches = children.select do |c| + c.match(/./) or + (c.kind_of?(HTML::Tag) and (c.closing == :self or ! c.childless?)) + end + + matches = matches.select { |c| c.match(opts[:only]) } if opts[:only] + opts.each do |key, value| + next if key == :only + case key + when :count + if Integer === value + return false if matches.length != value + else + return false unless value.include?(matches.length) + end + when :less_than + return false unless matches.length < value + when :greater_than + return false unless matches.length > value + else raise "unknown count condition #{key}" + end + end + end + + # test siblings + if conditions[:sibling] || conditions[:before] || conditions[:after] + siblings = parent ? parent.children : [] + self_index = siblings.index(self) + + if conditions[:sibling] + return false unless siblings.detect do |s| + s != self && s.match(conditions[:sibling]) + end + end + + if conditions[:before] + return false unless siblings[self_index+1..-1].detect do |s| + s != self && s.match(conditions[:before]) + end + end + + if conditions[:after] + return false unless siblings[0,self_index].detect do |s| + s != self && s.match(conditions[:after]) + end + end + end + + true + end + + def ==(node) + return false unless super + return false unless closing == node.closing && self.name == node.name + attributes == node.attributes + end + + private + # Match the given value to the given condition. + def match_condition(value, condition) + case condition + when String + value && value == condition + when Regexp + value && value.match(condition) + when Numeric + value == condition.to_s + when true + !value.nil? + when false, nil + value.nil? + else + false + end + end + end +end +require 'strscan' + +module HTML #:nodoc: + + # A simple HTML tokenizer. It simply breaks a stream of text into tokens, where each + # token is a string. Each string represents either "text", or an HTML element. + # + # This currently assumes valid XHTML, which means no free < or > characters. + # + # Usage: + # + # tokenizer = HTML::Tokenizer.new(text) + # while token = tokenizer.next + # p token + # end + class Tokenizer #:nodoc: + + # The current (byte) position in the text + attr_reader :position + + # The current line number + attr_reader :line + + # Create a new Tokenizer for the given text. + def initialize(text) + @scanner = StringScanner.new(text) + @position = 0 + @line = 0 + @current_line = 1 + end + + # Return the next token in the sequence, or +nil+ if there are no more tokens in + # the stream. + def next + return nil if @scanner.eos? + @position = @scanner.pos + @line = @current_line + if @scanner.check(/<\S/) + update_current_line(scan_tag) + else + update_current_line(scan_text) + end + end + + private + + # Treat the text at the current position as a tag, and scan it. Supports + # comments, doctype tags, and regular tags, and ignores less-than and + # greater-than characters within quoted strings. + def scan_tag + tag = @scanner.getch + if @scanner.scan(/!--/) # comment + tag << @scanner.matched + tag << (@scanner.scan_until(/--\s*>/) || @scanner.scan_until(/\Z/)) + elsif @scanner.scan(/!\[CDATA\[/) + tag << @scanner.matched + tag << @scanner.scan_until(/\]\]>/) + elsif @scanner.scan(/!/) # doctype + tag << @scanner.matched + tag << consume_quoted_regions + else + tag << consume_quoted_regions + end + tag + end + + # Scan all text up to the next < character and return it. + def scan_text + "#{@scanner.getch}#{@scanner.scan(/[^<]*/)}" + end + + # Counts the number of newlines in the text and updates the current line + # accordingly. + def update_current_line(text) + text.scan(/\r?\n/) { @current_line += 1 } + end + + # Skips over quoted strings, so that less-than and greater-than characters + # within the strings are ignored. + def consume_quoted_regions + text = "" + loop do + match = @scanner.scan_until(/['"<>]/) or break + + delim = @scanner.matched + if delim == "<" + match = match.chop + @scanner.pos -= 1 + end + + text << match + break if delim == "<" || delim == ">" + + # consume the quoted region + while match = @scanner.scan_until(/[\\#{delim}]/) + text << match + break if @scanner.matched == delim + text << @scanner.getch # skip the escaped character + end + end + text + end + end + +end +module HTML #:nodoc: + module Version #:nodoc: + + MAJOR = 0 + MINOR = 5 + TINY = 3 + + STRING = [ MAJOR, MINOR, TINY ].join(".") + + end +end +require 'rexml/document' + +# SimpleXML like xml parser. Written by leon breet from the ruby on rails Mailing list +class XmlNode #:nodoc: + attr :node + + def initialize(node, options = {}) + @node = node + @children = {} + @raise_errors = options[:raise_errors] + end + + def self.from_xml(xml_or_io) + document = REXML::Document.new(xml_or_io) + if document.root + XmlNode.new(document.root) + else + XmlNode.new(document) + end + end + + def node_encoding + @node.encoding + end + + def node_name + @node.name + end + + def node_value + @node.text + end + + def node_value=(value) + @node.text = value + end + + def xpath(expr) + matches = nil + REXML::XPath.each(@node, expr) do |element| + matches ||= XmlNodeList.new + matches << (@children[element] ||= XmlNode.new(element)) + end + matches + end + + def method_missing(name, *args) + name = name.to_s + nodes = nil + @node.each_element(name) do |element| + nodes ||= XmlNodeList.new + nodes << (@children[element] ||= XmlNode.new(element)) + end + nodes + end + + def <<(node) + if node.is_a? REXML::Node + child = node + elsif node.respond_to? :node + child = node.node + end + @node.add_element child + @children[child] ||= XmlNode.new(child) + end + + def [](name) + @node.attributes[name.to_s] + end + + def []=(name, value) + @node.attributes[name.to_s] = value + end + + def to_s + @node.to_s + end + + def to_i + to_s.to_i + end +end + +class XmlNodeList < Array #:nodoc: + def [](i) + i.is_a?(String) ? super(0)[i] : super(i) + end + + def []=(i, value) + i.is_a?(String) ? self[0][i] = value : super(i, value) + end + + def method_missing(name, *args) + name = name.to_s + self[0].__send__(name, *args) + end +end# = XmlSimple +# +# Author:: Maik Schmidt <contact@maik-schmidt.de> +# Copyright:: Copyright (c) 2003 Maik Schmidt +# License:: Distributes under the same terms as Ruby. +# +require 'rexml/document' + +# Easy API to maintain XML (especially configuration files). +class XmlSimple #:nodoc: + include REXML + + @@VERSION = '1.0.2' + + # A simple cache for XML documents that were already transformed + # by xml_in. + class Cache #:nodoc: + # Creates and initializes a new Cache object. + def initialize + @mem_share_cache = {} + @mem_copy_cache = {} + end + + # Saves a data structure into a file. + # + # data:: + # Data structure to be saved. + # filename:: + # Name of the file belonging to the data structure. + def save_storable(data, filename) + cache_file = get_cache_filename(filename) + File.open(cache_file, "w+") { |f| Marshal.dump(data, f) } + end + + # Restores a data structure from a file. If restoring the data + # structure failed for any reason, nil will be returned. + # + # filename:: + # Name of the file belonging to the data structure. + def restore_storable(filename) + cache_file = get_cache_filename(filename) + return nil unless File::exist?(cache_file) + return nil unless File::mtime(cache_file).to_i > File::mtime(filename).to_i + data = nil + File.open(cache_file) { |f| data = Marshal.load(f) } + data + end + + # Saves a data structure in a shared memory cache. + # + # data:: + # Data structure to be saved. + # filename:: + # Name of the file belonging to the data structure. + def save_mem_share(data, filename) + @mem_share_cache[filename] = [Time::now.to_i, data] + end + + # Restores a data structure from a shared memory cache. You + # should consider these elements as "read only". If restoring + # the data structure failed for any reason, nil will be + # returned. + # + # filename:: + # Name of the file belonging to the data structure. + def restore_mem_share(filename) + get_from_memory_cache(filename, @mem_share_cache) + end + + # Copies a data structure to a memory cache. + # + # data:: + # Data structure to be copied. + # filename:: + # Name of the file belonging to the data structure. + def save_mem_copy(data, filename) + @mem_share_cache[filename] = [Time::now.to_i, Marshal.dump(data)] + end + + # Restores a data structure from a memory cache. If restoring + # the data structure failed for any reason, nil will be + # returned. + # + # filename:: + # Name of the file belonging to the data structure. + def restore_mem_copy(filename) + data = get_from_memory_cache(filename, @mem_share_cache) + data = Marshal.load(data) unless data.nil? + data + end + + private + + # Returns the "cache filename" belonging to a filename, i.e. + # the extension '.xml' in the original filename will be replaced + # by '.stor'. If filename does not have this extension, '.stor' + # will be appended. + # + # filename:: + # Filename to get "cache filename" for. + def get_cache_filename(filename) + filename.sub(/(\.xml)?$/, '.stor') + end + + # Returns a cache entry from a memory cache belonging to a + # certain filename. If no entry could be found for any reason, + # nil will be returned. + # + # filename:: + # Name of the file the cache entry belongs to. + # cache:: + # Memory cache to get entry from. + def get_from_memory_cache(filename, cache) + return nil unless cache[filename] + return nil unless cache[filename][0] > File::mtime(filename).to_i + return cache[filename][1] + end + end + + # Create a "global" cache. + @@cache = Cache.new + + # Creates and intializes a new XmlSimple object. + # + # defaults:: + # Default values for options. + def initialize(defaults = nil) + unless defaults.nil? || defaults.instance_of?(Hash) + raise ArgumentError, "Options have to be a Hash." + end + @default_options = normalize_option_names(defaults, KNOWN_OPTIONS['in'] & KNOWN_OPTIONS['out']) + @options = Hash.new + @_var_values = nil + end + + # Converts an XML document in the same way as the Perl module XML::Simple. + # + # string:: + # XML source. Could be one of the following: + # + # - nil: Tries to load and parse '<scriptname>.xml'. + # - filename: Tries to load and parse filename. + # - IO object: Reads from object until EOF is detected and parses result. + # - XML string: Parses string. + # + # options:: + # Options to be used. + def xml_in(string = nil, options = nil) + handle_options('in', options) + + # If no XML string or filename was supplied look for scriptname.xml. + if string.nil? + string = File::basename($0) + string.sub!(/\.[^.]+$/, '') + string += '.xml' + + directory = File::dirname($0) + @options['searchpath'].unshift(directory) unless directory.nil? + end + + if string.instance_of?(String) + if string =~ /<.*?>/m + @doc = parse(string) + elsif string == '-' + @doc = parse($stdin.readlines.to_s) + else + filename = find_xml_file(string, @options['searchpath']) + + if @options.has_key?('cache') + @options['cache'].each { |scheme| + case(scheme) + when 'storable' + content = @@cache.restore_storable(filename) + when 'mem_share' + content = @@cache.restore_mem_share(filename) + when 'mem_copy' + content = @@cache.restore_mem_copy(filename) + else + raise ArgumentError, "Unsupported caching scheme: <#{scheme}>." + end + return content if content + } + end + + @doc = load_xml_file(filename) + end + elsif string.kind_of?(IO) + @doc = parse(string.readlines.to_s) + else + raise ArgumentError, "Could not parse object of type: <#{string.type}>." + end + + result = collapse(@doc.root) + result = @options['keeproot'] ? merge({}, @doc.root.name, result) : result + put_into_cache(result, filename) + result + end + + # This is the functional version of the instance method xml_in. + def XmlSimple.xml_in(string = nil, options = nil) + xml_simple = XmlSimple.new + xml_simple.xml_in(string, options) + end + + # Converts a data structure into an XML document. + # + # ref:: + # Reference to data structure to be converted into XML. + # options:: + # Options to be used. + def xml_out(ref, options = nil) + handle_options('out', options) + if ref.instance_of?(Array) + ref = { @options['anonymoustag'] => ref } + end + + if @options['keeproot'] + keys = ref.keys + if keys.size == 1 + ref = ref[keys[0]] + @options['rootname'] = keys[0] + end + elsif @options['rootname'] == '' + if ref.instance_of?(Hash) + refsave = ref + ref = {} + refsave.each { |key, value| + if !scalar(value) + ref[key] = value + else + ref[key] = [ value.to_s ] + end + } + end + end + + @ancestors = [] + xml = value_to_xml(ref, @options['rootname'], '') + @ancestors = nil + + if @options['xmldeclaration'] + xml = @options['xmldeclaration'] + "\n" + xml + end + + if @options.has_key?('outputfile') + if @options['outputfile'].kind_of?(IO) + return @options['outputfile'].write(xml) + else + File.open(@options['outputfile'], "w") { |file| file.write(xml) } + end + end + xml + end + + # This is the functional version of the instance method xml_out. + def XmlSimple.xml_out(hash, options = nil) + xml_simple = XmlSimple.new + xml_simple.xml_out(hash, options) + end + + private + + # Declare options that are valid for xml_in and xml_out. + KNOWN_OPTIONS = { + 'in' => %w( + keyattr keeproot forcecontent contentkey noattr + searchpath forcearray suppressempty anonymoustag + cache grouptags normalisespace normalizespace + variables varattr + ), + 'out' => %w( + keyattr keeproot contentkey noattr rootname + xmldeclaration outputfile noescape suppressempty + anonymoustag indent grouptags noindent + ) + } + + # Define some reasonable defaults. + DEF_KEY_ATTRIBUTES = [] + DEF_ROOT_NAME = 'opt' + DEF_CONTENT_KEY = 'content' + DEF_XML_DECLARATION = "<?xml version='1.0' standalone='yes'?>" + DEF_ANONYMOUS_TAG = 'anon' + DEF_FORCE_ARRAY = true + DEF_INDENTATION = ' ' + + # Normalizes option names in a hash, i.e., turns all + # characters to lower case and removes all underscores. + # Additionally, this method checks, if an unknown option + # was used and raises an according exception. + # + # options:: + # Hash to be normalized. + # known_options:: + # List of known options. + def normalize_option_names(options, known_options) + return nil if options.nil? + result = Hash.new + options.each { |key, value| + lkey = key.downcase + lkey.gsub!(/_/, '') + if !known_options.member?(lkey) + raise ArgumentError, "Unrecognised option: #{lkey}." + end + result[lkey] = value + } + result + end + + # Merges a set of options with the default options. + # + # direction:: + # 'in': If options should be handled for xml_in. + # 'out': If options should be handled for xml_out. + # options:: + # Options to be merged with the default options. + def handle_options(direction, options) + @options = options || Hash.new + + raise ArgumentError, "Options must be a Hash!" unless @options.instance_of?(Hash) + + unless KNOWN_OPTIONS.has_key?(direction) + raise ArgumentError, "Unknown direction: <#{direction}>." + end + + known_options = KNOWN_OPTIONS[direction] + @options = normalize_option_names(@options, known_options) + + unless @default_options.nil? + known_options.each { |option| + unless @options.has_key?(option) + if @default_options.has_key?(option) + @options[option] = @default_options[option] + end + end + } + end + + unless @options.has_key?('noattr') + @options['noattr'] = false + end + + if @options.has_key?('rootname') + @options['rootname'] = '' if @options['rootname'].nil? + else + @options['rootname'] = DEF_ROOT_NAME + end + + if @options.has_key?('xmldeclaration') && @options['xmldeclaration'] == true + @options['xmldeclaration'] = DEF_XML_DECLARATION + end + + if @options.has_key?('contentkey') + if @options['contentkey'] =~ /^-(.*)$/ + @options['contentkey'] = $1 + @options['collapseagain'] = true + end + else + @options['contentkey'] = DEF_CONTENT_KEY + end + + unless @options.has_key?('normalisespace') + @options['normalisespace'] = @options['normalizespace'] + end + @options['normalisespace'] = 0 if @options['normalisespace'].nil? + + if @options.has_key?('searchpath') + unless @options['searchpath'].instance_of?(Array) + @options['searchpath'] = [ @options['searchpath'] ] + end + else + @options['searchpath'] = [] + end + + if @options.has_key?('cache') && scalar(@options['cache']) + @options['cache'] = [ @options['cache'] ] + end + + @options['anonymoustag'] = DEF_ANONYMOUS_TAG unless @options.has_key?('anonymoustag') + + if !@options.has_key?('indent') || @options['indent'].nil? + @options['indent'] = DEF_INDENTATION + end + + @options['indent'] = '' if @options.has_key?('noindent') + + # Special cleanup for 'keyattr' which could be an array or + # a hash or left to default to array. + if @options.has_key?('keyattr') + if !scalar(@options['keyattr']) + # Convert keyattr => { elem => '+attr' } + # to keyattr => { elem => ['attr', '+'] } + if @options['keyattr'].instance_of?(Hash) + @options['keyattr'].each { |key, value| + if value =~ /^([-+])?(.*)$/ + @options['keyattr'][key] = [$2, $1 ? $1 : ''] + end + } + elsif !@options['keyattr'].instance_of?(Array) + raise ArgumentError, "'keyattr' must be String, Hash, or Array!" + end + else + @options['keyattr'] = [ @options['keyattr'] ] + end + else + @options['keyattr'] = DEF_KEY_ATTRIBUTES + end + + if @options.has_key?('forcearray') + if @options['forcearray'].instance_of?(Regexp) + @options['forcearray'] = [ @options['forcearray'] ] + end + + if @options['forcearray'].instance_of?(Array) + force_list = @options['forcearray'] + unless force_list.empty? + @options['forcearray'] = {} + force_list.each { |tag| + if tag.instance_of?(Regexp) + unless @options['forcearray']['_regex'].instance_of?(Array) + @options['forcearray']['_regex'] = [] + end + @options['forcearray']['_regex'] << tag + else + @options['forcearray'][tag] = true + end + } + else + @options['forcearray'] = false + end + else + @options['forcearray'] = @options['forcearray'] ? true : false + end + else + @options['forcearray'] = DEF_FORCE_ARRAY + end + + if @options.has_key?('grouptags') && !@options['grouptags'].instance_of?(Hash) + raise ArgumentError, "Illegal value for 'GroupTags' option - expected a Hash." + end + + if @options.has_key?('variables') && !@options['variables'].instance_of?(Hash) + raise ArgumentError, "Illegal value for 'Variables' option - expected a Hash." + end + + if @options.has_key?('variables') + @_var_values = @options['variables'] + elsif @options.has_key?('varattr') + @_var_values = {} + end + end + + # Actually converts an XML document element into a data structure. + # + # element:: + # The document element to be collapsed. + def collapse(element) + result = @options['noattr'] ? {} : get_attributes(element) + + if @options['normalisespace'] == 2 + result.each { |k, v| result[k] = normalise_space(v) } + end + + if element.has_elements? + element.each_element { |child| + value = collapse(child) + if empty(value) && (element.attributes.empty? || @options['noattr']) + next if @options.has_key?('suppressempty') && @options['suppressempty'] == true + end + result = merge(result, child.name, value) + } + if has_mixed_content?(element) + # normalisespace? + content = element.texts.map { |x| x.to_s } + content = content[0] if content.size == 1 + result[@options['contentkey']] = content + end + elsif element.has_text? # i.e. it has only text. + return collapse_text_node(result, element) + end + + # Turn Arrays into Hashes if key fields present. + count = fold_arrays(result) + + # Disintermediate grouped tags. + if @options.has_key?('grouptags') + result.each { |key, value| + next unless (value.instance_of?(Hash) && (value.size == 1)) + child_key, child_value = value.to_a[0] + if @options['grouptags'][key] == child_key + result[key] = child_value + end + } + end + + # Fold Hases containing a single anonymous Array up into just the Array. + if count == 1 + anonymoustag = @options['anonymoustag'] + if result.has_key?(anonymoustag) && result[anonymoustag].instance_of?(Array) + return result[anonymoustag] + end + end + + if result.empty? && @options.has_key?('suppressempty') + return @options['suppressempty'] == '' ? '' : nil + end + + result + end + + # Collapses a text node and merges it with an existing Hash, if + # possible. + # Thanks to Curtis Schofield for reporting a subtle bug. + # + # hash:: + # Hash to merge text node value with, if possible. + # element:: + # Text node to be collapsed. + def collapse_text_node(hash, element) + value = node_to_text(element) + if empty(value) && !element.has_attributes? + return {} + end + + if element.has_attributes? && !@options['noattr'] + return merge(hash, @options['contentkey'], value) + else + if @options['forcecontent'] + return merge(hash, @options['contentkey'], value) + else + return value + end + end + end + + # Folds all arrays in a Hash. + # + # hash:: + # Hash to be folded. + def fold_arrays(hash) + fold_amount = 0 + keyattr = @options['keyattr'] + if (keyattr.instance_of?(Array) || keyattr.instance_of?(Hash)) + hash.each { |key, value| + if value.instance_of?(Array) + if keyattr.instance_of?(Array) + hash[key] = fold_array(value) + else + hash[key] = fold_array_by_name(key, value) + end + fold_amount += 1 + end + } + end + fold_amount + end + + # Folds an Array to a Hash, if possible. Folding happens + # according to the content of keyattr, which has to be + # an array. + # + # array:: + # Array to be folded. + def fold_array(array) + hash = Hash.new + array.each { |x| + return array unless x.instance_of?(Hash) + key_matched = false + @options['keyattr'].each { |key| + if x.has_key?(key) + key_matched = true + value = x[key] + return array if value.instance_of?(Hash) || value.instance_of?(Array) + value = normalise_space(value) if @options['normalisespace'] == 1 + x.delete(key) + hash[value] = x + break + end + } + return array unless key_matched + } + hash = collapse_content(hash) if @options['collapseagain'] + hash + end + + # Folds an Array to a Hash, if possible. Folding happens + # according to the content of keyattr, which has to be + # a Hash. + # + # name:: + # Name of the attribute to be folded upon. + # array:: + # Array to be folded. + def fold_array_by_name(name, array) + return array unless @options['keyattr'].has_key?(name) + key, flag = @options['keyattr'][name] + + hash = Hash.new + array.each { |x| + if x.instance_of?(Hash) && x.has_key?(key) + value = x[key] + return array if value.instance_of?(Hash) || value.instance_of?(Array) + value = normalise_space(value) if @options['normalisespace'] == 1 + hash[value] = x + hash[value]["-#{key}"] = hash[value][key] if flag == '-' + hash[value].delete(key) unless flag == '+' + else + $stderr.puts("Warning: <#{name}> element has no '#{key}' attribute.") + return array + end + } + hash = collapse_content(hash) if @options['collapseagain'] + hash + end + + # Tries to collapse a Hash even more ;-) + # + # hash:: + # Hash to be collapsed again. + def collapse_content(hash) + content_key = @options['contentkey'] + hash.each_value { |value| + return hash unless value.instance_of?(Hash) && value.size == 1 && value.has_key?(content_key) + hash.each_key { |key| hash[key] = hash[key][content_key] } + } + hash + end + + # Adds a new key/value pair to an existing Hash. If the key to be added + # does already exist and the existing value associated with key is not + # an Array, it will be converted into an Array. Then the new value is + # appended to that Array. + # + # hash:: + # Hash to add key/value pair to. + # key:: + # Key to be added. + # value:: + # Value to be associated with key. + def merge(hash, key, value) + if value.instance_of?(String) + value = normalise_space(value) if @options['normalisespace'] == 2 + + # do variable substitutions + unless @_var_values.nil? || @_var_values.empty? + value.gsub!(/\$\{(\w+)\}/) { |x| get_var($1) } + end + + # look for variable definitions + if @options.has_key?('varattr') + varattr = @options['varattr'] + if hash.has_key?(varattr) + set_var(hash[varattr], value) + end + end + end + if hash.has_key?(key) + if hash[key].instance_of?(Array) + hash[key] << value + else + hash[key] = [ hash[key], value ] + end + elsif value.instance_of?(Array) # Handle anonymous arrays. + hash[key] = [ value ] + else + if force_array?(key) + hash[key] = [ value ] + else + hash[key] = value + end + end + hash + end + + # Checks, if the 'forcearray' option has to be used for + # a certain key. + def force_array?(key) + return false if key == @options['contentkey'] + return true if @options['forcearray'] == true + forcearray = @options['forcearray'] + if forcearray.instance_of?(Hash) + return true if forcearray.has_key?(key) + return false unless forcearray.has_key?('_regex') + forcearray['_regex'].each { |x| return true if key =~ x } + end + return false + end + + # Converts the attributes array of a document node into a Hash. + # Returns an empty Hash, if node has no attributes. + # + # node:: + # Document node to extract attributes from. + def get_attributes(node) + attributes = {} + node.attributes.each { |n,v| attributes[n] = v } + attributes + end + + # Determines, if a document element has mixed content. + # + # element:: + # Document element to be checked. + def has_mixed_content?(element) + if element.has_text? && element.has_elements? + return true if element.texts.join('') !~ /^\s*$/s + end + false + end + + # Called when a variable definition is encountered in the XML. + # A variable definition looks like + # <element attrname="name">value</element> + # where attrname matches the varattr setting. + def set_var(name, value) + @_var_values[name] = value + end + + # Called during variable substitution to get the value for the + # named variable. + def get_var(name) + if @_var_values.has_key?(name) + return @_var_values[name] + else + return "${#{name}}" + end + end + + # Recurses through a data structure building up and returning an + # XML representation of that structure as a string. + # + # ref:: + # Reference to the data structure to be encoded. + # name:: + # The XML tag name to be used for this item. + # indent:: + # A string of spaces for use as the current indent level. + def value_to_xml(ref, name, indent) + named = !name.nil? && name != '' + nl = @options.has_key?('noindent') ? '' : "\n" + + if !scalar(ref) + if @ancestors.member?(ref) + raise ArgumentError, "Circular data structures not supported!" + end + @ancestors << ref + else + if named + return [indent, '<', name, '>', @options['noescape'] ? ref.to_s : escape_value(ref.to_s), '</', name, '>', nl].join('') + else + return ref.to_s + nl + end + end + + # Unfold hash to array if possible. + if ref.instance_of?(Hash) && !ref.empty? && !@options['keyattr'].empty? && indent != '' + ref = hash_to_array(name, ref) + end + + result = [] + if ref.instance_of?(Hash) + # Reintermediate grouped values if applicable. + if @options.has_key?('grouptags') + ref.each { |key, value| + if @options['grouptags'].has_key?(key) + ref[key] = { @options['grouptags'][key] => value } + end + } + end + + nested = [] + text_content = nil + if named + result << indent << '<' << name + end + + if !ref.empty? + ref.each { |key, value| + next if !key.nil? && key[0, 1] == '-' + if value.nil? + unless @options.has_key?('suppressempty') && @options['suppressempty'].nil? + raise ArgumentError, "Use of uninitialized value!" + end + value = {} + end + + if !scalar(value) || @options['noattr'] + nested << value_to_xml(value, key, indent + @options['indent']) + else + value = value.to_s + value = escape_value(value) unless @options['noescape'] + if key == @options['contentkey'] + text_content = value + else + result << ' ' << key << '="' << value << '"' + end + end + } + else + text_content = '' + end + + if !nested.empty? || !text_content.nil? + if named + result << '>' + if !text_content.nil? + result << text_content + nested[0].sub!(/^\s+/, '') if !nested.empty? + else + result << nl + end + if !nested.empty? + result << nested << indent + end + result << '</' << name << '>' << nl + else + result << nested + end + else + result << ' />' << nl + end + elsif ref.instance_of?(Array) + ref.each { |value| + if scalar(value) + result << indent << '<' << name << '>' + result << (@options['noescape'] ? value.to_s : escape_value(value.to_s)) + result << '</' << name << '>' << nl + elsif value.instance_of?(Hash) + result << value_to_xml(value, name, indent) + else + result << indent << '<' << name << '>' << nl + result << value_to_xml(value, @options['anonymoustag'], indent + @options['indent']) + result << indent << '</' << name << '>' << nl + end + } + else + # Probably, this is obsolete. + raise ArgumentError, "Can't encode a value of type: #{ref.type}." + end + @ancestors.pop if !scalar(ref) + result.join('') + end + + # Checks, if a certain value is a "scalar" value. Whatever + # that will be in Ruby ... ;-) + # + # value:: + # Value to be checked. + def scalar(value) + return false if value.instance_of?(Hash) || value.instance_of?(Array) + return true + end + + # Attempts to unfold a hash of hashes into an array of hashes. Returns + # a reference to th array on success or the original hash, if unfolding + # is not possible. + # + # parent:: + # + # hashref:: + # Reference to the hash to be unfolded. + def hash_to_array(parent, hashref) + arrayref = [] + hashref.each { |key, value| + return hashref unless value.instance_of?(Hash) + + if @options['keyattr'].instance_of?(Hash) + return hashref unless @options['keyattr'].has_key?(parent) + arrayref << { @options['keyattr'][parent][0] => key }.update(value) + else + arrayref << { @options['keyattr'][0] => key }.update(value) + end + } + arrayref + end + + # Replaces XML markup characters by their external entities. + # + # data:: + # The string to be escaped. + def escape_value(data) + return data if data.nil? || data == '' + result = data.dup + result.gsub!('&', '&') + result.gsub!('<', '<') + result.gsub!('>', '>') + result.gsub!('"', '"') + result.gsub!("'", ''') + result + end + + # Removes leading and trailing whitespace and sequences of + # whitespaces from a string. + # + # text:: + # String to be normalised. + def normalise_space(text) + text.sub!(/^\s+/, '') + text.sub!(/\s+$/, '') + text.gsub!(/\s\s+/, ' ') + text + end + + # Checks, if an object is nil, an empty String or an empty Hash. + # Thanks to Norbert Gawor for a bugfix. + # + # value:: + # Value to be checked for emptyness. + def empty(value) + case value + when Hash + return value.empty? + when String + return value !~ /\S/m + else + return value.nil? + end + end + + # Converts a document node into a String. + # If the node could not be converted into a String + # for any reason, default will be returned. + # + # node:: + # Document node to be converted. + # default:: + # Value to be returned, if node could not be converted. + def node_to_text(node, default = nil) + if node.instance_of?(Element) + return node.texts.join('') + elsif node.instance_of?(Attribute) + return node.value.nil? ? default : node.value.strip + elsif node.instance_of?(Text) + return node.to_s.strip + else + return default + end + end + + # Parses an XML string and returns the according document. + # + # xml_string:: + # XML string to be parsed. + # + # The following exception may be raised: + # + # REXML::ParseException:: + # If the specified file is not wellformed. + def parse(xml_string) + Document.new(xml_string) + end + + # Searches in a list of paths for a certain file. Returns + # the full path to the file, if it could be found. Otherwise, + # an exception will be raised. + # + # filename:: + # Name of the file to search for. + # searchpath:: + # List of paths to search in. + def find_xml_file(file, searchpath) + filename = File::basename(file) + + if filename != file + return file if File::file?(file) + else + searchpath.each { |path| + full_path = File::join(path, filename) + return full_path if File::file?(full_path) + } + end + + if searchpath.empty? + return file if File::file?(file) + raise ArgumentError, "File does not exist: #{file}." + end + raise ArgumentError, "Could not find <#{filename}> in <#{searchpath.join(':')}>" + end + + # Loads and parses an XML configuration file. + # + # filename:: + # Name of the configuration file to be loaded. + # + # The following exceptions may be raised: + # + # Errno::ENOENT:: + # If the specified file does not exist. + # REXML::ParseException:: + # If the specified file is not wellformed. + def load_xml_file(filename) + parse(File.readlines(filename).to_s) + end + + # Caches the data belonging to a certain file. + # + # data:: + # Data to be cached. + # filename:: + # Name of file the data was read from. + def put_into_cache(data, filename) + if @options.has_key?('cache') + @options['cache'].each { |scheme| + case(scheme) + when 'storable' + @@cache.save_storable(data, filename) + when 'mem_share' + @@cache.save_mem_share(data, filename) + when 'mem_copy' + @@cache.save_mem_copy(data, filename) + else + raise ArgumentError, "Unsupported caching scheme: <#{scheme}>." + end + } + end + end +end + +# vim:sw=2 +module ActionController #:nodoc: + module Verification #:nodoc: + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + end + + # This module provides a class-level method for specifying that certain + # actions are guarded against being called without certain prerequisites + # being met. This is essentially a special kind of before_filter. + # + # An action may be guarded against being invoked without certain request + # parameters being set, or without certain session values existing. + # + # When a verification is violated, values may be inserted into the flash, and + # a specified redirection is triggered. + # + # Usage: + # + # class GlobalController < ActionController::Base + # # prevent the #update_settings action from being invoked unless + # # the 'admin_privileges' request parameter exists. + # verify :params => "admin_privileges", :only => :update_post, + # :redirect_to => { :action => "settings" } + # + # # disallow a post from being updated if there was no information + # # submitted with the post, and if there is no active post in the + # # session, and if there is no "note" key in the flash. + # verify :params => "post", :session => "post", "flash" => "note", + # :only => :update_post, + # :add_flash => { "alert" => "Failed to create your message" }, + # :redirect_to => :category_url + # + module ClassMethods + # Verify the given actions so that if certain prerequisites are not met, + # the user is redirected to a different action. The +options+ parameter + # is a hash consisting of the following key/value pairs: + # + # * <tt>:params</tt>: a single key or an array of keys that must + # be in the <tt>params</tt> hash in order for the action(s) to be safely + # called. + # * <tt>:session</tt>: a single key or an array of keys that must + # be in the @session in order for the action(s) to be safely called. + # * <tt>:flash</tt>: a single key or an array of keys that must + # be in the flash in order for the action(s) to be safely called. + # * <tt>:method</tt>: a single key or an array of keys--any one of which + # must match the current request method in order for the action(s) to + # be safely called. (The key should be a symbol: <tt>:get</tt> or + # <tt>:post</tt>, for example.) + # * <tt>:xhr</tt>: true/false option to ensure that the request is coming + # from an Ajax call or not. + # * <tt>:add_flash</tt>: a hash of name/value pairs that should be merged + # into the session's flash if the prerequisites cannot be satisfied. + # * <tt>:redirect_to</tt>: the redirection parameters to be used when + # redirecting if the prerequisites cannot be satisfied. + # * <tt>:render</tt>: the render parameters to be used when + # the prerequisites cannot be satisfied. + # * <tt>:only</tt>: only apply this verification to the actions specified + # in the associated array (may also be a single value). + # * <tt>:except</tt>: do not apply this verification to the actions + # specified in the associated array (may also be a single value). + def verify(options={}) + filter_opts = { :only => options[:only], :except => options[:except] } + before_filter(filter_opts) do |c| + c.send :verify_action, options + end + end + end + + def verify_action(options) #:nodoc: + prereqs_invalid = + [*options[:params] ].find { |v| @params[v].nil? } || + [*options[:session]].find { |v| @session[v].nil? } || + [*options[:flash] ].find { |v| flash[v].nil? } + + if !prereqs_invalid && options[:method] + prereqs_invalid ||= + [*options[:method]].all? { |v| @request.method != v.to_sym } + end + + prereqs_invalid ||= (request.xhr? != options[:xhr]) unless options[:xhr].nil? + + if prereqs_invalid + flash.update(options[:add_flash]) if options[:add_flash] + unless performed? + render(options[:render]) if options[:render] + redirect_to(options[:redirect_to]) if options[:redirect_to] + end + return false + end + + true + end + private :verify_action + end +end +#-- +# Copyright (c) 2004 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +$:.unshift(File.dirname(__FILE__)) unless + $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) + +unless defined?(ActiveSupport) + begin + $:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib") + require 'active_support' + rescue LoadError + require 'rubygems' + require_gem 'activesupport' + end +end + +require 'action_controller/base' +require 'action_controller/deprecated_redirects' +require 'action_controller/request' +require 'action_controller/deprecated_request_methods' +require 'action_controller/rescue' +require 'action_controller/benchmarking' +require 'action_controller/flash' +require 'action_controller/filters' +require 'action_controller/layout' +require 'action_controller/dependencies' +require 'action_controller/mime_responds' +require 'action_controller/pagination' +require 'action_controller/scaffolding' +require 'action_controller/helpers' +require 'action_controller/cookies' +require 'action_controller/cgi_process' +require 'action_controller/caching' +require 'action_controller/verification' +require 'action_controller/streaming' +require 'action_controller/session_management' +require 'action_controller/components' +require 'action_controller/macros/auto_complete' +require 'action_controller/macros/in_place_editing' + +require 'action_view' +ActionController::Base.template_class = ActionView::Base + +ActionController::Base.class_eval do + include ActionController::Flash + include ActionController::Filters + include ActionController::Layout + include ActionController::Benchmarking + include ActionController::Rescue + include ActionController::Dependencies + include ActionController::MimeResponds + include ActionController::Pagination + include ActionController::Scaffolding + include ActionController::Helpers + include ActionController::Cookies + include ActionController::Caching + include ActionController::Verification + include ActionController::Streaming + include ActionController::SessionManagement + include ActionController::Components + include ActionController::Macros::AutoComplete + include ActionController::Macros::InPlaceEditing +end +module ActionPack #:nodoc: + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 12 + TINY = 5 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end +#-- +# Copyright (c) 2004 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +require 'action_pack/version' +require 'erb' + +module ActionView #:nodoc: + + class ActionViewError < StandardError #:nodoc: + end + + # Action View templates can be written in three ways. If the template file has a +.rhtml+ extension then it uses a mixture of ERb + # (included in Ruby) and HTML. If the template file has a +.rxml+ extension then Jim Weirich's Builder::XmlMarkup library is used. + # If the template file has a +.rjs+ extension then it will use ActionView::Helpers::PrototypeHelper::JavaScriptGenerator. + # + # = ERb + # + # You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the + # following loop for names: + # + # <b>Names of all the people</b> + # <% for person in @people %> + # Name: <%= person.name %><br/> + # <% end %> + # + # The loop is setup in regular embedding tags <% %> and the name is written using the output embedding tag <%= %>. Note that this + # is not just a usage suggestion. Regular output functions like print or puts won't work with ERb templates. So this would be wrong: + # + # Hi, Mr. <% puts "Frodo" %> + # + # If you absolutely must write from within a function, you can use the TextHelper#concat + # + # <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>. + # + # == Using sub templates + # + # Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The + # classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts): + # + # <%= render "shared/header" %> + # Something really specific and terrific + # <%= render "shared/footer" %> + # + # As you see, we use the output embeddings for the render methods. The render call itself will just return a string holding the + # result of the rendering. The output embedding writes it to the current template. + # + # But you don't have to restrict yourself to static includes. Templates can share variables amongst themselves by using instance + # variables defined using the regular embedding tags. Like this: + # + # <% @page_title = "A Wonderful Hello" %> + # <%= render "shared/header" %> + # + # Now the header can pick up on the @page_title variable and use it for outputting a title tag: + # + # <title><%= @page_title %></title> + # + # == Passing local variables to sub templates + # + # You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values: + # + # <%= render "shared/header", { "headline" => "Welcome", "person" => person } %> + # + # These can now be accessed in shared/header with: + # + # Headline: <%= headline %> + # First name: <%= person.first_name %> + # + # == Template caching + # + # By default, Rails will compile each template to a method in order to render it. When you alter a template, Rails will + # check the file's modification time and recompile it. + # + # == Builder + # + # Builder templates are a more programmatic alternative to ERb. They are especially useful for generating XML content. An +XmlMarkup+ object + # named +xml+ is automatically made available to templates with a +.rxml+ extension. + # + # Here are some basic examples: + # + # xml.em("emphasized") # => <em>emphasized</em> + # xml.em { xml.b("emp & bold") } # => <em><b>emph & bold</b></em> + # xml.a("A Link", "href"=>"http://onestepback.org") # => <a href="http://onestepback.org">A Link</a> + # xml.target("name"=>"compile", "option"=>"fast") # => <target option="fast" name="compile"\> + # # NOTE: order of attributes is not specified. + # + # Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following: + # + # xml.div { + # xml.h1(@person.name) + # xml.p(@person.bio) + # } + # + # would produce something like: + # + # <div> + # <h1>David Heinemeier Hansson</h1> + # <p>A product of Danish Design during the Winter of '79...</p> + # </div> + # + # A full-length RSS example actually used on Basecamp: + # + # xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do + # xml.channel do + # xml.title(@feed_title) + # xml.link(@url) + # xml.description "Basecamp: Recent items" + # xml.language "en-us" + # xml.ttl "40" + # + # for item in @recent_items + # xml.item do + # xml.title(item_title(item)) + # xml.description(item_description(item)) if item_description(item) + # xml.pubDate(item_pubDate(item)) + # xml.guid(@person.firm.account.url + @recent_items.url(item)) + # xml.link(@person.firm.account.url + @recent_items.url(item)) + # + # xml.tag!("dc:creator", item.author_name) if item_has_creator?(item) + # end + # end + # end + # end + # + # More builder documentation can be found at http://builder.rubyforge.org. + # + # == JavaScriptGenerator + # + # JavaScriptGenerator templates end in +.rjs+. Unlike conventional templates which are used to + # render the results of an action, these templates generate instructions on how to modify an already rendered page. This makes it easy to + # modify multiple elements on your page in one declarative Ajax response. Actions with these templates are called in the background with Ajax + # and make updates to the page where the request originated from. + # + # An instance of the JavaScriptGenerator object named +page+ is automatically made available to your template, which is implicitly wrapped in an ActionView::Helpers::PrototypeHelper#update_page block. + # + # When an .rjs action is called with +link_to_remote+, the generated JavaScript is automatically evaluated. Example: + # + # link_to_remote :url => {:action => 'delete'} + # + # The subsequently rendered +delete.rjs+ might look like: + # + # page.replace_html 'sidebar', :partial => 'sidebar' + # page.remove "person-#{@person.id}" + # page.visual_effect :highlight, 'user-list' + # + # This refreshes the sidebar, removes a person element and highlights the user list. + # + # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details. + class Base + include ERB::Util + + attr_reader :first_render + attr_accessor :base_path, :assigns, :template_extension + attr_accessor :controller + + attr_reader :logger, :params, :request, :response, :session, :headers, :flash + + # Specify trim mode for the ERB compiler. Defaults to '-'. + # See ERB documentation for suitable values. + @@erb_trim_mode = '-' + cattr_accessor :erb_trim_mode + + # Specify whether file modification times should be checked to see if a template needs recompilation + @@cache_template_loading = false + cattr_accessor :cache_template_loading + + # Specify whether file extension lookup should be cached. + # Should be +false+ for development environments. Defaults to +true+. + @@cache_template_extensions = true + cattr_accessor :cache_template_extensions + + # Specify whether local_assigns should be able to use string keys. + # Defaults to +true+. String keys are deprecated and will be removed + # shortly. + @@local_assigns_support_string_keys = true + cattr_accessor :local_assigns_support_string_keys + + # Specify whether RJS responses should be wrapped in a try/catch block + # that alert()s the caught exception (and then re-raises it). + @@debug_rjs = false + cattr_accessor :debug_rjs + + @@template_handlers = HashWithIndifferentAccess.new + + module CompiledTemplates #:nodoc: + # holds compiled template code + end + include CompiledTemplates + + # maps inline templates to their method names + @@method_names = {} + # map method names to their compile time + @@compile_time = {} + # map method names to the names passed in local assigns so far + @@template_args = {} + # count the number of inline templates + @@inline_template_count = 0 + # maps template paths without extension to their file extension returned by pick_template_extension. + # if for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions + # used by pick_template_extension determines whether ext1 or ext2 will be stored + @@cached_template_extension = {} + + class ObjectWrapper < Struct.new(:value) #:nodoc: + end + + def self.load_helpers(helper_dir)#:nodoc: + Dir.foreach(helper_dir) do |helper_file| + next unless helper_file =~ /^([a-z][a-z_]*_helper).rb$/ + require File.join(helper_dir, $1) + helper_module_name = $1.camelize + class_eval("include ActionView::Helpers::#{helper_module_name}") if Helpers.const_defined?(helper_module_name) + end + end + + # Register a class that knows how to handle template files with the given + # extension. This can be used to implement new template types. + # The constructor for the class must take the ActiveView::Base instance + # as a parameter, and the class must implement a #render method that + # takes the contents of the template to render as well as the Hash of + # local assigns available to the template. The #render method ought to + # return the rendered template as a string. + def self.register_template_handler(extension, klass) + @@template_handlers[extension] = klass + end + + def initialize(base_path = nil, assigns_for_first_render = {}, controller = nil)#:nodoc: + @base_path, @assigns = base_path, assigns_for_first_render + @assigns_added = nil + @controller = controller + @logger = controller && controller.logger + end + + # Renders the template present at <tt>template_path</tt>. If <tt>use_full_path</tt> is set to true, + # it's relative to the template_root, otherwise it's absolute. The hash in <tt>local_assigns</tt> + # is made available as local variables. + def render_file(template_path, use_full_path = true, local_assigns = {}) #:nodoc: + @first_render ||= template_path + + if use_full_path + template_path_without_extension, template_extension = path_and_extension(template_path) + + if template_extension + template_file_name = full_template_path(template_path_without_extension, template_extension) + else + template_extension = pick_template_extension(template_path).to_s + template_file_name = full_template_path(template_path, template_extension) + end + else + template_file_name = template_path + template_extension = template_path.split('.').last + end + + template_source = nil # Don't read the source until we know that it is required + + begin + render_template(template_extension, template_source, template_file_name, local_assigns) + rescue Exception => e + if TemplateError === e + e.sub_template_of(template_file_name) + raise e + else + raise TemplateError.new(@base_path, template_file_name, @assigns, template_source, e) + end + end + end + + # Renders the template present at <tt>template_path</tt> (relative to the template_root). + # The hash in <tt>local_assigns</tt> is made available as local variables. + def render(options = {}, old_local_assigns = {}, &block) #:nodoc: + if options.is_a?(String) + render_file(options, true, old_local_assigns) + elsif options == :update + update_page(&block) + elsif options.is_a?(Hash) + options[:locals] ||= {} + options[:use_full_path] = options[:use_full_path].nil? ? true : options[:use_full_path] + + if options[:file] + render_file(options[:file], options[:use_full_path], options[:locals]) + elsif options[:partial] && options[:collection] + render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals]) + elsif options[:partial] + render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) + elsif options[:inline] + render_template(options[:type] || :rhtml, options[:inline], nil, options[:locals] || {}) + end + end + end + + # Renders the +template+ which is given as a string as either rhtml or rxml depending on <tt>template_extension</tt>. + # The hash in <tt>local_assigns</tt> is made available as local variables. + def render_template(template_extension, template, file_path = nil, local_assigns = {}) #:nodoc: + if handler = @@template_handlers[template_extension] + template ||= read_template_file(file_path, template_extension) # Make sure that a lazyily-read template is loaded. + delegate_render(handler, template, local_assigns) + else + compile_and_render_template(template_extension, template, file_path, local_assigns) + end + end + + # Render the provided template with the given local assigns. If the template has not been rendered with the provided + # local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method. + # + + # Either, but not both, of template and file_path may be nil. If file_path is given, the template + # will only be read if it has to be compiled. + # + def compile_and_render_template(extension, template = nil, file_path = nil, local_assigns = {}) #:nodoc: + # compile the given template, if necessary + if compile_template?(template, file_path, local_assigns) + template ||= read_template_file(file_path, extension) + compile_template(extension, template, file_path, local_assigns) + end + + # Get the method name for this template and run it + method_name = @@method_names[file_path || template] + evaluate_assigns + + local_assigns = local_assigns.symbolize_keys if @@local_assigns_support_string_keys + + send(method_name, local_assigns) do |*name| + instance_variable_get "@content_for_#{name.first || 'layout'}" + end + end + + def pick_template_extension(template_path)#:nodoc: + if @@cache_template_extensions + @@cached_template_extension[template_path] ||= find_template_extension_for(template_path) + else + find_template_extension_for(template_path) + end + end + + def delegate_template_exists?(template_path)#:nodoc: + @@template_handlers.find { |k,| template_exists?(template_path, k) } + end + + def erb_template_exists?(template_path)#:nodoc: + template_exists?(template_path, :rhtml) + end + + def builder_template_exists?(template_path)#:nodoc: + template_exists?(template_path, :rxml) + end + + def javascript_template_exists?(template_path)#:nodoc: + template_exists?(template_path, :rjs) + end + + def file_exists?(template_path)#:nodoc: + template_file_name, template_file_extension = path_and_extension(template_path) + + if template_file_extension + template_exists?(template_file_name, template_file_extension) + else + cached_template_extension(template_path) || + %w(erb builder javascript delegate).any? do |template_type| + send("#{template_type}_template_exists?", template_path) + end + end + end + + # Returns true is the file may be rendered implicitly. + def file_public?(template_path)#:nodoc: + template_path.split('/').last[0,1] != '_' + end + + private + def full_template_path(template_path, extension) + "#{@base_path}/#{template_path}.#{extension}" + end + + def template_exists?(template_path, extension) + file_path = full_template_path(template_path, extension) + @@method_names.has_key?(file_path) || FileTest.exists?(file_path) + end + + def path_and_extension(template_path) + template_path_without_extension = template_path.sub(/\.(\w+)$/, '') + [ template_path_without_extension, $1 ] + end + + def cached_template_extension(template_path) + @@cache_template_extensions && @@cached_template_extension[template_path] + end + + def find_template_extension_for(template_path) + if match = delegate_template_exists?(template_path) + match.first.to_sym + elsif erb_template_exists?(template_path): :rhtml + elsif builder_template_exists?(template_path): :rxml + elsif javascript_template_exists?(template_path): :rjs + else + raise ActionViewError, "No rhtml, rxml, rjs or delegate template found for #{template_path}" + end + end + + # This method reads a template file. + def read_template_file(template_path, extension) + File.read(template_path) + end + + def evaluate_assigns + unless @assigns_added + assign_variables_from_controller + @assigns_added = true + end + end + + def delegate_render(handler, template, local_assigns) + handler.new(self).render(template, local_assigns) + end + + def assign_variables_from_controller + @assigns.each { |key, value| instance_variable_set("@#{key}", value) } + end + + + # Return true if the given template was compiled for a superset of the keys in local_assigns + def supports_local_assigns?(render_symbol, local_assigns) + local_assigns.empty? || + ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) + end + + # Check whether compilation is necessary. + # Compile if the inline template or file has not been compiled yet. + # Or if local_assigns has a new key, which isn't supported by the compiled code yet. + # Or if the file has changed on disk and checking file mods hasn't been disabled. + def compile_template?(template, file_name, local_assigns) + method_key = file_name || template + render_symbol = @@method_names[method_key] + + if @@compile_time[render_symbol] && supports_local_assigns?(render_symbol, local_assigns) + if file_name && !@@cache_template_loading + @@compile_time[render_symbol] < File.mtime(file_name) || (File.symlink?(file_name) ? + @@compile_time[render_symbol] < File.lstat(file_name).mtime : false) + end + else + true + end + end + + # Create source code for given template + def create_template_source(extension, template, render_symbol, locals) + if template_requires_setup?(extension) + body = case extension.to_sym + when :rxml + "xml = Builder::XmlMarkup.new(:indent => 2)\n" + + "@controller.headers['Content-Type'] ||= 'application/xml'\n" + + template + when :rjs + "@controller.headers['Content-Type'] ||= 'text/javascript'\n" + + "update_page do |page|\n#{template}\nend" + end + else + body = ERB.new(template, nil, @@erb_trim_mode).src + end + + @@template_args[render_symbol] ||= {} + locals_keys = @@template_args[render_symbol].keys | locals + @@template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } + + locals_code = "" + locals_keys.each do |key| + locals_code << "#{key} = local_assigns[:#{key}] if local_assigns.has_key?(:#{key})\n" + end + + "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" + end + + def template_requires_setup?(extension) + templates_requiring_setup.include? extension.to_s + end + + def templates_requiring_setup + %w(rxml rjs) + end + + def assign_method_name(extension, template, file_name) + method_name = '_run_' + method_name << "#{extension}_" if extension + + if file_name + file_path = File.expand_path(file_name) + base_path = File.expand_path(@base_path) + + i = file_path.index(base_path) + l = base_path.length + + method_name_file_part = i ? file_path[i+l+1,file_path.length-l-1] : file_path.clone + method_name_file_part.sub!(/\.r(html|xml|js)$/,'') + method_name_file_part.tr!('/:-', '_') + method_name_file_part.gsub!(/[^a-zA-Z0-9_]/){|s| s[0].to_s} + + method_name += method_name_file_part + else + @@inline_template_count += 1 + method_name << @@inline_template_count.to_s + end + + @@method_names[file_name || template] = method_name.intern + end + + def compile_template(extension, template, file_name, local_assigns) + method_key = file_name || template + + render_symbol = @@method_names[method_key] || assign_method_name(extension, template, file_name) + render_source = create_template_source(extension, template, render_symbol, local_assigns.keys) + + line_offset = @@template_args[render_symbol].size + if extension + case extension.to_sym + when :rxml, :rjs + line_offset += 2 + end + end + + begin + unless file_name.blank? + CompiledTemplates.module_eval(render_source, file_name, -line_offset) + else + CompiledTemplates.module_eval(render_source, 'compiled-template', -line_offset) + end + rescue Object => e + if logger + logger.debug "ERROR: compiling #{render_symbol} RAISED #{e}" + logger.debug "Function body: #{render_source}" + logger.debug "Backtrace: #{e.backtrace.join("\n")}" + end + + raise TemplateError.new(@base_path, method_key, @assigns, template, e) + end + + @@compile_time[render_symbol] = Time.now + # logger.debug "Compiled template #{method_key}\n ==> #{render_symbol}" if logger + end + end +end + +require 'action_view/template_error' + +module ActionView + + # CompiledTemplates modules hold methods that have been compiled. + # Templates are compiled into these methods so that they do not need to be + # re-read and re-parsed each request. + # + # Each template may be compiled into one or more methods. Each method accepts a given + # set of parameters which is used to implement local assigns passing. + # + # To use a compiled template module, create a new instance and include it into the class + # in which you want the template to be rendered. + class CompiledTemplates < Module #:nodoc: + attr_reader :method_names + + def initialize + @method_names = Hash.new do |hash, key| + hash[key] = "__compiled_method_#{(hash.length + 1)}" + end + @mtimes = {} + end + + # Return the full key for the given identifier and argument names + def full_key(identifier, arg_names) + [identifier, arg_names] + end + + # Return the selector for this method or nil if it has not been compiled + def selector(identifier, arg_names) + key = full_key(identifier, arg_names) + method_names.key?(key) ? method_names[key] : nil + end + alias :compiled? :selector + + # Return the time at which the method for the given identifier and argument names was compiled. + def mtime(identifier, arg_names) + @mtimes[full_key(identifier, arg_names)] + end + + # Compile the provided source code for the given argument names and with the given initial line number. + # The identifier should be unique to this source. + # + # The file_name, if provided will appear in backtraces. If not provded, the file_name defaults + # to the identifier. + # + # This method will return the selector for the compiled version of this method. + def compile_source(identifier, arg_names, source, initial_line_number = 0, file_name = nil) + file_name ||= identifier + name = method_names[full_key(identifier, arg_names)] + arg_desc = arg_names.empty? ? '' : "(#{arg_names * ', '})" + fake_file_name = "#{file_name}#{arg_desc}" # Include the arguments for this version (for now) + + method_def = wrap_source(name, arg_names, source) + + begin + module_eval(method_def, fake_file_name, initial_line_number) + @mtimes[full_key(identifier, arg_names)] = Time.now + rescue Object => e + e.blame_file! identifier + raise + end + name + end + + # Wrap the provided source in a def ... end block. + def wrap_source(name, arg_names, source) + "def #{name}(#{arg_names * ', '})\n#{source}\nend" + end + end +end +require 'cgi' +require File.dirname(__FILE__) + '/form_helper' + +module ActionView + class Base + @@field_error_proc = Proc.new{ |html_tag, instance| "<div class=\"fieldWithErrors\">#{html_tag}</div>" } + cattr_accessor :field_error_proc + end + + module Helpers + # The Active Record Helper makes it easier to create forms for records kept in instance variables. The most far-reaching is the form + # method that creates a complete form for all the basic content types of the record (not associations or aggregations, though). This + # is a great of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form. + # In that case, it's better to use the input method and the specialized form methods in link:classes/ActionView/Helpers/FormHelper.html + module ActiveRecordHelper + # Returns a default input tag for the type of object returned by the method. Example + # (title is a VARCHAR column and holds "Hello World"): + # input("post", "title") => + # <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /> + def input(record_name, method, options = {}) + InstanceTag.new(record_name, method, self).to_tag(options) + end + + # Returns an entire form with input tags and everything for a specified Active Record object. Example + # (post is a new record that has a title using VARCHAR and a body using TEXT): + # form("post") => + # <form action='/post/create' method='post'> + # <p> + # <label for="post_title">Title</label><br /> + # <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /> + # </p> + # <p> + # <label for="post_body">Body</label><br /> + # <textarea cols="40" id="post_body" name="post[body]" rows="20"> + # Back to the hill and over it again! + # </textarea> + # </p> + # <input type='submit' value='Create' /> + # </form> + # + # It's possible to specialize the form builder by using a different action name and by supplying another + # block renderer. Example (entry is a new record that has a message attribute using VARCHAR): + # + # form("entry", :action => "sign", :input_block => + # Proc.new { |record, column| "#{column.human_name}: #{input(record, column.name)}<br />" }) => + # + # <form action='/post/sign' method='post'> + # Message: + # <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /><br /> + # <input type='submit' value='Sign' /> + # </form> + # + # It's also possible to add additional content to the form by giving it a block, such as: + # + # form("entry", :action => "sign") do |form| + # form << content_tag("b", "Department") + # form << collection_select("department", "id", @departments, "id", "name") + # end + def form(record_name, options = {}) + record = instance_variable_get("@#{record_name}") + + options = options.symbolize_keys + options[:action] ||= record.new_record? ? "create" : "update" + action = url_for(:action => options[:action], :id => record) + + submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize + + contents = '' + contents << hidden_field(record_name, :id) unless record.new_record? + contents << all_input_tags(record, record_name, options) + yield contents if block_given? + contents << submit_tag(submit_value) + + content_tag('form', contents, :action => action, :method => 'post', :enctype => options[:multipart] ? 'multipart/form-data': nil) + end + + # Returns a string containing the error message attached to the +method+ on the +object+, if one exists. + # This error message is wrapped in a DIV tag, which can be specialized to include both a +prepend_text+ and +append_text+ + # to properly introduce the error and a +css_class+ to style it accordingly. Examples (post has an error message + # "can't be empty" on the title attribute): + # + # <%= error_message_on "post", "title" %> => + # <div class="formError">can't be empty</div> + # + # <%= error_message_on "post", "title", "Title simply ", " (or it won't work)", "inputError" %> => + # <div class="inputError">Title simply can't be empty (or it won't work)</div> + def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError") + if errors = instance_variable_get("@#{object}").errors.on(method) + content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class) + end + end + + # Returns a string with a div containing all the error messages for the object located as an instance variable by the name + # of <tt>object_name</tt>. This div can be tailored by the following options: + # + # * <tt>header_tag</tt> - Used for the header of the error div (default: h2) + # * <tt>id</tt> - The id of the error div (default: errorExplanation) + # * <tt>class</tt> - The class of the error div (default: errorExplanation) + # + # NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what + # you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors + # instance yourself and set it up. View the source of this method to see how easy it is. + def error_messages_for(object_name, options = {}) + options = options.symbolize_keys + object = instance_variable_get("@#{object_name}") + if object && !object.errors.empty? + content_tag("div", + content_tag( + options[:header_tag] || "h2", + "#{pluralize(object.errors.count, "error")} prohibited this #{object_name.to_s.gsub("_", " ")} from being saved" + ) + + content_tag("p", "There were problems with the following fields:") + + content_tag("ul", object.errors.full_messages.collect { |msg| content_tag("li", msg) }), + "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation" + ) + else + "" + end + end + + private + def all_input_tags(record, record_name, options) + input_block = options[:input_block] || default_input_block + record.class.content_columns.collect{ |column| input_block.call(record_name, column) }.join("\n") + end + + def default_input_block + Proc.new { |record, column| %(<p><label for="#{record}_#{column.name}">#{column.human_name}</label><br />#{input(record, column.name)}</p>) } + end + end + + class InstanceTag #:nodoc: + def to_tag(options = {}) + case column_type + when :string + field_type = @method_name.include?("password") ? "password" : "text" + to_input_field_tag(field_type, options) + when :text + to_text_area_tag(options) + when :integer, :float + to_input_field_tag("text", options) + when :date + to_date_select_tag(options) + when :datetime, :timestamp + to_datetime_select_tag(options) + when :boolean + to_boolean_select_tag(options) + end + end + + alias_method :tag_without_error_wrapping, :tag + def tag(name, options) + if object.respond_to?("errors") && object.errors.respond_to?("on") + error_wrapping(tag_without_error_wrapping(name, options), object.errors.on(@method_name)) + else + tag_without_error_wrapping(name, options) + end + end + + alias_method :content_tag_without_error_wrapping, :content_tag + def content_tag(name, value, options) + if object.respond_to?("errors") && object.errors.respond_to?("on") + error_wrapping(content_tag_without_error_wrapping(name, value, options), object.errors.on(@method_name)) + else + content_tag_without_error_wrapping(name, value, options) + end + end + + alias_method :to_date_select_tag_without_error_wrapping, :to_date_select_tag + def to_date_select_tag(options = {}) + if object.respond_to?("errors") && object.errors.respond_to?("on") + error_wrapping(to_date_select_tag_without_error_wrapping(options), object.errors.on(@method_name)) + else + to_date_select_tag_without_error_wrapping(options) + end + end + + alias_method :to_datetime_select_tag_without_error_wrapping, :to_datetime_select_tag + def to_datetime_select_tag(options = {}) + if object.respond_to?("errors") && object.errors.respond_to?("on") + error_wrapping(to_datetime_select_tag_without_error_wrapping(options), object.errors.on(@method_name)) + else + to_datetime_select_tag_without_error_wrapping(options) + end + end + + def error_wrapping(html_tag, has_error) + has_error ? Base.field_error_proc.call(html_tag, self) : html_tag + end + + def error_message + object.errors.on(@method_name) + end + + def column_type + object.send("column_for_attribute", @method_name).type + end + end + end +end +require 'cgi' +require File.dirname(__FILE__) + '/url_helper' +require File.dirname(__FILE__) + '/tag_helper' + +module ActionView + module Helpers + # Provides methods for linking a HTML page together with other assets, such as javascripts, stylesheets, and feeds. + module AssetTagHelper + # Returns a link tag that browsers and news readers can use to auto-detect a RSS or ATOM feed for this page. The +type+ can + # either be <tt>:rss</tt> (default) or <tt>:atom</tt> and the +options+ follow the url_for style of declaring a link target. + # + # Examples: + # auto_discovery_link_tag # => + # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/action" /> + # auto_discovery_link_tag(:atom) # => + # <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.curenthost.com/controller/action" /> + # auto_discovery_link_tag(:rss, {:action => "feed"}) # => + # <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.curenthost.com/controller/feed" /> + # auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My RSS"}) # => + # <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.curenthost.com/controller/feed" /> + def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {}) + tag( + "link", + "rel" => tag_options[:rel] || "alternate", + "type" => tag_options[:type] || "application/#{type}+xml", + "title" => tag_options[:title] || type.to_s.upcase, + "href" => url_options.is_a?(Hash) ? url_for(url_options.merge(:only_path => false)) : url_options + ) + end + + # Returns path to a javascript asset. Example: + # + # javascript_path "xmlhr" # => /javascripts/xmlhr.js + def javascript_path(source) + compute_public_path(source, 'javascripts', 'js') + end + + JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls'] unless const_defined?(:JAVASCRIPT_DEFAULT_SOURCES) + @@javascript_default_sources = JAVASCRIPT_DEFAULT_SOURCES.dup + + # Returns a script include tag per source given as argument. Examples: + # + # javascript_include_tag "xmlhr" # => + # <script type="text/javascript" src="/javascripts/xmlhr.js"></script> + # + # javascript_include_tag "common.javascript", "/elsewhere/cools" # => + # <script type="text/javascript" src="/javascripts/common.javascript"></script> + # <script type="text/javascript" src="/elsewhere/cools.js"></script> + # + # javascript_include_tag :defaults # => + # <script type="text/javascript" src="/javascripts/prototype.js"></script> + # <script type="text/javascript" src="/javascripts/effects.js"></script> + # ... + # <script type="text/javascript" src="/javascripts/application.js"></script> *see below + # + # If there's an <tt>application.js</tt> file in your <tt>public/javascripts</tt> directory, + # <tt>javascript_include_tag :defaults</tt> will automatically include it. This file + # facilitates the inclusion of small snippets of JavaScript code, along the lines of + # <tt>controllers/application.rb</tt> and <tt>helpers/application_helper.rb</tt>. + def javascript_include_tag(*sources) + options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { } + + if sources.include?(:defaults) + sources = sources[0..(sources.index(:defaults))] + + @@javascript_default_sources.dup + + sources[(sources.index(:defaults) + 1)..sources.length] + + sources.delete(:defaults) + sources << "application" if defined?(RAILS_ROOT) && File.exists?("#{RAILS_ROOT}/public/javascripts/application.js") + end + + sources.collect { |source| + source = javascript_path(source) + content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options)) + }.join("\n") + end + + # Register one or more additional JavaScript files to be included when + # + # javascript_include_tag :defaults + # + # is called. This method is intended to be called only from plugin initialization + # to register extra .js files the plugin installed in <tt>public/javascripts</tt>. + def self.register_javascript_include_default(*sources) + @@javascript_default_sources.concat(sources) + end + + def self.reset_javascript_include_default #:nodoc: + @@javascript_default_sources = JAVASCRIPT_DEFAULT_SOURCES.dup + end + + # Returns path to a stylesheet asset. Example: + # + # stylesheet_path "style" # => /stylesheets/style.css + def stylesheet_path(source) + compute_public_path(source, 'stylesheets', 'css') + end + + # Returns a css link tag per source given as argument. Examples: + # + # stylesheet_link_tag "style" # => + # <link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" /> + # + # stylesheet_link_tag "style", :media => "all" # => + # <link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" /> + # + # stylesheet_link_tag "random.styles", "/css/stylish" # => + # <link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" /> + # <link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" /> + def stylesheet_link_tag(*sources) + options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { } + sources.collect { |source| + source = stylesheet_path(source) + tag("link", { "rel" => "Stylesheet", "type" => "text/css", "media" => "screen", "href" => source }.merge(options)) + }.join("\n") + end + + # Returns path to an image asset. Example: + # + # The +src+ can be supplied as a... + # * full path, like "/my_images/image.gif" + # * file name, like "rss.gif", that gets expanded to "/images/rss.gif" + # * file name without extension, like "logo", that gets expanded to "/images/logo.png" + def image_path(source) + compute_public_path(source, 'images', 'png') + end + + # Returns an image tag converting the +options+ into html options on the tag, but with these special cases: + # + # * <tt>:alt</tt> - If no alt text is given, the file name part of the +src+ is used (capitalized and without the extension) + # * <tt>:size</tt> - Supplied as "XxY", so "30x45" becomes width="30" and height="45" + # + # The +src+ can be supplied as a... + # * full path, like "/my_images/image.gif" + # * file name, like "rss.gif", that gets expanded to "/images/rss.gif" + # * file name without extension, like "logo", that gets expanded to "/images/logo.png" + def image_tag(source, options = {}) + options.symbolize_keys! + + options[:src] = image_path(source) + options[:alt] ||= File.basename(options[:src], '.*').split('.').first.capitalize + + if options[:size] + options[:width], options[:height] = options[:size].split("x") + options.delete :size + end + + tag("img", options) + end + + private + def compute_public_path(source, dir, ext) + source = "/#{dir}/#{source}" unless source.first == "/" || source.include?(":") + source << ".#{ext}" unless source.split("/").last.include?(".") + source << '?' + rails_asset_id(source) if defined?(RAILS_ROOT) && %r{^[-a-z]+://} !~ source + source = "#{@controller.request.relative_url_root}#{source}" unless %r{^[-a-z]+://} =~ source + source = ActionController::Base.asset_host + source unless source.include?(":") + source + end + + def rails_asset_id(source) + ENV["RAILS_ASSET_ID"] || + File.mtime("#{RAILS_ROOT}/public/#{source}").to_i.to_s rescue "" + end + end + end +end +require 'benchmark' + +module ActionView + module Helpers + module BenchmarkHelper + # Measures the execution time of a block in a template and reports the result to the log. Example: + # + # <% benchmark "Notes section" do %> + # <%= expensive_notes_operation %> + # <% end %> + # + # Will add something like "Notes section (0.34523)" to the log. + # + # You may give an optional logger level as the second argument + # (:debug, :info, :warn, :error). The default is :info. + def benchmark(message = "Benchmarking", level = :info) + if @logger + real = Benchmark.realtime { yield } + @logger.send level, "#{message} (#{'%.5f' % real})" + end + end + end + end +end +module ActionView + module Helpers + # See ActionController::Caching::Fragments for usage instructions. + module CacheHelper + def cache(name = {}, &block) + @controller.cache_erb_fragment(block, name) + end + end + end +end +module ActionView + module Helpers + # Capture lets you extract parts of code which + # can be used in other points of the template or even layout file. + # + # == Capturing a block into an instance variable + # + # <% @script = capture do %> + # [some html...] + # <% end %> + # + # == Add javascript to header using content_for + # + # content_for("name") is a wrapper for capture which will + # make the fragment available by name to a yielding layout or template. + # + # layout.rhtml: + # + # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> + # <head> + # <title>layout with js</title> + # <script type="text/javascript"> + # <%= yield :script %> + # </script> + # </head> + # <body> + # <%= yield %> + # </body> + # </html> + # + # view.rhtml + # + # This page shows an alert box! + # + # <% content_for("script") do %> + # alert('hello world') + # <% end %> + # + # Normal view text + module CaptureHelper + # Capture allows you to extract a part of the template into an + # instance variable. You can use this instance variable anywhere + # in your templates and even in your layout. + # + # Example of capture being used in a .rhtml page: + # + # <% @greeting = capture do %> + # Welcome To my shiny new web page! + # <% end %> + # + # Example of capture being used in a .rxml page: + # + # @greeting = capture do + # 'Welcome To my shiny new web page!' + # end + def capture(*args, &block) + # execute the block + begin + buffer = eval("_erbout", block.binding) + rescue + buffer = nil + end + + if buffer.nil? + capture_block(*args, &block) + else + capture_erb_with_buffer(buffer, *args, &block) + end + end + + # Calling content_for stores the block of markup for later use. + # Subsequently, you can make calls to it by name with <tt>yield</tt> + # in another template or in the layout. + # + # Example: + # + # <% content_for("header") do %> + # alert('hello world') + # <% end %> + # + # You can use yield :header anywhere in your templates. + # + # <%= yield :header %> + # + # NOTE: Beware that content_for is ignored in caches. So you shouldn't use it + # for elements that are going to be fragment cached. + # + # The deprecated way of accessing a content_for block was to use a instance variable + # named @@content_for_#{name_of_the_content_block}@. So <tt><%= content_for('footer') %></tt> + # would be avaiable as <tt><%= @content_for_footer %></tt>. The preferred notation now is + # <tt><%= yield :footer %></tt>. + def content_for(name, &block) + eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)" + end + + private + def capture_block(*args, &block) + block.call(*args) + end + + def capture_erb(*args, &block) + buffer = eval("_erbout", block.binding) + capture_erb_with_buffer(buffer, *args, &block) + end + + def capture_erb_with_buffer(buffer, *args, &block) + pos = buffer.length + block.call(*args) + + # extract the block + data = buffer[pos..-1] + + # replace it in the original with empty string + buffer[pos..-1] = '' + + data + end + + def erb_content_for(name, &block) + eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_erb(&block)" + end + + def block_content_for(name, &block) + eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_block(&block)" + end + end + end +end +require "date" + +module ActionView + module Helpers + # The Date Helper primarily creates select/option tags for different kinds of dates and date elements. All of the select-type methods + # share a number of common options that are as follows: + # + # * <tt>:prefix</tt> - overwrites the default prefix of "date" used for the select names. So specifying "birthday" would give + # birthday[month] instead of date[month] if passed to the select_month method. + # * <tt>:include_blank</tt> - set to true if it should be possible to set an empty date. + # * <tt>:discard_type</tt> - set to true if you want to discard the type part of the select name. If set to true, the select_month + # method would use simply "date" (which can be overwritten using <tt>:prefix</tt>) instead of "date[month]". + module DateHelper + DEFAULT_PREFIX = 'date' unless const_defined?('DEFAULT_PREFIX') + + # Reports the approximate distance in time between two Time objects or integers. + # For example, if the distance is 47 minutes, it'll return + # "about 1 hour". See the source for the complete wording list. + # + # Integers are interpreted as seconds. So, + # <tt>distance_of_time_in_words(50)</tt> returns "less than a minute". + # + # Set <tt>include_seconds</tt> to true if you want more detailed approximations if distance < 1 minute + def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false) + from_time = from_time.to_time if from_time.respond_to?(:to_time) + to_time = to_time.to_time if to_time.respond_to?(:to_time) + distance_in_minutes = (((to_time - from_time).abs)/60).round + distance_in_seconds = ((to_time - from_time).abs).round + + case distance_in_minutes + when 0..1 + return (distance_in_minutes==0) ? 'less than a minute' : '1 minute' unless include_seconds + case distance_in_seconds + when 0..5 then 'less than 5 seconds' + when 6..10 then 'less than 10 seconds' + when 11..20 then 'less than 20 seconds' + when 21..40 then 'half a minute' + when 41..59 then 'less than a minute' + else '1 minute' + end + + when 2..45 then "#{distance_in_minutes} minutes" + when 46..90 then 'about 1 hour' + when 90..1440 then "about #{(distance_in_minutes.to_f / 60.0).round} hours" + when 1441..2880 then '1 day' + else "#{(distance_in_minutes / 1440).round} days" + end + end + + # Like distance_of_time_in_words, but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>. + def time_ago_in_words(from_time, include_seconds = false) + distance_of_time_in_words(from_time, Time.now, include_seconds) + end + + alias_method :distance_of_time_in_words_to_now, :time_ago_in_words + + # Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based attribute (identified by + # +method+) on an object assigned to the template (identified by +object+). It's possible to tailor the selects through the +options+ hash, + # which accepts all the keys that each of the individual select builders do (like :use_month_numbers for select_month) as well as a range of + # discard options. The discard options are <tt>:discard_year</tt>, <tt>:discard_month</tt> and <tt>:discard_day</tt>. Set to true, they'll + # drop the respective select. Discarding the month select will also automatically discard the day select. It's also possible to explicitly + # set the order of the tags using the <tt>:order</tt> option with an array of symbols <tt>:year</tt>, <tt>:month</tt> and <tt>:day</tt> in + # the desired order. Symbols may be omitted and the respective select is not included. + # + # Passing :disabled => true as part of the +options+ will make elements inaccessible for change. + # + # NOTE: Discarded selects will default to 1. So if no month select is available, January will be assumed. + # + # Examples: + # + # date_select("post", "written_on") + # date_select("post", "written_on", :start_year => 1995) + # date_select("post", "written_on", :start_year => 1995, :use_month_numbers => true, + # :discard_day => true, :include_blank => true) + # date_select("post", "written_on", :order => [:day, :month, :year]) + # date_select("user", "birthday", :order => [:month, :day]) + # + # The selects are prepared for multi-parameter assignment to an Active Record object. + def date_select(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_date_select_tag(options) + end + + # Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based + # attribute (identified by +method+) on an object assigned to the template (identified by +object+). Examples: + # + # datetime_select("post", "written_on") + # datetime_select("post", "written_on", :start_year => 1995) + # + # The selects are prepared for multi-parameter assignment to an Active Record object. + def datetime_select(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_datetime_select_tag(options) + end + + # Returns a set of html select-tags (one for year, month, and day) pre-selected with the +date+. + def select_date(date = Date.today, options = {}) + select_year(date, options) + select_month(date, options) + select_day(date, options) + end + + # Returns a set of html select-tags (one for year, month, day, hour, and minute) pre-selected with the +datetime+. + def select_datetime(datetime = Time.now, options = {}) + select_year(datetime, options) + select_month(datetime, options) + select_day(datetime, options) + + select_hour(datetime, options) + select_minute(datetime, options) + end + + # Returns a set of html select-tags (one for hour and minute) + def select_time(datetime = Time.now, options = {}) + h = select_hour(datetime, options) + select_minute(datetime, options) + (options[:include_seconds] ? select_second(datetime, options) : '') + end + + # Returns a select tag with options for each of the seconds 0 through 59 with the current second selected. + # The <tt>second</tt> can also be substituted for a second number. + # Override the field name using the <tt>:field_name</tt> option, 'second' by default. + def select_second(datetime, options = {}) + second_options = [] + + 0.upto(59) do |second| + second_options << ((datetime && (datetime.kind_of?(Fixnum) ? datetime : datetime.sec) == second) ? + %(<option value="#{leading_zero_on_single_digits(second)}" selected="selected">#{leading_zero_on_single_digits(second)}</option>\n) : + %(<option value="#{leading_zero_on_single_digits(second)}">#{leading_zero_on_single_digits(second)}</option>\n) + ) + end + + select_html(options[:field_name] || 'second', second_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected. + # Also can return a select tag with options by <tt>minute_step</tt> from 0 through 59 with the 00 minute selected + # The <tt>minute</tt> can also be substituted for a minute number. + # Override the field name using the <tt>:field_name</tt> option, 'minute' by default. + def select_minute(datetime, options = {}) + minute_options = [] + + 0.step(59, options[:minute_step] || 1) do |minute| + minute_options << ((datetime && (datetime.kind_of?(Fixnum) ? datetime : datetime.min) == minute) ? + %(<option value="#{leading_zero_on_single_digits(minute)}" selected="selected">#{leading_zero_on_single_digits(minute)}</option>\n) : + %(<option value="#{leading_zero_on_single_digits(minute)}">#{leading_zero_on_single_digits(minute)}</option>\n) + ) + end + + select_html(options[:field_name] || 'minute', minute_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # Returns a select tag with options for each of the hours 0 through 23 with the current hour selected. + # The <tt>hour</tt> can also be substituted for a hour number. + # Override the field name using the <tt>:field_name</tt> option, 'hour' by default. + def select_hour(datetime, options = {}) + hour_options = [] + + 0.upto(23) do |hour| + hour_options << ((datetime && (datetime.kind_of?(Fixnum) ? datetime : datetime.hour) == hour) ? + %(<option value="#{leading_zero_on_single_digits(hour)}" selected="selected">#{leading_zero_on_single_digits(hour)}</option>\n) : + %(<option value="#{leading_zero_on_single_digits(hour)}">#{leading_zero_on_single_digits(hour)}</option>\n) + ) + end + + select_html(options[:field_name] || 'hour', hour_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # Returns a select tag with options for each of the days 1 through 31 with the current day selected. + # The <tt>date</tt> can also be substituted for a hour number. + # Override the field name using the <tt>:field_name</tt> option, 'day' by default. + def select_day(date, options = {}) + day_options = [] + + 1.upto(31) do |day| + day_options << ((date && (date.kind_of?(Fixnum) ? date : date.day) == day) ? + %(<option value="#{day}" selected="selected">#{day}</option>\n) : + %(<option value="#{day}">#{day}</option>\n) + ) + end + + select_html(options[:field_name] || 'day', day_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # Returns a select tag with options for each of the months January through December with the current month selected. + # The month names are presented as keys (what's shown to the user) and the month numbers (1-12) are used as values + # (what's submitted to the server). It's also possible to use month numbers for the presentation instead of names -- + # set the <tt>:use_month_numbers</tt> key in +options+ to true for this to happen. If you want both numbers and names, + # set the <tt>:add_month_numbers</tt> key in +options+ to true. Examples: + # + # select_month(Date.today) # Will use keys like "January", "March" + # select_month(Date.today, :use_month_numbers => true) # Will use keys like "1", "3" + # select_month(Date.today, :add_month_numbers => true) # Will use keys like "1 - January", "3 - March" + # + # Override the field name using the <tt>:field_name</tt> option, 'month' by default. + # + # If you would prefer to show month names as abbreviations, set the + # <tt>:use_short_month</tt> key in +options+ to true. + def select_month(date, options = {}) + month_options = [] + month_names = options[:use_short_month] ? Date::ABBR_MONTHNAMES : Date::MONTHNAMES + + 1.upto(12) do |month_number| + month_name = if options[:use_month_numbers] + month_number + elsif options[:add_month_numbers] + month_number.to_s + ' - ' + month_names[month_number] + else + month_names[month_number] + end + + month_options << ((date && (date.kind_of?(Fixnum) ? date : date.month) == month_number) ? + %(<option value="#{month_number}" selected="selected">#{month_name}</option>\n) : + %(<option value="#{month_number}">#{month_name}</option>\n) + ) + end + + select_html(options[:field_name] || 'month', month_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + # Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius + # can be changed using the <tt>:start_year</tt> and <tt>:end_year</tt> keys in the +options+. Both ascending and descending year + # lists are supported by making <tt>:start_year</tt> less than or greater than <tt>:end_year</tt>. The <tt>date</tt> can also be + # substituted for a year given as a number. Example: + # + # select_year(Date.today, :start_year => 1992, :end_year => 2007) # ascending year values + # select_year(Date.today, :start_year => 2005, :end_year => 1900) # descending year values + # + # Override the field name using the <tt>:field_name</tt> option, 'year' by default. + def select_year(date, options = {}) + year_options = [] + y = date ? (date.kind_of?(Fixnum) ? (y = (date == 0) ? Date.today.year : date) : date.year) : Date.today.year + + start_year, end_year = (options[:start_year] || y-5), (options[:end_year] || y+5) + step_val = start_year < end_year ? 1 : -1 + + start_year.step(end_year, step_val) do |year| + year_options << ((date && (date.kind_of?(Fixnum) ? date : date.year) == year) ? + %(<option value="#{year}" selected="selected">#{year}</option>\n) : + %(<option value="#{year}">#{year}</option>\n) + ) + end + + select_html(options[:field_name] || 'year', year_options, options[:prefix], options[:include_blank], options[:discard_type], options[:disabled]) + end + + private + def select_html(type, options, prefix = nil, include_blank = false, discard_type = false, disabled = false) + select_html = %(<select name="#{prefix || DEFAULT_PREFIX}) + select_html << "[#{type}]" unless discard_type + select_html << %(") + select_html << %( disabled="disabled") if disabled + select_html << %(>\n) + select_html << %(<option value=""></option>\n) if include_blank + select_html << options.to_s + select_html << "</select>\n" + end + + def leading_zero_on_single_digits(number) + number > 9 ? number : "0#{number}" + end + end + + class InstanceTag #:nodoc: + include DateHelper + + def to_date_select_tag(options = {}) + defaults = { :discard_type => true } + options = defaults.merge(options) + options_with_prefix = Proc.new { |position| options.merge(:prefix => "#{@object_name}[#{@method_name}(#{position}i)]") } + date = options[:include_blank] ? (value || 0) : (value || Date.today) + + date_select = '' + options[:order] = [:month, :year, :day] if options[:month_before_year] # For backwards compatibility + options[:order] ||= [:year, :month, :day] + + position = {:year => 1, :month => 2, :day => 3} + + discard = {} + discard[:year] = true if options[:discard_year] + discard[:month] = true if options[:discard_month] + discard[:day] = true if options[:discard_day] or options[:discard_month] + + options[:order].each do |param| + date_select << self.send("select_#{param}", date, options_with_prefix.call(position[param])) unless discard[param] + end + + date_select + end + + def to_datetime_select_tag(options = {}) + defaults = { :discard_type => true } + options = defaults.merge(options) + options_with_prefix = Proc.new { |position| options.merge(:prefix => "#{@object_name}[#{@method_name}(#{position}i)]") } + datetime = options[:include_blank] ? (value || nil) : (value || Time.now) + + datetime_select = select_year(datetime, options_with_prefix.call(1)) + datetime_select << select_month(datetime, options_with_prefix.call(2)) unless options[:discard_month] + datetime_select << select_day(datetime, options_with_prefix.call(3)) unless options[:discard_day] || options[:discard_month] + datetime_select << ' — ' + select_hour(datetime, options_with_prefix.call(4)) unless options[:discard_hour] + datetime_select << ' : ' + select_minute(datetime, options_with_prefix.call(5)) unless options[:discard_minute] || options[:discard_hour] + + datetime_select + end + end + + class FormBuilder + def date_select(method, options = {}) + @template.date_select(@object_name, method, options.merge(:object => @object)) + end + + def datetime_select(method, options = {}) + @template.datetime_select(@object_name, method, options.merge(:object => @object)) + end + end + end +end +module ActionView + module Helpers + # Provides a set of methods for making it easier to locate problems. + module DebugHelper + # Returns a <pre>-tag set with the +object+ dumped by YAML. Very readable way to inspect an object. + def debug(object) + begin + Marshal::dump(object) + "<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", " ")}</pre>" + rescue Object => e + # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback + "<code class='debug_dump'>#{h(object.inspect)}</code>" + end + end + end + end +endrequire 'cgi' +require File.dirname(__FILE__) + '/date_helper' +require File.dirname(__FILE__) + '/tag_helper' + +module ActionView + module Helpers + # Provides a set of methods for working with forms and especially forms related to objects assigned to the template. + # The following is an example of a complete form for a person object that works for both creates and updates built + # with all the form helpers. The <tt>@person</tt> object was assigned by an action on the controller: + # <form action="save_person" method="post"> + # Name: + # <%= text_field "person", "name", "size" => 20 %> + # + # Password: + # <%= password_field "person", "password", "maxsize" => 20 %> + # + # Single?: + # <%= check_box "person", "single" %> + # + # Description: + # <%= text_area "person", "description", "cols" => 20 %> + # + # <input type="submit" value="Save"> + # </form> + # + # ...is compiled to: + # + # <form action="save_person" method="post"> + # Name: + # <input type="text" id="person_name" name="person[name]" + # size="20" value="<%= @person.name %>" /> + # + # Password: + # <input type="password" id="person_password" name="person[password]" + # size="20" maxsize="20" value="<%= @person.password %>" /> + # + # Single?: + # <input type="checkbox" id="person_single" name="person[single]" value="1" /> + # + # Description: + # <textarea cols="20" rows="40" id="person_description" name="person[description]"> + # <%= @person.description %> + # </textarea> + # + # <input type="submit" value="Save"> + # </form> + # + # If the object name contains square brackets the id for the object will be inserted. Example: + # + # <%= text_field "person[]", "name" %> + # + # ...becomes: + # + # <input type="text" id="person_<%= @person.id %>_name" name="person[<%= @person.id %>][name]" value="<%= @person.name %>" /> + # + # If the helper is being used to generate a repetitive sequence of similar form elements, for example in a partial + # used by render_collection_of_partials, the "index" option may come in handy. Example: + # + # <%= text_field "person", "name", "index" => 1 %> + # + # becomes + # + # <input type="text" id="person_1_name" name="person[1][name]" value="<%= @person.name %>" /> + # + # There's also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html, + # link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html + module FormHelper + # Creates a form and a scope around a specific model object, which is then used as a base for questioning about + # values for the fields. Examples: + # + # <% form_for :person, @person, :url => { :action => "update" } do |f| %> + # First name: <%= f.text_field :first_name %> + # Last name : <%= f.text_field :last_name %> + # Biography : <%= f.text_area :biography %> + # Admin? : <%= f.check_box :admin %> + # <% end %> + # + # Worth noting is that the form_for tag is called in a ERb evaluation block, not a ERb output block. So that's <tt><% %></tt>, + # not <tt><%= %></tt>. Also worth noting is that the form_for yields a form_builder object, in this example as f, which emulates + # the API for the stand-alone FormHelper methods, but without the object name. So instead of <tt>text_field :person, :name</tt>, + # you get away with <tt>f.text_field :name</tt>. + # + # That in itself is a modest increase in comfort. The big news is that form_for allows us to more easily escape the instance + # variable convention, so while the stand-alone approach would require <tt>text_field :person, :name, :object => person</tt> + # to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with + # <tt>:person, person</tt> and all subsequent field calls save <tt>:person</tt> and <tt>:object => person</tt>. + # + # Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods + # and methods from FormTagHelper. Example: + # + # <% form_for :person, @person, :url => { :action => "update" } do |f| %> + # First name: <%= f.text_field :first_name %> + # Last name : <%= f.text_field :last_name %> + # Biography : <%= text_area :person, :biography %> + # Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %> + # <% end %> + # + # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. + # Like collection_select and datetime_select. + # + # Html attributes for the form tag can be given as :html => {...}. Example: + # + # <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %> + # ... + # <% end %> + # + # You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, + # then use your custom builder like so: + # + # <% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %> + # <%= f.text_field :first_name %> + # <%= f.text_field :last_name %> + # <%= text_area :person, :biography %> + # <%= check_box_tag "person[admin]", @person.company.admin? %> + # <% end %> + # + # In many cases you will want to wrap the above in another helper, such as: + # + # def labelled_form_for(name, object, options, &proc) + # form_for(name, object, options.merge(:builder => LabellingFormBuiler), &proc) + # end + # + def form_for(object_name, *args, &proc) + raise ArgumentError, "Missing block" unless block_given? + options = args.last.is_a?(Hash) ? args.pop : {} + concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}), proc.binding) + fields_for(object_name, *(args << options), &proc) + concat('</form>', proc.binding) + end + + # Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes + # fields_for suitable for specifying additional model objects in the same form. Example: + # + # <% form_for :person, @person, :url => { :action => "update" } do |person_form| %> + # First name: <%= person_form.text_field :first_name %> + # Last name : <%= person_form.text_field :last_name %> + # + # <% fields_for :permission, @person.permission do |permission_fields| %> + # Admin? : <%= permission_fields.check_box :admin %> + # <% end %> + # <% end %> + # + # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base. + # Like collection_select and datetime_select. + def fields_for(object_name, *args, &proc) + raise ArgumentError, "Missing block" unless block_given? + options = args.last.is_a?(Hash) ? args.pop : {} + object = args.first + yield((options[:builder] || FormBuilder).new(object_name, object, self, options, proc)) + end + + # Returns an input tag of the "text" type tailored for accessing a specified attribute (identified by +method+) on an object + # assigned to the template (identified by +object+). Additional options on the input tag can be passed as a + # hash with +options+. + # + # Examples (call, result): + # text_field("post", "title", "size" => 20) + # <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" /> + def text_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("text", options) + end + + # Works just like text_field, but returns an input tag of the "password" type instead. + def password_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("password", options) + end + + # Works just like text_field, but returns an input tag of the "hidden" type instead. + def hidden_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("hidden", options) + end + + # Works just like text_field, but returns an input tag of the "file" type instead, which won't have a default value. + def file_field(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_input_field_tag("file", options) + end + + # Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by +method+) + # on an object assigned to the template (identified by +object+). Additional options on the input tag can be passed as a + # hash with +options+. + # + # Example (call, result): + # text_area("post", "body", "cols" => 20, "rows" => 40) + # <textarea cols="20" rows="40" id="post_body" name="post[body]"> + # #{@post.body} + # </textarea> + def text_area(object_name, method, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_text_area_tag(options) + end + + # Returns a checkbox tag tailored for accessing a specified attribute (identified by +method+) on an object + # assigned to the template (identified by +object+). It's intended that +method+ returns an integer and if that + # integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a + # hash with +options+. The +checked_value+ defaults to 1 while the default +unchecked_value+ + # is set to 0 which is convenient for boolean values. Usually unchecked checkboxes don't post anything. + # We work around this problem by adding a hidden value with the same name as the checkbox. + # + # Example (call, result). Imagine that @post.validated? returns 1: + # check_box("post", "validated") + # <input type="checkbox" id="post_validate" name="post[validated]" value="1" checked="checked" /> + # <input name="post[validated]" type="hidden" value="0" /> + # + # Example (call, result). Imagine that @puppy.gooddog returns no: + # check_box("puppy", "gooddog", {}, "yes", "no") + # <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" /> + # <input name="puppy[gooddog]" type="hidden" value="no" /> + def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_check_box_tag(options, checked_value, unchecked_value) + end + + # Returns a radio button tag for accessing a specified attribute (identified by +method+) on an object + # assigned to the template (identified by +object+). If the current value of +method+ is +tag_value+ the + # radio button will be checked. Additional options on the input tag can be passed as a + # hash with +options+. + # Example (call, result). Imagine that @post.category returns "rails": + # radio_button("post", "category", "rails") + # radio_button("post", "category", "java") + # <input type="radio" id="post_category" name="post[category]" value="rails" checked="checked" /> + # <input type="radio" id="post_category" name="post[category]" value="java" /> + # + def radio_button(object_name, method, tag_value, options = {}) + InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_radio_button_tag(tag_value, options) + end + end + + class InstanceTag #:nodoc: + include Helpers::TagHelper + + attr_reader :method_name, :object_name + + DEFAULT_FIELD_OPTIONS = { "size" => 30 }.freeze unless const_defined?(:DEFAULT_FIELD_OPTIONS) + DEFAULT_RADIO_OPTIONS = { }.freeze unless const_defined?(:DEFAULT_RADIO_OPTIONS) + DEFAULT_TEXT_AREA_OPTIONS = { "cols" => 40, "rows" => 20 }.freeze unless const_defined?(:DEFAULT_TEXT_AREA_OPTIONS) + DEFAULT_DATE_OPTIONS = { :discard_type => true }.freeze unless const_defined?(:DEFAULT_DATE_OPTIONS) + + def initialize(object_name, method_name, template_object, local_binding = nil, object = nil) + @object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup + @template_object, @local_binding = template_object, local_binding + @object = object + if @object_name.sub!(/\[\]$/,"") + @auto_index = @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}").id_before_type_cast + end + end + + def to_input_field_tag(field_type, options = {}) + options = options.stringify_keys + options["size"] ||= options["maxlength"] || DEFAULT_FIELD_OPTIONS["size"] + options = DEFAULT_FIELD_OPTIONS.merge(options) + if field_type == "hidden" + options.delete("size") + end + options["type"] = field_type + options["value"] ||= value_before_type_cast unless field_type == "file" + add_default_name_and_id(options) + tag("input", options) + end + + def to_radio_button_tag(tag_value, options = {}) + options = DEFAULT_RADIO_OPTIONS.merge(options.stringify_keys) + options["type"] = "radio" + options["value"] = tag_value + options["checked"] = "checked" if value.to_s == tag_value.to_s + pretty_tag_value = tag_value.to_s.gsub(/\s/, "_").gsub(/\W/, "").downcase + options["id"] = @auto_index ? + "#{@object_name}_#{@auto_index}_#{@method_name}_#{pretty_tag_value}" : + "#{@object_name}_#{@method_name}_#{pretty_tag_value}" + add_default_name_and_id(options) + tag("input", options) + end + + def to_text_area_tag(options = {}) + options = DEFAULT_TEXT_AREA_OPTIONS.merge(options.stringify_keys) + add_default_name_and_id(options) + content_tag("textarea", html_escape(options.delete('value') || value_before_type_cast), options) + end + + def to_check_box_tag(options = {}, checked_value = "1", unchecked_value = "0") + options = options.stringify_keys + options["type"] = "checkbox" + options["value"] = checked_value + checked = case value + when TrueClass, FalseClass + value + when NilClass + false + when Integer + value != 0 + when String + value == checked_value + else + value.to_i != 0 + end + if checked || options["checked"] == "checked" + options["checked"] = "checked" + else + options.delete("checked") + end + add_default_name_and_id(options) + tag("input", options) << tag("input", "name" => options["name"], "type" => "hidden", "value" => unchecked_value) + end + + def to_date_tag() + defaults = DEFAULT_DATE_OPTIONS.dup + date = value || Date.today + options = Proc.new { |position| defaults.merge(:prefix => "#{@object_name}[#{@method_name}(#{position}i)]") } + html_day_select(date, options.call(3)) + + html_month_select(date, options.call(2)) + + html_year_select(date, options.call(1)) + end + + def to_boolean_select_tag(options = {}) + options = options.stringify_keys + add_default_name_and_id(options) + tag_text = "<select" + tag_text << tag_options(options) + tag_text << "><option value=\"false\"" + tag_text << " selected" if value == false + tag_text << ">False</option><option value=\"true\"" + tag_text << " selected" if value + tag_text << ">True</option></select>" + end + + def to_content_tag(tag_name, options = {}) + content_tag(tag_name, value, options) + end + + def object + @object || @template_object.instance_variable_get("@#{@object_name}") + end + + def value + unless object.nil? + object.send(@method_name) + end + end + + def value_before_type_cast + unless object.nil? + object.respond_to?(@method_name + "_before_type_cast") ? + object.send(@method_name + "_before_type_cast") : + object.send(@method_name) + end + end + + private + def add_default_name_and_id(options) + if options.has_key?("index") + options["name"] ||= tag_name_with_index(options["index"]) + options["id"] ||= tag_id_with_index(options["index"]) + options.delete("index") + elsif @auto_index + options["name"] ||= tag_name_with_index(@auto_index) + options["id"] ||= tag_id_with_index(@auto_index) + else + options["name"] ||= tag_name + options["id"] ||= tag_id + end + end + + def tag_name + "#{@object_name}[#{@method_name}]" + end + + def tag_name_with_index(index) + "#{@object_name}[#{index}][#{@method_name}]" + end + + def tag_id + "#{@object_name}_#{@method_name}" + end + + def tag_id_with_index(index) + "#{@object_name}_#{index}_#{@method_name}" + end + end + + class FormBuilder #:nodoc: + # The methods which wrap a form helper call. + class_inheritable_accessor :field_helpers + self.field_helpers = (FormHelper.instance_methods - ['form_for']) + + attr_accessor :object_name, :object + + def initialize(object_name, object, template, options, proc) + @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc + end + + (field_helpers - %w(check_box radio_button)).each do |selector| + src = <<-end_src + def #{selector}(method, options = {}) + @template.send(#{selector.inspect}, @object_name, method, options.merge(:object => @object)) + end + end_src + class_eval src, __FILE__, __LINE__ + end + + def check_box(method, options = {}, checked_value = "1", unchecked_value = "0") + @template.check_box(@object_name, method, options.merge(:object => @object), checked_value, unchecked_value) + end + + def radio_button(method, tag_value, options = {}) + @template.radio_button(@object_name, method, tag_value, options.merge(:object => @object)) + end + end + end +end +require 'cgi' +require 'erb' +require File.dirname(__FILE__) + '/form_helper' + +module ActionView + module Helpers + # Provides a number of methods for turning different kinds of containers into a set of option tags. + # == Options + # The <tt>collection_select</tt>, <tt>country_select</tt>, <tt>select</tt>, + # and <tt>time_zone_select</tt> methods take an <tt>options</tt> parameter, + # a hash. + # + # * <tt>:include_blank</tt> - set to true if the first option element of the select element is a blank. Useful if there is not a default value required for the select element. For example, + # + # select("post", "category", Post::CATEGORIES, {:include_blank => true}) + # + # could become: + # + # <select name="post[category]"> + # <option></option> + # <option>joke</option> + # <option>poem</option> + # </select> + # + # * <tt>:prompt</tt> - set to true or a prompt string. When the select element doesn't have a value yet, this prepends an option with a generic prompt -- "Please select" -- or the given prompt string. + # + # Another common case is a select tag for an <tt>belongs_to</tt>-associated object. For example, + # + # select("post", "person_id", Person.find_all.collect {|p| [ p.name, p.id ] }) + # + # could become: + # + # <select name="post[person_id]"> + # <option value="1">David</option> + # <option value="2">Sam</option> + # <option value="3">Tobias</option> + # </select> + module FormOptionsHelper + include ERB::Util + + # Create a select tag and a series of contained option tags for the provided object and method. + # The option currently held by the object will be selected, provided that the object is available. + # See options_for_select for the required format of the choices parameter. + # + # Example with @post.person_id => 1: + # select("post", "person_id", Person.find_all.collect {|p| [ p.name, p.id ] }, { :include_blank => true }) + # + # could become: + # + # <select name="post[person_id]"> + # <option></option> + # <option value="1" selected="selected">David</option> + # <option value="2">Sam</option> + # <option value="3">Tobias</option> + # </select> + # + # This can be used to provide a default set of options in the standard way: before rendering the create form, a + # new model instance is assigned the default options and bound to @model_name. Usually this model is not saved + # to the database. Instead, a second model object is created when the create request is received. + # This allows the user to submit a form page more than once with the expected results of creating multiple records. + # In addition, this allows a single partial to be used to generate form inputs for both edit and create forms. + # + # By default, post.person_id is the selected option. Specify :selected => value to use a different selection + # or :selected => nil to leave all options unselected. + def select(object, method, choices, options = {}, html_options = {}) + InstanceTag.new(object, method, self, nil, options.delete(:object)).to_select_tag(choices, options, html_options) + end + + # Return select and option tags for the given object and method using options_from_collection_for_select to generate the list of option tags. + def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) + InstanceTag.new(object, method, self, nil, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options) + end + + # Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags. + def country_select(object, method, priority_countries = nil, options = {}, html_options = {}) + InstanceTag.new(object, method, self, nil, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options) + end + + # Return select and option tags for the given object and method, using + # #time_zone_options_for_select to generate the list of option tags. + # + # In addition to the <tt>:include_blank</tt> option documented above, + # this method also supports a <tt>:model</tt> option, which defaults + # to TimeZone. This may be used by users to specify a different time + # zone model object. (See #time_zone_options_for_select for more + # information.) + def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) + InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) + end + + # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container + # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and + # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values + # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +Selected+ + # may also be an array of values to be selected when using a multiple select. + # + # Examples (call, result): + # options_for_select([["Dollar", "$"], ["Kroner", "DKK"]]) + # <option value="$">Dollar</option>\n<option value="DKK">Kroner</option> + # + # options_for_select([ "VISA", "MasterCard" ], "MasterCard") + # <option>VISA</option>\n<option selected="selected">MasterCard</option> + # + # options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40") + # <option value="$20">Basic</option>\n<option value="$40" selected="selected">Plus</option> + # + # options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"]) + # <option selected="selected">VISA</option>\n<option>MasterCard</option>\n<option selected="selected">Discover</option> + # + # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. + def options_for_select(container, selected = nil) + container = container.to_a if Hash === container + + options_for_select = container.inject([]) do |options, element| + if !element.is_a?(String) and element.respond_to?(:first) and element.respond_to?(:last) + is_selected = ( (selected.respond_to?(:include?) ? selected.include?(element.last) : element.last == selected) ) + is_selected = ( (selected.respond_to?(:include?) && !selected.is_a?(String) ? selected.include?(element.last) : element.last == selected) ) + if is_selected + options << "<option value=\"#{html_escape(element.last.to_s)}\" selected=\"selected\">#{html_escape(element.first.to_s)}</option>" + else + options << "<option value=\"#{html_escape(element.last.to_s)}\">#{html_escape(element.first.to_s)}</option>" + end + else + is_selected = ( (selected.respond_to?(:include?) ? selected.include?(element) : element == selected) ) + is_selected = ( (selected.respond_to?(:include?) && !selected.is_a?(String) ? selected.include?(element) : element == selected) ) + options << ((is_selected) ? "<option value=\"#{html_escape(element.to_s)}\" selected=\"selected\">#{html_escape(element.to_s)}</option>" : "<option value=\"#{html_escape(element.to_s)}\">#{html_escape(element.to_s)}</option>") + end + end + + options_for_select.join("\n") + end + + # Returns a string of option tags that have been compiled by iterating over the +collection+ and assigning the + # the result of a call to the +value_method+ as the option value and the +text_method+ as the option text. + # If +selected_value+ is specified, the element returning a match on +value_method+ will get the selected option tag. + # + # Example (call, result). Imagine a loop iterating over each +person+ in <tt>@project.people</tt> to generate an input tag: + # options_from_collection_for_select(@project.people, "id", "name") + # <option value="#{person.id}">#{person.name}</option> + # + # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. + def options_from_collection_for_select(collection, value_method, text_method, selected_value = nil) + options_for_select( + collection.inject([]) { |options, object| options << [ object.send(text_method), object.send(value_method) ] }, + selected_value + ) + end + + # Returns a string of option tags, like options_from_collection_for_select, but surrounds them with <optgroup> tags. + # + # An array of group objects are passed. Each group should return an array of options when calling group_method + # Each group should return its name when calling group_label_method. + # + # html_option_groups_from_collection(@continents, "countries", "continent_name", "country_id", "country_name", @selected_country.id) + # + # Could become: + # <optgroup label="Africa"> + # <select>Egypt</select> + # <select>Rwanda</select> + # ... + # </optgroup> + # <optgroup label="Asia"> + # <select>China</select> + # <select>India</select> + # <select>Japan</select> + # ... + # </optgroup> + # + # with objects of the following classes: + # class Continent + # def initialize(p_name, p_countries) @continent_name = p_name; @countries = p_countries; end + # def continent_name() @continent_name; end + # def countries() @countries; end + # end + # class Country + # def initialize(id, name) @id = id; @name = name end + # def country_id() @id; end + # def country_name() @name; end + # end + # + # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. + def option_groups_from_collection_for_select(collection, group_method, group_label_method, + option_key_method, option_value_method, selected_key = nil) + collection.inject("") do |options_for_select, group| + group_label_string = eval("group.#{group_label_method}") + options_for_select += "<optgroup label=\"#{html_escape(group_label_string)}\">" + options_for_select += options_from_collection_for_select(eval("group.#{group_method}"), option_key_method, option_value_method, selected_key) + options_for_select += '</optgroup>' + end + end + + # Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to + # have it marked as the selected option tag. You can also supply an array of countries as +priority_countries+, so + # that they will be listed above the rest of the (long) list. + # + # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag. + def country_options_for_select(selected = nil, priority_countries = nil) + country_options = "" + + if priority_countries + country_options += options_for_select(priority_countries, selected) + country_options += "<option value=\"\">-------------</option>\n" + end + + if priority_countries && priority_countries.include?(selected) + country_options += options_for_select(COUNTRIES - priority_countries, selected) + else + country_options += options_for_select(COUNTRIES, selected) + end + + return country_options + end + + # Returns a string of option tags for pretty much any time zone in the + # world. Supply a TimeZone name as +selected+ to have it marked as the + # selected option tag. You can also supply an array of TimeZone objects + # as +priority_zones+, so that they will be listed above the rest of the + # (long) list. (You can use TimeZone.us_zones as a convenience for + # obtaining a list of the US time zones.) + # + # The +selected+ parameter must be either +nil+, or a string that names + # a TimeZone. + # + # By default, +model+ is the TimeZone constant (which can be obtained + # in ActiveRecord as a value object). The only requirement is that the + # +model+ parameter be an object that responds to #all, and returns + # an array of objects that represent time zones. + # + # NOTE: Only the option tags are returned, you have to wrap this call in + # a regular HTML select tag. + def time_zone_options_for_select(selected = nil, priority_zones = nil, model = TimeZone) + zone_options = "" + + zones = model.all + convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } } + + if priority_zones + zone_options += options_for_select(convert_zones[priority_zones], selected) + zone_options += "<option value=\"\">-------------</option>\n" + + zones = zones.reject { |z| priority_zones.include?( z ) } + end + + zone_options += options_for_select(convert_zones[zones], selected) + zone_options + end + + private + # All the countries included in the country_options output. + COUNTRIES = [ "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", + "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", + "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", + "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", + "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory", + "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burma", "Burundi", "Cambodia", + "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", + "Chad", "Chile", "China", "Christmas Island", "Cocos (Keeling) Islands", "Colombia", + "Comoros", "Congo", "Congo, the Democratic Republic of the", "Cook Islands", + "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", + "Djibouti", "Dominica", "Dominican Republic", "East Timor", "Ecuador", "Egypt", + "El Salvador", "England", "Equatorial Guinea", "Eritrea", "Espana", "Estonia", + "Ethiopia", "Falkland Islands", "Faroe Islands", "Fiji", "Finland", "France", + "French Guiana", "French Polynesia", "French Southern Territories", "Gabon", "Gambia", + "Georgia", "Germany", "Ghana", "Gibraltar", "Great Britain", "Greece", "Greenland", + "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", + "Haiti", "Heard and Mc Donald Islands", "Honduras", "Hong Kong", "Hungary", "Iceland", + "India", "Indonesia", "Ireland", "Israel", "Italy", "Iran", "Iraq", "Jamaica", "Japan", "Jordan", + "Kazakhstan", "Kenya", "Kiribati", "Korea, Republic of", "Korea (South)", "Kuwait", + "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", + "Liberia", "Liechtenstein", "Lithuania", "Luxembourg", "Macau", "Macedonia", + "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", + "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", + "Micronesia, Federated States of", "Moldova, Republic of", "Monaco", "Mongolia", + "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", + "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", + "Niger", "Nigeria", "Niue", "Norfolk Island", "Northern Ireland", + "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Panama", + "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", + "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russia", "Rwanda", + "Saint Kitts and Nevis", "Saint Lucia", "Saint Vincent and the Grenadines", + "Samoa (Independent)", "San Marino", "Sao Tome and Principe", "Saudi Arabia", + "Scotland", "Senegal", "Serbia and Montenegro", "Seychelles", "Sierra Leone", "Singapore", + "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", + "South Georgia and the South Sandwich Islands", "South Korea", "Spain", "Sri Lanka", + "St. Helena", "St. Pierre and Miquelon", "Suriname", "Svalbard and Jan Mayen Islands", + "Swaziland", "Sweden", "Switzerland", "Taiwan", "Tajikistan", "Tanzania", "Thailand", + "Togo", "Tokelau", "Tonga", "Trinidad", "Trinidad and Tobago", "Tunisia", "Turkey", + "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", + "United Arab Emirates", "United Kingdom", "United States", + "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", + "Vatican City State (Holy See)", "Venezuela", "Viet Nam", "Virgin Islands (British)", + "Virgin Islands (U.S.)", "Wales", "Wallis and Futuna Islands", "Western Sahara", + "Yemen", "Zambia", "Zimbabwe" ] unless const_defined?("COUNTRIES") + end + + class InstanceTag #:nodoc: + include FormOptionsHelper + + def to_select_tag(choices, options, html_options) + html_options = html_options.stringify_keys + add_default_name_and_id(html_options) + selected_value = options.has_key?(:selected) ? options[:selected] : value + content_tag("select", add_options(options_for_select(choices, selected_value), options, value), html_options) + end + + def to_collection_select_tag(collection, value_method, text_method, options, html_options) + html_options = html_options.stringify_keys + add_default_name_and_id(html_options) + content_tag( + "select", add_options(options_from_collection_for_select(collection, value_method, text_method, value), options, value), html_options + ) + end + + def to_country_select_tag(priority_countries, options, html_options) + html_options = html_options.stringify_keys + add_default_name_and_id(html_options) + content_tag("select", add_options(country_options_for_select(value, priority_countries), options, value), html_options) + end + + def to_time_zone_select_tag(priority_zones, options, html_options) + html_options = html_options.stringify_keys + add_default_name_and_id(html_options) + content_tag("select", + add_options( + time_zone_options_for_select(value, priority_zones, options[:model] || TimeZone), + options, value + ), html_options + ) + end + + private + def add_options(option_tags, options, value = nil) + option_tags = "<option value=\"\"></option>\n" + option_tags if options[:include_blank] + + if value.blank? && options[:prompt] + ("<option value=\"\">#{options[:prompt].kind_of?(String) ? options[:prompt] : 'Please select'}</option>\n") + option_tags + else + option_tags + end + end + end + + class FormBuilder + def select(method, choices, options = {}, html_options = {}) + @template.select(@object_name, method, choices, options.merge(:object => @object), html_options) + end + + def collection_select(method, collection, value_method, text_method, options = {}, html_options = {}) + @template.collection_select(@object_name, method, collection, value_method, text_method, options.merge(:object => @object), html_options) + end + + def country_select(method, priority_countries = nil, options = {}, html_options = {}) + @template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options) + end + + def time_zone_select(method, priority_zones = nil, options = {}, html_options = {}) + @template.time_zone_select(@object_name, method, priority_zones, options.merge(:object => @object), html_options) + end + end + end +end +require 'cgi' +require File.dirname(__FILE__) + '/tag_helper' + +module ActionView + module Helpers + # Provides a number of methods for creating form tags that doesn't rely on conventions with an object assigned to the template like + # FormHelper does. With the FormTagHelper, you provide the names and values yourself. + # + # NOTE: The html options disabled, readonly, and multiple can all be treated as booleans. So specifying <tt>:disabled => true</tt> + # will give <tt>disabled="disabled"</tt>. + module FormTagHelper + # Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like + # ActionController::Base#url_for. The method for the form defaults to POST. + # + # Options: + # * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data". + # * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post". + def form_tag(url_for_options = {}, options = {}, *parameters_for_url, &proc) + html_options = { "method" => "post" }.merge(options.stringify_keys) + html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart") + html_options["action"] = url_for(url_for_options, *parameters_for_url) + tag :form, html_options, true + end + + alias_method :start_form_tag, :form_tag + + # Outputs "</form>" + def end_form_tag + "</form>" + end + + # Creates a dropdown selection box, or if the <tt>:multiple</tt> option is set to true, a multiple + # choice selection box. + # + # Helpers::FormOptions can be used to create common select boxes such as countries, time zones, or + # associated records. + # + # <tt>option_tags</tt> is a string containing the option tags for the select box: + # # Outputs <select id="people" name="people"><option>David</option></select> + # select_tag "people", "<option>David</option>" + # + # Options: + # * <tt>:multiple</tt> - If set to true the selection will allow multiple choices. + def select_tag(name, option_tags = nil, options = {}) + content_tag :select, option_tags, { "name" => name, "id" => name }.update(options.stringify_keys) + end + + # Creates a standard text field. + # + # Options: + # * <tt>:disabled</tt> - If set to true, the user will not be able to use this input. + # * <tt>:size</tt> - The number of visible characters that will fit in the input. + # * <tt>:maxlength</tt> - The maximum number of characters that the browser will allow the user to enter. + # + # A hash of standard HTML options for the tag. + def text_field_tag(name, value = nil, options = {}) + tag :input, { "type" => "text", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys) + end + + # Creates a hidden field. + # + # Takes the same options as text_field_tag + def hidden_field_tag(name, value = nil, options = {}) + text_field_tag(name, value, options.stringify_keys.update("type" => "hidden")) + end + + # Creates a file upload field. + # + # If you are using file uploads then you will also need to set the multipart option for the form: + # <%= form_tag { :action => "post" }, { :multipart => true } %> + # <label for="file">File to Upload</label> <%= file_field_tag "file" %> + # <%= submit_tag %> + # <%= end_form_tag %> + # + # The specified URL will then be passed a File object containing the selected file, or if the field + # was left blank, a StringIO object. + def file_field_tag(name, options = {}) + text_field_tag(name, nil, options.update("type" => "file")) + end + + # Creates a password field. + # + # Takes the same options as text_field_tag + def password_field_tag(name = "password", value = nil, options = {}) + text_field_tag(name, value, options.update("type" => "password")) + end + + # Creates a text input area. + # + # Options: + # * <tt>:size</tt> - A string specifying the dimensions of the textarea. + # # Outputs <textarea name="body" id="body" cols="25" rows="10"></textarea> + # <%= text_area_tag "body", nil, :size => "25x10" %> + def text_area_tag(name, content = nil, options = {}) + options.stringify_keys! + + if size = options.delete("size") + options["cols"], options["rows"] = size.split("x") + end + + content_tag :textarea, content, { "name" => name, "id" => name }.update(options.stringify_keys) + end + + # Creates a check box. + def check_box_tag(name, value = "1", checked = false, options = {}) + html_options = { "type" => "checkbox", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys) + html_options["checked"] = "checked" if checked + tag :input, html_options + end + + # Creates a radio button. + def radio_button_tag(name, value, checked = false, options = {}) + html_options = { "type" => "radio", "name" => name, "id" => name, "value" => value }.update(options.stringify_keys) + html_options["checked"] = "checked" if checked + tag :input, html_options + end + + # Creates a submit button with the text <tt>value</tt> as the caption. If options contains a pair with the key of "disable_with", + # then the value will be used to rename a disabled version of the submit button. + def submit_tag(value = "Save changes", options = {}) + options.stringify_keys! + + if disable_with = options.delete("disable_with") + options["onclick"] = "this.disabled=true;this.value='#{disable_with}';this.form.submit();#{options["onclick"]}" + end + + tag :input, { "type" => "submit", "name" => "commit", "value" => value }.update(options.stringify_keys) + end + + # Displays an image which when clicked will submit the form. + # + # <tt>source</tt> is passed to AssetTagHelper#image_path + def image_submit_tag(source, options = {}) + tag :input, { "type" => "image", "src" => image_path(source) }.update(options.stringify_keys) + end + end + end +end +require File.dirname(__FILE__) + '/tag_helper' + +module ActionView + module Helpers + # Provides a set of helpers for creating JavaScript macros that rely on and often bundle methods from JavaScriptHelper into + # larger units. These macros also rely on counterparts in the controller that provide them with their backing. The in-place + # editing relies on ActionController::Base.in_place_edit_for and the autocompletion relies on + # ActionController::Base.auto_complete_for. + module JavaScriptMacrosHelper + # Makes an HTML element specified by the DOM ID +field_id+ become an in-place + # editor of a property. + # + # A form is automatically created and displayed when the user clicks the element, + # something like this: + # <form id="myElement-in-place-edit-form" target="specified url"> + # <input name="value" text="The content of myElement"/> + # <input type="submit" value="ok"/> + # <a onclick="javascript to cancel the editing">cancel</a> + # </form> + # + # The form is serialized and sent to the server using an AJAX call, the action on + # the server should process the value and return the updated value in the body of + # the reponse. The element will automatically be updated with the changed value + # (as returned from the server). + # + # Required +options+ are: + # <tt>:url</tt>:: Specifies the url where the updated value should + # be sent after the user presses "ok". + # + # + # Addtional +options+ are: + # <tt>:rows</tt>:: Number of rows (more than 1 will use a TEXTAREA) + # <tt>:cols</tt>:: Number of characters the text input should span (works for both INPUT and TEXTAREA) + # <tt>:size</tt>:: Synonym for :cols when using a single line text input. + # <tt>:cancel_text</tt>:: The text on the cancel link. (default: "cancel") + # <tt>:save_text</tt>:: The text on the save link. (default: "ok") + # <tt>:loading_text</tt>:: The text to display when submitting to the server (default: "Saving...") + # <tt>:external_control</tt>:: The id of an external control used to enter edit mode. + # <tt>:load_text_url</tt>:: URL where initial value of editor (content) is retrieved. + # <tt>:options</tt>:: Pass through options to the AJAX call (see prototype's Ajax.Updater) + # <tt>:with</tt>:: JavaScript snippet that should return what is to be sent + # in the AJAX call, +form+ is an implicit parameter + # <tt>:script</tt>:: Instructs the in-place editor to evaluate the remote JavaScript response (default: false) + def in_place_editor(field_id, options = {}) + function = "new Ajax.InPlaceEditor(" + function << "'#{field_id}', " + function << "'#{url_for(options[:url])}'" + + js_options = {} + js_options['cancelText'] = %('#{options[:cancel_text]}') if options[:cancel_text] + js_options['okText'] = %('#{options[:save_text]}') if options[:save_text] + js_options['loadingText'] = %('#{options[:loading_text]}') if options[:loading_text] + js_options['rows'] = options[:rows] if options[:rows] + js_options['cols'] = options[:cols] if options[:cols] + js_options['size'] = options[:size] if options[:size] + js_options['externalControl'] = "'#{options[:external_control]}'" if options[:external_control] + js_options['loadTextURL'] = "'#{url_for(options[:load_text_url])}'" if options[:load_text_url] + js_options['ajaxOptions'] = options[:options] if options[:options] + js_options['evalScripts'] = options[:script] if options[:script] + js_options['callback'] = "function(form) { return #{options[:with]} }" if options[:with] + function << (', ' + options_for_javascript(js_options)) unless js_options.empty? + + function << ')' + + javascript_tag(function) + end + + # Renders the value of the specified object and method with in-place editing capabilities. + # + # See the RDoc on ActionController::InPlaceEditing to learn more about this. + def in_place_editor_field(object, method, tag_options = {}, in_place_editor_options = {}) + tag = ::ActionView::Helpers::InstanceTag.new(object, method, self) + tag_options = {:tag => "span", :id => "#{object}_#{method}_#{tag.object.id}_in_place_editor", :class => "in_place_editor_field"}.merge!(tag_options) + in_place_editor_options[:url] = in_place_editor_options[:url] || url_for({ :action => "set_#{object}_#{method}", :id => tag.object.id }) + tag.to_content_tag(tag_options.delete(:tag), tag_options) + + in_place_editor(tag_options[:id], in_place_editor_options) + end + + # Adds AJAX autocomplete functionality to the text input field with the + # DOM ID specified by +field_id+. + # + # This function expects that the called action returns a HTML <ul> list, + # or nothing if no entries should be displayed for autocompletion. + # + # You'll probably want to turn the browser's built-in autocompletion off, + # so be sure to include a autocomplete="off" attribute with your text + # input field. + # + # The autocompleter object is assigned to a Javascript variable named <tt>field_id</tt>_auto_completer. + # This object is useful if you for example want to trigger the auto-complete suggestions through + # other means than user input (for that specific case, call the <tt>activate</tt> method on that object). + # + # Required +options+ are: + # <tt>:url</tt>:: URL to call for autocompletion results + # in url_for format. + # + # Addtional +options+ are: + # <tt>:update</tt>:: Specifies the DOM ID of the element whose + # innerHTML should be updated with the autocomplete + # entries returned by the AJAX request. + # Defaults to field_id + '_auto_complete' + # <tt>:with</tt>:: A JavaScript expression specifying the + # parameters for the XMLHttpRequest. This defaults + # to 'fieldname=value'. + # <tt>:frequency</tt>:: Determines the time to wait after the last keystroke + # for the AJAX request to be initiated. + # <tt>:indicator</tt>:: Specifies the DOM ID of an element which will be + # displayed while autocomplete is running. + # <tt>:tokens</tt>:: A string or an array of strings containing + # separator tokens for tokenized incremental + # autocompletion. Example: <tt>:tokens => ','</tt> would + # allow multiple autocompletion entries, separated + # by commas. + # <tt>:min_chars</tt>:: The minimum number of characters that should be + # in the input field before an Ajax call is made + # to the server. + # <tt>:on_hide</tt>:: A Javascript expression that is called when the + # autocompletion div is hidden. The expression + # should take two variables: element and update. + # Element is a DOM element for the field, update + # is a DOM element for the div from which the + # innerHTML is replaced. + # <tt>:on_show</tt>:: Like on_hide, only now the expression is called + # then the div is shown. + # <tt>:after_update_element</tt>:: A Javascript expression that is called when the + # user has selected one of the proposed values. + # The expression should take two variables: element and value. + # Element is a DOM element for the field, value + # is the value selected by the user. + # <tt>:select</tt>:: Pick the class of the element from which the value for + # insertion should be extracted. If this is not specified, + # the entire element is used. + def auto_complete_field(field_id, options = {}) + function = "var #{field_id}_auto_completer = new Ajax.Autocompleter(" + function << "'#{field_id}', " + function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', " + function << "'#{url_for(options[:url])}'" + + js_options = {} + js_options[:tokens] = array_or_string_for_javascript(options[:tokens]) if options[:tokens] + js_options[:callback] = "function(element, value) { return #{options[:with]} }" if options[:with] + js_options[:indicator] = "'#{options[:indicator]}'" if options[:indicator] + js_options[:select] = "'#{options[:select]}'" if options[:select] + js_options[:frequency] = "#{options[:frequency]}" if options[:frequency] + + { :after_update_element => :afterUpdateElement, + :on_show => :onShow, :on_hide => :onHide, :min_chars => :minChars }.each do |k,v| + js_options[v] = options[k] if options[k] + end + + function << (', ' + options_for_javascript(js_options) + ')') + + javascript_tag(function) + end + + # Use this method in your view to generate a return for the AJAX autocomplete requests. + # + # Example action: + # + # def auto_complete_for_item_title + # @items = Item.find(:all, + # :conditions => [ 'LOWER(description) LIKE ?', + # '%' + request.raw_post.downcase + '%' ]) + # render :inline => '<%= auto_complete_result(@items, 'description') %>' + # end + # + # The auto_complete_result can of course also be called from a view belonging to the + # auto_complete action if you need to decorate it further. + def auto_complete_result(entries, field, phrase = nil) + return unless entries + items = entries.map { |entry| content_tag("li", phrase ? highlight(entry[field], phrase) : h(entry[field])) } + content_tag("ul", items.uniq) + end + + # Wrapper for text_field with added AJAX autocompletion functionality. + # + # In your controller, you'll need to define an action called + # auto_complete_for_object_method to respond the AJAX calls, + # + # See the RDoc on ActionController::AutoComplete to learn more about this. + def text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {}) + (completion_options[:skip_style] ? "" : auto_complete_stylesheet) + + text_field(object, method, tag_options) + + content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") + + auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" } }.update(completion_options)) + end + + private + def auto_complete_stylesheet + content_tag("style", <<-EOT + div.auto_complete { + width: 350px; + background: #fff; + } + div.auto_complete ul { + border:1px solid #888; + margin:0; + padding:0; + width:100%; + list-style-type:none; + } + div.auto_complete ul li { + margin:0; + padding:3px; + } + div.auto_complete ul li.selected { + background-color: #ffb; + } + div.auto_complete ul strong.highlight { + color: #800; + margin:0; + padding:0; + } + EOT + ) + end + + end + end +end +require File.dirname(__FILE__) + '/tag_helper' + +module ActionView + module Helpers + # Provides functionality for working with JavaScript in your views. + # + # == Ajax, controls and visual effects + # + # * For information on using Ajax, see + # ActionView::Helpers::PrototypeHelper. + # * For information on using controls and visual effects, see + # ActionView::Helpers::ScriptaculousHelper. + # + # == Including the JavaScript libraries into your pages + # + # Rails includes the Prototype JavaScript framework and the Scriptaculous + # JavaScript controls and visual effects library. If you wish to use + # these libraries and their helpers (ActionView::Helpers::PrototypeHelper + # and ActionView::Helpers::ScriptaculousHelper), you must do one of the + # following: + # + # * Use <tt><%= javascript_include_tag :defaults %></tt> in the HEAD + # section of your page (recommended): This function will return + # references to the JavaScript files created by the +rails+ command in + # your <tt>public/javascripts</tt> directory. Using it is recommended as + # the browser can then cache the libraries instead of fetching all the + # functions anew on every request. + # * Use <tt><%= javascript_include_tag 'prototype' %></tt>: As above, but + # will only include the Prototype core library, which means you are able + # to use all basic AJAX functionality. For the Scriptaculous-based + # JavaScript helpers, like visual effects, autocompletion, drag and drop + # and so on, you should use the method described above. + # * Use <tt><%= define_javascript_functions %></tt>: this will copy all the + # JavaScript support functions within a single script block. Not + # recommended. + # + # For documentation on +javascript_include_tag+ see + # ActionView::Helpers::AssetTagHelper. + module JavaScriptHelper + unless const_defined? :JAVASCRIPT_PATH + JAVASCRIPT_PATH = File.join(File.dirname(__FILE__), 'javascripts') + end + + # Returns a link that'll trigger a JavaScript +function+ using the + # onclick handler and return false after the fact. + # + # Examples: + # link_to_function "Greeting", "alert('Hello world!')" + # link_to_function(image_tag("delete"), "if confirm('Really?'){ do_delete(); }") + def link_to_function(name, function, html_options = {}) + html_options.symbolize_keys! + content_tag( + "a", name, + html_options.merge({ + :href => html_options[:href] || "#", + :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function}; return false;" + }) + ) + end + + # Returns a link that'll trigger a JavaScript +function+ using the + # onclick handler. + # + # Examples: + # button_to_function "Greeting", "alert('Hello world!')" + # button_to_function "Delete", "if confirm('Really?'){ do_delete(); }") + def button_to_function(name, function, html_options = {}) + html_options.symbolize_keys! + tag(:input, html_options.merge({ + :type => "button", :value => name, + :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" + })) + end + + # Includes the Action Pack JavaScript libraries inside a single <script> + # tag. The function first includes prototype.js and then its core extensions, + # (determined by filenames starting with "prototype"). + # Afterwards, any additional scripts will be included in undefined order. + # + # Note: The recommended approach is to copy the contents of + # lib/action_view/helpers/javascripts/ into your application's + # public/javascripts/ directory, and use +javascript_include_tag+ to + # create remote <script> links. + def define_javascript_functions + javascript = '<script type="text/javascript">' + + # load prototype.js and its extensions first + prototype_libs = Dir.glob(File.join(JAVASCRIPT_PATH, 'prototype*')).sort.reverse + prototype_libs.each do |filename| + javascript << "\n" << IO.read(filename) + end + + # load other librairies + (Dir.glob(File.join(JAVASCRIPT_PATH, '*')) - prototype_libs).each do |filename| + javascript << "\n" << IO.read(filename) + end + javascript << '</script>' + end + + # Escape carrier returns and single and double quotes for JavaScript segments. + def escape_javascript(javascript) + (javascript || '').gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" } + end + + # Returns a JavaScript tag with the +content+ inside. Example: + # javascript_tag "alert('All is good')" # => <script type="text/javascript">alert('All is good')</script> + def javascript_tag(content) + content_tag("script", javascript_cdata_section(content), :type => "text/javascript") + end + + def javascript_cdata_section(content) #:nodoc: + "\n//#{cdata_section("\n#{content}\n//")}\n" + end + + protected + def options_for_javascript(options) + '{' + options.map {|k, v| "#{k}:#{v}"}.sort.join(', ') + '}' + end + + def array_or_string_for_javascript(option) + js_option = if option.kind_of?(Array) + "['#{option.join('\',\'')}']" + elsif !option.nil? + "'#{option}'" + end + js_option + end + end + + JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper + end +end +module ActionView + module Helpers + # Provides methods for converting a number into a formatted string that currently represents + # one of the following forms: phone number, percentage, money, or precision level. + module NumberHelper + + # Formats a +number+ into a US phone number string. The +options+ can be a hash used to customize the format of the output. + # The area code can be surrounded by parentheses by setting +:area_code+ to true; default is false + # The delimiter can be set using +:delimiter+; default is "-" + # Examples: + # number_to_phone(1235551234) => 123-555-1234 + # number_to_phone(1235551234, {:area_code => true}) => (123) 555-1234 + # number_to_phone(1235551234, {:delimiter => " "}) => 123 555 1234 + # number_to_phone(1235551234, {:area_code => true, :extension => 555}) => (123) 555-1234 x 555 + def number_to_phone(number, options = {}) + options = options.stringify_keys + area_code = options.delete("area_code") { false } + delimiter = options.delete("delimiter") { "-" } + extension = options.delete("extension") { "" } + begin + str = area_code == true ? number.to_s.gsub(/([0-9]{3})([0-9]{3})([0-9]{4})/,"(\\1) \\2#{delimiter}\\3") : number.to_s.gsub(/([0-9]{3})([0-9]{3})([0-9]{4})/,"\\1#{delimiter}\\2#{delimiter}\\3") + extension.to_s.strip.empty? ? str : "#{str} x #{extension.to_s.strip}" + rescue + number + end + end + + # Formats a +number+ into a currency string. The +options+ hash can be used to customize the format of the output. + # The +number+ can contain a level of precision using the +precision+ key; default is 2 + # The currency type can be set using the +unit+ key; default is "$" + # The unit separator can be set using the +separator+ key; default is "." + # The delimiter can be set using the +delimiter+ key; default is "," + # Examples: + # number_to_currency(1234567890.50) => $1,234,567,890.50 + # number_to_currency(1234567890.506) => $1,234,567,890.51 + # number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""}) => £1234567890,50 + def number_to_currency(number, options = {}) + options = options.stringify_keys + precision, unit, separator, delimiter = options.delete("precision") { 2 }, options.delete("unit") { "$" }, options.delete("separator") { "." }, options.delete("delimiter") { "," } + separator = "" unless precision > 0 + begin + parts = number_with_precision(number, precision).split('.') + unit + number_with_delimiter(parts[0], delimiter) + separator + parts[1].to_s + rescue + number + end + end + + # Formats a +number+ as into a percentage string. The +options+ hash can be used to customize the format of the output. + # The +number+ can contain a level of precision using the +precision+ key; default is 3 + # The unit separator can be set using the +separator+ key; default is "." + # Examples: + # number_to_percentage(100) => 100.000% + # number_to_percentage(100, {:precision => 0}) => 100% + # number_to_percentage(302.0574, {:precision => 2}) => 302.06% + def number_to_percentage(number, options = {}) + options = options.stringify_keys + precision, separator = options.delete("precision") { 3 }, options.delete("separator") { "." } + begin + number = number_with_precision(number, precision) + parts = number.split('.') + if parts.at(1).nil? + parts[0] + "%" + else + parts[0] + separator + parts[1].to_s + "%" + end + rescue + number + end + end + + # Formats a +number+ with a +delimiter+. + # Example: + # number_with_delimiter(12345678) => 12,345,678 + def number_with_delimiter(number, delimiter=",") + number.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}") + end + + # Returns a formatted-for-humans file size. + # + # Examples: + # human_size(123) => 123 Bytes + # human_size(1234) => 1.2 KB + # human_size(12345) => 12.1 KB + # human_size(1234567) => 1.2 MB + # human_size(1234567890) => 1.1 GB + def number_to_human_size(size) + case + when size < 1.kilobyte: '%d Bytes' % size + when size < 1.megabyte: '%.1f KB' % (size / 1.0.kilobyte) + when size < 1.gigabyte: '%.1f MB' % (size / 1.0.megabyte) + when size < 1.terabyte: '%.1f GB' % (size / 1.0.gigabyte) + else '%.1f TB' % (size / 1.0.terabyte) + end.sub('.0', '') + rescue + nil + end + + alias_method :human_size, :number_to_human_size # deprecated alias + + # Formats a +number+ with a level of +precision+. + # Example: + # number_with_precision(111.2345) => 111.235 + def number_with_precision(number, precision=3) + sprintf("%01.#{precision}f", number) + end + end + end +end +module ActionView + module Helpers + # Provides methods for linking to ActionController::Pagination objects. + # + # You can also build your links manually, like in this example: + # + # <%= link_to "Previous page", { :page => paginator.current.previous } if paginator.current.previous %> + # + # <%= link_to "Next page", { :page => paginator.current.next } if paginator.current.next %> + module PaginationHelper + unless const_defined?(:DEFAULT_OPTIONS) + DEFAULT_OPTIONS = { + :name => :page, + :window_size => 2, + :always_show_anchors => true, + :link_to_current_page => false, + :params => {} + } + end + + # Creates a basic HTML link bar for the given +paginator+. + # +html_options+ are passed to +link_to+. + # + # +options+ are: + # <tt>:name</tt>:: the routing name for this paginator + # (defaults to +page+) + # <tt>:window_size</tt>:: the number of pages to show around + # the current page (defaults to +2+) + # <tt>:always_show_anchors</tt>:: whether or not the first and last + # pages should always be shown + # (defaults to +true+) + # <tt>:link_to_current_page</tt>:: whether or not the current page + # should be linked to (defaults to + # +false+) + # <tt>:params</tt>:: any additional routing parameters + # for page URLs + def pagination_links(paginator, options={}, html_options={}) + name = options[:name] || DEFAULT_OPTIONS[:name] + params = (options[:params] || DEFAULT_OPTIONS[:params]).clone + + pagination_links_each(paginator, options) do |n| + params[name] = n + link_to(n.to_s, params, html_options) + end + end + + # Iterate through the pages of a given +paginator+, invoking a + # block for each page number that needs to be rendered as a link. + def pagination_links_each(paginator, options) + options = DEFAULT_OPTIONS.merge(options) + link_to_current_page = options[:link_to_current_page] + always_show_anchors = options[:always_show_anchors] + + current_page = paginator.current_page + window_pages = current_page.window(options[:window_size]).pages + return if window_pages.length <= 1 unless link_to_current_page + + first, last = paginator.first, paginator.last + + html = '' + if always_show_anchors and not (wp_first = window_pages[0]).first? + html << yield(first.number) + html << ' ... ' if wp_first.number - first.number > 1 + html << ' ' + end + + window_pages.each do |page| + if current_page == page && !link_to_current_page + html << page.number.to_s + else + html << yield(page.number) + end + html << ' ' + end + + if always_show_anchors and not (wp_last = window_pages[-1]).last? + html << ' ... ' if last.number - wp_last.number > 1 + html << yield(last.number) + end + + html + end + + end # PaginationHelper + end # Helpers +end # ActionView +require File.dirname(__FILE__) + '/javascript_helper' +require 'set' + +module ActionView + module Helpers + # Provides a set of helpers for calling Prototype JavaScript functions, + # including functionality to call remote methods using + # Ajax[http://www.adaptivepath.com/publications/essays/archives/000385.php]. + # This means that you can call actions in your controllers without + # reloading the page, but still update certain parts of it using + # injections into the DOM. The common use case is having a form that adds + # a new element to a list without reloading the page. + # + # To be able to use these helpers, you must include the Prototype + # JavaScript framework in your pages. See the documentation for + # ActionView::Helpers::JavaScriptHelper for more information on including + # the necessary JavaScript. + # + # See link_to_remote for documentation of options common to all Ajax + # helpers. + # + # See also ActionView::Helpers::ScriptaculousHelper for helpers which work + # with the Scriptaculous controls and visual effects library. + # + # See JavaScriptGenerator for information on updating multiple elements + # on the page in an Ajax response. + module PrototypeHelper + unless const_defined? :CALLBACKS + CALLBACKS = Set.new([ :uninitialized, :loading, :loaded, + :interactive, :complete, :failure, :success ] + + (100..599).to_a) + AJAX_OPTIONS = Set.new([ :before, :after, :condition, :url, + :asynchronous, :method, :insertion, :position, + :form, :with, :update, :script ]).merge(CALLBACKS) + end + + # Returns a link to a remote action defined by <tt>options[:url]</tt> + # (using the url_for format) that's called in the background using + # XMLHttpRequest. The result of that request can then be inserted into a + # DOM object whose id can be specified with <tt>options[:update]</tt>. + # Usually, the result would be a partial prepared by the controller with + # either render_partial or render_partial_collection. + # + # Examples: + # link_to_remote "Delete this post", :update => "posts", + # :url => { :action => "destroy", :id => post.id } + # link_to_remote(image_tag("refresh"), :update => "emails", + # :url => { :action => "list_emails" }) + # + # You can also specify a hash for <tt>options[:update]</tt> to allow for + # easy redirection of output to an other DOM element if a server-side + # error occurs: + # + # Example: + # link_to_remote "Delete this post", + # :url => { :action => "destroy", :id => post.id }, + # :update => { :success => "posts", :failure => "error" } + # + # Optionally, you can use the <tt>options[:position]</tt> parameter to + # influence how the target DOM element is updated. It must be one of + # <tt>:before</tt>, <tt>:top</tt>, <tt>:bottom</tt>, or <tt>:after</tt>. + # + # By default, these remote requests are processed asynchronous during + # which various JavaScript callbacks can be triggered (for progress + # indicators and the likes). All callbacks get access to the + # <tt>request</tt> object, which holds the underlying XMLHttpRequest. + # + # To access the server response, use <tt>request.responseText</tt>, to + # find out the HTTP status, use <tt>request.status</tt>. + # + # Example: + # link_to_remote word, + # :url => { :action => "undo", :n => word_counter }, + # :complete => "undoRequestCompleted(request)" + # + # The callbacks that may be specified are (in order): + # + # <tt>:loading</tt>:: Called when the remote document is being + # loaded with data by the browser. + # <tt>:loaded</tt>:: Called when the browser has finished loading + # the remote document. + # <tt>:interactive</tt>:: Called when the user can interact with the + # remote document, even though it has not + # finished loading. + # <tt>:success</tt>:: Called when the XMLHttpRequest is completed, + # and the HTTP status code is in the 2XX range. + # <tt>:failure</tt>:: Called when the XMLHttpRequest is completed, + # and the HTTP status code is not in the 2XX + # range. + # <tt>:complete</tt>:: Called when the XMLHttpRequest is complete + # (fires after success/failure if they are + # present). + # + # You can further refine <tt>:success</tt> and <tt>:failure</tt> by + # adding additional callbacks for specific status codes. + # + # Example: + # link_to_remote word, + # :url => { :action => "action" }, + # 404 => "alert('Not found...? Wrong URL...?')", + # :failure => "alert('HTTP Error ' + request.status + '!')" + # + # A status code callback overrides the success/failure handlers if + # present. + # + # If you for some reason or another need synchronous processing (that'll + # block the browser while the request is happening), you can specify + # <tt>options[:type] = :synchronous</tt>. + # + # You can customize further browser side call logic by passing in + # JavaScript code snippets via some optional parameters. In their order + # of use these are: + # + # <tt>:confirm</tt>:: Adds confirmation dialog. + # <tt>:condition</tt>:: Perform remote request conditionally + # by this expression. Use this to + # describe browser-side conditions when + # request should not be initiated. + # <tt>:before</tt>:: Called before request is initiated. + # <tt>:after</tt>:: Called immediately after request was + # initiated and before <tt>:loading</tt>. + # <tt>:submit</tt>:: Specifies the DOM element ID that's used + # as the parent of the form elements. By + # default this is the current form, but + # it could just as well be the ID of a + # table row or any other DOM element. + def link_to_remote(name, options = {}, html_options = {}) + link_to_function(name, remote_function(options), html_options) + end + + # Periodically calls the specified url (<tt>options[:url]</tt>) every + # <tt>options[:frequency]</tt> seconds (default is 10). Usually used to + # update a specified div (<tt>options[:update]</tt>) with the results + # of the remote call. The options for specifying the target with :url + # and defining callbacks is the same as link_to_remote. + def periodically_call_remote(options = {}) + frequency = options[:frequency] || 10 # every ten seconds by default + code = "new PeriodicalExecuter(function() {#{remote_function(options)}}, #{frequency})" + javascript_tag(code) + end + + # Returns a form tag that will submit using XMLHttpRequest in the + # background instead of the regular reloading POST arrangement. Even + # though it's using JavaScript to serialize the form elements, the form + # submission will work just like a regular submission as viewed by the + # receiving side (all elements available in <tt>params</tt>). The options for + # specifying the target with :url and defining callbacks is the same as + # link_to_remote. + # + # A "fall-through" target for browsers that doesn't do JavaScript can be + # specified with the :action/:method options on :html. + # + # Example: + # form_remote_tag :html => { :action => + # url_for(:controller => "some", :action => "place") } + # + # The Hash passed to the :html key is equivalent to the options (2nd) + # argument in the FormTagHelper.form_tag method. + # + # By default the fall-through action is the same as the one specified in + # the :url (and the default method is :post). + def form_remote_tag(options = {}) + options[:form] = true + + options[:html] ||= {} + options[:html][:onsubmit] = "#{remote_function(options)}; return false;" + options[:html][:action] = options[:html][:action] || url_for(options[:url]) + options[:html][:method] = options[:html][:method] || "post" + + tag("form", options[:html], true) + end + + # Works like form_remote_tag, but uses form_for semantics. + def remote_form_for(object_name, *args, &proc) + options = args.last.is_a?(Hash) ? args.pop : {} + concat(form_remote_tag(options), proc.binding) + fields_for(object_name, *(args << options), &proc) + concat('</form>', proc.binding) + end + alias_method :form_remote_for, :remote_form_for + + # Returns a button input tag that will submit form using XMLHttpRequest + # in the background instead of regular reloading POST arrangement. + # <tt>options</tt> argument is the same as in <tt>form_remote_tag</tt>. + def submit_to_remote(name, value, options = {}) + options[:with] ||= 'Form.serialize(this.form)' + + options[:html] ||= {} + options[:html][:type] = 'button' + options[:html][:onclick] = "#{remote_function(options)}; return false;" + options[:html][:name] = name + options[:html][:value] = value + + tag("input", options[:html], false) + end + + # Returns a JavaScript function (or expression) that'll update a DOM + # element according to the options passed. + # + # * <tt>:content</tt>: The content to use for updating. Can be left out + # if using block, see example. + # * <tt>:action</tt>: Valid options are :update (assumed by default), + # :empty, :remove + # * <tt>:position</tt> If the :action is :update, you can optionally + # specify one of the following positions: :before, :top, :bottom, + # :after. + # + # Examples: + # <%= javascript_tag(update_element_function("products", + # :position => :bottom, :content => "<p>New product!</p>")) %> + # + # <% replacement_function = update_element_function("products") do %> + # <p>Product 1</p> + # <p>Product 2</p> + # <% end %> + # <%= javascript_tag(replacement_function) %> + # + # This method can also be used in combination with remote method call + # where the result is evaluated afterwards to cause multiple updates on + # a page. Example: + # + # # Calling view + # <%= form_remote_tag :url => { :action => "buy" }, + # :complete => evaluate_remote_response %> + # all the inputs here... + # + # # Controller action + # def buy + # @product = Product.find(1) + # end + # + # # Returning view + # <%= update_element_function( + # "cart", :action => :update, :position => :bottom, + # :content => "<p>New Product: #{@product.name}</p>")) %> + # <% update_element_function("status", :binding => binding) do %> + # You've bought a new product! + # <% end %> + # + # Notice how the second call doesn't need to be in an ERb output block + # since it uses a block and passes in the binding to render directly. + # This trick will however only work in ERb (not Builder or other + # template forms). + # + # See also JavaScriptGenerator and update_page. + def update_element_function(element_id, options = {}, &block) + content = escape_javascript(options[:content] || '') + content = escape_javascript(capture(&block)) if block + + javascript_function = case (options[:action] || :update) + when :update + if options[:position] + "new Insertion.#{options[:position].to_s.camelize}('#{element_id}','#{content}')" + else + "$('#{element_id}').innerHTML = '#{content}'" + end + + when :empty + "$('#{element_id}').innerHTML = ''" + + when :remove + "Element.remove('#{element_id}')" + + else + raise ArgumentError, "Invalid action, choose one of :update, :remove, :empty" + end + + javascript_function << ";\n" + options[:binding] ? concat(javascript_function, options[:binding]) : javascript_function + end + + # Returns 'eval(request.responseText)' which is the JavaScript function + # that form_remote_tag can call in :complete to evaluate a multiple + # update return document using update_element_function calls. + def evaluate_remote_response + "eval(request.responseText)" + end + + # Returns the JavaScript needed for a remote function. + # Takes the same arguments as link_to_remote. + # + # Example: + # <select id="options" onchange="<%= remote_function(:update => "options", + # :url => { :action => :update_options }) %>"> + # <option value="0">Hello</option> + # <option value="1">World</option> + # </select> + def remote_function(options) + javascript_options = options_for_ajax(options) + + update = '' + if options[:update] and options[:update].is_a?Hash + update = [] + update << "success:'#{options[:update][:success]}'" if options[:update][:success] + update << "failure:'#{options[:update][:failure]}'" if options[:update][:failure] + update = '{' + update.join(',') + '}' + elsif options[:update] + update << "'#{options[:update]}'" + end + + function = update.empty? ? + "new Ajax.Request(" : + "new Ajax.Updater(#{update}, " + + url_options = options[:url] + url_options = url_options.merge(:escape => false) if url_options.is_a? Hash + function << "'#{url_for(url_options)}'" + function << ", #{javascript_options})" + + function = "#{options[:before]}; #{function}" if options[:before] + function = "#{function}; #{options[:after]}" if options[:after] + function = "if (#{options[:condition]}) { #{function}; }" if options[:condition] + function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm] + + return function + end + + # Observes the field with the DOM ID specified by +field_id+ and makes + # an Ajax call when its contents have changed. + # + # Required +options+ are either of: + # <tt>:url</tt>:: +url_for+-style options for the action to call + # when the field has changed. + # <tt>:function</tt>:: Instead of making a remote call to a URL, you + # can specify a function to be called instead. + # + # Additional options are: + # <tt>:frequency</tt>:: The frequency (in seconds) at which changes to + # this field will be detected. Not setting this + # option at all or to a value equal to or less than + # zero will use event based observation instead of + # time based observation. + # <tt>:update</tt>:: Specifies the DOM ID of the element whose + # innerHTML should be updated with the + # XMLHttpRequest response text. + # <tt>:with</tt>:: A JavaScript expression specifying the + # parameters for the XMLHttpRequest. This defaults + # to 'value', which in the evaluated context + # refers to the new field value. If you specify a + # string without a "=", it'll be extended to mean + # the form key that the value should be assigned to. + # So :with => "term" gives "'term'=value". If a "=" is + # present, no extension will happen. + # <tt>:on</tt>:: Specifies which event handler to observe. By default, + # it's set to "changed" for text fields and areas and + # "click" for radio buttons and checkboxes. With this, + # you can specify it instead to be "blur" or "focus" or + # any other event. + # + # Additionally, you may specify any of the options documented in + # link_to_remote. + def observe_field(field_id, options = {}) + if options[:frequency] && options[:frequency] > 0 + build_observer('Form.Element.Observer', field_id, options) + else + build_observer('Form.Element.EventObserver', field_id, options) + end + end + + # Like +observe_field+, but operates on an entire form identified by the + # DOM ID +form_id+. +options+ are the same as +observe_field+, except + # the default value of the <tt>:with</tt> option evaluates to the + # serialized (request string) value of the form. + def observe_form(form_id, options = {}) + if options[:frequency] + build_observer('Form.Observer', form_id, options) + else + build_observer('Form.EventObserver', form_id, options) + end + end + + # All the methods were moved to GeneratorMethods so that + # #include_helpers_from_context has nothing to overwrite. + class JavaScriptGenerator #:nodoc: + def initialize(context, &block) #:nodoc: + @context, @lines = context, [] + include_helpers_from_context + @context.instance_exec(self, &block) + end + + private + def include_helpers_from_context + @context.extended_by.each do |mod| + extend mod unless mod.name =~ /^ActionView::Helpers/ + end + extend GeneratorMethods + end + + # JavaScriptGenerator generates blocks of JavaScript code that allow you + # to change the content and presentation of multiple DOM elements. Use + # this in your Ajax response bodies, either in a <script> tag or as plain + # JavaScript sent with a Content-type of "text/javascript". + # + # Create new instances with PrototypeHelper#update_page or with + # ActionController::Base#render, then call #insert_html, #replace_html, + # #remove, #show, #hide, #visual_effect, or any other of the built-in + # methods on the yielded generator in any order you like to modify the + # content and appearance of the current page. + # + # Example: + # + # update_page do |page| + # page.insert_html :bottom, 'list', "<li>#{@item.name}</li>" + # page.visual_effect :highlight, 'list' + # page.hide 'status-indicator', 'cancel-link' + # end + # + # generates the following JavaScript: + # + # new Insertion.Bottom("list", "<li>Some item</li>"); + # new Effect.Highlight("list"); + # ["status-indicator", "cancel-link"].each(Element.hide); + # + # Helper methods can be used in conjunction with JavaScriptGenerator. + # When a helper method is called inside an update block on the +page+ + # object, that method will also have access to a +page+ object. + # + # Example: + # + # module ApplicationHelper + # def update_time + # page.replace_html 'time', Time.now.to_s(:db) + # page.visual_effect :highlight, 'time' + # end + # end + # + # # Controller action + # def poll + # render(:update) { |page| page.update_time } + # end + # + # You can also use PrototypeHelper#update_page_tag instead of + # PrototypeHelper#update_page to wrap the generated JavaScript in a + # <script> tag. + module GeneratorMethods + def to_s #:nodoc: + returning javascript = @lines * $/ do + if ActionView::Base.debug_rjs + source = javascript.dup + javascript.replace "try {\n#{source}\n} catch (e) " + javascript << "{ alert('RJS error:\\n\\n' + e.toString()); alert('#{source.gsub(/\r\n|\n|\r/, "\\n").gsub(/["']/) { |m| "\\#{m}" }}'); throw e }" + end + end + end + + # Returns a element reference by finding it through +id+ in the DOM. This element can then be + # used for further method calls. Examples: + # + # page['blank_slate'] # => $('blank_slate'); + # page['blank_slate'].show # => $('blank_slate').show(); + # page['blank_slate'].show('first').up # => $('blank_slate').show('first').up(); + def [](id) + JavaScriptElementProxy.new(self, id) + end + + # Returns a collection reference by finding it through a CSS +pattern+ in the DOM. This collection can then be + # used for further method calls. Examples: + # + # page.select('p') # => $$('p'); + # page.select('p.welcome b').first # => $$('p.welcome b').first(); + # page.select('p.welcome b').first.hide # => $$('p.welcome b').first().hide(); + # + # You can also use prototype enumerations with the collection. Observe: + # + # page.select('#items li').each do |value| + # value.hide + # end + # # => $$('#items li').each(function(value) { value.hide(); }); + # + # Though you can call the block param anything you want, they are always rendered in the + # javascript as 'value, index.' Other enumerations, like collect() return the last statement: + # + # page.select('#items li').collect('hidden') do |item| + # item.hide + # end + # # => var hidden = $$('#items li').collect(function(value, index) { return value.hide(); }); + def select(pattern) + JavaScriptElementCollectionProxy.new(self, pattern) + end + + # Inserts HTML at the specified +position+ relative to the DOM element + # identified by the given +id+. + # + # +position+ may be one of: + # + # <tt>:top</tt>:: HTML is inserted inside the element, before the + # element's existing content. + # <tt>:bottom</tt>:: HTML is inserted inside the element, after the + # element's existing content. + # <tt>:before</tt>:: HTML is inserted immediately preceeding the element. + # <tt>:after</tt>:: HTML is inserted immediately following the element. + # + # +options_for_render+ may be either a string of HTML to insert, or a hash + # of options to be passed to ActionView::Base#render. For example: + # + # # Insert the rendered 'navigation' partial just before the DOM + # # element with ID 'content'. + # insert_html :before, 'content', :partial => 'navigation' + # + # # Add a list item to the bottom of the <ul> with ID 'list'. + # insert_html :bottom, 'list', '<li>Last item</li>' + # + def insert_html(position, id, *options_for_render) + insertion = position.to_s.camelize + call "new Insertion.#{insertion}", id, render(*options_for_render) + end + + # Replaces the inner HTML of the DOM element with the given +id+. + # + # +options_for_render+ may be either a string of HTML to insert, or a hash + # of options to be passed to ActionView::Base#render. For example: + # + # # Replace the HTML of the DOM element having ID 'person-45' with the + # # 'person' partial for the appropriate object. + # replace_html 'person-45', :partial => 'person', :object => @person + # + def replace_html(id, *options_for_render) + call 'Element.update', id, render(*options_for_render) + end + + # Replaces the "outer HTML" (i.e., the entire element, not just its + # contents) of the DOM element with the given +id+. + # + # +options_for_render+ may be either a string of HTML to insert, or a hash + # of options to be passed to ActionView::Base#render. For example: + # + # # Replace the DOM element having ID 'person-45' with the + # # 'person' partial for the appropriate object. + # replace_html 'person-45', :partial => 'person', :object => @person + # + # This allows the same partial that is used for the +insert_html+ to + # be also used for the input to +replace+ without resorting to + # the use of wrapper elements. + # + # Examples: + # + # <div id="people"> + # <%= render :partial => 'person', :collection => @people %> + # </div> + # + # # Insert a new person + # page.insert_html :bottom, :partial => 'person', :object => @person + # + # # Replace an existing person + # page.replace 'person_45', :partial => 'person', :object => @person + # + def replace(id, *options_for_render) + call 'Element.replace', id, render(*options_for_render) + end + + # Removes the DOM elements with the given +ids+ from the page. + def remove(*ids) + record "#{javascript_object_for(ids)}.each(Element.remove)" + end + + # Shows hidden DOM elements with the given +ids+. + def show(*ids) + call 'Element.show', *ids + end + + # Hides the visible DOM elements with the given +ids+. + def hide(*ids) + call 'Element.hide', *ids + end + + # Toggles the visibility of the DOM elements with the given +ids+. + def toggle(*ids) + call 'Element.toggle', *ids + end + + # Displays an alert dialog with the given +message+. + def alert(message) + call 'alert', message + end + + # Redirects the browser to the given +location+, in the same form as + # +url_for+. + def redirect_to(location) + assign 'window.location.href', @context.url_for(location) + end + + # Calls the JavaScript +function+, optionally with the given + # +arguments+. + def call(function, *arguments) + record "#{function}(#{arguments_for_call(arguments)})" + end + + # Assigns the JavaScript +variable+ the given +value+. + def assign(variable, value) + record "#{variable} = #{javascript_object_for(value)}" + end + + # Writes raw JavaScript to the page. + def <<(javascript) + @lines << javascript + end + + # Executes the content of the block after a delay of +seconds+. Example: + # + # page.delay(20) do + # page.visual_effect :fade, 'notice' + # end + def delay(seconds = 1) + record "setTimeout(function() {\n\n" + yield + record "}, #{(seconds * 1000).to_i})" + end + + # Starts a script.aculo.us visual effect. See + # ActionView::Helpers::ScriptaculousHelper for more information. + def visual_effect(name, id = nil, options = {}) + record @context.send(:visual_effect, name, id, options) + end + + # Creates a script.aculo.us sortable element. Useful + # to recreate sortable elements after items get added + # or deleted. + # See ActionView::Helpers::ScriptaculousHelper for more information. + def sortable(id, options = {}) + record @context.send(:sortable_element_js, id, options) + end + + # Creates a script.aculo.us draggable element. + # See ActionView::Helpers::ScriptaculousHelper for more information. + def draggable(id, options = {}) + record @context.send(:draggable_element_js, id, options) + end + + # Creates a script.aculo.us drop receiving element. + # See ActionView::Helpers::ScriptaculousHelper for more information. + def drop_receiving(id, options = {}) + record @context.send(:drop_receiving_element_js, id, options) + end + + private + def page + self + end + + def record(line) + returning line = "#{line.to_s.chomp.gsub /\;$/, ''};" do + self << line + end + end + + def render(*options_for_render) + Hash === options_for_render.first ? + @context.render(*options_for_render) : + options_for_render.first.to_s + end + + def javascript_object_for(object) + object.respond_to?(:to_json) ? object.to_json : object.inspect + end + + def arguments_for_call(arguments) + arguments.map { |argument| javascript_object_for(argument) }.join ', ' + end + + def method_missing(method, *arguments) + JavaScriptProxy.new(self, method.to_s.camelize) + end + end + end + + # Yields a JavaScriptGenerator and returns the generated JavaScript code. + # Use this to update multiple elements on a page in an Ajax response. + # See JavaScriptGenerator for more information. + def update_page(&block) + JavaScriptGenerator.new(@template, &block).to_s + end + + # Works like update_page but wraps the generated JavaScript in a <script> + # tag. Use this to include generated JavaScript in an ERb template. + # See JavaScriptGenerator for more information. + def update_page_tag(&block) + javascript_tag update_page(&block) + end + + protected + def options_for_ajax(options) + js_options = build_callbacks(options) + + js_options['asynchronous'] = options[:type] != :synchronous + js_options['method'] = method_option_to_s(options[:method]) if options[:method] + js_options['insertion'] = "Insertion.#{options[:position].to_s.camelize}" if options[:position] + js_options['evalScripts'] = options[:script].nil? || options[:script] + + if options[:form] + js_options['parameters'] = 'Form.serialize(this)' + elsif options[:submit] + js_options['parameters'] = "Form.serialize('#{options[:submit]}')" + elsif options[:with] + js_options['parameters'] = options[:with] + end + + options_for_javascript(js_options) + end + + def method_option_to_s(method) + (method.is_a?(String) and !method.index("'").nil?) ? method : "'#{method}'" + end + + def build_observer(klass, name, options = {}) + if options[:with] && !options[:with].include?("=") + options[:with] = "'#{options[:with]}=' + value" + else + options[:with] ||= 'value' if options[:update] + end + + callback = options[:function] || remote_function(options) + javascript = "new #{klass}('#{name}', " + javascript << "#{options[:frequency]}, " if options[:frequency] + javascript << "function(element, value) {" + javascript << "#{callback}}" + javascript << ", '#{options[:on]}'" if options[:on] + javascript << ")" + javascript_tag(javascript) + end + + def build_callbacks(options) + callbacks = {} + options.each do |callback, code| + if CALLBACKS.include?(callback) + name = 'on' + callback.to_s.capitalize + callbacks[name] = "function(request){#{code}}" + end + end + callbacks + end + end + + # Converts chained method calls on DOM proxy elements into JavaScript chains + class JavaScriptProxy < Builder::BlankSlate #:nodoc: + def initialize(generator, root = nil) + @generator = generator + @generator << root if root + end + + private + def method_missing(method, *arguments) + if method.to_s =~ /(.*)=$/ + assign($1, arguments.first) + else + call("#{method.to_s.camelize(:lower)}", *arguments) + end + end + + def call(function, *arguments) + append_to_function_chain!("#{function}(#{@generator.send(:arguments_for_call, arguments)})") + self + end + + def assign(variable, value) + append_to_function_chain!("#{variable} = #{@generator.send(:javascript_object_for, value)}") + end + + def function_chain + @function_chain ||= @generator.instance_variable_get("@lines") + end + + def append_to_function_chain!(call) + function_chain[-1].chomp!(';') + function_chain[-1] += ".#{call};" + end + end + + class JavaScriptElementProxy < JavaScriptProxy #:nodoc: + def initialize(generator, id) + @id = id + super(generator, "$(#{id.to_json})") + end + + def replace_html(*options_for_render) + call 'update', @generator.send(:render, *options_for_render) + end + + def replace(*options_for_render) + call 'replace', @generator.send(:render, *options_for_render) + end + + def reload + replace :partial => @id.to_s + end + + end + + class JavaScriptVariableProxy < JavaScriptProxy #:nodoc: + def initialize(generator, variable) + @variable = variable + @empty = true # only record lines if we have to. gets rid of unnecessary linebreaks + super(generator) + end + + # The JSON Encoder calls this to check for the #to_json method + # Since it's a blank slate object, I suppose it responds to anything. + def respond_to?(method) + true + end + + def to_json + @variable + end + + private + def append_to_function_chain!(call) + @generator << @variable if @empty + @empty = false + super + end + end + + class JavaScriptCollectionProxy < JavaScriptProxy #:nodoc: + ENUMERABLE_METHODS_WITH_RETURN = [:all, :any, :collect, :map, :detect, :find, :find_all, :select, :max, :min, :partition, :reject, :sort_by] + ENUMERABLE_METHODS = ENUMERABLE_METHODS_WITH_RETURN + [:each] + attr_reader :generator + delegate :arguments_for_call, :to => :generator + + def initialize(generator, pattern) + super(generator, @pattern = pattern) + end + + def grep(variable, pattern, &block) + enumerate :grep, :variable => variable, :return => true, :method_args => [pattern], :yield_args => %w(value index), &block + end + + def inject(variable, memo, &block) + enumerate :inject, :variable => variable, :method_args => [memo], :yield_args => %w(memo value index), :return => true, &block + end + + def pluck(variable, property) + add_variable_assignment!(variable) + append_enumerable_function!("pluck(#{property.to_json});") + end + + def zip(variable, *arguments, &block) + add_variable_assignment!(variable) + append_enumerable_function!("zip(#{arguments_for_call arguments}") + if block + function_chain[-1] += ", function(array) {" + yield ActiveSupport::JSON::Variable.new('array') + add_return_statement! + @generator << '});' + else + function_chain[-1] += ');' + end + end + + private + def method_missing(method, *arguments, &block) + if ENUMERABLE_METHODS.include?(method) + returnable = ENUMERABLE_METHODS_WITH_RETURN.include?(method) + variable = arguments.first if returnable + enumerate(method, {:variable => (arguments.first if returnable), :return => returnable, :yield_args => %w(value index)}, &block) + else + super + end + end + + # Options + # * variable - name of the variable to set the result of the enumeration to + # * method_args - array of the javascript enumeration method args that occur before the function + # * yield_args - array of the javascript yield args + # * return - true if the enumeration should return the last statement + def enumerate(enumerable, options = {}, &block) + options[:method_args] ||= [] + options[:yield_args] ||= [] + yield_args = options[:yield_args] * ', ' + method_args = arguments_for_call options[:method_args] # foo, bar, function + method_args << ', ' unless method_args.blank? + add_variable_assignment!(options[:variable]) if options[:variable] + append_enumerable_function!("#{enumerable.to_s.camelize(:lower)}(#{method_args}function(#{yield_args}) {") + # only yield as many params as were passed in the block + yield *options[:yield_args].collect { |p| JavaScriptVariableProxy.new(@generator, p) }[0..block.arity-1] + add_return_statement! if options[:return] + @generator << '});' + end + + def add_variable_assignment!(variable) + function_chain.push("var #{variable} = #{function_chain.pop}") + end + + def add_return_statement! + unless function_chain.last =~ /return/ + function_chain.push("return #{function_chain.pop.chomp(';')};") + end + end + + def append_enumerable_function!(call) + function_chain[-1].chomp!(';') + function_chain[-1] += ".#{call}" + end + end + + class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\ + def initialize(generator, pattern) + super(generator, "$$(#{pattern.to_json})") + end + end + end +end +require File.dirname(__FILE__) + '/javascript_helper' + +module ActionView + module Helpers + # Provides a set of helpers for calling Scriptaculous JavaScript + # functions, including those which create Ajax controls and visual effects. + # + # To be able to use these helpers, you must include the Prototype + # JavaScript framework and the Scriptaculous JavaScript library in your + # pages. See the documentation for ActionView::Helpers::JavaScriptHelper + # for more information on including the necessary JavaScript. + # + # The Scriptaculous helpers' behavior can be tweaked with various options. + # See the documentation at http://script.aculo.us for more information on + # using these helpers in your application. + module ScriptaculousHelper + unless const_defined? :TOGGLE_EFFECTS + TOGGLE_EFFECTS = [:toggle_appear, :toggle_slide, :toggle_blind] + end + + # Returns a JavaScript snippet to be used on the Ajax callbacks for + # starting visual effects. + # + # Example: + # <%= link_to_remote "Reload", :update => "posts", + # :url => { :action => "reload" }, + # :complete => visual_effect(:highlight, "posts", :duration => 0.5) + # + # If no element_id is given, it assumes "element" which should be a local + # variable in the generated JavaScript execution context. This can be + # used for example with drop_receiving_element: + # + # <%= drop_receving_element (...), :loading => visual_effect(:fade) %> + # + # This would fade the element that was dropped on the drop receiving + # element. + # + # For toggling visual effects, you can use :toggle_appear, :toggle_slide, and + # :toggle_blind which will alternate between appear/fade, slidedown/slideup, and + # blinddown/blindup respectively. + # + # You can change the behaviour with various options, see + # http://script.aculo.us for more documentation. + def visual_effect(name, element_id = false, js_options = {}) + element = element_id ? element_id.to_json : "element" + + js_options[:queue] = if js_options[:queue].is_a?(Hash) + '{' + js_options[:queue].map {|k, v| k == :limit ? "#{k}:#{v}" : "#{k}:'#{v}'" }.join(',') + '}' + elsif js_options[:queue] + "'#{js_options[:queue]}'" + end if js_options[:queue] + + if TOGGLE_EFFECTS.include? name.to_sym + "Effect.toggle(#{element},'#{name.to_s.gsub(/^toggle_/,'')}',#{options_for_javascript(js_options)});" + else + "new Effect.#{name.to_s.camelize}(#{element},#{options_for_javascript(js_options)});" + end + end + + # Makes the element with the DOM ID specified by +element_id+ sortable + # by drag-and-drop and make an Ajax call whenever the sort order has + # changed. By default, the action called gets the serialized sortable + # element as parameters. + # + # Example: + # <%= sortable_element("my_list", :url => { :action => "order" }) %> + # + # In the example, the action gets a "my_list" array parameter + # containing the values of the ids of elements the sortable consists + # of, in the current order. + # + # You can change the behaviour with various options, see + # http://script.aculo.us for more documentation. + def sortable_element(element_id, options = {}) + javascript_tag(sortable_element_js(element_id, options).chop!) + end + + def sortable_element_js(element_id, options = {}) #:nodoc: + options[:with] ||= "Sortable.serialize(#{element_id.to_json})" + options[:onUpdate] ||= "function(){" + remote_function(options) + "}" + options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) } + + [:tag, :overlap, :constraint, :handle].each do |option| + options[option] = "'#{options[option]}'" if options[option] + end + + options[:containment] = array_or_string_for_javascript(options[:containment]) if options[:containment] + options[:only] = array_or_string_for_javascript(options[:only]) if options[:only] + + %(Sortable.create(#{element_id.to_json}, #{options_for_javascript(options)});) + end + + # Makes the element with the DOM ID specified by +element_id+ draggable. + # + # Example: + # <%= draggable_element("my_image", :revert => true) + # + # You can change the behaviour with various options, see + # http://script.aculo.us for more documentation. + def draggable_element(element_id, options = {}) + javascript_tag(draggable_element_js(element_id, options).chop!) + end + + def draggable_element_js(element_id, options = {}) #:nodoc: + %(new Draggable(#{element_id.to_json}, #{options_for_javascript(options)});) + end + + # Makes the element with the DOM ID specified by +element_id+ receive + # dropped draggable elements (created by draggable_element). + # and make an AJAX call By default, the action called gets the DOM ID + # of the element as parameter. + # + # Example: + # <%= drop_receiving_element("my_cart", :url => + # { :controller => "cart", :action => "add" }) %> + # + # You can change the behaviour with various options, see + # http://script.aculo.us for more documentation. + def drop_receiving_element(element_id, options = {}) + javascript_tag(drop_receiving_element_js(element_id, options).chop!) + end + + def drop_receiving_element_js(element_id, options = {}) #:nodoc: + options[:with] ||= "'id=' + encodeURIComponent(element.id)" + options[:onDrop] ||= "function(element){" + remote_function(options) + "}" + options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) } + + options[:accept] = array_or_string_for_javascript(options[:accept]) if options[:accept] + options[:hoverclass] = "'#{options[:hoverclass]}'" if options[:hoverclass] + + %(Droppables.add(#{element_id.to_json}, #{options_for_javascript(options)});) + end + end + end +end +require 'cgi' +require 'erb' + +module ActionView + module Helpers + # This is poor man's Builder for the rare cases where you need to programmatically make tags but can't use Builder. + module TagHelper + include ERB::Util + + # Examples: + # * <tt>tag("br") => <br /></tt> + # * <tt>tag("input", { "type" => "text"}) => <input type="text" /></tt> + def tag(name, options = nil, open = false) + "<#{name}#{tag_options(options.stringify_keys) if options}" + (open ? ">" : " />") + end + + # Examples: + # * <tt>content_tag("p", "Hello world!") => <p>Hello world!</p></tt> + # * <tt>content_tag("div", content_tag("p", "Hello world!"), "class" => "strong") => </tt> + # <tt><div class="strong"><p>Hello world!</p></div></tt> + def content_tag(name, content, options = nil) + "<#{name}#{tag_options(options.stringify_keys) if options}>#{content}</#{name}>" + end + + # Returns a CDATA section for the given +content+. CDATA sections + # are used to escape blocks of text containing characters which would + # otherwise be recognized as markup. CDATA sections begin with the string + # <tt><![CDATA[</tt> and end with (and may not contain) the string + # <tt>]]></tt>. + def cdata_section(content) + "<![CDATA[#{content}]]>" + end + + private + def tag_options(options) + cleaned_options = convert_booleans(options.stringify_keys.reject {|key, value| value.nil?}) + ' ' + cleaned_options.map {|key, value| %(#{key}="#{html_escape(value.to_s)}")}.sort * ' ' unless cleaned_options.empty? + end + + def convert_booleans(options) + %w( disabled readonly multiple ).each { |a| boolean_attribute(options, a) } + options + end + + def boolean_attribute(options, attribute) + options[attribute] ? options[attribute] = attribute : options.delete(attribute) + end + end + end +end +require File.dirname(__FILE__) + '/tag_helper' + +module ActionView + module Helpers #:nodoc: + # Provides a set of methods for working with text strings that can help unburden the level of inline Ruby code in the + # templates. In the example below we iterate over a collection of posts provided to the template and print each title + # after making sure it doesn't run longer than 20 characters: + # <% for post in @posts %> + # Title: <%= truncate(post.title, 20) %> + # <% end %> + module TextHelper + # The regular puts and print are outlawed in eRuby. It's recommended to use the <%= "hello" %> form instead of print "hello". + # If you absolutely must use a method-based output, you can use concat. It's used like this: <% concat "hello", binding %>. Notice that + # it doesn't have an equal sign in front. Using <%= concat "hello" %> would result in a double hello. + def concat(string, binding) + eval("_erbout", binding).concat(string) + end + + # Truncates +text+ to the length of +length+ and replaces the last three characters with the +truncate_string+ + # if the +text+ is longer than +length+. + def truncate(text, length = 30, truncate_string = "...") + if text.nil? then return end + l = length - truncate_string.length + if $KCODE == "NONE" + text.length > length ? text[0...l] + truncate_string : text + else + chars = text.split(//) + chars.length > length ? chars[0...l].join + truncate_string : text + end + end + + # Highlights the +phrase+ where it is found in the +text+ by surrounding it like + # <strong class="highlight">I'm a highlight phrase</strong>. The highlighter can be specialized by + # passing +highlighter+ as single-quoted string with \1 where the phrase is supposed to be inserted. + # N.B.: The +phrase+ is sanitized to include only letters, digits, and spaces before use. + def highlight(text, phrase, highlighter = '<strong class="highlight">\1</strong>') + if phrase.blank? then return text end + text.gsub(/(#{Regexp.escape(phrase)})/i, highlighter) unless text.nil? + end + + # Extracts an excerpt from the +text+ surrounding the +phrase+ with a number of characters on each side determined + # by +radius+. If the phrase isn't found, nil is returned. Ex: + # excerpt("hello my world", "my", 3) => "...lo my wo..." + def excerpt(text, phrase, radius = 100, excerpt_string = "...") + if text.nil? || phrase.nil? then return end + phrase = Regexp.escape(phrase) + + if found_pos = text =~ /(#{phrase})/i + start_pos = [ found_pos - radius, 0 ].max + end_pos = [ found_pos + phrase.length + radius, text.length ].min + + prefix = start_pos > 0 ? excerpt_string : "" + postfix = end_pos < text.length ? excerpt_string : "" + + prefix + text[start_pos..end_pos].strip + postfix + else + nil + end + end + + # Attempts to pluralize the +singular+ word unless +count+ is 1. See source for pluralization rules. + def pluralize(count, singular, plural = nil) + "#{count} " + if count == 1 + singular + elsif plural + plural + elsif Object.const_defined?("Inflector") + Inflector.pluralize(singular) + else + singular + "s" + end + end + + # Word wrap long lines to line_width. + def word_wrap(text, line_width = 80) + text.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip + end + + begin + require_library_or_gem "redcloth" unless Object.const_defined?(:RedCloth) + + # Returns the text with all the Textile codes turned into HTML-tags. + # <i>This method is only available if RedCloth can be required</i>. + def textilize(text) + if text.blank? + "" + else + textilized = RedCloth.new(text, [ :hard_breaks ]) + textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=") + textilized.to_html + end + end + + # Returns the text with all the Textile codes turned into HTML-tags, but without the regular bounding <p> tag. + # <i>This method is only available if RedCloth can be required</i>. + def textilize_without_paragraph(text) + textiled = textilize(text) + if textiled[0..2] == "<p>" then textiled = textiled[3..-1] end + if textiled[-4..-1] == "</p>" then textiled = textiled[0..-5] end + return textiled + end + rescue LoadError + # We can't really help what's not there + end + + begin + require_library_or_gem "bluecloth" unless Object.const_defined?(:BlueCloth) + + # Returns the text with all the Markdown codes turned into HTML-tags. + # <i>This method is only available if BlueCloth can be required</i>. + def markdown(text) + text.blank? ? "" : BlueCloth.new(text).to_html + end + rescue LoadError + # We can't really help what's not there + end + + # Returns +text+ transformed into HTML using very simple formatting rules + # Surrounds paragraphs with <tt><p></tt> tags, and converts line breaks into <tt><br/></tt> + # Two consecutive newlines(<tt>\n\n</tt>) are considered as a paragraph, one newline (<tt>\n</tt>) is + # considered a linebreak, three or more consecutive newlines are turned into two newlines + def simple_format(text) + text.gsub!(/(\r\n|\n|\r)/, "\n") # lets make them newlines crossplatform + text.gsub!(/\n\n+/, "\n\n") # zap dupes + text.gsub!(/\n\n/, '</p>\0<p>') # turn two newlines into paragraph + text.gsub!(/([^\n])(\n)([^\n])/, '\1\2<br />\3') # turn single newline into <br /> + + content_tag("p", text) + end + + # Turns all urls and email addresses into clickable links. The +link+ parameter can limit what should be linked. + # Options are <tt>:all</tt> (default), <tt>:email_addresses</tt>, and <tt>:urls</tt>. + # + # Example: + # auto_link("Go to http://www.rubyonrails.com and say hello to david@loudthinking.com") => + # Go to <a href="http://www.rubyonrails.com">http://www.rubyonrails.com</a> and + # say hello to <a href="mailto:david@loudthinking.com">david@loudthinking.com</a> + # + # If a block is given, each url and email address is yielded and the + # result is used as the link text. Example: + # auto_link(post.body, :all, :target => '_blank') do |text| + # truncate(text, 15) + # end + def auto_link(text, link = :all, href_options = {}, &block) + return '' if text.blank? + case link + when :all then auto_link_urls(auto_link_email_addresses(text, &block), href_options, &block) + when :email_addresses then auto_link_email_addresses(text, &block) + when :urls then auto_link_urls(text, href_options, &block) + end + end + + # Turns all links into words, like "<a href="something">else</a>" to "else". + def strip_links(text) + text.gsub(/<a.*>(.*)<\/a>/m, '\1') + end + + # Try to require the html-scanner library + begin + require 'html/tokenizer' + require 'html/node' + rescue LoadError + # if there isn't a copy installed, use the vendor version in + # action controller + $:.unshift File.join(File.dirname(__FILE__), "..", "..", + "action_controller", "vendor", "html-scanner") + require 'html/tokenizer' + require 'html/node' + end + + VERBOTEN_TAGS = %w(form script) unless defined?(VERBOTEN_TAGS) + VERBOTEN_ATTRS = /^on/i unless defined?(VERBOTEN_ATTRS) + + # Sanitizes the given HTML by making form and script tags into regular + # text, and removing all "onxxx" attributes (so that arbitrary Javascript + # cannot be executed). Also removes href attributes that start with + # "javascript:". + # + # Returns the sanitized text. + def sanitize(html) + # only do this if absolutely necessary + if html.index("<") + tokenizer = HTML::Tokenizer.new(html) + new_text = "" + + while token = tokenizer.next + node = HTML::Node.parse(nil, 0, 0, token, false) + new_text << case node + when HTML::Tag + if VERBOTEN_TAGS.include?(node.name) + node.to_s.gsub(/</, "<") + else + if node.closing != :close + node.attributes.delete_if { |attr,v| attr =~ VERBOTEN_ATTRS } + if node.attributes["href"] =~ /^javascript:/i + node.attributes.delete "href" + end + end + node.to_s + end + else + node.to_s.gsub(/</, "<") + end + end + + html = new_text + end + + html + end + + # Strips all HTML tags from the input, including comments. This uses the html-scanner + # tokenizer and so it's HTML parsing ability is limited by that of html-scanner. + # + # Returns the tag free text. + def strip_tags(html) + if html.index("<") + text = "" + tokenizer = HTML::Tokenizer.new(html) + + while token = tokenizer.next + node = HTML::Node.parse(nil, 0, 0, token, false) + # result is only the content of any Text nodes + text << node.to_s if node.class == HTML::Text + end + # strip any comments, and if they have a newline at the end (ie. line with + # only a comment) strip that too + text.gsub(/<!--(.*?)-->[\n]?/m, "") + else + html # already plain text + end + end + + # Returns a Cycle object whose to_s value cycles through items of an + # array every time it is called. This can be used to alternate classes + # for table rows: + # + # <%- for item in @items do -%> + # <tr class="<%= cycle("even", "odd") %>"> + # ... use item ... + # </tr> + # <%- end -%> + # + # You can use named cycles to prevent clashes in nested loops. You'll + # have to reset the inner cycle, manually: + # + # <%- for item in @items do -%> + # <tr class="<%= cycle("even", "odd", :name => "row_class") + # <td> + # <%- for value in item.values do -%> + # <span style="color:'<%= cycle("red", "green", "blue" + # :name => "colors") %>'"> + # item + # </span> + # <%- end -%> + # <%- reset_cycle("colors") -%> + # </td> + # </tr> + # <%- end -%> + def cycle(first_value, *values) + if (values.last.instance_of? Hash) + params = values.pop + name = params[:name] + else + name = "default" + end + values.unshift(first_value) + + cycle = get_cycle(name) + if (cycle.nil? || cycle.values != values) + cycle = set_cycle(name, Cycle.new(*values)) + end + return cycle.to_s + end + + # Resets a cycle so that it starts from the first element in the array + # the next time it is used. + def reset_cycle(name = "default") + cycle = get_cycle(name) + return if cycle.nil? + cycle.reset + end + + class Cycle #:nodoc: + attr_reader :values + + def initialize(first_value, *values) + @values = values.unshift(first_value) + reset + end + + def reset + @index = 0 + end + + def to_s + value = @values[@index].to_s + @index = (@index + 1) % @values.size + return value + end + end + + private + # The cycle helpers need to store the cycles in a place that is + # guaranteed to be reset every time a page is rendered, so it + # uses an instance variable of ActionView::Base. + def get_cycle(name) + @_cycles = Hash.new if @_cycles.nil? + return @_cycles[name] + end + + def set_cycle(name, cycle_object) + @_cycles = Hash.new if @_cycles.nil? + @_cycles[name] = cycle_object + end + + AUTO_LINK_RE = / + ( # leading text + <\w+.*?>| # leading HTML tag, or + [^=!:'"\/]| # leading punctuation, or + ^ # beginning of line + ) + ( + (?:http[s]?:\/\/)| # protocol spec, or + (?:www\.) # www.* + ) + ( + ([\w]+:?[=?&\/.-]?)* # url segment + \w+[\/]? # url tail + (?:\#\w*)? # trailing anchor + ) + ([[:punct:]]|\s|<|$) # trailing text + /x unless const_defined?(:AUTO_LINK_RE) + + # Turns all urls into clickable links. If a block is given, each url + # is yielded and the result is used as the link text. Example: + # auto_link_urls(post.body, :all, :target => '_blank') do |text| + # truncate(text, 15) + # end + def auto_link_urls(text, href_options = {}) + extra_options = tag_options(href_options.stringify_keys) || "" + text.gsub(AUTO_LINK_RE) do + all, a, b, c, d = $&, $1, $2, $3, $5 + if a =~ /<a\s/i # don't replace URL's that are already linked + all + else + text = b + c + text = yield(text) if block_given? + %(#{a}<a href="#{b=="www."?"http://www.":b}#{c}"#{extra_options}>#{text}</a>#{d}) + }) + end + end + end + + # Turns all email addresses into clickable links. If a block is given, + # each email is yielded and the result is used as the link text. + # Example: + # auto_link_email_addresses(post.body) do |text| + # truncate(text, 15) + # end + def auto_link_email_addresses(text) + text.gsub(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do + text = $1 + text = yield(text) if block_given? + %{<a href="mailto:#{$1}">#{text}</a>} + end + end + end + end +end +require File.dirname(__FILE__) + '/javascript_helper' + +module ActionView + module Helpers + # Provides a set of methods for making easy links and getting urls that depend on the controller and action. This means that + # you can use the same format for links in the views that you do in the controller. The different methods are even named + # synchronously, so link_to uses that same url as is generated by url_for, which again is the same url used for + # redirection in redirect_to. + module UrlHelper + include JavaScriptHelper + + # Returns the URL for the set of +options+ provided. This takes the same options + # as url_for. For a list, see the documentation for ActionController::Base#url_for. + # Note that it'll set :only_path => true so you'll get /controller/action instead of the + # http://example.com/controller/action part (makes it harder to parse httpd log files) + # + # When called from a view, url_for returns an HTML escaped url. If you need an unescaped + # url, pass :escape => false to url_for. + # + def url_for(options = {}, *parameters_for_method_reference) + if options.kind_of? Hash + options = { :only_path => true }.update(options.symbolize_keys) + escape = options.key?(:escape) ? options.delete(:escape) : true + else + escape = true + end + url = @controller.send(:url_for, options, *parameters_for_method_reference) + escape ? html_escape(url) : url + end + + # Creates a link tag of the given +name+ using an URL created by the set of +options+. See the valid options in + # the documentation for ActionController::Base#url_for. It's also possible to pass a string instead of an options hash to + # get a link tag that just points without consideration. If nil is passed as a name, the link itself will become the name. + # + # The html_options has three special features. One for creating javascript confirm alerts where if you pass :confirm => 'Are you sure?', + # the link will be guarded with a JS popup asking that question. If the user accepts, the link is processed, otherwise not. + # + # Another for creating a popup window, which is done by either passing :popup with true or the options of the window in + # Javascript form. + # + # And a third for making the link do a POST request (instead of the regular GET) through a dynamically added form element that + # is instantly submitted. Note that if the user has turned off Javascript, the request will fall back on the GET. So its + # your responsibility to determine what the action should be once it arrives at the controller. The POST form is turned on by + # passing :post as true. Note, it's not possible to use POST requests and popup targets at the same time (an exception will be thrown). + # + # Examples: + # link_to "Delete this page", { :action => "destroy", :id => @page.id }, :confirm => "Are you sure?" + # link_to "Help", { :action => "help" }, :popup => true + # link_to "Busy loop", { :action => "busy" }, :popup => ['new_window', 'height=300,width=600'] + # link_to "Destroy account", { :action => "destroy" }, :confirm => "Are you sure?", :post => true + def link_to(name, options = {}, html_options = nil, *parameters_for_method_reference) + if html_options + html_options = html_options.stringify_keys + convert_options_to_javascript!(html_options) + tag_options = tag_options(html_options) + else + tag_options = nil + end + url = options.is_a?(String) ? options : self.url_for(options, *parameters_for_method_reference) + "<a href=\"#{url}\"#{tag_options}>#{name || url}</a>" + end + + # Generates a form containing a sole button that submits to the + # URL given by _options_. Use this method instead of +link_to+ + # for actions that do not have the safe HTTP GET semantics + # implied by using a hypertext link. + # + # The parameters are the same as for +link_to+. Any _html_options_ + # that you pass will be applied to the inner +input+ element. + # In particular, pass + # + # :disabled => true/false + # + # as part of _html_options_ to control whether the button is + # disabled. The generated form element is given the class + # 'button-to', to which you can attach CSS styles for display + # purposes. + # + # Example 1: + # + # # inside of controller for "feeds" + # button_to "Edit", :action => 'edit', :id => 3 + # + # Generates the following HTML (sans formatting): + # + # <form method="post" action="/feeds/edit/3" class="button-to"> + # <div><input value="Edit" type="submit" /></div> + # </form> + # + # Example 2: + # + # button_to "Destroy", { :action => 'destroy', :id => 3 }, + # :confirm => "Are you sure?" + # + # Generates the following HTML (sans formatting): + # + # <form method="post" action="/feeds/destroy/3" class="button-to"> + # <div><input onclick="return confirm('Are you sure?');" + # value="Destroy" type="submit" /> + # </div> + # </form> + # + # *NOTE*: This method generates HTML code that represents a form. + # Forms are "block" content, which means that you should not try to + # insert them into your HTML where only inline content is expected. + # For example, you can legally insert a form inside of a +div+ or + # +td+ element or in between +p+ elements, but not in the middle of + # a run of text, nor can you place a form within another form. + # (Bottom line: Always validate your HTML before going public.) + def button_to(name, options = {}, html_options = nil) + html_options = (html_options || {}).stringify_keys + convert_boolean_attributes!(html_options, %w( disabled )) + + if confirm = html_options.delete("confirm") + html_options["onclick"] = "return #{confirm_javascript_function(confirm)};" + end + + url = options.is_a?(String) ? options : url_for(options) + name ||= url + + html_options.merge!("type" => "submit", "value" => name) + + "<form method=\"post\" action=\"#{h url}\" class=\"button-to\"><div>" + + tag("input", html_options) + "</div></form>" + end + + + # This tag is deprecated. Combine the link_to and AssetTagHelper::image_tag yourself instead, like: + # link_to(image_tag("rss", :size => "30x45", :border => 0), "http://www.example.com") + def link_image_to(src, options = {}, html_options = {}, *parameters_for_method_reference) + image_options = { "src" => src.include?("/") ? src : "/images/#{src}" } + image_options["src"] += ".png" unless image_options["src"].include?(".") + + html_options = html_options.stringify_keys + if html_options["alt"] + image_options["alt"] = html_options["alt"] + html_options.delete "alt" + else + image_options["alt"] = src.split("/").last.split(".").first.capitalize + end + + if html_options["size"] + image_options["width"], image_options["height"] = html_options["size"].split("x") + html_options.delete "size" + end + + if html_options["border"] + image_options["border"] = html_options["border"] + html_options.delete "border" + end + + if html_options["align"] + image_options["align"] = html_options["align"] + html_options.delete "align" + end + + link_to(tag("img", image_options), options, html_options, *parameters_for_method_reference) + end + + alias_method :link_to_image, :link_image_to # deprecated name + + # Creates a link tag of the given +name+ using an URL created by the set of +options+, unless the current + # request uri is the same as the link's, in which case only the name is returned (or the + # given block is yielded, if one exists). This is useful for creating link bars where you don't want to link + # to the page currently being viewed. + def link_to_unless_current(name, options = {}, html_options = {}, *parameters_for_method_reference, &block) + link_to_unless current_page?(options), name, options, html_options, *parameters_for_method_reference, &block + end + + # Create a link tag of the given +name+ using an URL created by the set of +options+, unless +condition+ + # is true, in which case only the name is returned (or the given block is yielded, if one exists). + def link_to_unless(condition, name, options = {}, html_options = {}, *parameters_for_method_reference, &block) + if condition + if block_given? + block.arity <= 1 ? yield(name) : yield(name, options, html_options, *parameters_for_method_reference) + else + name + end + else + link_to(name, options, html_options, *parameters_for_method_reference) + end + end + + # Create a link tag of the given +name+ using an URL created by the set of +options+, if +condition+ + # is true, in which case only the name is returned (or the given block is yielded, if one exists). + def link_to_if(condition, name, options = {}, html_options = {}, *parameters_for_method_reference, &block) + link_to_unless !condition, name, options, html_options, *parameters_for_method_reference, &block + end + + # Creates a link tag for starting an email to the specified <tt>email_address</tt>, which is also used as the name of the + # link unless +name+ is specified. Additional HTML options, such as class or id, can be passed in the <tt>html_options</tt> hash. + # + # You can also make it difficult for spiders to harvest email address by obfuscating them. + # Examples: + # mail_to "me@domain.com", "My email", :encode => "javascript" # => + # <script type="text/javascript" language="javascript">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script> + # + # mail_to "me@domain.com", "My email", :encode => "hex" # => + # <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a> + # + # You can also specify the cc address, bcc address, subject, and body parts of the message header to create a complex e-mail using the + # corresponding +cc+, +bcc+, +subject+, and +body+ <tt>html_options</tt> keys. Each of these options are URI escaped and then appended to + # the <tt>email_address</tt> before being output. <b>Be aware that javascript keywords will not be escaped and may break this feature + # when encoding with javascript.</b> + # Examples: + # mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com", :bcc => "bccaddress@domain.com", :subject => "This is an example email", :body => "This is the body of the message." # => + # <a href="mailto:me@domain.com?cc="ccaddress@domain.com"&bcc="bccaddress@domain.com"&body="This%20is%20the%20body%20of%20the%20message."&subject="This%20is%20an%20example%20email">My email</a> + def mail_to(email_address, name = nil, html_options = {}) + html_options = html_options.stringify_keys + encode = html_options.delete("encode") + cc, bcc, subject, body = html_options.delete("cc"), html_options.delete("bcc"), html_options.delete("subject"), html_options.delete("body") + + string = '' + extras = '' + extras << "cc=#{CGI.escape(cc).gsub("+", "%20")}&" unless cc.nil? + extras << "bcc=#{CGI.escape(bcc).gsub("+", "%20")}&" unless bcc.nil? + extras << "body=#{CGI.escape(body).gsub("+", "%20")}&" unless body.nil? + extras << "subject=#{CGI.escape(subject).gsub("+", "%20")}&" unless subject.nil? + extras = "?" << extras.gsub!(/&?$/,"") unless extras.empty? + + email_address_obfuscated = email_address.dup + email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.has_key?("replace_at") + email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot") + + if encode == 'javascript' + tmp = "document.write('#{content_tag("a", name || email_address, html_options.merge({ "href" => "mailto:"+email_address.to_s+extras }))}');" + for i in 0...tmp.length + string << sprintf("%%%x",tmp[i]) + end + "<script type=\"text/javascript\">eval(unescape('#{string}'))</script>" + elsif encode == 'hex' + for i in 0...email_address.length + if email_address[i,1] =~ /\w/ + string << sprintf("%%%x",email_address[i]) + else + string << email_address[i,1] + end + end + content_tag "a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:#{string}#{extras}" }) + else + content_tag "a", name || email_address_obfuscated, html_options.merge({ "href" => "mailto:#{email_address}#{extras}" }) + end + end + + # Returns true if the current page uri is generated by the options passed (in url_for format). + def current_page?(options) + CGI.escapeHTML(url_for(options)) == @controller.request.request_uri + end + + private + def convert_options_to_javascript!(html_options) + confirm, popup, post = html_options.delete("confirm"), html_options.delete("popup"), html_options.delete("post") + + html_options["onclick"] = case + when popup && post + raise ActionView::ActionViewError, "You can't use :popup and :post in the same link" + when confirm && popup + "if (#{confirm_javascript_function(confirm)}) { #{popup_javascript_function(popup)} };return false;" + when confirm && post + "if (#{confirm_javascript_function(confirm)}) { #{post_javascript_function} };return false;" + when confirm + "return #{confirm_javascript_function(confirm)};" + when post + "#{post_javascript_function}return false;" + when popup + popup_javascript_function(popup) + 'return false;' + else + html_options["onclick"] + end + end + + def confirm_javascript_function(confirm) + "confirm('#{escape_javascript(confirm)}')" + end + + def popup_javascript_function(popup) + popup.is_a?(Array) ? "window.open(this.href,'#{popup.first}','#{popup.last}');" : "window.open(this.href);" + end + + def post_javascript_function + "var f = document.createElement('form'); this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();" + end + + # Processes the _html_options_ hash, converting the boolean + # attributes from true/false form into the form required by + # HTML/XHTML. (An attribute is considered to be boolean if + # its name is listed in the given _bool_attrs_ array.) + # + # More specifically, for each boolean attribute in _html_options_ + # given as: + # + # "attr" => bool_value + # + # if the associated _bool_value_ evaluates to true, it is + # replaced with the attribute's name; otherwise the attribute is + # removed from the _html_options_ hash. (See the XHTML 1.0 spec, + # section 4.5 "Attribute Minimization" for more: + # http://www.w3.org/TR/xhtml1/#h-4.5) + # + # Returns the updated _html_options_ hash, which is also modified + # in place. + # + # Example: + # + # convert_boolean_attributes!( html_options, + # %w( checked disabled readonly ) ) + def convert_boolean_attributes!(html_options, bool_attrs) + bool_attrs.each { |x| html_options[x] = x if html_options.delete(x) } + html_options + end + end + end +end +module ActionView + # There's also a convenience method for rendering sub templates within the current controller that depends on a single object + # (we call this kind of sub templates for partials). It relies on the fact that partials should follow the naming convention of being + # prefixed with an underscore -- as to separate them from regular templates that could be rendered on their own. + # + # In a template for Advertiser#account: + # + # <%= render :partial => "account" %> + # + # This would render "advertiser/_account.rhtml" and pass the instance variable @account in as a local variable +account+ to + # the template for display. + # + # In another template for Advertiser#buy, we could have: + # + # <%= render :partial => "account", :locals => { :account => @buyer } %> + # + # <% for ad in @advertisements %> + # <%= render :partial => "ad", :locals => { :ad => ad } %> + # <% end %> + # + # This would first render "advertiser/_account.rhtml" with @buyer passed in as the local variable +account+, then render + # "advertiser/_ad.rhtml" and pass the local variable +ad+ to the template for display. + # + # == Rendering a collection of partials + # + # The example of partial use describes a familiar pattern where a template needs to iterate over an array and render a sub + # template for each of the elements. This pattern has been implemented as a single method that accepts an array and renders + # a partial by the same name as the elements contained within. So the three-lined example in "Using partials" can be rewritten + # with a single line: + # + # <%= render :partial => "ad", :collection => @advertisements %> + # + # This will render "advertiser/_ad.rhtml" and pass the local variable +ad+ to the template for display. An iteration counter + # will automatically be made available to the template with a name of the form +partial_name_counter+. In the case of the + # example above, the template would be fed +ad_counter+. + # + # NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also just keep domain objects, + # like Active Records, in there. + # + # == Rendering shared partials + # + # Two controllers can share a set of partials and render them like this: + # + # <%= render :partial => "advertisement/ad", :locals => { :ad => @advertisement } %> + # + # This will render the partial "advertisement/_ad.rhtml" regardless of which controller this is being called from. + module Partials + # Deprecated, use render :partial + def render_partial(partial_path, local_assigns = nil, deprecated_local_assigns = nil) #:nodoc: + path, partial_name = partial_pieces(partial_path) + object = extracting_object(partial_name, local_assigns, deprecated_local_assigns) + local_assigns = extract_local_assigns(local_assigns, deprecated_local_assigns) + local_assigns = local_assigns ? local_assigns.clone : {} + add_counter_to_local_assigns!(partial_name, local_assigns) + add_object_to_local_assigns!(partial_name, local_assigns, object) + + if logger + ActionController::Base.benchmark("Rendered #{path}/_#{partial_name}", Logger::DEBUG, false) do + render("#{path}/_#{partial_name}", local_assigns) + end + else + render("#{path}/_#{partial_name}", local_assigns) + end + end + + # Deprecated, use render :partial, :collection + def render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = nil) #:nodoc: + collection_of_partials = Array.new + counter_name = partial_counter_name(partial_name) + local_assigns = local_assigns ? local_assigns.clone : {} + collection.each_with_index do |element, counter| + local_assigns[counter_name] = counter + collection_of_partials.push(render_partial(partial_name, element, local_assigns)) + end + + return " " if collection_of_partials.empty? + + if partial_spacer_template + spacer_path, spacer_name = partial_pieces(partial_spacer_template) + collection_of_partials.join(render("#{spacer_path}/_#{spacer_name}")) + else + collection_of_partials.join + end + end + + alias_method :render_collection_of_partials, :render_partial_collection + + private + def partial_pieces(partial_path) + if partial_path.include?('/') + return File.dirname(partial_path), File.basename(partial_path) + else + return controller.class.controller_path, partial_path + end + end + + def partial_counter_name(partial_name) + "#{partial_name.split('/').last}_counter".intern + end + + def extracting_object(partial_name, local_assigns, deprecated_local_assigns) + if local_assigns.is_a?(Hash) || local_assigns.nil? + controller.instance_variable_get("@#{partial_name}") + else + # deprecated form where object could be passed in as second parameter + local_assigns + end + end + + def extract_local_assigns(local_assigns, deprecated_local_assigns) + local_assigns.is_a?(Hash) ? local_assigns : deprecated_local_assigns + end + + def add_counter_to_local_assigns!(partial_name, local_assigns) + counter_name = partial_counter_name(partial_name) + local_assigns[counter_name] = 1 unless local_assigns.has_key?(counter_name) + end + + def add_object_to_local_assigns!(partial_name, local_assigns, object) + local_assigns[partial_name.intern] ||= + if object.is_a?(ActionView::Base::ObjectWrapper) + object.value + else + object + end || controller.instance_variable_get("@#{partial_name}") + end + end +end +module ActionView + # The TemplateError exception is raised when the compilation of the template fails. This exception then gathers a + # bunch of intimate details and uses it to report a very precise exception message. + class TemplateError < ActionViewError #:nodoc: + SOURCE_CODE_RADIUS = 3 + + attr_reader :original_exception + + def initialize(base_path, file_name, assigns, source, original_exception) + @base_path, @assigns, @source, @original_exception = + base_path, assigns, source, original_exception + @file_name = file_name + end + + def message + original_exception.message + end + + def sub_template_message + if @sub_templates + "Trace of template inclusion: " + + @sub_templates.collect { |template| strip_base_path(template) }.join(", ") + else + "" + end + end + + def source_extract(indention = 0) + source_code = IO.readlines(@file_name) + + start_on_line = [ line_number - SOURCE_CODE_RADIUS - 1, 0 ].max + end_on_line = [ line_number + SOURCE_CODE_RADIUS - 1, source_code.length].min + + line_counter = start_on_line + extract = source_code[start_on_line..end_on_line].collect do |line| + line_counter += 1 + "#{' ' * indention}#{line_counter}: " + line + end + + extract.join + end + + def sub_template_of(file_name) + @sub_templates ||= [] + @sub_templates << file_name + end + + def line_number + if file_name + regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/ + [@original_exception.message, @original_exception.clean_backtrace].flatten.each do |line| + return $1.to_i if regexp =~ line + end + end + 0 + end + + def file_name + stripped = strip_base_path(@file_name) + stripped[0] == ?/ ? stripped[1..-1] : stripped + end + + def to_s + "\n\n#{self.class} (#{message}) on line ##{line_number} of #{file_name}:\n" + + source_extract + "\n " + + original_exception.clean_backtrace.join("\n ") + + "\n\n" + end + + def backtrace + [ + "On line ##{line_number} of #{file_name}\n\n#{source_extract(4)}\n " + + original_exception.clean_backtrace.join("\n ") + ] + end + + private + def strip_base_path(file_name) + file_name = File.expand_path(file_name).gsub(/^#{Regexp.escape File.expand_path(RAILS_ROOT)}/, '') + file_name.gsub(@base_path, "") + end + end +end + +Exception::TraceSubstitutions << [/:in\s+`_run_(html|xml).*'\s*$/, ''] if defined?(Exception::TraceSubstitutions) +Exception::TraceSubstitutions << [%r{^\s*#{Regexp.escape RAILS_ROOT}}, '#{RAILS_ROOT}'] if defined?(RAILS_ROOT) +#-- +# Copyright (c) 2004 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +$:.unshift(File.dirname(__FILE__) + "/action_view/vendor") +require 'action_view/base' +require 'action_view/partials' + +ActionView::Base.class_eval do + include ActionView::Partials +end + +ActionView::Base.load_helpers(File.dirname(__FILE__) + "/action_view/helpers/") +$:.unshift(File.dirname(__FILE__) + '/../lib') +$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib/active_support') +$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers') + +require 'yaml' +require 'test/unit' +require 'action_controller' +require 'breakpoint' + +require 'action_controller/test_process' + +ActionController::Base.logger = nil +ActionController::Base.ignore_missing_templates = false +ActionController::Routing::Routes.reload rescue nilrequire File.dirname(__FILE__) + '/abstract_unit' + +# Define the essentials +class ActiveRecordTestConnector + cattr_accessor :able_to_connect + cattr_accessor :connected + + # Set our defaults + self.connected = false + self.able_to_connect = true +end + +# Try to grab AR +begin + PATH_TO_AR = File.dirname(__FILE__) + '/../../activerecord' + require "#{PATH_TO_AR}/lib/active_record" unless Object.const_defined?(:ActiveRecord) + require "#{PATH_TO_AR}/lib/active_record/fixtures" unless Object.const_defined?(:Fixtures) +rescue Object => e + $stderr.puts "\nSkipping ActiveRecord assertion tests: #{e}" + ActiveRecordTestConnector.able_to_connect = false +end + +# Define the rest of the connector +class ActiveRecordTestConnector + def self.setup + unless self.connected || !self.able_to_connect + setup_connection + load_schema + self.connected = true + end + rescue Object => e + $stderr.puts "\nSkipping ActiveRecord assertion tests: #{e}" + #$stderr.puts " #{e.backtrace.join("\n ")}\n" + self.able_to_connect = false + end + + private + + def self.setup_connection + if Object.const_defined?(:ActiveRecord) + + begin + ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :dbfile => ':memory:') + ActiveRecord::Base.connection + rescue Object + $stderr.puts 'SQLite 3 unavailable; falling to SQLite 2.' + ActiveRecord::Base.establish_connection(:adapter => 'sqlite', :dbfile => ':memory:') + ActiveRecord::Base.connection + end + + Object.send(:const_set, :QUOTED_TYPE, ActiveRecord::Base.connection.quote_column_name('type')) unless Object.const_defined?(:QUOTED_TYPE) + else + raise "Couldn't locate ActiveRecord." + end + end + + # Load actionpack sqlite tables + def self.load_schema + File.read(File.dirname(__FILE__) + "/fixtures/db_definitions/sqlite.sql").split(';').each do |sql| + ActiveRecord::Base.connection.execute(sql) unless sql.blank? + end + end +end + +# Test case for inheiritance +class ActiveRecordTestCase < Test::Unit::TestCase + # Set our fixture path + self.fixture_path = "#{File.dirname(__FILE__)}/fixtures/" + + def setup + abort_tests unless ActiveRecordTestConnector.connected = true + end + + # Default so Test::Unit::TestCase doesn't complain + def test_truth + end + + private + + # If things go wrong, we don't want to run our test cases. We'll just define them to test nothing. + def abort_tests + self.class.public_instance_methods.grep(/^test./).each do |method| + self.class.class_eval { define_method(method.to_sym){} } + end + end +end + +ActiveRecordTestConnector.setuprequire "#{File.dirname(__FILE__)}/../active_record_unit" +require 'fixtures/company' + +class ActiveRecordAssertionsController < ActionController::Base + self.template_root = "#{File.dirname(__FILE__)}/../fixtures/" + + # fail with 1 bad column + def nasty_columns_1 + @company = Company.new + @company.name = "B" + @company.rating = 2 + render :inline => "snicker...." + end + + # fail with 2 bad columns + def nasty_columns_2 + @company = Company.new + @company.name = "" + @company.rating = 2 + render :inline => "double snicker...." + end + + # this will pass validation + def good_company + @company = Company.new + @company.name = "A" + @company.rating = 69 + render :inline => "Goodness Gracious!" + end + + # this will fail validation + def bad_company + @company = Company.new + render :inline => "Who's Bad?" + end + + # the safety dance...... + def rescue_action(e) raise; end +end + +class ActiveRecordAssertionsControllerTest < ActiveRecordTestCase + fixtures :companies + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = ActiveRecordAssertionsController.new + super + end + + # test for 1 bad apple column + def test_some_invalid_columns + process :nasty_columns_1 + assert_success + assert_invalid_record 'company' + assert_invalid_column_on_record 'company', 'rating' + assert_valid_column_on_record 'company', 'name' + assert_valid_column_on_record 'company', %w(name id) + end + + # test for 2 bad apples columns + def test_all_invalid_columns + process :nasty_columns_2 + assert_success + assert_invalid_record 'company' + assert_invalid_column_on_record 'company', 'rating' + assert_invalid_column_on_record 'company', 'name' + assert_invalid_column_on_record 'company', %w(name rating) + end + + # ensure we have no problems with an ActiveRecord + def test_valid_record + process :good_company + assert_success + assert_valid_record 'company' + end + + # ensure we have problems with an ActiveRecord + def test_invalid_record + process :bad_company + assert_success + assert_invalid_record 'company' + end +end# Unfurl the safety net. +path_to_ar = File.dirname(__FILE__) + '/../../../activerecord' +if Object.const_defined?(:ActiveRecord) or File.exist?(path_to_ar) + begin + +# These tests exercise CGI::Session::ActiveRecordStore, so you're going to +# need AR in a sibling directory to AP and have SQLite installed. + +unless Object.const_defined?(:ActiveRecord) + require File.join(path_to_ar, 'lib', 'active_record') +end + +require File.dirname(__FILE__) + '/../abstract_unit' +require 'action_controller/session/active_record_store' + +#ActiveRecord::Base.logger = Logger.new($stdout) +begin + CGI::Session::ActiveRecordStore::Session.establish_connection(:adapter => 'sqlite3', :database => ':memory:') + CGI::Session::ActiveRecordStore::Session.connection +rescue Object + $stderr.puts 'SQLite 3 unavailable; falling back to SQLite 2.' + begin + CGI::Session::ActiveRecordStore::Session.establish_connection(:adapter => 'sqlite', :database => ':memory:') + CGI::Session::ActiveRecordStore::Session.connection + rescue Object + $stderr.puts 'SQLite 2 unavailable; skipping ActiveRecordStore test suite.' + raise SystemExit + end +end + + +module CommonActiveRecordStoreTests + def test_basics + s = session_class.new(:session_id => '1234', :data => { 'foo' => 'bar' }) + assert_equal 'bar', s.data['foo'] + assert s.save + assert_equal 'bar', s.data['foo'] + + assert_not_nil t = session_class.find_by_session_id('1234') + assert_not_nil t.data + assert_equal 'bar', t.data['foo'] + end + + def test_reload_same_session + @new_session.update + reloaded = CGI::Session.new(CGI.new, 'session_id' => @new_session.session_id, 'database_manager' => CGI::Session::ActiveRecordStore) + assert_equal 'bar', reloaded['foo'] + end + + def test_tolerates_close_close + assert_nothing_raised do + @new_session.close + @new_session.close + end + end +end + +class ActiveRecordStoreTest < Test::Unit::TestCase + include CommonActiveRecordStoreTests + + def session_class + CGI::Session::ActiveRecordStore::Session + end + + def session_id_column + "session_id" + end + + def setup + session_class.create_table! + + ENV['REQUEST_METHOD'] = 'GET' + CGI::Session::ActiveRecordStore.session_class = session_class + + @cgi = CGI.new + @new_session = CGI::Session.new(@cgi, 'database_manager' => CGI::Session::ActiveRecordStore, 'new_session' => true) + @new_session['foo'] = 'bar' + end + +# this test only applies for eager sesssion saving +# def test_another_instance +# @another = CGI::Session.new(@cgi, 'session_id' => @new_session.session_id, 'database_manager' => CGI::Session::ActiveRecordStore) +# assert_equal @new_session.session_id, @another.session_id +# end + + def test_model_attribute + assert_kind_of CGI::Session::ActiveRecordStore::Session, @new_session.model + assert_equal({ 'foo' => 'bar' }, @new_session.model.data) + end + + def test_save_unloaded_session + c = session_class.connection + bogus_class = c.quote(Base64.encode64("\004\010o:\vBlammo\000")) + c.insert("INSERT INTO #{session_class.table_name} ('#{session_id_column}', 'data') VALUES ('abcdefghijklmnop', #{bogus_class})") + + sess = session_class.find_by_session_id('abcdefghijklmnop') + assert_not_nil sess + assert !sess.loaded? + + # because the session is not loaded, the save should be a no-op. If it + # isn't, this'll try and unmarshall the bogus class, and should get an error. + assert_nothing_raised { sess.save } + end + + def teardown + session_class.drop_table! + end +end + +class ColumnLimitTest < Test::Unit::TestCase + def setup + @session_class = CGI::Session::ActiveRecordStore::Session + @session_class.create_table! + end + + def teardown + @session_class.drop_table! + end + + def test_protection_from_data_larger_than_column + # Can't test this unless there is a limit + return unless limit = @session_class.data_column_size_limit + too_big = ':(' * limit + s = @session_class.new(:session_id => '666', :data => {'foo' => too_big}) + s.data + assert_raise(ActionController::SessionOverflowError) { s.save } + end +end + +class DeprecatedActiveRecordStoreTest < ActiveRecordStoreTest + def session_id_column + "sessid" + end + + def setup + session_class.connection.execute 'create table old_sessions (id integer primary key, sessid text unique, data text)' + session_class.table_name = 'old_sessions' + session_class.send :setup_sessid_compatibility! + + ENV['REQUEST_METHOD'] = 'GET' + CGI::Session::ActiveRecordStore.session_class = session_class + + @new_session = CGI::Session.new(CGI.new, 'database_manager' => CGI::Session::ActiveRecordStore, 'new_session' => true) + @new_session['foo'] = 'bar' + end + + def teardown + session_class.connection.execute 'drop table old_sessions' + session_class.table_name = 'sessions' + end +end + +class SqlBypassActiveRecordStoreTest < ActiveRecordStoreTest + def session_class + unless @session_class + @session_class = CGI::Session::ActiveRecordStore::SqlBypass + @session_class.connection = CGI::Session::ActiveRecordStore::Session.connection + end + @session_class + end + + def test_model_attribute + assert_kind_of CGI::Session::ActiveRecordStore::SqlBypass, @new_session.model + assert_equal({ 'foo' => 'bar' }, @new_session.model.data) + end +end + + +# End of safety net. + rescue Object => e + $stderr.puts "Skipping CGI::Session::ActiveRecordStore tests: #{e}" + #$stderr.puts " #{e.backtrace.join("\n ")}" + end +end +require File.dirname(__FILE__) + '/../active_record_unit' + +require 'fixtures/topic' +require 'fixtures/reply' +require 'fixtures/developer' +require 'fixtures/project' + +class PaginationTest < ActiveRecordTestCase + fixtures :topics, :replies, :developers, :projects, :developers_projects + + class PaginationController < ActionController::Base + self.template_root = "#{File.dirname(__FILE__)}/../fixtures/" + + def simple_paginate + @topic_pages, @topics = paginate(:topics) + render :nothing => true + end + + def paginate_with_per_page + @topic_pages, @topics = paginate(:topics, :per_page => 1) + render :nothing => true + end + + def paginate_with_order + @topic_pages, @topics = paginate(:topics, :order => 'created_at asc') + render :nothing => true + end + + def paginate_with_order_by + @topic_pages, @topics = paginate(:topics, :order_by => 'created_at asc') + render :nothing => true + end + + def paginate_with_include_and_order + @topic_pages, @topics = paginate(:topics, :include => :replies, :order => 'replies.created_at asc, topics.created_at asc') + render :nothing => true + end + + def paginate_with_conditions + @topic_pages, @topics = paginate(:topics, :conditions => ["created_at > ?", 30.minutes.ago]) + render :nothing => true + end + + def paginate_with_class_name + @developer_pages, @developers = paginate(:developers, :class_name => "DeVeLoPeR") + render :nothing => true + end + + def paginate_with_singular_name + @developer_pages, @developers = paginate() + render :nothing => true + end + + def paginate_with_joins + @developer_pages, @developers = paginate(:developers, + :joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id', + :conditions => 'project_id=1') + render :nothing => true + end + + def paginate_with_join + @developer_pages, @developers = paginate(:developers, + :join => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id', + :conditions => 'project_id=1') + render :nothing => true + end + + def paginate_with_join_and_count + @developer_pages, @developers = paginate(:developers, + :join => 'd LEFT JOIN developers_projects ON d.id = developers_projects.developer_id', + :conditions => 'project_id=1', + :count => "d.id") + render :nothing => true + end + + def rescue_errors(e) raise e end + + def rescue_action(e) raise end + + end + + def setup + @controller = PaginationController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + super + end + + # Single Action Pagination Tests + + def test_simple_paginate + get :simple_paginate + assert_equal 1, assigns(:topic_pages).page_count + assert_equal 3, assigns(:topics).size + end + + def test_paginate_with_per_page + get :paginate_with_per_page + assert_equal 1, assigns(:topics).size + assert_equal 3, assigns(:topic_pages).page_count + end + + def test_paginate_with_order + get :paginate_with_order + expected = [topics(:futurama), + topics(:harvey_birdman), + topics(:rails)] + assert_equal expected, assigns(:topics) + assert_equal 1, assigns(:topic_pages).page_count + end + + def test_paginate_with_order_by + get :paginate_with_order + expected = assigns(:topics) + get :paginate_with_order_by + assert_equal expected, assigns(:topics) + assert_equal 1, assigns(:topic_pages).page_count + end + + def test_paginate_with_conditions + get :paginate_with_conditions + expected = [topics(:rails)] + assert_equal expected, assigns(:topics) + assert_equal 1, assigns(:topic_pages).page_count + end + + def test_paginate_with_class_name + get :paginate_with_class_name + + assert assigns(:developers).size > 0 + assert_equal DeVeLoPeR, assigns(:developers).first.class + end + + def test_paginate_with_joins + get :paginate_with_joins + assert_equal 2, assigns(:developers).size + developer_names = assigns(:developers).map { |d| d.name } + assert developer_names.include?('David') + assert developer_names.include?('Jamis') + end + + def test_paginate_with_join_and_conditions + get :paginate_with_joins + expected = assigns(:developers) + get :paginate_with_join + assert_equal expected, assigns(:developers) + end + + def test_paginate_with_join_and_count + get :paginate_with_joins + expected = assigns(:developers) + get :paginate_with_join_and_count + assert_equal expected, assigns(:developers) + end + + def test_paginate_with_include_and_order + get :paginate_with_include_and_order + expected = Topic.find(:all, :include => 'replies', :order => 'replies.created_at asc, topics.created_at asc', :limit => 10) + assert_equal expected, assigns(:topics) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +# a controller class to facilitate the tests +class ActionPackAssertionsController < ActionController::Base + + # this does absolutely nothing + def nothing() render_text ""; end + + # a standard template + def hello_world() render "test/hello_world"; end + + # a standard template + def hello_xml_world() render "test/hello_xml_world"; end + + # a redirect to an internal location + def redirect_internal() redirect_to "/nothing"; end + + def redirect_to_action() redirect_to :action => "flash_me", :id => 1, :params => { "panda" => "fun" }; end + + def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end + + def redirect_to_path() redirect_to '/some/path' end + + def redirect_to_named_route() redirect_to route_one_url end + + # a redirect to an external location + def redirect_external() redirect_to_url "http://www.rubyonrails.org"; end + + # a 404 + def response404() render_text "", "404 AWOL"; end + + # a 500 + def response500() render_text "", "500 Sorry"; end + + # a fictional 599 + def response599() render_text "", "599 Whoah!"; end + + # putting stuff in the flash + def flash_me + flash['hello'] = 'my name is inigo montoya...' + render_text "Inconceivable!" + end + + # we have a flash, but nothing is in it + def flash_me_naked + flash.clear + render_text "wow!" + end + + # assign some template instance variables + def assign_this + @howdy = "ho" + render :inline => "Mr. Henke" + end + + def render_based_on_parameters + render_text "Mr. #{@params["name"]}" + end + + def render_url + render_text "<div>#{url_for(:action => 'flash_me', :only_path => true)}</div>" + end + + # puts something in the session + def session_stuffing + session['xmas'] = 'turkey' + render_text "ho ho ho" + end + + # raises exception on get requests + def raise_on_get + raise "get" if @request.get? + render_text "request method: #{@request.env['REQUEST_METHOD']}" + end + + # raises exception on post requests + def raise_on_post + raise "post" if @request.post? + render_text "request method: #{@request.env['REQUEST_METHOD']}" + end + + def get_valid_record + @record = Class.new do + def valid? + true + end + + def errors + Class.new do + def full_messages; []; end + end.new + end + + end.new + + render :nothing => true + end + + + def get_invalid_record + @record = Class.new do + + def valid? + false + end + + def errors + Class.new do + def full_messages; ['...stuff...']; end + end.new + end + end.new + + render :nothing => true + end + + # 911 + def rescue_action(e) raise; end +end + +module Admin + class InnerModuleController < ActionController::Base + def redirect_to_absolute_controller + redirect_to :controller => '/content' + end + def redirect_to_fellow_controller + redirect_to :controller => 'user' + end + end +end + +# --------------------------------------------------------------------------- + + +# tell the controller where to find its templates but start from parent +# directory of test_request_response to simulate the behaviour of a +# production environment +ActionPackAssertionsController.template_root = File.dirname(__FILE__) + "/../fixtures/" + + +# a test case to exercise the new capabilities TestRequest & TestResponse +class ActionPackAssertionsControllerTest < Test::Unit::TestCase + # let's get this party started + def setup + @controller = ActionPackAssertionsController.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new + end + + # -- assertion-based testing ------------------------------------------------ + + def test_assert_tag_and_url_for + get :render_url + assert_tag :content => "/action_pack_assertions/flash_me" + end + + # test the session assertion to make sure something is there. + def test_assert_session_has + process :session_stuffing + assert_session_has 'xmas' + assert_session_has_no 'halloween' + end + + # test the get method, make sure the request really was a get + def test_get + assert_raise(RuntimeError) { get :raise_on_get } + get :raise_on_post + assert_equal @response.body, 'request method: GET' + end + + # test the get method, make sure the request really was a get + def test_post + assert_raise(RuntimeError) { post :raise_on_post } + post :raise_on_get + assert_equal @response.body, 'request method: POST' + end + +# the following test fails because the request_method is now cached on the request instance +# test the get/post switch within one test action +# def test_get_post_switch +# post :raise_on_get +# assert_equal @response.body, 'request method: POST' +# get :raise_on_post +# assert_equal @response.body, 'request method: GET' +# post :raise_on_get +# assert_equal @response.body, 'request method: POST' +# get :raise_on_post +# assert_equal @response.body, 'request method: GET' +# end + + # test the assertion of goodies in the template + def test_assert_template_has + process :assign_this + assert_template_has 'howdy' + end + + # test the assertion for goodies that shouldn't exist in the template + def test_assert_template_has_no + process :nothing + assert_template_has_no 'maple syrup' + assert_template_has_no 'howdy' + end + + # test the redirection assertions + def test_assert_redirect + process :redirect_internal + assert_redirect + end + + # test the redirect url string + def test_assert_redirect_url + process :redirect_external + assert_redirect_url 'http://www.rubyonrails.org' + end + + # test the redirection pattern matching on a string + def test_assert_redirect_url_match_string + process :redirect_external + assert_redirect_url_match 'rails.org' + end + + # test the redirection pattern matching on a pattern + def test_assert_redirect_url_match_pattern + process :redirect_external + assert_redirect_url_match /ruby/ + end + + # test the redirection to a named route + def test_assert_redirect_to_named_route + process :redirect_to_named_route + assert_raise(Test::Unit::AssertionFailedError) do + assert_redirected_to 'http://test.host/route_two' + end + end + + # test the flash-based assertions with something is in the flash + def test_flash_assertions_full + process :flash_me + assert @response.has_flash_with_contents? + assert_flash_exists + assert_flash_not_empty + assert_flash_has 'hello' + assert_flash_has_no 'stds' + end + + # test the flash-based assertions with no flash at all + def test_flash_assertions_negative + process :nothing + assert_flash_empty + assert_flash_has_no 'hello' + assert_flash_has_no 'qwerty' + end + + # test the assert_rendered_file + def test_assert_rendered_file + process :hello_world + assert_rendered_file 'test/hello_world' + assert_rendered_file 'hello_world' + end + + # test the assert_success assertion + def test_assert_success + process :nothing + assert_success + assert_rendered_file + end + + # -- standard request/response object testing -------------------------------- + + # ensure our session is working properly + def test_session_objects + process :session_stuffing + assert @response.has_session_object?('xmas') + assert_session_equal 'turkey', 'xmas' + assert !@response.has_session_object?('easter') + end + + # make sure that the template objects exist + def test_template_objects_alive + process :assign_this + assert !@response.has_template_object?('hi') + assert @response.has_template_object?('howdy') + end + + # make sure we don't have template objects when we shouldn't + def test_template_object_missing + process :nothing + assert_nil @response.template_objects['howdy'] + end + + def test_assigned_equal + process :assign_this + assert_assigned_equal "ho", :howdy + end + + # check the empty flashing + def test_flash_me_naked + process :flash_me_naked + assert !@response.has_flash? + assert !@response.has_flash_with_contents? + end + + # check if we have flash objects + def test_flash_haves + process :flash_me + assert @response.has_flash? + assert @response.has_flash_with_contents? + assert @response.has_flash_object?('hello') + end + + # ensure we don't have flash objects + def test_flash_have_nots + process :nothing + assert !@response.has_flash? + assert !@response.has_flash_with_contents? + assert_nil @response.flash['hello'] + end + + # examine that the flash objects are what we expect + def test_flash_equals + process :flash_me + assert_flash_equal 'my name is inigo montoya...', 'hello' + end + + + # check if we were rendered by a file-based template? + def test_rendered_action + process :nothing + assert !@response.rendered_with_file? + + process :hello_world + assert @response.rendered_with_file? + assert 'hello_world', @response.rendered_file + end + + # check the redirection location + def test_redirection_location + process :redirect_internal + assert_equal 'http://test.host/nothing', @response.redirect_url + + process :redirect_external + assert_equal 'http://www.rubyonrails.org', @response.redirect_url + + process :nothing + assert_nil @response.redirect_url + end + + + # check server errors + def test_server_error_response_code + process :response500 + assert @response.server_error? + + process :response599 + assert @response.server_error? + + process :response404 + assert !@response.server_error? + end + + # check a 404 response code + def test_missing_response_code + process :response404 + assert @response.missing? + end + + # check to see if our redirection matches a pattern + def test_redirect_url_match + process :redirect_external + assert @response.redirect? + assert @response.redirect_url_match?("rubyonrails") + assert @response.redirect_url_match?(/rubyonrails/) + assert !@response.redirect_url_match?("phpoffrails") + assert !@response.redirect_url_match?(/perloffrails/) + end + + # check for a redirection + def test_redirection + process :redirect_internal + assert @response.redirect? + + process :redirect_external + assert @response.redirect? + + process :nothing + assert !@response.redirect? + end + + # check a successful response code + def test_successful_response_code + process :nothing + assert @response.success? + end + + # a basic check to make sure we have a TestResponse object + def test_has_response + process :nothing + assert_kind_of ActionController::TestResponse, @response + end + + def test_render_based_on_parameters + process :render_based_on_parameters, "name" => "David" + assert_equal "Mr. David", @response.body + end + + def test_assert_template_xpath_match_no_matches + process :hello_xml_world + assert_raises Test::Unit::AssertionFailedError do + assert_template_xpath_match('/no/such/node/in/document') + end + end + + def test_simple_one_element_xpath_match + process :hello_xml_world + assert_template_xpath_match('//title', "Hello World") + end + + def test_array_of_elements_in_xpath_match + process :hello_xml_world + assert_template_xpath_match('//p', %w( abes monks wiseguys )) + end + + def test_follow_redirect + process :redirect_to_action + assert_redirected_to :action => "flash_me" + + follow_redirect + assert_equal 1, @request.parameters["id"].to_i + + assert "Inconceivable!", @response.body + end + + def test_follow_redirect_outside_current_action + process :redirect_to_controller + assert_redirected_to :controller => "elsewhere", :action => "flash_me" + + assert_raises(RuntimeError, "Can't follow redirects outside of current controller (elsewhere)") { follow_redirect } + end + + def test_redirected_to_url_leadling_slash + process :redirect_to_path + assert_redirected_to '/some/path' + end + def test_redirected_to_url_no_leadling_slash + process :redirect_to_path + assert_redirected_to 'some/path' + end + def test_redirected_to_url_full_url + process :redirect_to_path + assert_redirected_to 'http://test.host/some/path' + end + + def test_redirected_to_with_nested_controller + @controller = Admin::InnerModuleController.new + get :redirect_to_absolute_controller + assert_redirected_to :controller => 'content' + + get :redirect_to_fellow_controller + assert_redirected_to :controller => 'admin/user' + end + + def test_assert_valid + get :get_valid_record + assert_valid assigns('record') + end + + def test_assert_valid_failing + get :get_invalid_record + + begin + assert_valid assigns('record') + assert false + rescue Test::Unit::AssertionFailedError => e + end + end +end + +class ActionPackHeaderTest < Test::Unit::TestCase + def setup + @controller = ActionPackAssertionsController.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new + end + + def test_rendering_xml_sets_content_type + process :hello_xml_world + assert_equal('application/xml', @controller.headers['Content-Type']) + end + + def test_rendering_xml_respects_content_type + @response.headers['Content-Type'] = 'application/pdf' + process :hello_xml_world + assert_equal('application/pdf', @controller.headers['Content-Type']) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class Address + + def Address.count(conditions = nil, join = nil) + nil + end + + def Address.find_all(arg1, arg2, arg3, arg4) + [] + end + + def self.find(*args) + [] + end +end + +class AddressesTestController < ActionController::Base + + scaffold :address + + def self.controller_name; "addresses"; end + def self.controller_path; "addresses"; end + +end + +AddressesTestController.template_root = File.dirname(__FILE__) + "/../fixtures/" + +class AddressesTest < Test::Unit::TestCase + def setup + @controller = AddressesTestController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_list + get :list + assert_equal "We only need to get this far!", @response.body.chomp + end + + +end +require File.dirname(__FILE__) + '/../abstract_unit' +require 'test/unit' +require 'pp' # require 'pp' early to prevent hidden_methods from not picking up the pretty-print methods until too late + +# Provide some controller to run the tests on. +module Submodule + class ContainedEmptyController < ActionController::Base + end + class ContainedNonEmptyController < ActionController::Base + def public_action + end + + hide_action :hidden_action + def hidden_action + end + + def another_hidden_action + end + hide_action :another_hidden_action + end + class SubclassedController < ContainedNonEmptyController + hide_action :public_action # Hiding it here should not affect the superclass. + end +end +class EmptyController < ActionController::Base + include ActionController::Caching +end +class NonEmptyController < ActionController::Base + def public_action + end + + hide_action :hidden_action + def hidden_action + end +end + +class ControllerClassTests < Test::Unit::TestCase + def test_controller_path + assert_equal 'empty', EmptyController.controller_path + assert_equal 'submodule/contained_empty', Submodule::ContainedEmptyController.controller_path + end + def test_controller_name + assert_equal 'empty', EmptyController.controller_name + assert_equal 'contained_empty', Submodule::ContainedEmptyController.controller_name + end +end + +class ControllerInstanceTests < Test::Unit::TestCase + def setup + @empty = EmptyController.new + @contained = Submodule::ContainedEmptyController.new + @empty_controllers = [@empty, @contained, Submodule::SubclassedController.new] + + @non_empty_controllers = [NonEmptyController.new, + Submodule::ContainedNonEmptyController.new] + end + + def test_action_methods + @empty_controllers.each do |c| + assert_equal Set.new, c.send(:action_methods), "#{c.class.controller_path} should be empty!" + end + @non_empty_controllers.each do |c| + assert_equal Set.new('public_action'), c.send(:action_methods), "#{c.class.controller_path} should not be empty!" + end + end +end +require File.dirname(__FILE__) + '/../abstract_unit' +require 'test/unit' + +# Provide some static controllers. +class BenchmarkedController < ActionController::Base + def public_action + render :nothing => true + end + + def rescue_action(e) + raise e + end +end + +class BenchmarkTest < Test::Unit::TestCase + class MockLogger + def method_missing(*args) + end + end + + def setup + @controller = BenchmarkedController.new + # benchmark doesn't do anything unless a logger is set + @controller.logger = MockLogger.new + @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new + @request.host = "test.actioncontroller.i" + end + + def test_with_http_1_0_request + @request.host = nil + assert_nothing_raised { get :public_action } + end +end +require 'fileutils' +require File.dirname(__FILE__) + '/../abstract_unit' + +class TestLogDevice < Logger::LogDevice + attr :last_message, true + + def initialize + @last_message=String.new + end + + def write(message) + @last_message << message + end + + def clear + @last_message = String.new + end +end + +#setup our really sophisticated logger +TestLog = TestLogDevice.new +RAILS_DEFAULT_LOGGER = Logger.new(TestLog) +ActionController::Base.logger = RAILS_DEFAULT_LOGGER + +def use_store + #generate a random key to ensure the cache is always in a different location + RANDOM_KEY = rand(99999999).to_s + FILE_STORE_PATH = File.dirname(__FILE__) + '/../temp/' + RANDOM_KEY + ActionController::Base.perform_caching = true + ActionController::Base.fragment_cache_store = :file_store, FILE_STORE_PATH +end + +class TestController < ActionController::Base + caches_action :render_to_cache, :index + + def render_to_cache + render_text "Render Cached" + end + alias :index :render_to_cache +end + +class FileStoreTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = TestController.new + @request.host = "hostname.com" + end + + def teardown + FileUtils.rm_rf(FILE_STORE_PATH) + end + + def test_render_cached + assert_fragment_cached { get :render_to_cache } + assert_fragment_hit { get :render_to_cache } + end + + + private + def assert_fragment_cached + yield + assert(TestLog.last_message.include?("Cached fragment:"), "--ERROR-- FileStore write failed ----") + assert(!TestLog.last_message.include?("Couldn't create cache directory:"), "--ERROR-- FileStore create directory failed ----") + TestLog.clear + end + + def assert_fragment_hit + yield + assert(TestLog.last_message.include?("Fragment read:"), "--ERROR-- Fragment not found in FileStore ----") + assert(!TestLog.last_message.include?("Cached fragment:"), "--ERROR-- Did cache ----") + TestLog.clear + end +endrequire File.dirname(__FILE__) + '/../abstract_unit' + +class CaptureController < ActionController::Base + def self.controller_name; "test"; end + def self.controller_path; "test"; end + + def content_for + render :layout => "talk_from_action" + end + + def erb_content_for + render :layout => "talk_from_action" + end + + def block_content_for + render :layout => "talk_from_action" + end + + def non_erb_block_content_for + render :layout => "talk_from_action" + end + + def rescue_action(e) raise end +end + +CaptureController.template_root = File.dirname(__FILE__) + "/../fixtures/" + +class CaptureTest < Test::Unit::TestCase + def setup + @controller = CaptureController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_simple_capture + get :capturing + assert_equal "Dreamy days", @response.body.strip + end + + def test_content_for + get :content_for + assert_equal expected_content_for_output, @response.body + end + + def test_erb_content_for + get :content_for + assert_equal expected_content_for_output, @response.body + end + + def test_block_content_for + get :block_content_for + assert_equal expected_content_for_output, @response.body + end + + def test_non_erb_block_content_for + get :non_erb_block_content_for + assert_equal expected_content_for_output, @response.body + end + + def test_update_element_with_capture + get :update_element_with_capture + assert_equal( + "<script type=\"text/javascript\">\n//<![CDATA[\n$('products').innerHTML = '\\n <p>Product 1</p>\\n <p>Product 2</p>\\n';\n\n//]]>\n</script>" + + "\n\n$('status').innerHTML = '\\n <b>You bought something!</b>\\n';", + @response.body.strip + ) + end + + private + def expected_content_for_output + "<title>Putting stuff in the title!</title>\n\nGreat stuff!" + end +end +require File.dirname(__FILE__) + '/../abstract_unit' +require 'action_controller/cgi_process' +require 'action_controller/cgi_ext/cgi_ext' + + +require 'stringio' + +class CGITest < Test::Unit::TestCase + def setup + @query_string = "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1" + @query_string_with_nil = "action=create_customer&full_name=" + @query_string_with_array = "action=create_customer&selected[]=1&selected[]=2&selected[]=3" + @query_string_with_amps = "action=create_customer&name=Don%27t+%26+Does" + @query_string_with_multiple_of_same_name = + "action=update_order&full_name=Lau%20Taarnskov&products=4&products=2&products=3" + @query_string_with_many_equal = "action=create_customer&full_name=abc=def=ghi" + @query_string_without_equal = "action" + @query_string_with_many_ampersands = + "&action=create_customer&&&full_name=David%20Heinemeier%20Hansson" + end + + def test_query_string + assert_equal( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson", "customerId" => "1"}, + CGIMethods.parse_query_parameters(@query_string) + ) + end + + def test_deep_query_string + assert_equal({'x' => {'y' => {'z' => '10'}}}, CGIMethods.parse_query_parameters('x[y][z]=10')) + end + + def test_deep_query_string_with_array + assert_equal({'x' => {'y' => {'z' => ['10']}}}, CGIMethods.parse_query_parameters('x[y][z][]=10')) + assert_equal({'x' => {'y' => {'z' => ['10', '5']}}}, CGIMethods.parse_query_parameters('x[y][z][]=10&x[y][z][]=5')) + end + + def test_query_string_with_nil + assert_equal( + { "action" => "create_customer", "full_name" => nil}, + CGIMethods.parse_query_parameters(@query_string_with_nil) + ) + end + + def test_query_string_with_array + assert_equal( + { "action" => "create_customer", "selected" => ["1", "2", "3"]}, + CGIMethods.parse_query_parameters(@query_string_with_array) + ) + end + + def test_query_string_with_amps + assert_equal( + { "action" => "create_customer", "name" => "Don't & Does"}, + CGIMethods.parse_query_parameters(@query_string_with_amps) + ) + end + + def test_query_string_with_many_equal + assert_equal( + { "action" => "create_customer", "full_name" => "abc=def=ghi"}, + CGIMethods.parse_query_parameters(@query_string_with_many_equal) + ) + end + + def test_query_string_without_equal + assert_equal( + { "action" => nil }, + CGIMethods.parse_query_parameters(@query_string_without_equal) + ) + end + + def test_query_string_with_many_ampersands + assert_equal( + { "action" => "create_customer", "full_name" => "David Heinemeier Hansson"}, + CGIMethods.parse_query_parameters(@query_string_with_many_ampersands) + ) + end + + def test_parse_params + input = { + "customers[boston][first][name]" => [ "David" ], + "customers[boston][first][url]" => [ "http://David" ], + "customers[boston][second][name]" => [ "Allan" ], + "customers[boston][second][url]" => [ "http://Allan" ], + "something_else" => [ "blah" ], + "something_nil" => [ nil ], + "something_empty" => [ "" ], + "products[first]" => [ "Apple Computer" ], + "products[second]" => [ "Pc" ] + } + + expected_output = { + "customers" => { + "boston" => { + "first" => { + "name" => "David", + "url" => "http://David" + }, + "second" => { + "name" => "Allan", + "url" => "http://Allan" + } + } + }, + "something_else" => "blah", + "something_empty" => "", + "something_nil" => "", + "products" => { + "first" => "Apple Computer", + "second" => "Pc" + } + } + + assert_equal expected_output, CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_from_multipart_upload + mockup = Struct.new(:content_type, :original_filename) + file = mockup.new('img/jpeg', 'foo.jpg') + ie_file = mockup.new('img/jpeg', 'c:\\Documents and Settings\\foo\\Desktop\\bar.jpg') + + input = { + "something" => [ StringIO.new("") ], + "array_of_stringios" => [[ StringIO.new("One"), StringIO.new("Two") ]], + "mixed_types_array" => [[ StringIO.new("Three"), "NotStringIO" ]], + "mixed_types_as_checkboxes[strings][nested]" => [[ file, "String", StringIO.new("StringIO")]], + "ie_mixed_types_as_checkboxes[strings][nested]" => [[ ie_file, "String", StringIO.new("StringIO")]], + "products[string]" => [ StringIO.new("Apple Computer") ], + "products[file]" => [ file ], + "ie_products[string]" => [ StringIO.new("Microsoft") ], + "ie_products[file]" => [ ie_file ] + } + + expected_output = { + "something" => "", + "array_of_stringios" => ["One", "Two"], + "mixed_types_array" => [ "Three", "NotStringIO" ], + "mixed_types_as_checkboxes" => { + "strings" => { + "nested" => [ file, "String", "StringIO" ] + }, + }, + "ie_mixed_types_as_checkboxes" => { + "strings" => { + "nested" => [ ie_file, "String", "StringIO" ] + }, + }, + "products" => { + "string" => "Apple Computer", + "file" => file + }, + "ie_products" => { + "string" => "Microsoft", + "file" => ie_file + } + } + + params = CGIMethods.parse_request_parameters(input) + assert_equal expected_output, params + + # Lone filenames are preserved. + assert_equal 'foo.jpg', params['mixed_types_as_checkboxes']['strings']['nested'].first.original_filename + assert_equal 'foo.jpg', params['products']['file'].original_filename + + # But full Windows paths are reduced to their basename. + assert_equal 'bar.jpg', params['ie_mixed_types_as_checkboxes']['strings']['nested'].first.original_filename + assert_equal 'bar.jpg', params['ie_products']['file'].original_filename + end + + def test_parse_params_with_file + input = { + "customers[boston][first][name]" => [ "David" ], + "something_else" => [ "blah" ], + "logo" => [ File.new(File.dirname(__FILE__) + "/cgi_test.rb").path ] + } + + expected_output = { + "customers" => { + "boston" => { + "first" => { + "name" => "David" + } + } + }, + "something_else" => "blah", + "logo" => File.new(File.dirname(__FILE__) + "/cgi_test.rb").path, + } + + assert_equal expected_output, CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_with_array + input = { "selected[]" => [ "1", "2", "3" ] } + + expected_output = { "selected" => [ "1", "2", "3" ] } + + assert_equal expected_output, CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_with_non_alphanumeric_name + input = { "a/b[c]" => %w(d) } + expected = { "a/b" => { "c" => "d" }} + assert_equal expected, CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_with_single_brackets_in_middle + input = { "a/b[c]d" => %w(e) } + expected = { "a/b[c]d" => "e" } + assert_equal expected, CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_with_separated_brackets + input = { "a/b@[c]d[e]" => %w(f) } + expected = { "a/b@" => { "c]d[e" => "f" }} + assert_equal expected, CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_with_separated_brackets_and_array + input = { "a/b@[c]d[e][]" => %w(f) } + expected = { "a/b@" => { "c]d[e" => ["f"] }} + assert_equal expected , CGIMethods.parse_request_parameters(input) + end + + def test_parse_params_with_unmatched_brackets_and_array + input = { "a/b@[c][d[e][]" => %w(f) } + expected = { "a/b@" => { "c" => { "d[e" => ["f"] }}} + assert_equal expected, CGIMethods.parse_request_parameters(input) + end +end + +class MultipartCGITest < Test::Unit::TestCase + FIXTURE_PATH = File.dirname(__FILE__) + '/../fixtures/multipart' + + def setup + ENV['REQUEST_METHOD'] = 'POST' + ENV['CONTENT_LENGTH'] = '0' + ENV['CONTENT_TYPE'] = 'multipart/form-data, boundary=AaB03x' + end + + def test_single_parameter + params = process('single_parameter') + assert_equal({ 'foo' => 'bar' }, params) + end + + def test_text_file + params = process('text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of StringIO, file + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain\r", file.content_type + assert_equal 'contents', file.read + end + + def test_large_text_file + params = process('large_text_file') + assert_equal %w(file foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of Tempfile, file + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain\r", file.content_type + assert ('a' * 20480) == file.read + end + + def test_binary_file + params = process('binary_file') + assert_equal %w(file flowers foo), params.keys.sort + assert_equal 'bar', params['foo'] + + file = params['file'] + assert_kind_of StringIO, file + assert_equal 'file.txt', file.original_filename + assert_equal "text/plain\r", file.content_type + assert_equal 'contents', file.read + + file = params['flowers'] + assert_kind_of StringIO, file + assert_equal 'flowers.jpg', file.original_filename + assert_equal "image/jpeg\r", file.content_type + assert_equal 19512, file.size + #assert_equal File.read(File.dirname(__FILE__) + '/../../../activerecord/test/fixtures/flowers.jpg'), file.read + end + + def test_mixed_files + params = process('mixed_files') + assert_equal %w(files foo), params.keys.sort + assert_equal 'bar', params['foo'] + + # Ruby CGI doesn't handle multipart/mixed for us. + assert_kind_of StringIO, params['files'] + assert_equal 19756, params['files'].size + end + + private + def process(name) + old_stdin = $stdin + File.open(File.join(FIXTURE_PATH, name), 'rb') do |file| + ENV['CONTENT_LENGTH'] = file.stat.size.to_s + $stdin = file + CGIMethods.parse_request_parameters CGI.new.params + end + ensure + $stdin = old_stdin + end +end + + +class CGIRequestTest < Test::Unit::TestCase + def setup + @request_hash = {"HTTP_MAX_FORWARDS"=>"10", "SERVER_NAME"=>"glu.ttono.us:8007", "FCGI_ROLE"=>"RESPONDER", "HTTP_X_FORWARDED_HOST"=>"glu.ttono.us", "HTTP_ACCEPT_ENCODING"=>"gzip, deflate", "HTTP_USER_AGENT"=>"Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.5.1 (KHTML, like Gecko) Safari/312.3.1", "PATH_INFO"=>"", "HTTP_ACCEPT_LANGUAGE"=>"en", "HTTP_HOST"=>"glu.ttono.us:8007", "SERVER_PROTOCOL"=>"HTTP/1.1", "REDIRECT_URI"=>"/dispatch.fcgi", "SCRIPT_NAME"=>"/dispatch.fcgi", "SERVER_ADDR"=>"207.7.108.53", "REMOTE_ADDR"=>"207.7.108.53", "SERVER_SOFTWARE"=>"lighttpd/1.4.5", "HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2; is_admin=yes", "HTTP_X_FORWARDED_SERVER"=>"glu.ttono.us", "REQUEST_URI"=>"/admin", "DOCUMENT_ROOT"=>"/home/kevinc/sites/typo/public", "SERVER_PORT"=>"8007", "QUERY_STRING"=>"", "REMOTE_PORT"=>"63137", "GATEWAY_INTERFACE"=>"CGI/1.1", "HTTP_X_FORWARDED_FOR"=>"65.88.180.234", "HTTP_ACCEPT"=>"*/*", "SCRIPT_FILENAME"=>"/home/kevinc/sites/typo/public/dispatch.fcgi", "REDIRECT_STATUS"=>"200", "REQUEST_METHOD"=>"GET"} + # cookie as returned by some Nokia phone browsers (no space after semicolon separator) + @alt_cookie_fmt_request_hash = {"HTTP_COOKIE"=>"_session_id=c84ace84796670c052c6ceb2451fb0f2;is_admin=yes"} + @fake_cgi = Struct.new(:env_table).new(@request_hash) + @request = ActionController::CgiRequest.new(@fake_cgi) + end + + def test_proxy_request + assert_equal 'glu.ttono.us', @request.host_with_port + end + + def test_http_host + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash['HTTP_HOST'] = "rubyonrails.org:8080" + assert_equal "rubyonrails.org:8080", @request.host_with_port + + @request_hash['HTTP_X_FORWARDED_HOST'] = "www.firsthost.org, www.secondhost.org" + assert_equal "www.secondhost.org", @request.host + end + + def test_http_host_with_default_port_overrides_server_port + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash['HTTP_HOST'] = "rubyonrails.org" + assert_equal "rubyonrails.org", @request.host_with_port + end + + def test_host_with_port_defaults_to_server_name_if_no_host_headers + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash.delete "HTTP_HOST" + assert_equal "glu.ttono.us:8007", @request.host_with_port + end + + def test_host_with_port_falls_back_to_server_addr_if_necessary + @request_hash.delete "HTTP_X_FORWARDED_HOST" + @request_hash.delete "HTTP_HOST" + @request_hash.delete "SERVER_NAME" + assert_equal "207.7.108.53:8007", @request.host_with_port + end + + def test_cookie_syntax_resilience + cookies = CGI::Cookie::parse(@request_hash["HTTP_COOKIE"]); + assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], cookies["_session_id"] + assert_equal ["yes"], cookies["is_admin"] + + alt_cookies = CGI::Cookie::parse(@alt_cookie_fmt_request_hash["HTTP_COOKIE"]); + assert_equal ["c84ace84796670c052c6ceb2451fb0f2"], alt_cookies["_session_id"] + assert_equal ["yes"], alt_cookies["is_admin"] + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class CallerController < ActionController::Base + def calling_from_controller + render_component(:controller => "callee", :action => "being_called") + end + + def calling_from_controller_with_params + render_component(:controller => "callee", :action => "being_called", :params => { "name" => "David" }) + end + + def calling_from_controller_with_different_status_code + render_component(:controller => "callee", :action => "blowing_up") + end + + def calling_from_template + render_template "Ring, ring: <%= render_component(:controller => 'callee', :action => 'being_called') %>" + end + + def internal_caller + render_template "Are you there? <%= render_component(:action => 'internal_callee') %>" + end + + def internal_callee + render_text "Yes, ma'am" + end + + def set_flash + render_component(:controller => "callee", :action => "set_flash") + end + + def use_flash + render_component(:controller => "callee", :action => "use_flash") + end + + def calling_redirected + render_component(:controller => "callee", :action => "redirected") + end + + def calling_redirected_as_string + render_template "<%= render_component(:controller => 'callee', :action => 'redirected') %>" + end + + def rescue_action(e) raise end +end + +class CalleeController < ActionController::Base + def being_called + render_text "#{@params["name"] || "Lady"} of the House, speaking" + end + + def blowing_up + render_text "It's game over, man, just game over, man!", "500 Internal Server Error" + end + + def set_flash + flash[:notice] = 'My stoney baby' + render :text => 'flash is set' + end + + def use_flash + render :text => flash[:notice] || 'no flash' + end + + def redirected + redirect_to :controller => "callee", :action => "being_called" + end + + def rescue_action(e) raise end +end + +class ComponentsTest < Test::Unit::TestCase + def setup + @controller = CallerController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_calling_from_controller + get :calling_from_controller + assert_equal "Lady of the House, speaking", @response.body + end + + def test_calling_from_controller_with_params + get :calling_from_controller_with_params + assert_equal "David of the House, speaking", @response.body + end + + def test_calling_from_controller_with_different_status_code + get :calling_from_controller_with_different_status_code + assert_equal 500, @response.response_code + end + + def test_calling_from_template + get :calling_from_template + assert_equal "Ring, ring: Lady of the House, speaking", @response.body + end + + def test_internal_calling + get :internal_caller + assert_equal "Are you there? Yes, ma'am", @response.body + end + + def test_flash + get :set_flash + assert_equal 'My stoney baby', flash[:notice] + get :use_flash + assert_equal 'My stoney baby', @response.body + get :use_flash + assert_equal 'no flash', @response.body + end + + def test_component_redirect_redirects + get :calling_redirected + + assert_redirected_to :action => "being_called" + end + + def test_component_multiple_redirect_redirects + test_component_redirect_redirects + test_internal_calling + end + + def test_component_as_string_redirect_renders_redirecte_action + get :calling_redirected_as_string + + assert_equal "Lady of the House, speaking", @response.body + end +endrequire File.dirname(__FILE__) + '/../abstract_unit' + +class CookieTest < Test::Unit::TestCase + class TestController < ActionController::Base + def authenticate_with_deprecated_writer + cookie "name" => "user_name", "value" => "david" + render_text "hello world" + end + + def authenticate + cookies["user_name"] = "david" + render_text "hello world" + end + + def authenticate_for_fourten_days + cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) } + render_text "hello world" + end + + def authenticate_for_fourten_days_with_symbols + cookies[:user_name] = { :value => "david", :expires => Time.local(2005, 10, 10) } + render_text "hello world" + end + + def set_multiple_cookies + cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) } + cookies["login"] = "XJ-122" + render_text "hello world" + end + + def access_frozen_cookies + @cookies["will"] = "work" + render_text "hello world" + end + + def rescue_action(e) raise end + end + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_setting_cookie_with_deprecated_writer + @request.action = "authenticate_with_deprecated_writer" + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], process_request.headers["cookie"] + end + + def test_setting_cookie + @request.action = "authenticate" + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], process_request.headers["cookie"] + end + + def test_setting_cookie_for_fourteen_days + @request.action = "authenticate_for_fourten_days" + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], process_request.headers["cookie"] + end + + def test_setting_cookie_for_fourteen_days_with_symbols + @request.action = "authenticate_for_fourten_days" + assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], process_request.headers["cookie"] + end + + def test_multiple_cookies + @request.action = "set_multiple_cookies" + assert_equal 2, process_request.headers["cookie"].size + end + + def test_setting_test_cookie + @request.action = "access_frozen_cookies" + assert_nothing_raised { process_request } + end + + private + def process_request + TestController.process(@request, @response) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class CustomHandler + def initialize( view ) + @view = view + end + + def render( template, local_assigns ) + [ template, + local_assigns, + @view ] + end +end + +class CustomHandlerTest < Test::Unit::TestCase + def setup + ActionView::Base.register_template_handler "foo", CustomHandler + ActionView::Base.register_template_handler :foo2, CustomHandler + @view = ActionView::Base.new + end + + def test_custom_render + result = @view.render_template( "foo", "hello <%= one %>", nil, :one => "two" ) + assert_equal( + [ "hello <%= one %>", { :one => "two" }, @view ], + result ) + end + + def test_custom_render2 + result = @view.render_template( "foo2", "hello <%= one %>", nil, :one => "two" ) + assert_equal( + [ "hello <%= one %>", { :one => "two" }, @view ], + result ) + end + + def test_unhandled_extension + # uses the ERb handler by default if the extension isn't recognized + result = @view.render_template( "bar", "hello <%= one %>", nil, :one => "two" ) + assert_equal "hello two", result + end +end +class << Object; alias_method :const_available?, :const_defined?; end + +class ContentController < Class.new(ActionController::Base) +end +class NotAController +end +module Admin + class << self; alias_method :const_available?, :const_defined?; end + SomeConstant = 10 + class UserController < Class.new(ActionController::Base); end + class NewsFeedController < Class.new(ActionController::Base); end +end + +ActionController::Routing::Routes.draw do |map| + map.route_one 'route_one', :controller => 'elsewhere', :action => 'flash_me' + map.connect ':controller/:action/:id' +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class FilterParamController < ActionController::Base +end + +class FilterParamTest < Test::Unit::TestCase + def setup + @controller = FilterParamController.new + end + + def test_filter_parameters + assert FilterParamController.respond_to?(:filter_parameter_logging) + assert !@controller.respond_to?(:filter_parameters) + + FilterParamController.filter_parameter_logging + assert @controller.respond_to?(:filter_parameters) + + test_hashes = [[{},{},[]], + [{'foo'=>'bar'},{'foo'=>'bar'},[]], + [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'], + [{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'], + [{'foo'=>'bar', 'bar'=>'foo'},{'foo'=>'[FILTERED]', 'bar'=>'foo'},%w'foo baz'], + [{'foo'=>'bar', 'baz'=>'foo'},{'foo'=>'[FILTERED]', 'baz'=>'[FILTERED]'},%w'foo baz'], + [{'bar'=>{'foo'=>'bar','bar'=>'foo'}},{'bar'=>{'foo'=>'[FILTERED]','bar'=>'foo'}},%w'fo'], + [{'foo'=>{'foo'=>'bar','bar'=>'foo'}},{'foo'=>'[FILTERED]'},%w'f banana']] + + test_hashes.each do |before_filter, after_filter, filter_words| + FilterParamController.filter_parameter_logging(*filter_words) + assert_equal after_filter, @controller.filter_parameters(before_filter) + + filter_words.push('blah') + FilterParamController.filter_parameter_logging(*filter_words) do |key, value| + value.reverse! if key =~ /bargain/ + end + + before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}} + after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}} + + assert_equal after_filter, @controller.filter_parameters(before_filter) + end + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class FilterTest < Test::Unit::TestCase + class TestController < ActionController::Base + before_filter :ensure_login + after_filter :clean_up + + def show + render :inline => "ran action" + end + + private + def ensure_login + @ran_filter ||= [] + @ran_filter << "ensure_login" + end + + def clean_up + @ran_after_filter ||= [] + @ran_after_filter << "clean_up" + end + end + + class RenderingController < ActionController::Base + before_filter :render_something_else + + def show + @ran_action = true + render :inline => "ran action" + end + + private + def render_something_else + render :inline => "something else" + end + end + + class ConditionalFilterController < ActionController::Base + def show + render :inline => "ran action" + end + + def another_action + render :inline => "ran action" + end + + def show_without_filter + render :inline => "ran action without filter" + end + + private + def ensure_login + @ran_filter ||= [] + @ran_filter << "ensure_login" + end + + def clean_up_tmp + @ran_filter ||= [] + @ran_filter << "clean_up_tmp" + end + + def rescue_action(e) raise(e) end + end + + class ConditionalCollectionFilterController < ConditionalFilterController + before_filter :ensure_login, :except => [ :show_without_filter, :another_action ] + end + + class OnlyConditionSymController < ConditionalFilterController + before_filter :ensure_login, :only => :show + end + + class ExceptConditionSymController < ConditionalFilterController + before_filter :ensure_login, :except => :show_without_filter + end + + class BeforeAndAfterConditionController < ConditionalFilterController + before_filter :ensure_login, :only => :show + after_filter :clean_up_tmp, :only => :show + end + + class OnlyConditionProcController < ConditionalFilterController + before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true } + end + + class ExceptConditionProcController < ConditionalFilterController + before_filter(:except => :show_without_filter) {|c| c.assigns["ran_proc_filter"] = true } + end + + class ConditionalClassFilter + def self.filter(controller) controller.assigns["ran_class_filter"] = true end + end + + class OnlyConditionClassController < ConditionalFilterController + before_filter ConditionalClassFilter, :only => :show + end + + class ExceptConditionClassController < ConditionalFilterController + before_filter ConditionalClassFilter, :except => :show_without_filter + end + + class AnomolousYetValidConditionController < ConditionalFilterController + before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true} + end + + class PrependingController < TestController + prepend_before_filter :wonderful_life + # skip_before_filter :fire_flash + + private + def wonderful_life + @ran_filter ||= [] + @ran_filter << "wonderful_life" + end + end + + class ConditionalSkippingController < TestController + skip_before_filter :ensure_login, :only => [ :login ] + skip_after_filter :clean_up, :only => [ :login ] + + before_filter :find_user, :only => [ :change_password ] + + def login + render :inline => "ran action" + end + + def change_password + render :inline => "ran action" + end + + protected + def find_user + @ran_filter ||= [] + @ran_filter << "find_user" + end + end + + class ConditionalParentOfConditionalSkippingController < ConditionalFilterController + before_filter :conditional_in_parent, :only => [:show, :another_action] + after_filter :conditional_in_parent, :only => [:show, :another_action] + + private + + def conditional_in_parent + @ran_filter ||= [] + @ran_filter << 'conditional_in_parent' + end + end + + class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController + skip_before_filter :conditional_in_parent, :only => :another_action + skip_after_filter :conditional_in_parent, :only => :another_action + end + + class ProcController < PrependingController + before_filter(proc { |c| c.assigns["ran_proc_filter"] = true }) + end + + class ImplicitProcController < PrependingController + before_filter { |c| c.assigns["ran_proc_filter"] = true } + end + + class AuditFilter + def self.filter(controller) + controller.assigns["was_audited"] = true + end + end + + class AroundFilter + def before(controller) + @execution_log = "before" + controller.class.execution_log << " before aroundfilter " if controller.respond_to? :execution_log + controller.assigns["before_ran"] = true + end + + def after(controller) + controller.assigns["execution_log"] = @execution_log + " and after" + controller.assigns["after_ran"] = true + controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log + end + end + + class AppendedAroundFilter + def before(controller) + controller.class.execution_log << " before appended aroundfilter " + end + + def after(controller) + controller.class.execution_log << " after appended aroundfilter " + end + end + + class AuditController < ActionController::Base + before_filter(AuditFilter) + + def show + render_text "hello" + end + end + + class BadFilterController < ActionController::Base + before_filter 2 + + def show() "show" end + + protected + def rescue_action(e) raise(e) end + end + + class AroundFilterController < PrependingController + around_filter AroundFilter.new + end + + class MixedFilterController < PrependingController + cattr_accessor :execution_log + + def initialize + @@execution_log = "" + end + + before_filter { |c| c.class.execution_log << " before procfilter " } + prepend_around_filter AroundFilter.new + + after_filter { |c| c.class.execution_log << " after procfilter " } + append_around_filter AppendedAroundFilter.new + end + + class MixedSpecializationController < ActionController::Base + class OutOfOrder < StandardError; end + + before_filter :first + before_filter :second, :only => :foo + + def foo + render_text 'foo' + end + + def bar + render_text 'bar' + end + + protected + def first + @first = true + end + + def second + raise OutOfOrder unless @first + end + end + + class DynamicDispatchController < ActionController::Base + before_filter :choose + + %w(foo bar baz).each do |action| + define_method(action) { render :text => action } + end + + private + def choose + self.action_name = params[:choose] + end + end + + def test_added_filter_to_inheritance_graph + assert_equal [ :ensure_login ], TestController.before_filters + end + + def test_base_class_in_isolation + assert_equal [ ], ActionController::Base.before_filters + end + + def test_prepending_filter + assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters + end + + def test_running_filters + assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"] + end + + def test_running_filters_with_proc + assert test_process(ProcController).template.assigns["ran_proc_filter"] + end + + def test_running_filters_with_implicit_proc + assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"] + end + + def test_running_filters_with_class + assert test_process(AuditController).template.assigns["was_audited"] + end + + def test_running_anomolous_yet_valid_condition_filters + response = test_process(AnomolousYetValidConditionController) + assert_equal %w( ensure_login ), response.template.assigns["ran_filter"] + assert response.template.assigns["ran_class_filter"] + assert response.template.assigns["ran_proc_filter1"] + assert response.template.assigns["ran_proc_filter2"] + + response = test_process(AnomolousYetValidConditionController, "show_without_filter") + assert_equal nil, response.template.assigns["ran_filter"] + assert !response.template.assigns["ran_class_filter"] + assert !response.template.assigns["ran_proc_filter1"] + assert !response.template.assigns["ran_proc_filter2"] + end + + def test_running_collection_condition_filters + assert_equal %w( ensure_login ), test_process(ConditionalCollectionFilterController).template.assigns["ran_filter"] + assert_equal nil, test_process(ConditionalCollectionFilterController, "show_without_filter").template.assigns["ran_filter"] + assert_equal nil, test_process(ConditionalCollectionFilterController, "another_action").template.assigns["ran_filter"] + end + + def test_running_only_condition_filters + assert_equal %w( ensure_login ), test_process(OnlyConditionSymController).template.assigns["ran_filter"] + assert_equal nil, test_process(OnlyConditionSymController, "show_without_filter").template.assigns["ran_filter"] + + assert test_process(OnlyConditionProcController).template.assigns["ran_proc_filter"] + assert !test_process(OnlyConditionProcController, "show_without_filter").template.assigns["ran_proc_filter"] + + assert test_process(OnlyConditionClassController).template.assigns["ran_class_filter"] + assert !test_process(OnlyConditionClassController, "show_without_filter").template.assigns["ran_class_filter"] + end + + def test_running_except_condition_filters + assert_equal %w( ensure_login ), test_process(ExceptConditionSymController).template.assigns["ran_filter"] + assert_equal nil, test_process(ExceptConditionSymController, "show_without_filter").template.assigns["ran_filter"] + + assert test_process(ExceptConditionProcController).template.assigns["ran_proc_filter"] + assert !test_process(ExceptConditionProcController, "show_without_filter").template.assigns["ran_proc_filter"] + + assert test_process(ExceptConditionClassController).template.assigns["ran_class_filter"] + assert !test_process(ExceptConditionClassController, "show_without_filter").template.assigns["ran_class_filter"] + end + + def test_running_before_and_after_condition_filters + assert_equal %w( ensure_login clean_up_tmp), test_process(BeforeAndAfterConditionController).template.assigns["ran_filter"] + assert_equal nil, test_process(BeforeAndAfterConditionController, "show_without_filter").template.assigns["ran_filter"] + end + + def test_bad_filter + assert_raises(ActionController::ActionControllerError) { + test_process(BadFilterController) + } + end + + def test_around_filter + controller = test_process(AroundFilterController) + assert controller.template.assigns["before_ran"] + assert controller.template.assigns["after_ran"] + end + + def test_having_properties_in_around_filter + controller = test_process(AroundFilterController) + assert_equal "before and after", controller.template.assigns["execution_log"] + end + + def test_prepending_and_appending_around_filter + controller = test_process(MixedFilterController) + assert_equal " before aroundfilter before procfilter before appended aroundfilter " + + " after appended aroundfilter after aroundfilter after procfilter ", + MixedFilterController.execution_log + end + + def test_rendering_breaks_filtering_chain + response = test_process(RenderingController) + assert_equal "something else", response.body + assert !response.template.assigns["ran_action"] + end + + def test_filters_with_mixed_specialization_run_in_order + assert_nothing_raised do + response = test_process(MixedSpecializationController, 'bar') + assert_equal 'bar', response.body + end + + assert_nothing_raised do + response = test_process(MixedSpecializationController, 'foo') + assert_equal 'foo', response.body + end + end + + def test_dynamic_dispatch + %w(foo bar baz).each do |action| + request = ActionController::TestRequest.new + request.query_parameters[:choose] = action + response = DynamicDispatchController.process(request, ActionController::TestResponse.new) + assert_equal action, response.body + end + end + + def test_conditional_skipping_of_filters + assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"] + assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"] + + assert_nil test_process(ConditionalSkippingController, "login").template.controller.instance_variable_get("@ran_after_filter") + assert_equal %w( clean_up ), test_process(ConditionalSkippingController, "change_password").template.controller.instance_variable_get("@ran_after_filter") + end + + def test_conditional_skipping_of_filters_when_parent_filter_is_also_conditional + assert_equal %w( conditional_in_parent conditional_in_parent ), test_process(ChildOfConditionalParentController).template.assigns['ran_filter'] + assert_nil test_process(ChildOfConditionalParentController, 'another_action').template.assigns['ran_filter'] + end + + private + def test_process(controller, action = "show") + request = ActionController::TestRequest.new + request.action = action + controller.process(request, ActionController::TestResponse.new) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class FlashTest < Test::Unit::TestCase + class TestController < ActionController::Base + def set_flash + flash["that"] = "hello" + render :inline => "hello" + end + + def set_flash_now + flash.now["that"] = "hello" + flash.now["foo"] ||= "bar" + flash.now["foo"] ||= "err" + @flashy = flash.now["that"] + @flash_copy = {}.update flash + render :inline => "hello" + end + + def attempt_to_use_flash_now + @flash_copy = {}.update flash + @flashy = flash["that"] + render :inline => "hello" + end + + def use_flash + @flash_copy = {}.update flash + @flashy = flash["that"] + render :inline => "hello" + end + + def use_flash_and_keep_it + @flash_copy = {}.update flash + @flashy = flash["that"] + silence_warnings { keep_flash } + render :inline => "hello" + end + + def rescue_action(e) + raise unless ActionController::MissingTemplate === e + end + end + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = TestController.new + end + + def test_flash + get :set_flash + + get :use_flash + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "hello", @response.template.assigns["flashy"] + + get :use_flash + assert_nil @response.template.assigns["flash_copy"]["that"], "On second flash" + end + + def test_keep_flash + get :set_flash + + get :use_flash_and_keep_it + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "hello", @response.template.assigns["flashy"] + + get :use_flash + assert_equal "hello", @response.template.assigns["flash_copy"]["that"], "On second flash" + + get :use_flash + assert_nil @response.template.assigns["flash_copy"]["that"], "On third flash" + end + + def test_flash_now + get :set_flash_now + assert_equal "hello", @response.template.assigns["flash_copy"]["that"] + assert_equal "bar" , @response.template.assigns["flash_copy"]["foo"] + assert_equal "hello", @response.template.assigns["flashy"] + + get :attempt_to_use_flash_now + assert_nil @response.template.assigns["flash_copy"]["that"] + assert_nil @response.template.assigns["flash_copy"]["foo"] + assert_nil @response.template.assigns["flashy"] + end +endrequire File.dirname(__FILE__) + '/../abstract_unit' + +MemCache = Struct.new(:MemCache, :address) unless Object.const_defined?(:MemCache) + +class FragmentCacheStoreSettingTest < Test::Unit::TestCase + def teardown + ActionController::Base.fragment_cache_store = ActionController::Caching::Fragments::MemoryStore.new + end + + def test_file_fragment_cache_store + ActionController::Base.fragment_cache_store = :file_store, "/path/to/cache/directory" + assert_kind_of( + ActionController::Caching::Fragments::FileStore, + ActionController::Base.fragment_cache_store + ) + assert_equal "/path/to/cache/directory", ActionController::Base.fragment_cache_store.cache_path + end + + def test_drb_fragment_cache_store + ActionController::Base.fragment_cache_store = :drb_store, "druby://localhost:9192" + assert_kind_of( + ActionController::Caching::Fragments::DRbStore, + ActionController::Base.fragment_cache_store + ) + assert_equal "druby://localhost:9192", ActionController::Base.fragment_cache_store.address + end + + def test_mem_cache_fragment_cache_store + ActionController::Base.fragment_cache_store = :mem_cache_store, "localhost" + assert_kind_of( + ActionController::Caching::Fragments::MemCacheStore, + ActionController::Base.fragment_cache_store + ) + assert_equal %w(localhost), ActionController::Base.fragment_cache_store.addresses + end + + def test_object_assigned_fragment_cache_store + ActionController::Base.fragment_cache_store = ActionController::Caching::Fragments::FileStore.new("/path/to/cache/directory") + assert_kind_of( + ActionController::Caching::Fragments::FileStore, + ActionController::Base.fragment_cache_store + ) + assert_equal "/path/to/cache/directory", ActionController::Base.fragment_cache_store.cache_path + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class TestController < ActionController::Base + attr_accessor :delegate_attr + def delegate_method() end + def rescue_action(e) raise end +end + +module Fun + class GamesController < ActionController::Base + def render_hello_world + render :inline => "hello: <%= stratego %>" + end + + def rescue_action(e) raise end + end + + class PDFController < ActionController::Base + def test + render :inline => "test: <%= foobar %>" + end + + def rescue_action(e) raise end + end +end + +module LocalAbcHelper + def a() end + def b() end + def c() end +end + +class HelperTest < Test::Unit::TestCase + def setup + # Increment symbol counter. + @symbol = (@@counter ||= 'A0').succ!.dup + + # Generate new controller class. + controller_class_name = "Helper#{@symbol}Controller" + eval("class #{controller_class_name} < TestController; end") + @controller_class = self.class.const_get(controller_class_name) + + # Generate new template class and assign to controller. + template_class_name = "Test#{@symbol}View" + eval("class #{template_class_name} < ActionView::Base; end") + @template_class = self.class.const_get(template_class_name) + @controller_class.template_class = @template_class + + # Set default test helper. + self.test_helper = LocalAbcHelper + end + + def teardown + # Reset template class. + #ActionController::Base.template_class = ActionView::Base + end + + + def test_deprecated_helper + assert_equal expected_helper_methods, missing_methods + assert_nothing_raised { @controller_class.helper TestHelper } + assert_equal [], missing_methods + end + + def test_declare_helper + require 'abc_helper' + self.test_helper = AbcHelper + assert_equal expected_helper_methods, missing_methods + assert_nothing_raised { @controller_class.helper :abc } + assert_equal [], missing_methods + end + + def test_declare_missing_helper + assert_equal expected_helper_methods, missing_methods + assert_raise(MissingSourceFile) { @controller_class.helper :missing } + end + + def test_declare_missing_file_from_helper + require 'broken_helper' + rescue LoadError => e + assert_nil /\bbroken_helper\b/.match(e.to_s)[1] + end + + def test_helper_block + assert_nothing_raised { + @controller_class.helper { def block_helper_method; end } + } + assert master_helper_methods.include?('block_helper_method') + end + + def test_helper_block_include + assert_equal expected_helper_methods, missing_methods + assert_nothing_raised { + @controller_class.helper { include TestHelper } + } + assert [], missing_methods + end + + def test_helper_method + assert_nothing_raised { @controller_class.helper_method :delegate_method } + assert master_helper_methods.include?('delegate_method') + end + + def test_helper_attr + assert_nothing_raised { @controller_class.helper_attr :delegate_attr } + assert master_helper_methods.include?('delegate_attr') + assert master_helper_methods.include?('delegate_attr=') + end + + def test_helper_for_nested_controller + request = ActionController::TestRequest.new + response = ActionController::TestResponse.new + request.action = 'render_hello_world' + + assert_equal 'hello: Iz guuut!', Fun::GamesController.process(request, response).body + end + + def test_helper_for_acronym_controller + request = ActionController::TestRequest.new + response = ActionController::TestResponse.new + request.action = 'test' + + assert_equal 'test: baz', Fun::PDFController.process(request, response).body + end + + private + def expected_helper_methods + TestHelper.instance_methods + end + + def master_helper_methods + @controller_class.master_helper_module.instance_methods + end + + def missing_methods + expected_helper_methods - master_helper_methods + end + + def test_helper=(helper_module) + silence_warnings { self.class.const_set('TestHelper', helper_module) } + end +end + + +class IsolatedHelpersTest < Test::Unit::TestCase + class A < ActionController::Base + def index + render :inline => '<%= shout %>' + end + + def rescue_action(e) raise end + end + + class B < A + helper { def shout; 'B' end } + + def index + render :inline => '<%= shout %>' + end + end + + class C < A + helper { def shout; 'C' end } + + def index + render :inline => '<%= shout %>' + end + end + + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @request.action = 'index' + end + + def test_helper_in_a + assert_raise(NameError) { A.process(@request, @response) } + end + + def test_helper_in_b + assert_equal 'B', B.process(@request, @response).body + end + + def test_helper_in_c + assert_equal 'C', C.process(@request, @response).body + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +# The template_root must be set on Base and not LayoutTest so that LayoutTest's inherited method has access to +# the template_root when looking for a layout +ActionController::Base.template_root = File.dirname(__FILE__) + '/../fixtures/layout_tests/' + +class LayoutTest < ActionController::Base + def self.controller_path; 'views' end +end + +# Restore template root to be unset +ActionController::Base.template_root = nil + +class ProductController < LayoutTest +end + +class ItemController < LayoutTest +end + +class ThirdPartyTemplateLibraryController < LayoutTest +end + +module ControllerNameSpace +end + +class ControllerNameSpace::NestedController < LayoutTest +end + +class MabView + def initialize(view) + end + + def render(text, locals = {}) + text + end +end + +ActionView::Base::register_template_handler :mab, MabView + +class LayoutAutoDiscoveryTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_application_layout_is_default_when_no_controller_match + @controller = ProductController.new + get :hello + assert_equal 'layout_test.rhtml hello.rhtml', @response.body + end + + def test_controller_name_layout_name_match + @controller = ItemController.new + get :hello + assert_equal 'item.rhtml hello.rhtml', @response.body + end + + def test_third_party_template_library_auto_discovers_layout + @controller = ThirdPartyTemplateLibraryController.new + get :hello + assert_equal 'layouts/third_party_template_library', @controller.active_layout + assert_equal 'Mab', @response.body + end + + def test_namespaced_controllers_auto_detect_layouts + @controller = ControllerNameSpace::NestedController.new + get :hello + assert_equal 'layouts/controller_name_space/nested', @controller.active_layout + assert_equal 'controller_name_space/nested.rhtml hello.rhtml', @response.body + end +endrequire File.dirname(__FILE__) + '/../abstract_unit' + +class RespondToController < ActionController::Base + layout :set_layout + + def html_xml_or_rss + respond_to do |type| + type.html { render :text => "HTML" } + type.xml { render :text => "XML" } + type.rss { render :text => "RSS" } + type.all { render :text => "Nothing" } + end + end + + def js_or_html + respond_to do |type| + type.html { render :text => "HTML" } + type.js { render :text => "JS" } + type.all { render :text => "Nothing" } + end + end + + def html_or_xml + respond_to do |type| + type.html { render :text => "HTML" } + type.xml { render :text => "XML" } + type.all { render :text => "Nothing" } + end + end + + def just_xml + respond_to do |type| + type.xml { render :text => "XML" } + end + end + + def using_defaults + respond_to do |type| + type.html + type.js + type.xml + end + end + + def using_defaults_with_type_list + respond_to(:html, :js, :xml) + end + + def made_for_content_type + respond_to do |type| + type.rss { render :text => "RSS" } + type.atom { render :text => "ATOM" } + type.all { render :text => "Nothing" } + end + end + + def custom_type_handling + respond_to do |type| + type.html { render :text => "HTML" } + type.custom("application/crazy-xml") { render :text => "Crazy XML" } + type.all { render :text => "Nothing" } + end + end + + def handle_any + respond_to do |type| + type.html { render :text => "HTML" } + type.any(:js, :xml) { render :text => "Either JS or XML" } + end + end + + def all_types_with_layout + respond_to do |type| + type.html + type.js + end + end + + def rescue_action(e) + raise + end + + protected + def set_layout + if action_name == "all_types_with_layout" + "standard" + end + end +end + +RespondToController.template_root = File.dirname(__FILE__) + "/../fixtures/" + +class MimeControllerTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @controller = RespondToController.new + @request.host = "www.example.com" + end + + def test_html + @request.env["HTTP_ACCEPT"] = "text/html" + get :js_or_html + assert_equal 'HTML', @response.body + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_response 406 + end + + def test_all + @request.env["HTTP_ACCEPT"] = "*/*" + get :js_or_html + assert_equal 'HTML', @response.body # js is not part of all + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_equal 'XML', @response.body + end + + def test_xml + @request.env["HTTP_ACCEPT"] = "application/xml" + get :html_xml_or_rss + assert_equal 'XML', @response.body + end + + def test_js_or_html + @request.env["HTTP_ACCEPT"] = "text/javascript, text/html" + get :js_or_html + assert_equal 'JS', @response.body + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_response 406 + end + + def test_js_or_anything + @request.env["HTTP_ACCEPT"] = "text/javascript, */*" + get :js_or_html + assert_equal 'JS', @response.body + + get :html_or_xml + assert_equal 'HTML', @response.body + + get :just_xml + assert_equal 'XML', @response.body + end + + def test_using_defaults + @request.env["HTTP_ACCEPT"] = "*/*" + get :using_defaults + assert_equal 'Hello world!', @response.body + + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :using_defaults + assert_equal '$("body").visualEffect("highlight");', @response.body + + @request.env["HTTP_ACCEPT"] = "application/xml" + get :using_defaults + assert_equal "<p>Hello world!</p>\n", @response.body + end + + def test_using_defaults_with_type_list + @request.env["HTTP_ACCEPT"] = "*/*" + get :using_defaults_with_type_list + assert_equal 'Hello world!', @response.body + + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :using_defaults_with_type_list + assert_equal '$("body").visualEffect("highlight");', @response.body + + @request.env["HTTP_ACCEPT"] = "application/xml" + get :using_defaults_with_type_list + assert_equal "<p>Hello world!</p>\n", @response.body + end + + def test_with_content_type + @request.env["CONTENT_TYPE"] = "application/atom+xml" + get :made_for_content_type + assert_equal "ATOM", @response.body + + @request.env["CONTENT_TYPE"] = "application/rss+xml" + get :made_for_content_type + assert_equal "RSS", @response.body + end + + def test_synonyms + @request.env["HTTP_ACCEPT"] = "application/javascript" + get :js_or_html + assert_equal 'JS', @response.body + + @request.env["HTTP_ACCEPT"] = "application/x-xml" + get :html_xml_or_rss + assert_equal "XML", @response.body + end + + def test_custom_types + @request.env["HTTP_ACCEPT"] = "application/crazy-xml" + get :custom_type_handling + assert_equal 'Crazy XML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/html" + get :custom_type_handling + assert_equal 'HTML', @response.body + end + + def test_xhtml_alias + @request.env["HTTP_ACCEPT"] = "application/xhtml+xml,application/xml" + get :html_or_xml + assert_equal 'HTML', @response.body + end + + def test_firefox_simulation + @request.env["HTTP_ACCEPT"] = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" + get :html_or_xml + assert_equal 'HTML', @response.body + end + + def test_handle_any + @request.env["HTTP_ACCEPT"] = "*/*" + get :handle_any + assert_equal 'HTML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :handle_any + assert_equal 'Either JS or XML', @response.body + + @request.env["HTTP_ACCEPT"] = "text/xml" + get :handle_any + assert_equal 'Either JS or XML', @response.body + end + + def test_all_types_with_layout + @request.env["HTTP_ACCEPT"] = "text/javascript" + get :all_types_with_layout + assert_equal 'RJS for all_types_with_layout', @response.body + + @request.env["HTTP_ACCEPT"] = "text/html" + get :all_types_with_layout + assert_equal '<html>HTML for all_types_with_layout</html>', @response.body + end + + def test_xhr + xhr :get, :js_or_html + assert_equal 'JS', @response.body + + xhr :get, :using_defaults + assert_equal '$("body").visualEffect("highlight");', @response.body + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class MimeTypeTest < Test::Unit::TestCase + Mime::PNG = Mime::Type.new("image/png") + Mime::PLAIN = Mime::Type.new("text/plain") + + def test_parse_single + Mime::LOOKUP.keys.each do |mime_type| + assert_equal [Mime::Type.lookup(mime_type)], Mime::Type.parse(mime_type) + end + end + + def test_parse_without_q + accept = "text/xml,application/xhtml+xml,text/yaml,application/xml,text/html,image/png,text/plain,*/*" + expect = [Mime::HTML, Mime::XML, Mime::YAML, Mime::PNG, Mime::PLAIN, Mime::ALL] + assert_equal expect, Mime::Type.parse(accept) + end + + def test_parse_with_q + accept = "text/xml,application/xhtml+xml,text/yaml; q=0.3,application/xml,text/html; q=0.8,image/png,text/plain; q=0.5,*/*; q=0.2" + expect = [Mime::HTML, Mime::XML, Mime::PNG, Mime::PLAIN, Mime::YAML, Mime::ALL] + assert_equal expect, Mime::Type.parse(accept) + end +endrequire File.dirname(__FILE__) + '/../abstract_unit' + +silence_warnings { Customer = Struct.new("Customer", :name) } + +module Fun + class GamesController < ActionController::Base + def hello_world + end + end +end + +module NewRenderTestHelper + def rjs_helper_method_from_module + page.visual_effect :highlight + end +end + +class NewRenderTestController < ActionController::Base + layout :determine_layout + + def self.controller_name; "test"; end + def self.controller_path; "test"; end + + def hello_world + end + + def render_hello_world + render :template => "test/hello_world" + end + + def render_hello_world_from_variable + @person = "david" + render :text => "hello #{@person}" + end + + def render_action_hello_world + render :action => "hello_world" + end + + def render_action_hello_world_as_symbol + render :action => :hello_world + end + + def render_text_hello_world + render :text => "hello world" + end + + def render_text_hello_world_with_layout + @variable_for_layout = ", I'm here!" + render :text => "hello world", :layout => true + end + + def hello_world_with_layout_false + render :layout => false + end + + def render_custom_code + render :text => "hello world", :status => "404 Moved" + end + + def render_file_with_instance_variables + @secret = 'in the sauce' + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_ivar.rhtml') + render :file => path + end + + def render_file_with_locals + path = File.join(File.dirname(__FILE__), '../fixtures/test/render_file_with_locals.rhtml') + render :file => path, :locals => {:secret => 'in the sauce'} + end + + def render_file_not_using_full_path + @secret = 'in the sauce' + render :file => 'test/render_file_with_ivar', :use_full_path => true + end + + def render_file_not_using_full_path_with_relative_path + @secret = 'in the sauce' + render :file => 'test/../test/render_file_with_ivar', :use_full_path => true + end + + def render_file_not_using_full_path_with_dot_in_path + @secret = 'in the sauce' + render :file => 'test/dot.directory/render_file_with_ivar', :use_full_path => true + end + + def render_xml_hello + @name = "David" + render :template => "test/hello" + end + + def greeting + # let's just rely on the template + end + + def layout_test + render :action => "hello_world" + end + + def layout_test_with_different_layout + render :action => "hello_world", :layout => "standard" + end + + def rendering_without_layout + render :action => "hello_world", :layout => false + end + + def layout_overriding_layout + render :action => "hello_world", :layout => "standard" + end + + def rendering_nothing_on_layout + render :nothing => true + end + + def builder_layout_test + render :action => "hello" + end + + def partials_list + @test_unchanged = 'hello' + @customers = [ Customer.new("david"), Customer.new("mary") ] + render :action => "list" + end + + def partial_only + render :partial => true + end + + def partial_only_with_layout + render :partial => "partial_only", :layout => true + end + + def partial_with_locals + render :partial => "customer", :locals => { :customer => Customer.new("david") } + end + + def partial_collection + render :partial => "customer", :collection => [ Customer.new("david"), Customer.new("mary") ] + end + + def partial_collection_with_locals + render :partial => "customer_greeting", :collection => [ Customer.new("david"), Customer.new("mary") ], :locals => { :greeting => "Bonjour" } + end + + def empty_partial_collection + render :partial => "customer", :collection => [] + end + + def partial_with_hash_object + render :partial => "hash_object", :object => {:first_name => "Sam"} + end + + def partial_with_implicit_local_assignment + @customer = Customer.new("Marcel") + render :partial => "customer" + end + + def hello_in_a_string + @customers = [ Customer.new("david"), Customer.new("mary") ] + render :text => "How's there? #{render_to_string("test/list")}" + end + + def accessing_params_in_template + render :inline => "Hello: <%= params[:name] %>" + end + + def accessing_params_in_template_with_layout + render :layout => nil, :inline => "Hello: <%= params[:name] %>" + end + + def render_with_explicit_template + render "test/hello_world" + end + + def double_render + render :text => "hello" + render :text => "world" + end + + def double_redirect + redirect_to :action => "double_render" + redirect_to :action => "double_render" + end + + def render_and_redirect + render :text => "hello" + redirect_to :action => "double_render" + end + + def rendering_with_conflicting_local_vars + @name = "David" + def @template.name() nil end + render :action => "potential_conflicts" + end + + def hello_world_from_rxml_using_action + render :action => "hello_world.rxml" + end + + def hello_world_from_rxml_using_template + render :template => "test/hello_world.rxml" + end + + helper NewRenderTestHelper + helper do + def rjs_helper_method(value) + page.visual_effect :highlight, value + end + end + + def enum_rjs_test + render :update do |page| + page.select('.product').each do |value| + page.rjs_helper_method_from_module + page.rjs_helper_method(value) + page.sortable(value, :url => { :action => "order" }) + page.draggable(value) + end + end + end + + def delete_with_js + @project_id = 4 + end + + def render_js_with_explicit_template + @project_id = 4 + render :template => 'test/delete_with_js' + end + + def render_js_with_explicit_action_template + @project_id = 4 + render :action => 'delete_with_js' + end + + def update_page + render :update do |page| + page.replace_html 'balance', '$37,000,000.00' + page.visual_effect :highlight, 'balance' + end + end + + def update_page_with_instance_variables + @money = '$37,000,000.00' + @div_id = 'balance' + render :update do |page| + page.replace_html @div_id, @money + page.visual_effect :highlight, @div_id + end + end + + def action_talk_to_layout + # Action template sets variable that's picked up by layout + end + + def render_text_with_assigns + @hello = "world" + render :text => "foo" + end + + def yield_content_for + render :action => "content_for", :layout => "yield" + end + + def rescue_action(e) raise end + + private + def determine_layout + case action_name + when "hello_world", "layout_test", "rendering_without_layout", + "rendering_nothing_on_layout", "render_text_hello_world", + "render_text_hello_world_with_layout", + "hello_world_with_layout_false", + "partial_only", "partial_only_with_layout", + "accessing_params_in_template", + "accessing_params_in_template_with_layout", + "render_with_explicit_template", + "render_js_with_explicit_template", + "render_js_with_explicit_action_template", + "delete_with_js", "update_page", "update_page_with_instance_variables" + + "layouts/standard" + when "builder_layout_test" + "layouts/builder" + when "action_talk_to_layout", "layout_overriding_layout" + "layouts/talk_from_action" + end + end +end + +NewRenderTestController.template_root = File.dirname(__FILE__) + "/../fixtures/" +Fun::GamesController.template_root = File.dirname(__FILE__) + "/../fixtures/" + +class NewRenderTest < Test::Unit::TestCase + def setup + @controller = NewRenderTestController.new + + # enable a logger so that (e.g.) the benchmarking stuff runs, so we can get + # a more accurate simulation of what happens in "real life". + @controller.logger = Logger.new(nil) + + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + + @request.host = "www.nextangle.com" + end + + def test_simple_show + get :hello_world + assert_response :success + assert_template "test/hello_world" + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_do_with_render + get :render_hello_world + assert_template "test/hello_world" + end + + def test_do_with_render_from_variable + get :render_hello_world_from_variable + assert_equal "hello david", @response.body + end + + def test_do_with_render_action + get :render_action_hello_world + assert_template "test/hello_world" + end + + def test_do_with_render_action_as_symbol + get :render_action_hello_world_as_symbol + assert_template "test/hello_world" + end + + def test_do_with_render_text + get :render_text_hello_world + assert_equal "hello world", @response.body + end + + def test_do_with_render_text_and_layout + get :render_text_hello_world_with_layout + assert_equal "<html>hello world, I'm here!</html>", @response.body + end + + def test_do_with_render_action_and_layout_false + get :hello_world_with_layout_false + assert_equal 'Hello world!', @response.body + end + + def test_do_with_render_custom_code + get :render_custom_code + assert_response :missing + end + + def test_render_file_with_instance_variables + get :render_file_with_instance_variables + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_not_using_full_path + get :render_file_not_using_full_path + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_not_using_full_path_with_relative_path + get :render_file_not_using_full_path_with_relative_path + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_not_using_full_path_with_dot_in_path + get :render_file_not_using_full_path_with_dot_in_path + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_render_file_with_locals + get :render_file_with_locals + assert_equal "The secret is in the sauce\n", @response.body + end + + def test_attempt_to_access_object_method + assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } + end + + def test_private_methods + assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } + end + + def test_access_to_request_in_view + view_internals_old_value = ActionController::Base.view_controller_internals + + ActionController::Base.view_controller_internals = false + ActionController::Base.protected_variables_cache = nil + + get :hello_world + assert_nil(assigns["request"]) + + ActionController::Base.view_controller_internals = true + ActionController::Base.protected_variables_cache = nil + + get :hello_world + assert_kind_of ActionController::AbstractRequest, assigns["request"] + + ActionController::Base.view_controller_internals = view_internals_old_value + ActionController::Base.protected_variables_cache = nil + end + + def test_render_xml + get :render_xml_hello + assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body + end + + def test_enum_rjs_test + get :enum_rjs_test + assert_equal <<-EOS.strip, @response.body +$$(".product").each(function(value, index) { +new Effect.Highlight(element,{}); +new Effect.Highlight(value,{}); +Sortable.create(value, {onUpdate:function(){new Ajax.Request('/test/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(value)})}}); +new Draggable(value, {}); +}); +EOS + end + + def test_render_xml_with_default + get :greeting + assert_equal "<p>This is grand!</p>\n", @response.body + end + + def test_render_rjs_with_default + get :delete_with_js + assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_render_rjs_template_explicitly + get :render_js_with_explicit_template + assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_rendering_rjs_action_explicitly + get :render_js_with_explicit_action_template + assert_equal %!["person"].each(Element.remove);\nnew Effect.Highlight(\"project-4\",{});!, @response.body + end + + def test_layout_rendering + get :layout_test + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_layout_test_with_different_layout + get :layout_test_with_different_layout + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_rendering_without_layout + get :rendering_without_layout + assert_equal "Hello world!", @response.body + end + + def test_layout_overriding_layout + get :layout_overriding_layout + assert_no_match %r{<title>}, @response.body + end + + def test_rendering_nothing_on_layout + get :rendering_nothing_on_layout + assert_equal " ", @response.body + end + + def test_render_xml_with_layouts + get :builder_layout_test + assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body + end + + def test_partial_only + get :partial_only + assert_equal "only partial", @response.body + end + + def test_partial_only_with_layout + get :partial_only_with_layout + assert_equal "<html>only partial</html>", @response.body + end + + def test_render_to_string + get :hello_in_a_string + assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body + end + + def test_nested_rendering + get :hello_world + assert_equal "Living in a nested world", Fun::GamesController.process(@request, @response).body + end + + def test_accessing_params_in_template + get :accessing_params_in_template, :name => "David" + assert_equal "Hello: David", @response.body + end + + def test_accessing_params_in_template_with_layout + get :accessing_params_in_template_with_layout, :name => "David" + assert_equal "<html>Hello: David</html>", @response.body + end + + def test_render_with_explicit_template + get :render_with_explicit_template + assert_response :success + end + + def test_double_render + assert_raises(ActionController::DoubleRenderError) { get :double_render } + end + + def test_double_redirect + assert_raises(ActionController::DoubleRenderError) { get :double_redirect } + end + + def test_render_and_redirect + assert_raises(ActionController::DoubleRenderError) { get :render_and_redirect } + end + + def test_rendering_with_conflicting_local_vars + get :rendering_with_conflicting_local_vars + assert_equal("First: David\nSecond: Stephan\nThird: David\nFourth: David\nFifth: ", @response.body) + end + + def test_action_talk_to_layout + get :action_talk_to_layout + assert_equal "<title>Talking to the layout</title>\nAction was here!", @response.body + end + + def test_partials_list + get :partials_list + assert_equal "goodbyeHello: davidHello: marygoodbye\n", @response.body + end + + def test_partial_with_locals + get :partial_with_locals + assert_equal "Hello: david", @response.body + end + + def test_partial_collection + get :partial_collection + assert_equal "Hello: davidHello: mary", @response.body + end + + def test_partial_collection_with_locals + get :partial_collection_with_locals + assert_equal "Bonjour: davidBonjour: mary", @response.body + end + + def test_empty_partial_collection + get :empty_partial_collection + assert_equal " ", @response.body + end + + def test_partial_with_hash_object + get :partial_with_hash_object + assert_equal "Sam", @response.body + end + + def test_partial_with_implicit_local_assignment + get :partial_with_implicit_local_assignment + assert_equal "Hello: Marcel", @response.body + end + + def test_render_text_with_assigns + get :render_text_with_assigns + assert_equal "world", assigns["hello"] + end + + def test_update_page + get :update_page + assert_template nil + assert_equal 'text/javascript; charset=UTF-8', @response.headers['Content-Type'] + assert_equal 2, @response.body.split($/).length + end + + def test_update_page_with_instance_variables + get :update_page_with_instance_variables + assert_template nil + assert_equal 'text/javascript; charset=UTF-8', @response.headers['Content-Type'] + assert_match /balance/, @response.body + assert_match /\$37/, @response.body + end + + def test_yield_content_for + get :yield_content_for + assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body + end + + + def test_overwritting_rendering_relative_file_with_extension + get :hello_world_from_rxml_using_template + assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body + + get :hello_world_from_rxml_using_action + assert_equal "<html>\n <p>Hello</p>\n</html>\n", @response.body + end +end +require 'test/unit' +require 'cgi' +require 'stringio' +require File.dirname(__FILE__) + '/../../lib/action_controller/cgi_ext/raw_post_data_fix' + +class RawPostDataTest < Test::Unit::TestCase + def setup + ENV['REQUEST_METHOD'] = 'POST' + ENV['CONTENT_TYPE'] = '' + ENV['CONTENT_LENGTH'] = '0' + end + + def test_raw_post_data + process_raw "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1" + end + + private + def process_raw(query_string) + old_stdin = $stdin + begin + $stdin = StringIO.new(query_string.dup) + ENV['CONTENT_LENGTH'] = $stdin.size.to_s + CGI.new + assert_not_nil ENV['RAW_POST_DATA'] + assert ENV['RAW_POST_DATA'].frozen? + assert_equal query_string, ENV['RAW_POST_DATA'] + ensure + $stdin = old_stdin + end + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class RedirectController < ActionController::Base + def simple_redirect + redirect_to :action => "hello_world" + end + + def method_redirect + redirect_to :dashbord_url, 1, "hello" + end + + def host_redirect + redirect_to :action => "other_host", :only_path => false, :host => 'other.test.host' + end + + def module_redirect + redirect_to :controller => 'module_test/module_redirect', :action => "hello_world" + end + + def redirect_with_assigns + @hello = "world" + redirect_to :action => "hello_world" + end + + def redirect_to_back + redirect_to :back + end + + def rescue_errors(e) raise e end + + def rescue_action(e) raise end + + protected + def dashbord_url(id, message) + url_for :action => "dashboard", :params => { "id" => id, "message" => message } + end +end + +class RedirectTest < Test::Unit::TestCase + def setup + @controller = RedirectController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_simple_redirect + get :simple_redirect + assert_redirect_url "http://test.host/redirect/hello_world" + end + + def test_redirect_with_method_reference_and_parameters + get :method_redirect + assert_redirect_url "http://test.host/redirect/dashboard/1?message=hello" + end + + def test_simple_redirect_using_options + get :host_redirect + assert_redirected_to :action => "other_host", :only_path => false, :host => 'other.test.host' + end + + def test_redirect_error_with_pretty_diff + get :host_redirect + begin + assert_redirected_to :action => "other_host", :only_path => true + rescue Test::Unit::AssertionFailedError => err + redirection_msg, diff_msg = err.message.scan(/<\{[^\}]+\}>/).collect { |s| s[2..-3] } + assert_match %r(:only_path=>false), redirection_msg + assert_match %r(:host=>"other.test.host"), redirection_msg + assert_match %r(:action=>"other_host"), redirection_msg + assert_match %r(:only_path=>true), diff_msg + assert_match %r(:host=>"other.test.host"), diff_msg + end + end + + def test_module_redirect + get :module_redirect + assert_redirect_url "http://test.host/module_test/module_redirect/hello_world" + end + + def test_module_redirect_using_options + get :module_redirect + assert_redirected_to :controller => 'module_test/module_redirect', :action => 'hello_world' + end + + def test_redirect_with_assigns + get :redirect_with_assigns + assert_equal "world", assigns["hello"] + end + + def test_redirect_to_back + @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from" + get :redirect_to_back + assert_redirect_url "http://www.example.com/coming/from" + end + + def test_redirect_to_back_with_no_referer + assert_raises(ActionController::RedirectBackError) { + @request.env["HTTP_REFERER"] = nil + get :redirect_to_back + } + end +end + +module ModuleTest + class ModuleRedirectController < ::RedirectController + def module_redirect + redirect_to :controller => '/redirect', :action => "hello_world" + end + end + + class ModuleRedirectTest < Test::Unit::TestCase + def setup + @controller = ModuleRedirectController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_simple_redirect + get :simple_redirect + assert_redirect_url "http://test.host/module_test/module_redirect/hello_world" + end + + def test_redirect_with_method_reference_and_parameters + get :method_redirect + assert_redirect_url "http://test.host/module_test/module_redirect/dashboard/1?message=hello" + end + + def test_simple_redirect_using_options + get :host_redirect + assert_redirected_to :action => "other_host", :only_path => false, :host => 'other.test.host' + end + + def test_module_redirect + get :module_redirect + assert_redirect_url "http://test.host/redirect/hello_world" + end + + def test_module_redirect_using_options + get :module_redirect + assert_redirected_to :controller => 'redirect', :action => "hello_world" + end + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +unless defined?(Customer) + Customer = Struct.new("Customer", :name) +end + +module Fun + class GamesController < ActionController::Base + def hello_world + end + end +end + + +class TestController < ActionController::Base + layout :determine_layout + + def hello_world + end + + def render_hello_world + render "test/hello_world" + end + + def render_hello_world_from_variable + @person = "david" + render_text "hello #{@person}" + end + + def render_action_hello_world + render_action "hello_world" + end + + def render_action_hello_world_with_symbol + render_action :hello_world + end + + def render_text_hello_world + render_text "hello world" + end + + def render_custom_code + render_text "hello world", "404 Moved" + end + + def render_xml_hello + @name = "David" + render "test/hello" + end + + def greeting + # let's just rely on the template + end + + def layout_test + render_action "hello_world" + end + + def builder_layout_test + render_action "hello" + end + + def partials_list + @test_unchanged = 'hello' + @customers = [ Customer.new("david"), Customer.new("mary") ] + render_action "list" + end + + def partial_only + render_partial + end + + def hello_in_a_string + @customers = [ Customer.new("david"), Customer.new("mary") ] + render_text "How's there? #{render_to_string("test/list")}" + end + + def accessing_params_in_template + render_template "Hello: <%= params[:name] %>" + end + + def accessing_local_assigns_in_inline_template + name = params[:local_name] + render :inline => "<%= 'Goodbye, ' + local_name %>", + :locals => { :local_name => name } + end + + def accessing_local_assigns_in_inline_template_with_string_keys + name = params[:local_name] + ActionView::Base.local_assigns_support_string_keys = true + render :inline => "<%= 'Goodbye, ' + local_name %>", + :locals => { "local_name" => name } + ActionView::Base.local_assigns_support_string_keys = false + end + + def render_to_string_test + @foo = render_to_string :inline => "this is a test" + end + + def rescue_action(e) raise end + + private + def determine_layout + case action_name + when "layout_test": "layouts/standard" + when "builder_layout_test": "layouts/builder" + end + end +end + +TestController.template_root = File.dirname(__FILE__) + "/../fixtures/" +Fun::GamesController.template_root = File.dirname(__FILE__) + "/../fixtures/" + +class RenderTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + @controller = TestController.new + + @request.host = "www.nextangle.com" + end + + def test_simple_show + get :hello_world + assert_response 200 + assert_template "test/hello_world" + end + + def test_do_with_render + get :render_hello_world + assert_template "test/hello_world" + end + + def test_do_with_render_from_variable + get :render_hello_world_from_variable + assert_equal "hello david", @response.body + end + + def test_do_with_render_action + get :render_action_hello_world + assert_template "test/hello_world" + end + + def test_do_with_render_action_with_symbol + get :render_action_hello_world_with_symbol + assert_template "test/hello_world" + end + + def test_do_with_render_text + get :render_text_hello_world + assert_equal "hello world", @response.body + end + + def test_do_with_render_custom_code + get :render_custom_code + assert_response 404 + end + + def test_attempt_to_access_object_method + assert_raises(ActionController::UnknownAction, "No action responded to [clone]") { get :clone } + end + + def test_private_methods + assert_raises(ActionController::UnknownAction, "No action responded to [determine_layout]") { get :determine_layout } + end + + def test_access_to_request_in_view + view_internals_old_value = ActionController::Base.view_controller_internals + + ActionController::Base.view_controller_internals = false + ActionController::Base.protected_variables_cache = nil + + get :hello_world + assert_nil assigns["request"] + + ActionController::Base.view_controller_internals = true + ActionController::Base.protected_variables_cache = nil + + get :hello_world + assert_kind_of ActionController::AbstractRequest, assigns["request"] + + ActionController::Base.view_controller_internals = view_internals_old_value + ActionController::Base.protected_variables_cache = nil + end + + def test_render_xml + get :render_xml_hello + assert_equal "<html>\n <p>Hello David</p>\n<p>This is grand!</p>\n</html>\n", @response.body + end + + def test_render_xml_with_default + get :greeting + assert_equal "<p>This is grand!</p>\n", @response.body + end + + def test_layout_rendering + get :layout_test + assert_equal "<html>Hello world!</html>", @response.body + end + + def test_render_xml_with_layouts + get :builder_layout_test + assert_equal "<wrapper>\n<html>\n <p>Hello </p>\n<p>This is grand!</p>\n</html>\n</wrapper>\n", @response.body + end + + # def test_partials_list + # get :partials_list + # assert_equal "goodbyeHello: davidHello: marygoodbye\n", process_request.body + # end + + def test_partial_only + get :partial_only + assert_equal "only partial", @response.body + end + + def test_render_to_string + get :hello_in_a_string + assert_equal "How's there? goodbyeHello: davidHello: marygoodbye\n", @response.body + end + + def test_render_to_string_resets_assigns + get :render_to_string_test + assert_equal "The value of foo is: ::this is a test::\n", @response.body + end + + def test_nested_rendering + @controller = Fun::GamesController.new + get :hello_world + assert_equal "Living in a nested world", @response.body + end + + def test_accessing_params_in_template + get :accessing_params_in_template, :name => "David" + assert_equal "Hello: David", @response.body + end + + def test_accessing_local_assigns_in_inline_template + get :accessing_local_assigns_in_inline_template, :local_name => "Local David" + assert_equal "Goodbye, Local David", @response.body + end + + def test_accessing_local_assigns_in_inline_template_with_string_keys + get :accessing_local_assigns_in_inline_template_with_string_keys, :local_name => "Local David" + assert_equal "Goodbye, Local David", @response.body + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class RequestTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + end + + def test_remote_ip + assert_equal '0.0.0.0', @request.remote_ip + + @request.remote_addr = '1.2.3.4' + assert_equal '1.2.3.4', @request.remote_ip + + @request.env['HTTP_CLIENT_IP'] = '2.3.4.5' + assert_equal '2.3.4.5', @request.remote_ip + @request.env.delete 'HTTP_CLIENT_IP' + + @request.env['HTTP_X_FORWARDED_FOR'] = '3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '172.16.0.1,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '192.168.0.1,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1,3.4.5.6' + assert_equal '3.4.5.6', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = '127.0.0.1,3.4.5.6' + assert_equal '127.0.0.1', @request.remote_ip + + @request.env['HTTP_X_FORWARDED_FOR'] = 'unknown,192.168.0.1' + assert_equal '1.2.3.4', @request.remote_ip + @request.env.delete 'HTTP_X_FORWARDED_FOR' + end + + def test_domains + @request.host = "www.rubyonrails.org" + assert_equal "rubyonrails.org", @request.domain + + @request.host = "www.rubyonrails.co.uk" + assert_equal "rubyonrails.co.uk", @request.domain(2) + + @request.host = "192.168.1.200" + assert_nil @request.domain + + @request.host = nil + assert_nil @request.domain + end + + def test_subdomains + @request.host = "www.rubyonrails.org" + assert_equal %w( www ), @request.subdomains + + @request.host = "www.rubyonrails.co.uk" + assert_equal %w( www ), @request.subdomains(2) + + @request.host = "dev.www.rubyonrails.co.uk" + assert_equal %w( dev www ), @request.subdomains(2) + + @request.host = "foobar.foobar.com" + assert_equal %w( foobar ), @request.subdomains + + @request.host = nil + assert_equal [], @request.subdomains + end + + def test_port_string + @request.port = 80 + assert_equal "", @request.port_string + + @request.port = 8080 + assert_equal ":8080", @request.port_string + end + + def test_relative_url_root + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3' + assert_equal '', @request.relative_url_root, "relative_url_root should be disabled on lighttpd" + + @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text' + + @request.env['SCRIPT_NAME'] = nil + assert_equal "", @request.relative_url_root + + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "", @request.relative_url_root + + @request.env['SCRIPT_NAME'] = "/myapp.rb" + assert_equal "", @request.relative_url_root + + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + assert_equal "/hieraki", @request.relative_url_root + + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi" + assert_equal "/collaboration/hieraki", @request.relative_url_root + + # apache/scgi case + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/collaboration/hieraki" + assert_equal "/collaboration/hieraki", @request.relative_url_root + + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3' + @request.env['RAILS_RELATIVE_URL_ROOT'] = "/hieraki" + assert_equal "/hieraki", @request.relative_url_root + + # @env overrides path guess + @request.relative_url_root = nil + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text' + @request.env['RAILS_RELATIVE_URL_ROOT'] = "/real_url" + assert_equal "/real_url", @request.relative_url_root + end + + def test_request_uri + @request.env['SERVER_SOFTWARE'] = 'Apache 42.342.3432' + + @request.relative_url_root = nil + @request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri?mapped=1" + assert_equal "/path/of/some/uri?mapped=1", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri" + assert_equal "/path/of/some/uri", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/path/of/some/uri" + assert_equal "/path/of/some/uri", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/?m=b" + assert_equal "/?m=b", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/" + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/hieraki/" + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + assert_equal "/hieraki/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.set_REQUEST_URI "/collaboration/hieraki/books/edit/2" + @request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi" + assert_equal "/collaboration/hieraki/books/edit/2", @request.request_uri + assert_equal "/books/edit/2", @request.path + + # The following tests are for when REQUEST_URI is not supplied (as in IIS) + @request.relative_url_root = nil + @request.set_REQUEST_URI nil + @request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1" + @request.env['SCRIPT_NAME'] = nil #"/path/dispatch.rb" + assert_equal "/path/of/some/uri?mapped=1", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1" + @request.env['SCRIPT_NAME'] = "/path/dispatch.rb" + assert_equal "/path/of/some/uri?mapped=1", @request.request_uri + assert_equal "/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/path/of/some/uri" + @request.env['SCRIPT_NAME'] = nil + assert_equal "/path/of/some/uri", @request.request_uri + assert_equal "/path/of/some/uri", @request.path + + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/?m=b" + assert_equal "/?m=b", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/" + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "/", @request.request_uri + assert_equal "/", @request.path + + @request.relative_url_root = nil + @request.env['PATH_INFO'] = "/hieraki/" + @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi" + assert_equal "/hieraki/", @request.request_uri + assert_equal "/", @request.path + + # This test ensures that Rails uses REQUEST_URI over PATH_INFO + @request.relative_url_root = nil + @request.env['REQUEST_URI'] = "/some/path" + @request.env['PATH_INFO'] = "/another/path" + @request.env['SCRIPT_NAME'] = "/dispatch.cgi" + assert_equal "/some/path", @request.request_uri + assert_equal "/some/path", @request.path + end + + + def test_host_with_port + @request.host = "rubyonrails.org" + @request.port = 80 + assert_equal "rubyonrails.org", @request.host_with_port + + @request.host = "rubyonrails.org" + @request.port = 81 + assert_equal "rubyonrails.org:81", @request.host_with_port + end + + def test_server_software + assert_equal nil, @request.server_software + + @request.env['SERVER_SOFTWARE'] = 'Apache3.422' + assert_equal 'apache', @request.server_software + + @request.env['SERVER_SOFTWARE'] = 'lighttpd(1.1.4)' + assert_equal 'lighttpd', @request.server_software + end + + def test_xml_http_request + assert !@request.xml_http_request? + assert !@request.xhr? + + @request.env['HTTP_X_REQUESTED_WITH'] = "DefinitelyNotAjax1.0" + assert !@request.xml_http_request? + assert !@request.xhr? + + @request.env['HTTP_X_REQUESTED_WITH'] = "XMLHttpRequest" + assert @request.xml_http_request? + assert @request.xhr? + end + + def test_reports_ssl + assert !@request.ssl? + @request.env['HTTPS'] = 'on' + assert @request.ssl? + end + + def test_reports_ssl_when_proxied_via_lighttpd + assert !@request.ssl? + @request.env['HTTP_X_FORWARDED_PROTO'] = 'https' + assert @request.ssl? + end + +end +require File.dirname(__FILE__) + '/../abstract_unit' +require 'test/unit' +require File.dirname(__FILE__) + '/fake_controllers' +require 'stringio' + +RunTimeTests = ARGV.include? 'time' + +module ActionController::CodeGeneration + +class SourceTests < Test::Unit::TestCase + attr_accessor :source + def setup + @source = Source.new + end + + def test_initial_state + assert_equal [], source.lines + assert_equal 0, source.indentation_level + end + + def test_trivial_operations + source << "puts 'Hello World'" + assert_equal ["puts 'Hello World'"], source.lines + assert_equal "puts 'Hello World'", source.to_s + + source.line "puts 'Goodbye World'" + assert_equal ["puts 'Hello World'", "puts 'Goodbye World'"], source.lines + assert_equal "puts 'Hello World'\nputs 'Goodbye World'", source.to_s + end + + def test_indentation + source << "x = gets.to_i" + source << 'if x.odd?' + source.indent { source << "puts 'x is odd!'" } + source << 'else' + source.indent { source << "puts 'x is even!'" } + source << 'end' + + assert_equal ["x = gets.to_i", "if x.odd?", " puts 'x is odd!'", 'else', " puts 'x is even!'", 'end'], source.lines + + text = "x = gets.to_i +if x.odd? + puts 'x is odd!' +else + puts 'x is even!' +end" + + assert_equal text, source.to_s + end +end + +class CodeGeneratorTests < Test::Unit::TestCase + attr_accessor :generator + def setup + @generator = CodeGenerator.new + end + + def test_initial_state + assert_equal [], generator.source.lines + assert_equal [], generator.locals + end + + def test_trivial_operations + ["puts 'Hello World'", "puts 'Goodbye World'"].each {|l| generator << l} + assert_equal ["puts 'Hello World'", "puts 'Goodbye World'"], generator.source.lines + assert_equal "puts 'Hello World'\nputs 'Goodbye World'", generator.to_s + end + + def test_if + generator << "x = gets.to_i" + generator.if("x.odd?") { generator << "puts 'x is odd!'" } + + assert_equal "x = gets.to_i\nif x.odd?\n puts 'x is odd!'\nend", generator.to_s + end + + def test_else + test_if + generator.else { generator << "puts 'x is even!'" } + + assert_equal "x = gets.to_i\nif x.odd?\n puts 'x is odd!'\nelse \n puts 'x is even!'\nend", generator.to_s + end + + def test_dup + generator << 'x = 2' + generator.locals << :x + + g = generator.dup + assert_equal generator.source, g.source + assert_equal generator.locals, g.locals + + g << 'y = 3' + g.locals << :y + assert_equal [:x, :y], g.locals # Make sure they don't share the same array. + assert_equal [:x], generator.locals + end +end + +class RecognitionTests < Test::Unit::TestCase + attr_accessor :generator + alias :g :generator + def setup + @generator = RecognitionGenerator.new + end + + def go(components) + g.current = components.first + g.after = components[1..-1] || [] + g.go + end + + def execute(path, show = false) + path = path.split('/') if path.is_a? String + source = "index, path = 0, #{path.inspect}\n#{g.to_s}" + puts source if show + r = eval source + r ? r.symbolize_keys : nil + end + + Static = ::ActionController::Routing::StaticComponent + Dynamic = ::ActionController::Routing::DynamicComponent + Path = ::ActionController::Routing::PathComponent + Controller = ::ActionController::Routing::ControllerComponent + + def test_all_static + c = %w(hello world how are you).collect {|str| Static.new(str)} + + g.result :controller, "::ContentController", true + g.constant_result :action, 'index' + + go c + + assert_nil execute('x') + assert_nil execute('hello/world/how') + assert_nil execute('hello/world/how/are') + assert_nil execute('hello/world/how/are/you/today') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hello/world/how/are/you')) + end + + def test_basic_dynamic + c = [Static.new("hi"), Dynamic.new(:action)] + g.result :controller, "::ContentController", true + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi') + assert_nil execute('hi/dude/what') + assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) + end + + def test_basic_dynamic_backwards + c = [Dynamic.new(:action), Static.new("hi")] + go c + + assert_nil execute('') + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi') + assert_equal({:action => 'index'}, execute('index/hi')) + assert_equal({:action => 'show'}, execute('show/hi')) + assert_nil execute('hi/dude') + end + + def test_dynamic_with_default + c = [Static.new("hi"), Dynamic.new(:action, :default => 'index')] + g.result :controller, "::ContentController", true + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi/dude/what') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi')) + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) + assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) + end + + def test_dynamic_with_string_condition + c = [Static.new("hi"), Dynamic.new(:action, :condition => 'index')] + g.result :controller, "::ContentController", true + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi') + assert_nil execute('hi/dude/what') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) + assert_nil execute('hi/dude') + end + + def test_dynamic_with_string_condition_backwards + c = [Dynamic.new(:action, :condition => 'index'), Static.new("hi")] + g.result :controller, "::ContentController", true + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi') + assert_nil execute('dude/what/hi') + assert_nil execute('index/what') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('index/hi')) + assert_nil execute('dude/hi') + end + + def test_dynamic_with_regexp_condition + c = [Static.new("hi"), Dynamic.new(:action, :condition => /^[a-z]+$/)] + g.result :controller, "::ContentController", true + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi') + assert_nil execute('hi/FOXY') + assert_nil execute('hi/138708jkhdf') + assert_nil execute('hi/dkjfl8792343dfsf') + assert_nil execute('hi/dude/what') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) + assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) + end + + def test_dynamic_with_regexp_and_default + c = [Static.new("hi"), Dynamic.new(:action, :condition => /^[a-z]+$/, :default => 'index')] + g.result :controller, "::ContentController", true + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi/FOXY') + assert_nil execute('hi/138708jkhdf') + assert_nil execute('hi/dkjfl8792343dfsf') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi')) + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('hi/index')) + assert_equal({:controller => ::ContentController, :action => 'dude'}, execute('hi/dude')) + assert_nil execute('hi/dude/what') + end + + def test_path + c = [Static.new("hi"), Path.new(:file)] + g.result :controller, "::ContentController", true + g.constant_result :action, "download" + + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_equal({:controller => ::ContentController, :action => 'download', :file => []}, execute('hi')) + assert_equal({:controller => ::ContentController, :action => 'download', :file => %w(books agile_rails_dev.pdf)}, + execute('hi/books/agile_rails_dev.pdf')) + assert_equal({:controller => ::ContentController, :action => 'download', :file => ['dude']}, execute('hi/dude')) + assert_equal 'dude/what', execute('hi/dude/what')[:file].to_s + end + + def test_path_with_dynamic + c = [Dynamic.new(:action), Path.new(:file)] + g.result :controller, "::ContentController", true + + go c + + assert_nil execute('') + assert_equal({:controller => ::ContentController, :action => 'download', :file => []}, execute('download')) + assert_equal({:controller => ::ContentController, :action => 'download', :file => %w(books agile_rails_dev.pdf)}, + execute('download/books/agile_rails_dev.pdf')) + assert_equal({:controller => ::ContentController, :action => 'download', :file => ['dude']}, execute('download/dude')) + assert_equal 'dude/what', execute('hi/dude/what')[:file].to_s + end + + def test_path_with_dynamic_and_default + c = [Dynamic.new(:action, :default => 'index'), Path.new(:file)] + + go c + + assert_equal({:action => 'index', :file => []}, execute('')) + assert_equal({:action => 'index', :file => []}, execute('index')) + assert_equal({:action => 'blarg', :file => []}, execute('blarg')) + assert_equal({:action => 'index', :file => ['content']}, execute('index/content')) + assert_equal({:action => 'show', :file => ['rails_dev.pdf']}, execute('show/rails_dev.pdf')) + end + + def test_controller + c = [Static.new("hi"), Controller.new(:controller)] + g.constant_result :action, "hi" + + go c + + assert_nil execute('boo') + assert_nil execute('boo/blah') + assert_nil execute('hi/x') + assert_nil execute('hi/13870948') + assert_nil execute('hi/content/dog') + assert_nil execute('hi/admin/user/foo') + assert_equal({:controller => ::ContentController, :action => 'hi'}, execute('hi/content')) + assert_equal({:controller => ::Admin::UserController, :action => 'hi'}, execute('hi/admin/user')) + end + + def test_controller_with_regexp + c = [Static.new("hi"), Controller.new(:controller, :condition => /^admin\/.+$/)] + g.constant_result :action, "hi" + + go c + + assert_nil execute('hi') + assert_nil execute('hi/x') + assert_nil execute('hi/content') + assert_equal({:controller => ::Admin::UserController, :action => 'hi'}, execute('hi/admin/user')) + assert_equal({:controller => ::Admin::NewsFeedController, :action => 'hi'}, execute('hi/admin/news_feed')) + assert_nil execute('hi/admin/user/foo') + end + + def test_standard_route(time = ::RunTimeTests) + c = [Controller.new(:controller), Dynamic.new(:action, :default => 'index'), Dynamic.new(:id, :default => nil)] + go c + + # Make sure we get the right answers + assert_equal({:controller => ::ContentController, :action => 'index'}, execute('content')) + assert_equal({:controller => ::ContentController, :action => 'list'}, execute('content/list')) + assert_equal({:controller => ::ContentController, :action => 'show', :id => '10'}, execute('content/show/10')) + + assert_equal({:controller => ::Admin::UserController, :action => 'index'}, execute('admin/user')) + assert_equal({:controller => ::Admin::UserController, :action => 'list'}, execute('admin/user/list')) + assert_equal({:controller => ::Admin::UserController, :action => 'show', :id => 'nseckar'}, execute('admin/user/show/nseckar')) + + assert_nil execute('content/show/10/20') + assert_nil execute('food') + + if time + source = "def self.execute(path) + path = path.split('/') if path.is_a? String + index = 0 + r = #{g.to_s} + end" + eval(source) + + GC.start + n = 1000 + time = Benchmark.realtime do n.times { + execute('content') + execute('content/list') + execute('content/show/10') + + execute('admin/user') + execute('admin/user/list') + execute('admin/user/show/nseckar') + + execute('admin/user/show/nseckar/dude') + execute('admin/why/show/nseckar') + execute('content/show/10/20') + execute('food') + } end + time -= Benchmark.realtime do n.times { } end + + + puts "\n\nRecognition:" + per_url = time / (n * 10) + + puts "#{per_url * 1000} ms/url" + puts "#{1 / per_url} urls/s\n\n" + end + end + + def test_default_route + g.result :controller, "::ContentController", true + g.constant_result :action, 'index' + + go [] + + assert_nil execute('x') + assert_nil execute('hello/world/how') + assert_nil execute('hello/world/how/are') + assert_nil execute('hello/world/how/are/you/today') + assert_equal({:controller => ::ContentController, :action => 'index'}, execute([])) + end +end + +class GenerationTests < Test::Unit::TestCase + attr_accessor :generator + alias :g :generator + def setup + @generator = GenerationGenerator.new # ha! + end + + def go(components) + g.current = components.first + g.after = components[1..-1] || [] + g.go + end + + def execute(options, recall, show = false) + source = "\n +expire_on = ::ActionController::Routing.expiry_hash(options, recall) +hash = merged = recall.merge(options) +not_expired = true + +#{g.to_s}\n\n" + puts source if show + eval(source) + end + + Static = ::ActionController::Routing::StaticComponent + Dynamic = ::ActionController::Routing::DynamicComponent + Path = ::ActionController::Routing::PathComponent + Controller = ::ActionController::Routing::ControllerComponent + + def test_all_static_no_requirements + c = [Static.new("hello"), Static.new("world")] + go c + + assert_equal "/hello/world", execute({}, {}) + end + + def test_basic_dynamic + c = [Static.new("hi"), Dynamic.new(:action)] + go c + + assert_equal '/hi/index', execute({:action => 'index'}, {:action => 'index'}) + assert_equal '/hi/show', execute({:action => 'show'}, {:action => 'index'}) + assert_equal '/hi/list+people', execute({}, {:action => 'list people'}) + assert_nil execute({},{}) + end + + def test_dynamic_with_default + c = [Static.new("hi"), Dynamic.new(:action, :default => 'index')] + go c + + assert_equal '/hi', execute({:action => 'index'}, {:action => 'index'}) + assert_equal '/hi/show', execute({:action => 'show'}, {:action => 'index'}) + assert_equal '/hi/list+people', execute({}, {:action => 'list people'}) + assert_equal '/hi', execute({}, {}) + end + + def test_dynamic_with_regexp_condition + c = [Static.new("hi"), Dynamic.new(:action, :condition => /^[a-z]+$/)] + go c + + assert_equal '/hi/index', execute({:action => 'index'}, {:action => 'index'}) + assert_nil execute({:action => 'fox5'}, {:action => 'index'}) + assert_nil execute({:action => 'something_is_up'}, {:action => 'index'}) + assert_nil execute({}, {:action => 'list people'}) + assert_equal '/hi/abunchofcharacter', execute({:action => 'abunchofcharacter'}, {}) + assert_nil execute({}, {}) + end + + def test_dynamic_with_default_and_regexp_condition + c = [Static.new("hi"), Dynamic.new(:action, :default => 'index', :condition => /^[a-z]+$/)] + go c + + assert_equal '/hi', execute({:action => 'index'}, {:action => 'index'}) + assert_nil execute({:action => 'fox5'}, {:action => 'index'}) + assert_nil execute({:action => 'something_is_up'}, {:action => 'index'}) + assert_nil execute({}, {:action => 'list people'}) + assert_equal '/hi/abunchofcharacter', execute({:action => 'abunchofcharacter'}, {}) + assert_equal '/hi', execute({}, {}) + end + + def test_path + c = [Static.new("hi"), Path.new(:file)] + go c + + assert_equal '/hi', execute({:file => []}, {}) + assert_equal '/hi/books/agile_rails_dev.pdf', execute({:file => %w(books agile_rails_dev.pdf)}, {}) + assert_equal '/hi/books/development%26whatever/agile_rails_dev.pdf', execute({:file => %w(books development&whatever agile_rails_dev.pdf)}, {}) + + assert_equal '/hi', execute({:file => ''}, {}) + assert_equal '/hi/books/agile_rails_dev.pdf', execute({:file => 'books/agile_rails_dev.pdf'}, {}) + assert_equal '/hi/books/development%26whatever/agile_rails_dev.pdf', execute({:file => 'books/development&whatever/agile_rails_dev.pdf'}, {}) + end + + def test_controller + c = [Static.new("hi"), Controller.new(:controller)] + go c + + assert_nil execute({}, {}) + assert_equal '/hi/content', execute({:controller => 'content'}, {}) + assert_equal '/hi/admin/user', execute({:controller => 'admin/user'}, {}) + assert_equal '/hi/content', execute({}, {:controller => 'content'}) + assert_equal '/hi/admin/user', execute({}, {:controller => 'admin/user'}) + end + + def test_controller_with_regexp + c = [Static.new("hi"), Controller.new(:controller, :condition => /^admin\/.+$/)] + go c + + assert_nil execute({}, {}) + assert_nil execute({:controller => 'content'}, {}) + assert_equal '/hi/admin/user', execute({:controller => 'admin/user'}, {}) + assert_nil execute({}, {:controller => 'content'}) + assert_equal '/hi/admin/user', execute({}, {:controller => 'admin/user'}) + end + + def test_standard_route(time = ::RunTimeTests) + c = [Controller.new(:controller), Dynamic.new(:action, :default => 'index'), Dynamic.new(:id, :default => nil)] + go c + + # Make sure we get the right answers + assert_equal('/content', execute({:action => 'index'}, {:controller => 'content', :action => 'list'})) + assert_equal('/content/list', execute({:action => 'list'}, {:controller => 'content', :action => 'index'})) + assert_equal('/content/show/10', execute({:action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'})) + + assert_equal('/admin/user', execute({:action => 'index'}, {:controller => 'admin/user', :action => 'list'})) + assert_equal('/admin/user/list', execute({:action => 'list'}, {:controller => 'admin/user', :action => 'index'})) + assert_equal('/admin/user/show/10', execute({:action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'})) + + if time + GC.start + n = 1000 + time = Benchmark.realtime do n.times { + execute({:action => 'index'}, {:controller => 'content', :action => 'list'}) + execute({:action => 'list'}, {:controller => 'content', :action => 'index'}) + execute({:action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'}) + + execute({:action => 'index'}, {:controller => 'admin/user', :action => 'list'}) + execute({:action => 'list'}, {:controller => 'admin/user', :action => 'index'}) + execute({:action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'}) + } end + time -= Benchmark.realtime do n.times { } end + + puts "\n\nGeneration:" + per_url = time / (n * 6) + + puts "#{per_url * 1000} ms/url" + puts "#{1 / per_url} urls/s\n\n" + end + end + + def test_default_route + g.if(g.check_conditions(:controller => 'content', :action => 'welcome')) { go [] } + + assert_nil execute({:controller => 'foo', :action => 'welcome'}, {}) + assert_nil execute({:controller => 'content', :action => 'elcome'}, {}) + assert_nil execute({:action => 'elcome'}, {:controller => 'content'}) + + assert_equal '/', execute({:controller => 'content', :action => 'welcome'}, {}) + assert_equal '/', execute({:action => 'welcome'}, {:controller => 'content'}) + assert_equal '/', execute({:action => 'welcome', :id => '10'}, {:controller => 'content'}) + end +end + +class RouteTests < Test::Unit::TestCase + + def route(*args) + @route = ::ActionController::Routing::Route.new(*args) unless args.empty? + return @route + end + + def rec(path, show = false) + path = path.split('/') if path.is_a? String + index = 0 + source = route.write_recognition.to_s + puts "\n\n#{source}\n\n" if show + r = eval(source) + r ? r.symbolize_keys : r + end + def gen(options, recall = nil, show = false) + recall ||= options.dup + + expire_on = ::ActionController::Routing.expiry_hash(options, recall) + hash = merged = recall.merge(options) + not_expired = true + + source = route.write_generation.to_s + puts "\n\n#{source}\n\n" if show + eval(source) + + end + + def test_static + route 'hello/world', :known => 'known_value', :controller => 'content', :action => 'index' + + assert_nil rec('hello/turn') + assert_nil rec('turn/world') + assert_equal( + {:known => 'known_value', :controller => ::ContentController, :action => 'index'}, + rec('hello/world') + ) + + assert_nil gen(:known => 'foo') + assert_nil gen({}) + assert_equal '/hello/world', gen(:known => 'known_value', :controller => 'content', :action => 'index') + assert_equal '/hello/world', gen(:known => 'known_value', :extra => 'hi', :controller => 'content', :action => 'index') + assert_equal [:extra], route.extra_keys(:known => 'known_value', :extra => 'hi') + end + + def test_dynamic + route 'hello/:name', :controller => 'content', :action => 'show_person' + + assert_nil rec('hello') + assert_nil rec('foo/bar') + assert_equal({:controller => ::ContentController, :action => 'show_person', :name => 'rails'}, rec('hello/rails')) + assert_equal({:controller => ::ContentController, :action => 'show_person', :name => 'Nicholas Seckar'}, rec('hello/Nicholas+Seckar')) + + assert_nil gen(:controller => 'content', :action => 'show_dude', :name => 'rails') + assert_nil gen(:controller => 'content', :action => 'show_person') + assert_nil gen(:controller => 'admin/user', :action => 'show_person', :name => 'rails') + assert_equal '/hello/rails', gen(:controller => 'content', :action => 'show_person', :name => 'rails') + assert_equal '/hello/Nicholas+Seckar', gen(:controller => 'content', :action => 'show_person', :name => 'Nicholas Seckar') + end + + def test_typical + route ':controller/:action/:id', :action => 'index', :id => nil + assert_nil rec('hello') + assert_nil rec('foo bar') + assert_equal({:controller => ::ContentController, :action => 'index'}, rec('content')) + assert_equal({:controller => ::Admin::UserController, :action => 'index'}, rec('admin/user')) + + assert_equal({:controller => ::Admin::UserController, :action => 'index'}, rec('admin/user/index')) + assert_equal({:controller => ::Admin::UserController, :action => 'list'}, rec('admin/user/list')) + assert_equal({:controller => ::Admin::UserController, :action => 'show', :id => '10'}, rec('admin/user/show/10')) + + assert_equal({:controller => ::ContentController, :action => 'list'}, rec('content/list')) + assert_equal({:controller => ::ContentController, :action => 'show', :id => '10'}, rec('content/show/10')) + + + assert_equal '/content', gen(:controller => 'content', :action => 'index') + assert_equal '/content/list', gen(:controller => 'content', :action => 'list') + assert_equal '/content/show/10', gen(:controller => 'content', :action => 'show', :id => '10') + + assert_equal '/admin/user', gen(:controller => 'admin/user', :action => 'index') + assert_equal '/admin/user', gen(:controller => 'admin/user') + assert_equal '/admin/user', gen({:controller => 'admin/user'}, {:controller => 'content', :action => 'list', :id => '10'}) + assert_equal '/admin/user/show/10', gen(:controller => 'admin/user', :action => 'show', :id => '10') + end +end + +class RouteSetTests < Test::Unit::TestCase + attr_reader :rs + def setup + @rs = ::ActionController::Routing::RouteSet.new + @rs.draw {|m| m.connect ':controller/:action/:id' } + ::ActionController::Routing::NamedRoutes.clear + end + + def test_default_setup + assert_equal({:controller => ::ContentController, :action => 'index'}.stringify_keys, rs.recognize_path(%w(content))) + assert_equal({:controller => ::ContentController, :action => 'list'}.stringify_keys, rs.recognize_path(%w(content list))) + assert_equal({:controller => ::ContentController, :action => 'show', :id => '10'}.stringify_keys, rs.recognize_path(%w(content show 10))) + + assert_equal({:controller => ::Admin::UserController, :action => 'show', :id => '10'}.stringify_keys, rs.recognize_path(%w(admin user show 10))) + + assert_equal ['/admin/user/show/10', []], rs.generate({:controller => 'admin/user', :action => 'show', :id => 10}) + + assert_equal ['/admin/user/show', []], rs.generate({:action => 'show'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + assert_equal ['/admin/user/list/10', []], rs.generate({}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + + assert_equal ['/admin/stuff', []], rs.generate({:controller => 'stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + assert_equal ['/stuff', []], rs.generate({:controller => '/stuff'}, {:controller => 'admin/user', :action => 'list', :id => '10'}) + end + + def test_ignores_leading_slash + @rs.draw {|m| m.connect '/:controller/:action/:id'} + test_default_setup + end + + def test_time_recognition + n = 10000 + if RunTimeTests + GC.start + rectime = Benchmark.realtime do + n.times do + rs.recognize_path(%w(content)) + rs.recognize_path(%w(content list)) + rs.recognize_path(%w(content show 10)) + rs.recognize_path(%w(admin user)) + rs.recognize_path(%w(admin user list)) + rs.recognize_path(%w(admin user show 10)) + end + end + puts "\n\nRecognition (RouteSet):" + per_url = rectime / (n * 6) + puts "#{per_url * 1000} ms/url" + puts "#{1 / per_url} url/s\n\n" + end + end + def test_time_generation + n = 5000 + if RunTimeTests + GC.start + pairs = [ + [{:controller => 'content', :action => 'index'}, {:controller => 'content', :action => 'show'}], + [{:controller => 'content'}, {:controller => 'content', :action => 'index'}], + [{:controller => 'content', :action => 'list'}, {:controller => 'content', :action => 'index'}], + [{:controller => 'content', :action => 'show', :id => '10'}, {:controller => 'content', :action => 'list'}], + [{:controller => 'admin/user', :action => 'index'}, {:controller => 'admin/user', :action => 'show'}], + [{:controller => 'admin/user'}, {:controller => 'admin/user', :action => 'index'}], + [{:controller => 'admin/user', :action => 'list'}, {:controller => 'admin/user', :action => 'index'}], + [{:controller => 'admin/user', :action => 'show', :id => '10'}, {:controller => 'admin/user', :action => 'list'}], + ] + p = nil + gentime = Benchmark.realtime do + n.times do + pairs.each {|(a, b)| rs.generate(a, b)} + end + end + + puts "\n\nGeneration (RouteSet): (#{(n * 8)} urls)" + per_url = gentime / (n * 8) + puts "#{per_url * 1000} ms/url" + puts "#{1 / per_url} url/s\n\n" + end + end + + def test_route_with_colon_first + rs.draw do |map| + map.connect '/:controller/:action/:id', :action => 'index', :id => nil + map.connect ':url', :controller => 'tiny_url', :action => 'translate' + end + end + + def test_route_generating_string_literal_in_comparison_warning + old_stderr = $stderr + $stderr = StringIO.new + rs.draw do |map| + map.connect 'subscriptions/:action/:subscription_type', :controller => "subscriptions" + end + assert_equal "", $stderr.string + ensure + $stderr = old_stderr + end + + def test_route_with_regexp_for_controller + rs.draw do |map| + map.connect ':controller/:admintoken/:action/:id', :controller => /admin\/.+/ + map.connect ':controller/:action/:id' + end + assert_equal({:controller => ::Admin::UserController, :admintoken => "foo", :action => "index"}.stringify_keys, + rs.recognize_path(%w(admin user foo))) + assert_equal({:controller => ::ContentController, :action => "foo"}.stringify_keys, + rs.recognize_path(%w(content foo))) + assert_equal ['/admin/user/foo', []], rs.generate(:controller => "admin/user", :admintoken => "foo", :action => "index") + assert_equal ['/content/foo',[]], rs.generate(:controller => "content", :action => "foo") + end + + def test_basic_named_route + rs.home '', :controller => 'content', :action => 'list' + x = setup_for_named_route + assert_equal({:controller => '/content', :action => 'list'}, + x.new.send(:home_url)) + end + + def test_named_route_with_option + rs.page 'page/:title', :controller => 'content', :action => 'show_page' + x = setup_for_named_route + assert_equal({:controller => '/content', :action => 'show_page', :title => 'new stuff'}, + x.new.send(:page_url, :title => 'new stuff')) + end + + def test_named_route_with_default + rs.page 'page/:title', :controller => 'content', :action => 'show_page', :title => 'AboutPage' + x = setup_for_named_route + assert_equal({:controller => '/content', :action => 'show_page', :title => 'AboutPage'}, + x.new.send(:page_url)) + assert_equal({:controller => '/content', :action => 'show_page', :title => 'AboutRails'}, + x.new.send(:page_url, :title => "AboutRails")) + + end + + def setup_for_named_route + x = Class.new + x.send(:define_method, :url_for) {|x| x} + x.send :include, ::ActionController::Routing::NamedRoutes + x + end + + def test_named_route_without_hash + rs.draw do |map| + rs.normal ':controller/:action/:id' + end + end + + def test_named_route_with_regexps + rs.draw do |map| + rs.article 'page/:year/:month/:day/:title', :controller => 'page', :action => 'show', + :year => /^\d+$/, :month => /^\d+$/, :day => /^\d+$/ + rs.connect ':controller/:action/:id' + end + x = setup_for_named_route + assert_equal( + {:controller => '/page', :action => 'show', :title => 'hi'}, + x.new.send(:article_url, :title => 'hi') + ) + assert_equal( + {:controller => '/page', :action => 'show', :title => 'hi', :day => 10, :year => 2005, :month => 6}, + x.new.send(:article_url, :title => 'hi', :day => 10, :year => 2005, :month => 6) + ) + end + + def test_changing_controller + assert_equal ['/admin/stuff/show/10', []], rs.generate( + {:controller => 'stuff', :action => 'show', :id => 10}, + {:controller => 'admin/user', :action => 'index'} + ) + end + + def test_paths_escaped + rs.draw do |map| + rs.path 'file/*path', :controller => 'content', :action => 'show_file' + rs.connect ':controller/:action/:id' + end + results = rs.recognize_path %w(file hello+world how+are+you%3F) + assert results, "Recognition should have succeeded" + assert_equal ['hello world', 'how are you?'], results['path'] + + results = rs.recognize_path %w(file) + assert results, "Recognition should have succeeded" + assert_equal [], results['path'] + end + + def test_non_controllers_cannot_be_matched + rs.draw do + rs.connect ':controller/:action/:id' + end + assert_nil rs.recognize_path(%w(not_a show 10)), "Shouldn't recognize non-controllers as controllers!" + end + + def test_paths_do_not_accept_defaults + assert_raises(ActionController::RoutingError) do + rs.draw do |map| + rs.path 'file/*path', :controller => 'content', :action => 'show_file', :path => %w(fake default) + rs.connect ':controller/:action/:id' + end + end + + rs.draw do |map| + rs.path 'file/*path', :controller => 'content', :action => 'show_file', :path => [] + rs.connect ':controller/:action/:id' + end + end + + def test_backwards + rs.draw do |map| + rs.connect 'page/:id/:action', :controller => 'pages', :action => 'show' + rs.connect ':controller/:action/:id' + end + + assert_equal ['/page/20', []], rs.generate({:id => 20}, {:controller => 'pages'}) + assert_equal ['/page/20', []], rs.generate(:controller => 'pages', :id => 20, :action => 'show') + assert_equal ['/pages/boo', []], rs.generate(:controller => 'pages', :action => 'boo') + end + + def test_route_with_fixnum_default + rs.draw do |map| + rs.connect 'page/:id', :controller => 'content', :action => 'show_page', :id => 1 + rs.connect ':controller/:action/:id' + end + + assert_equal ['/page', []], rs.generate(:controller => 'content', :action => 'show_page') + assert_equal ['/page', []], rs.generate(:controller => 'content', :action => 'show_page', :id => 1) + assert_equal ['/page', []], rs.generate(:controller => 'content', :action => 'show_page', :id => '1') + assert_equal ['/page/10', []], rs.generate(:controller => 'content', :action => 'show_page', :id => 10) + + ctrl = ::ContentController + + assert_equal({'controller' => ctrl, 'action' => 'show_page', 'id' => 1}, rs.recognize_path(%w(page))) + assert_equal({'controller' => ctrl, 'action' => 'show_page', 'id' => '1'}, rs.recognize_path(%w(page 1))) + assert_equal({'controller' => ctrl, 'action' => 'show_page', 'id' => '10'}, rs.recognize_path(%w(page 10))) + end + + def test_action_expiry + assert_equal ['/content', []], rs.generate({:controller => 'content'}, {:controller => 'content', :action => 'show'}) + end + + def test_recognition_with_uppercase_controller_name + assert_equal({'controller' => ::ContentController, 'action' => 'index'}, rs.recognize_path(%w(Content))) + assert_equal({'controller' => ::ContentController, 'action' => 'list'}, rs.recognize_path(%w(Content list))) + assert_equal({'controller' => ::ContentController, 'action' => 'show', 'id' => '10'}, rs.recognize_path(%w(Content show 10))) + + assert_equal({'controller' => ::Admin::NewsFeedController, 'action' => 'index'}, rs.recognize_path(%w(Admin NewsFeed))) + assert_equal({'controller' => ::Admin::NewsFeedController, 'action' => 'index'}, rs.recognize_path(%w(Admin News_Feed))) + end + + def test_both_requirement_and_optional + rs.draw do + rs.blog('test/:year', :controller => 'post', :action => 'show', + :defaults => { :year => nil }, + :requirements => { :year => /\d{4}/ } + ) + rs.connect ':controller/:action/:id' + end + + assert_equal ['/test', []], rs.generate(:controller => 'post', :action => 'show') + assert_equal ['/test', []], rs.generate(:controller => 'post', :action => 'show', :year => nil) + + x = setup_for_named_route + assert_equal({:controller => '/post', :action => 'show'}, + x.new.send(:blog_url)) + end + + def test_set_to_nil_forgets + rs.draw do + rs.connect 'pages/:year/:month/:day', :controller => 'content', :action => 'list_pages', :month => nil, :day => nil + rs.connect ':controller/:action/:id' + end + + assert_equal ['/pages/2005', []], + rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005) + assert_equal ['/pages/2005/6', []], + rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6) + assert_equal ['/pages/2005/6/12', []], + rs.generate(:controller => 'content', :action => 'list_pages', :year => 2005, :month => 6, :day => 12) + + assert_equal ['/pages/2005/6/4', []], + rs.generate({:day => 4}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + + assert_equal ['/pages/2005/6', []], + rs.generate({:day => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + + assert_equal ['/pages/2005', []], + rs.generate({:day => nil, :month => nil}, {:controller => 'content', :action => 'list_pages', :year => '2005', :month => '6', :day => '12'}) + end + + def test_url_with_no_action_specified + rs.draw do + rs.connect '', :controller => 'content' + rs.connect ':controller/:action/:id' + end + + assert_equal ['/', []], rs.generate(:controller => 'content', :action => 'index') + assert_equal ['/', []], rs.generate(:controller => 'content') + end + + def test_named_url_with_no_action_specified + rs.draw do + rs.root '', :controller => 'content' + rs.connect ':controller/:action/:id' + end + + assert_equal ['/', []], rs.generate(:controller => 'content', :action => 'index') + assert_equal ['/', []], rs.generate(:controller => 'content') + + x = setup_for_named_route + assert_equal({:controller => '/content', :action => 'index'}, + x.new.send(:root_url)) + end + + def test_url_generated_when_forgetting_action + [{:controller => 'content', :action => 'index'}, {:controller => 'content'}].each do |hash| + rs.draw do + rs.root '', hash + rs.connect ':controller/:action/:id' + end + assert_equal ['/', []], rs.generate({:action => nil}, {:controller => 'content', :action => 'hello'}) + assert_equal ['/', []], rs.generate({:controller => 'content'}) + assert_equal ['/content/hi', []], rs.generate({:controller => 'content', :action => 'hi'}) + end + end + + def test_named_route_method + rs.draw do + assert_raises(ArgumentError) { rs.categories 'categories', :controller => 'content', :action => 'categories' } + + rs.named_route :categories, 'categories', :controller => 'content', :action => 'categories' + rs.connect ':controller/:action/:id' + end + + assert_equal ['/categories', []], rs.generate(:controller => 'content', :action => 'categories') + assert_equal ['/content/hi', []], rs.generate({:controller => 'content', :action => 'hi'}) + end + + def test_named_route_helper_array + test_named_route_method + assert_equal [:categories_url, :hash_for_categories_url], ::ActionController::Routing::NamedRoutes::Helpers + end + + def test_nil_defaults + rs.draw do + rs.connect 'journal', + :controller => 'content', + :action => 'list_journal', + :date => nil, :user_id => nil + rs.connect ':controller/:action/:id' + end + + assert_equal ['/journal', []], rs.generate(:controller => 'content', :action => 'list_journal', :date => nil, :user_id => nil) + end +end + +class ControllerComponentTest < Test::Unit::TestCase + + def test_traverse_to_controller_should_not_load_arbitrary_files + load_path = $:.dup + base = File.dirname(File.dirname(File.expand_path(__FILE__))) + $: << File.join(base, 'fixtures') + Object.send :const_set, :RAILS_ROOT, File.join(base, 'fixtures/application_root') + assert_equal nil, ActionController::Routing::ControllerComponent.traverse_to_controller(%w(dont_load pretty please)) + ensure + $:[0..-1] = load_path + Object.send :remove_const, :RAILS_ROOT + end + + def test_traverse_should_not_trip_on_non_module_constants + assert_equal nil, ActionController::Routing::ControllerComponent.traverse_to_controller(%w(admin some_constant a)) + end + + # This is evil, but people do it. + def test_traverse_to_controller_should_pass_thru_classes + load_path = $:.dup + base = File.dirname(File.dirname(File.expand_path(__FILE__))) + $: << File.join(base, 'fixtures') + $: << File.join(base, 'fixtures/application_root/app/controllers') + $: << File.join(base, 'fixtures/application_root/app/models') + Object.send :const_set, :RAILS_ROOT, File.join(base, 'fixtures/application_root') + pair = ActionController::Routing::ControllerComponent.traverse_to_controller(%w(a_class_that_contains_a_controller poorly_placed)) + + # Make sure the container class was loaded properly + assert defined?(AClassThatContainsAController) + assert_kind_of Class, AClassThatContainsAController + assert_equal :you_know_it, AClassThatContainsAController.is_special? + + # Make sure the controller was too + assert_kind_of Array, pair + assert_equal 2, pair[1] + klass = pair.first + assert_kind_of Class, klass + assert_equal :decidedly_so, klass.is_evil? + assert klass.ancestors.include?(ActionController::Base) + assert defined?(AClassThatContainsAController::PoorlyPlacedController) + assert_equal klass, AClassThatContainsAController::PoorlyPlacedController + ensure + $:[0..-1] = load_path + Object.send :remove_const, :RAILS_ROOT + end + + def test_traverse_to_nested_controller + load_path = $:.dup + base = File.dirname(File.dirname(File.expand_path(__FILE__))) + $: << File.join(base, 'fixtures') + $: << File.join(base, 'fixtures/application_root/app/controllers') + Object.send :const_set, :RAILS_ROOT, File.join(base, 'fixtures/application_root') + pair = ActionController::Routing::ControllerComponent.traverse_to_controller(%w(module_that_holds_controllers nested)) + + assert_not_equal nil, pair + + # Make sure that we created a module for the dir + assert defined?(ModuleThatHoldsControllers) + assert_kind_of Module, ModuleThatHoldsControllers + + # Make sure the controller is ok + assert_kind_of Array, pair + assert_equal 2, pair[1] + klass = pair.first + assert_kind_of Class, klass + assert klass.ancestors.include?(ActionController::Base) + assert defined?(ModuleThatHoldsControllers::NestedController) + assert_equal klass, ModuleThatHoldsControllers::NestedController + ensure + $:[0..-1] = load_path + Object.send :remove_const, :RAILS_ROOT + end + +end + +end +require File.join(File.dirname(__FILE__), '..', 'abstract_unit') + + +module TestFileUtils + def file_name() File.basename(__FILE__) end + def file_path() File.expand_path(__FILE__) end + def file_data() File.open(file_path, 'rb') { |f| f.read } end +end + + +class SendFileController < ActionController::Base + include TestFileUtils + layout "layouts/standard" # to make sure layouts don't interfere + + attr_writer :options + def options() @options ||= {} end + + def file() send_file(file_path, options) end + def data() send_data(file_data, options) end + + def rescue_action(e) raise end +end + +SendFileController.template_root = File.dirname(__FILE__) + "/../fixtures/" + +class SendFileTest < Test::Unit::TestCase + include TestFileUtils + + def setup + @controller = SendFileController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_file_nostream + @controller.options = { :stream => false } + response = nil + assert_nothing_raised { response = process('file') } + assert_not_nil response + assert_kind_of String, response.body + assert_equal file_data, response.body + end + + def test_file_stream + response = nil + assert_nothing_raised { response = process('file') } + assert_not_nil response + assert_kind_of Proc, response.body + + require 'stringio' + output = StringIO.new + output.binmode + assert_nothing_raised { response.body.call(response, output) } + assert_equal file_data, output.string + end + + def test_data + response = nil + assert_nothing_raised { response = process('data') } + assert_not_nil response + + assert_kind_of String, response.body + assert_equal file_data, response.body + end + + # Test that send_file_headers! is setting the correct HTTP headers. + def test_send_file_headers! + options = { + :length => 1, + :type => 'type', + :disposition => 'disposition', + :filename => 'filename' + } + + # Do it a few times: the resulting headers should be identical + # no matter how many times you send with the same options. + # Test resolving Ticket #458. + @controller.headers = {} + @controller.send(:send_file_headers!, options) + @controller.send(:send_file_headers!, options) + @controller.send(:send_file_headers!, options) + + h = @controller.headers + assert_equal 1, h['Content-Length'] + assert_equal 'type', h['Content-Type'] + assert_equal 'disposition; filename="filename"', h['Content-Disposition'] + assert_equal 'binary', h['Content-Transfer-Encoding'] + + # test overriding Cache-Control: no-cache header to fix IE open/save dialog + @controller.headers = { 'Cache-Control' => 'no-cache' } + @controller.send(:send_file_headers!, options) + h = @controller.headers + assert_equal 'private', h['Cache-Control'] + end + + %w(file data).each do |method| + define_method "test_send_#{method}_status" do + @controller.options = { :stream => false, :status => 500 } + assert_nothing_raised { assert_not_nil process(method) } + assert_equal '500', @controller.headers['Status'] + end + + define_method "test_default_send_#{method}_status" do + @controller.options = { :stream => false } + assert_nothing_raised { assert_not_nil process(method) } + assert_equal ActionController::Base::DEFAULT_RENDER_STATUS_CODE, @controller.headers['Status'] + end + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class SessionManagementTest < Test::Unit::TestCase + class SessionOffController < ActionController::Base + session :off + + def show + render_text "done" + end + + def tell + render_text "done" + end + end + + class TestController < ActionController::Base + session :off, :only => :show + session :session_secure => true, :except => :show + session :off, :only => :conditional, + :if => Proc.new { |r| r.parameters[:ws] } + + def show + render_text "done" + end + + def tell + render_text "done" + end + + def conditional + render_text ">>>#{params[:ws]}<<<" + end + end + + class SpecializedController < SessionOffController + session :disabled => false, :only => :something + + def something + render_text "done" + end + + def another + render_text "done" + end + end + + def setup + @request, @response = ActionController::TestRequest.new, + ActionController::TestResponse.new + end + + def test_session_off_globally + @controller = SessionOffController.new + get :show + assert_equal false, @request.session_options + get :tell + assert_equal false, @request.session_options + end + + def test_session_off_conditionally + @controller = TestController.new + get :show + assert_equal false, @request.session_options + get :tell + assert_instance_of Hash, @request.session_options + assert @request.session_options[:session_secure] + end + + def test_controller_specialization_overrides_settings + @controller = SpecializedController.new + get :something + assert_instance_of Hash, @request.session_options + get :another + assert_equal false, @request.session_options + end + + def test_session_off_with_if + @controller = TestController.new + get :conditional + assert_instance_of Hash, @request.session_options + get :conditional, :ws => "ws" + assert_equal false, @request.session_options + end + + def test_session_store_setting + ActionController::Base.session_store = :drb_store + assert_equal CGI::Session::DRbStore, ActionController::Base.session_store + + if Object.const_defined?(:ActiveRecord) + ActionController::Base.session_store = :active_record_store + assert_equal CGI::Session::ActiveRecordStore, ActionController::Base.session_store + end + end +end +require File.dirname(__FILE__) + '/../abstract_unit' +require File.dirname(__FILE__) + '/fake_controllers' + +class TestTest < Test::Unit::TestCase + class TestController < ActionController::Base + def set_flash + flash["test"] = ">#{flash["test"]}<" + render :text => 'ignore me' + end + + def render_raw_post + raise Test::Unit::AssertionFailedError, "#raw_post is blank" if request.raw_post.blank? + render :text => request.raw_post + end + + def test_params + render :text => params.inspect + end + + def test_uri + render :text => request.request_uri + end + + def test_html_output + render :text => <<HTML +<html> + <body> + <a href="/"><img src="/images/button.png" /></a> + <div id="foo"> + <ul> + <li class="item">hello</li> + <li class="item">goodbye</li> + </ul> + </div> + <div id="bar"> + <form action="/somewhere"> + Name: <input type="text" name="person[name]" id="person_name" /> + </form> + </div> + </body> +</html> +HTML + end + + def test_only_one_param + render :text => (params[:left] && params[:right]) ? "EEP, Both here!" : "OK" + end + + def test_remote_addr + render :text => (request.remote_addr || "not specified") + end + + def test_file_upload + render :text => params[:file].size + end + + def redirect_to_symbol + redirect_to :generate_url, :id => 5 + end + + private + + def rescue_action(e) + raise e + end + + def generate_url(opts) + url_for(opts.merge(:action => "test_uri")) + end + end + + def setup + @controller = TestController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + ActionController::Routing::Routes.reload + end + + def teardown + ActionController::Routing::Routes.reload + end + + def test_raw_post_handling + params = {:page => {:name => 'page name'}, 'some key' => 123} + get :render_raw_post, params.dup + + raw_post = params.map {|k,v| [CGI::escape(k.to_s), CGI::escape(v.to_s)].join('=')}.sort.join('&') + assert_equal raw_post, @response.body + end + + def test_process_without_flash + process :set_flash + assert_equal '><', flash['test'] + end + + def test_process_with_flash + process :set_flash, nil, nil, { "test" => "value" } + assert_equal '>value<', flash['test'] + end + + def test_process_with_request_uri_with_no_params + process :test_uri + assert_equal "/test_test/test/test_uri", @response.body + end + + def test_process_with_request_uri_with_params + process :test_uri, :id => 7 + assert_equal "/test_test/test/test_uri/7", @response.body + end + + def test_process_with_request_uri_with_params_with_explicit_uri + @request.set_REQUEST_URI "/explicit/uri" + process :test_uri, :id => 7 + assert_equal "/explicit/uri", @response.body + end + + def test_multiple_calls + process :test_only_one_param, :left => true + assert_equal "OK", @response.body + process :test_only_one_param, :right => true + assert_equal "OK", @response.body + end + + def test_assert_tag_tag + process :test_html_output + + # there is a 'form' tag + assert_tag :tag => 'form' + # there is not an 'hr' tag + assert_no_tag :tag => 'hr' + end + + def test_assert_tag_attributes + process :test_html_output + + # there is a tag with an 'id' of 'bar' + assert_tag :attributes => { :id => "bar" } + # there is no tag with a 'name' of 'baz' + assert_no_tag :attributes => { :name => "baz" } + end + + def test_assert_tag_parent + process :test_html_output + + # there is a tag with a parent 'form' tag + assert_tag :parent => { :tag => "form" } + # there is no tag with a parent of 'input' + assert_no_tag :parent => { :tag => "input" } + end + + def test_assert_tag_child + process :test_html_output + + # there is a tag with a child 'input' tag + assert_tag :child => { :tag => "input" } + # there is no tag with a child 'strong' tag + assert_no_tag :child => { :tag => "strong" } + end + + def test_assert_tag_ancestor + process :test_html_output + + # there is a 'li' tag with an ancestor having an id of 'foo' + assert_tag :ancestor => { :attributes => { :id => "foo" } }, :tag => "li" + # there is no tag of any kind with an ancestor having an href matching 'foo' + assert_no_tag :ancestor => { :attributes => { :href => /foo/ } } + end + + def test_assert_tag_descendant + process :test_html_output + + # there is a tag with a decendant 'li' tag + assert_tag :descendant => { :tag => "li" } + # there is no tag with a descendant 'html' tag + assert_no_tag :descendant => { :tag => "html" } + end + + def test_assert_tag_sibling + process :test_html_output + + # there is a tag with a sibling of class 'item' + assert_tag :sibling => { :attributes => { :class => "item" } } + # there is no tag with a sibling 'ul' tag + assert_no_tag :sibling => { :tag => "ul" } + end + + def test_assert_tag_after + process :test_html_output + + # there is a tag following a sibling 'div' tag + assert_tag :after => { :tag => "div" } + # there is no tag following a sibling tag with id 'bar' + assert_no_tag :after => { :attributes => { :id => "bar" } } + end + + def test_assert_tag_before + process :test_html_output + + # there is a tag preceeding a tag with id 'bar' + assert_tag :before => { :attributes => { :id => "bar" } } + # there is no tag preceeding a 'form' tag + assert_no_tag :before => { :tag => "form" } + end + + def test_assert_tag_children_count + process :test_html_output + + # there is a tag with 2 children + assert_tag :children => { :count => 2 } + # there is no tag with 4 children + assert_no_tag :children => { :count => 4 } + end + + def test_assert_tag_children_less_than + process :test_html_output + + # there is a tag with less than 5 children + assert_tag :children => { :less_than => 5 } + # there is no 'ul' tag with less than 2 children + assert_no_tag :children => { :less_than => 2 }, :tag => "ul" + end + + def test_assert_tag_children_greater_than + process :test_html_output + + # there is a 'body' tag with more than 1 children + assert_tag :children => { :greater_than => 1 }, :tag => "body" + # there is no tag with more than 10 children + assert_no_tag :children => { :greater_than => 10 } + end + + def test_assert_tag_children_only + process :test_html_output + + # there is a tag containing only one child with an id of 'foo' + assert_tag :children => { :count => 1, + :only => { :attributes => { :id => "foo" } } } + # there is no tag containing only one 'li' child + assert_no_tag :children => { :count => 1, :only => { :tag => "li" } } + end + + def test_assert_tag_content + process :test_html_output + + # the output contains the string "Name" + assert_tag :content => "Name" + # the output does not contain the string "test" + assert_no_tag :content => "test" + end + + def test_assert_tag_multiple + process :test_html_output + + # there is a 'div', id='bar', with an immediate child whose 'action' + # attribute matches the regexp /somewhere/. + assert_tag :tag => "div", :attributes => { :id => "bar" }, + :child => { :attributes => { :action => /somewhere/ } } + + # there is no 'div', id='foo', with a 'ul' child with more than + # 2 "li" children. + assert_no_tag :tag => "div", :attributes => { :id => "foo" }, + :child => { + :tag => "ul", + :children => { :greater_than => 2, + :only => { :tag => "li" } } } + end + + def test_assert_tag_children_without_content + process :test_html_output + + # there is a form tag with an 'input' child which is a self closing tag + assert_tag :tag => "form", + :children => { :count => 1, + :only => { :tag => "input" } } + + # the body tag has an 'a' child which in turn has an 'img' child + assert_tag :tag => "body", + :children => { :count => 1, + :only => { :tag => "a", + :children => { :count => 1, + :only => { :tag => "img" } } } } + end + + def test_assert_generates + assert_generates 'controller/action/5', :controller => 'controller', :action => 'action', :id => '5' + end + + def test_assert_routing + assert_routing 'content', :controller => 'content', :action => 'index' + end + + def test_assert_routing_in_module + assert_routing 'admin/user', :controller => 'admin/user', :action => 'index' + end + + def test_params_passing + get :test_params, :page => {:name => "Page name", :month => '4', :year => '2004', :day => '6'} + parsed_params = eval(@response.body) + assert_equal( + {'controller' => 'test_test/test', 'action' => 'test_params', + 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}}, + parsed_params + ) + end + + def test_id_converted_to_string + get :test_params, :id => 20, :foo => Object.new + assert_kind_of String, @request.path_parameters['id'] + end + + def test_array_path_parameter_handled_properly + with_routing do |set| + set.draw do + set.connect 'file/*path', :controller => 'test_test/test', :action => 'test_params' + set.connect ':controller/:action/:id' + end + + get :test_params, :path => ['hello', 'world'] + assert_equal ['hello', 'world'], @request.path_parameters['path'] + assert_equal 'hello/world', @request.path_parameters['path'].to_s + end + end + + def test_assert_realistic_path_parameters + get :test_params, :id => 20, :foo => Object.new + + # All elements of path_parameters should use string keys + @request.path_parameters.keys.each do |key| + assert_kind_of String, key + end + end + + def test_with_routing_places_routes_back + assert ActionController::Routing::Routes + routes_id = ActionController::Routing::Routes.object_id + + begin + with_routing { raise 'fail' } + fail 'Should not be here.' + rescue RuntimeError + end + + assert ActionController::Routing::Routes + assert_equal routes_id, ActionController::Routing::Routes.object_id + end + + def test_remote_addr + get :test_remote_addr + assert_equal "0.0.0.0", @response.body + + @request.remote_addr = "192.0.0.1" + get :test_remote_addr + assert_equal "192.0.0.1", @response.body + end + + def test_header_properly_reset_after_remote_http_request + xhr :get, :test_params + assert_nil @request.env['HTTP_X_REQUESTED_WITH'] + end + + def test_header_properly_reset_after_get_request + get :test_params + @request.recycle! + assert_nil @request.instance_variable_get("@request_method") + end + + %w(controller response request).each do |variable| + %w(get post put delete head process).each do |method| + define_method("test_#{variable}_missing_for_#{method}_raises_error") do + remove_instance_variable "@#{variable}" + begin + send(method, :test_remote_addr) + assert false, "expected RuntimeError, got nothing" + rescue RuntimeError => error + assert true + assert_match %r{@#{variable} is nil}, error.message + rescue => error + assert false, "expected RuntimeError, got #{error.class}" + end + end + end + end + + FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart' + + def test_test_uploaded_file + filename = 'mona_lisa.jpg' + path = "#{FILES_DIR}/#{filename}" + content_type = 'image/png' + + file = ActionController::TestUploadedFile.new(path, content_type) + assert_equal filename, file.original_filename + assert_equal content_type, file.content_type + assert_equal file.path, file.local_path + assert_equal File.read(path), file.read + end + + def test_fixture_file_upload + post :test_file_upload, :file => fixture_file_upload(FILES_DIR + "/mona_lisa.jpg", "image/jpg") + assert_equal 159528, @response.body + end + + def test_test_uploaded_file_exception_when_file_doesnt_exist + assert_raise(RuntimeError) { ActionController::TestUploadedFile.new('non_existent_file') } + end + + def test_assert_redirected_to_symbol + get :redirect_to_symbol + assert_redirected_to :generate_url + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class UrlRewriterTests < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @params = {} + @rewriter = ActionController::UrlRewriter.new(@request, @params) + end + + def test_simple_build_query_string + assert_query_equal '?x=1&y=2', @rewriter.send(:build_query_string, :x => '1', :y => '2') + end + def test_convert_ints_build_query_string + assert_query_equal '?x=1&y=2', @rewriter.send(:build_query_string, :x => 1, :y => 2) + end + def test_escape_spaces_build_query_string + assert_query_equal '?x=hello+world&y=goodbye+world', @rewriter.send(:build_query_string, :x => 'hello world', :y => 'goodbye world') + end + def test_expand_array_build_query_string + assert_query_equal '?x[]=1&x[]=2', @rewriter.send(:build_query_string, :x => [1, 2]) + end + + def test_escape_spaces_build_query_string_selected_keys + assert_query_equal '?x=hello+world', @rewriter.send(:build_query_string, {:x => 'hello world', :y => 'goodbye world'}, [:x]) + end + + def test_overwrite_params + @params[:controller] = 'hi' + @params[:action] = 'bye' + @params[:id] = '2' + + assert_equal '/hi/hi/2', @rewriter.rewrite(:only_path => true, :overwrite_params => {:action => 'hi'}) + u = @rewriter.rewrite(:only_path => false, :overwrite_params => {:action => 'hi'}) + assert_match %r(/hi/hi/2$), u + end + + + private + def split_query_string(str) + [str[0].chr] + str[1..-1].split(/&/).sort + end + + def assert_query_equal(q1, q2) + assert_equal(split_query_string(q1), split_query_string(q2)) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class VerificationTest < Test::Unit::TestCase + class TestController < ActionController::Base + verify :only => :guarded_one, :params => "one", + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_two, :params => %w( one two ), + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_with_flash, :params => "one", + :add_flash => { "notice" => "prereqs failed" }, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_in_session, :session => "one", + :redirect_to => { :action => "unguarded" } + + verify :only => [:multi_one, :multi_two], :session => %w( one two ), + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_by_method, :method => :post, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_by_xhr, :xhr => true, + :redirect_to => { :action => "unguarded" } + + verify :only => :guarded_by_not_xhr, :xhr => false, + :redirect_to => { :action => "unguarded" } + + before_filter :unconditional_redirect, :only => :two_redirects + verify :only => :two_redirects, :method => :post, + :redirect_to => { :action => "unguarded" } + + verify :only => :must_be_post, :method => :post, :render => { :status => 500, :text => "Must be post"} + + def guarded_one + render :text => "#{@params["one"]}" + end + + def guarded_with_flash + render :text => "#{@params["one"]}" + end + + def guarded_two + render :text => "#{@params["one"]}:#{@params["two"]}" + end + + def guarded_in_session + render :text => "#{@session["one"]}" + end + + def multi_one + render :text => "#{@session["one"]}:#{@session["two"]}" + end + + def multi_two + render :text => "#{@session["two"]}:#{@session["one"]}" + end + + def guarded_by_method + render :text => "#{@request.method}" + end + + def guarded_by_xhr + render :text => "#{@request.xhr?}" + end + + def guarded_by_not_xhr + render :text => "#{@request.xhr?}" + end + + def unguarded + render :text => "#{@params["one"]}" + end + + def two_redirects + render :nothing => true + end + + def must_be_post + render :text => "Was a post!" + end + + protected + def rescue_action(e) raise end + + def unconditional_redirect + redirect_to :action => "unguarded" + end + end + + def setup + @controller = TestController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_guarded_one_with_prereqs + get :guarded_one, :one => "here" + assert_equal "here", @response.body + end + + def test_guarded_one_without_prereqs + get :guarded_one + assert_redirected_to :action => "unguarded" + end + + def test_guarded_with_flash_with_prereqs + get :guarded_with_flash, :one => "here" + assert_equal "here", @response.body + assert_flash_empty + end + + def test_guarded_with_flash_without_prereqs + get :guarded_with_flash + assert_redirected_to :action => "unguarded" + assert_flash_equal "prereqs failed", "notice" + end + + def test_guarded_two_with_prereqs + get :guarded_two, :one => "here", :two => "there" + assert_equal "here:there", @response.body + end + + def test_guarded_two_without_prereqs_one + get :guarded_two, :two => "there" + assert_redirected_to :action => "unguarded" + end + + def test_guarded_two_without_prereqs_two + get :guarded_two, :one => "here" + assert_redirected_to :action => "unguarded" + end + + def test_guarded_two_without_prereqs_both + get :guarded_two + assert_redirected_to :action => "unguarded" + end + + def test_unguarded_with_params + get :unguarded, :one => "here" + assert_equal "here", @response.body + end + + def test_unguarded_without_params + get :unguarded + assert_equal "", @response.body + end + + def test_guarded_in_session_with_prereqs + get :guarded_in_session, {}, "one" => "here" + assert_equal "here", @response.body + end + + def test_guarded_in_session_without_prereqs + get :guarded_in_session + assert_redirected_to :action => "unguarded" + end + + def test_multi_one_with_prereqs + get :multi_one, {}, "one" => "here", "two" => "there" + assert_equal "here:there", @response.body + end + + def test_multi_one_without_prereqs + get :multi_one + assert_redirected_to :action => "unguarded" + end + + def test_multi_two_with_prereqs + get :multi_two, {}, "one" => "here", "two" => "there" + assert_equal "there:here", @response.body + end + + def test_multi_two_without_prereqs + get :multi_two + assert_redirected_to :action => "unguarded" + end + + def test_guarded_by_method_with_prereqs + post :guarded_by_method + assert_equal "post", @response.body + end + + def test_guarded_by_method_without_prereqs + get :guarded_by_method + assert_redirected_to :action => "unguarded" + end + + def test_guarded_by_xhr_with_prereqs + xhr :post, :guarded_by_xhr + assert_equal "true", @response.body + end + + def test_guarded_by_xhr_without_prereqs + get :guarded_by_xhr + assert_redirected_to :action => "unguarded" + end + + def test_guarded_by_not_xhr_with_prereqs + get :guarded_by_not_xhr + assert_equal "false", @response.body + end + + def test_guarded_by_not_xhr_without_prereqs + xhr :post, :guarded_by_not_xhr + assert_redirected_to :action => "unguarded" + end + + def test_guarded_post_and_calls_render_succeeds + post :must_be_post + assert_equal "Was a post!", @response.body + end + + def test_guarded_post_and_calls_render_fails + get :must_be_post + assert_response 500 + assert_equal "Must be post", @response.body + end + + + def test_second_redirect + assert_nothing_raised { get :two_redirects } + end +end +require File.dirname(__FILE__) + '/../abstract_unit' +require 'stringio' + +class WebServiceTest < Test::Unit::TestCase + + class MockCGI < CGI #:nodoc: + attr_accessor :stdinput, :stdoutput, :env_table + + def initialize(env, data = '') + self.env_table = env + self.stdinput = StringIO.new(data) + self.stdoutput = StringIO.new + super() + end + end + + + class TestController < ActionController::Base + session :off + + def assign_parameters + if params[:full] + render :text => dump_params_keys + else + render :text => (params.keys - ['controller', 'action']).sort.join(", ") + end + end + + def dump_params_keys(hash=params) + hash.keys.sort.inject("") do |s, k| + value = hash[k] + value = Hash === value ? "(#{dump_params_keys(value)})" : "" + s << ", " unless s.empty? + s << "#{k}#{value}" + end + end + + def rescue_action(e) raise end + end + + def setup + @controller = TestController.new + ActionController::Base.param_parsers.clear + ActionController::Base.param_parsers[Mime::XML] = :xml_node + end + + def test_check_parameters + process('GET') + assert_equal '', @controller.response.body + end + + def test_post_xml + process('POST', 'application/xml', '<entry attributed="true"><summary>content...</summary></entry>') + + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'content...', @controller.params["entry"].summary.node_value + assert_equal 'true', @controller.params["entry"]['attributed'] + end + + def test_put_xml + process('PUT', 'application/xml', '<entry attributed="true"><summary>content...</summary></entry>') + + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'content...', @controller.params["entry"].summary.node_value + assert_equal 'true', @controller.params["entry"]['attributed'] + end + + def test_register_and_use_yaml + ActionController::Base.param_parsers[Mime::YAML] = Proc.new { |d| YAML.load(d) } + process('POST', 'application/x-yaml', {"entry" => "loaded from yaml"}.to_yaml) + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'loaded from yaml', @controller.params["entry"] + end + + def test_register_and_use_yaml_as_symbol + ActionController::Base.param_parsers[Mime::YAML] = :yaml + process('POST', 'application/x-yaml', {"entry" => "loaded from yaml"}.to_yaml) + assert_equal 'entry', @controller.response.body + assert @controller.params.has_key?(:entry) + assert_equal 'loaded from yaml', @controller.params["entry"] + end + + def test_register_and_use_xml_simple + ActionController::Base.param_parsers[Mime::XML] = Proc.new { |data| XmlSimple.xml_in(data, 'ForceArray' => false) } + process('POST', 'application/xml', '<request><summary>content...</summary><title>SimpleXml</title></request>' ) + assert_equal 'summary, title', @controller.response.body + assert @controller.params.has_key?(:summary) + assert @controller.params.has_key?(:title) + assert_equal 'content...', @controller.params["summary"] + assert_equal 'SimpleXml', @controller.params["title"] + end + + def test_use_xml_ximple_with_empty_request + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + assert_nothing_raised { process('POST', 'application/xml', "") } + assert_equal "", @controller.response.body + end + + def test_deprecated_request_methods + process('POST', 'application/x-yaml') + assert_equal Mime::YAML, @controller.request.content_type + assert_equal true, @controller.request.post? + assert_equal :yaml, @controller.request.post_format + assert_equal true, @controller.request.yaml_post? + assert_equal false, @controller.request.xml_post? + end + + def test_dasherized_keys_as_xml + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', "<first-key>\n<sub-key>...</sub-key>\n</first-key>", true) + assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body + assert_equal "...", @controller.params[:first_key][:sub_key] + end + + def test_typecast_as_xml + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', <<-XML) + <data> + <a type="integer">15</a> + <b type="boolean">false</b> + <c type="boolean">true</c> + <d type="date">2005-03-17</d> + <e type="datetime">2005-03-17T21:41:07Z</e> + <f>unparsed</f> + <g type="integer">1</g> + <g>hello</g> + <g type="date">1974-07-25</g> + </data> + XML + params = @controller.params + assert_equal 15, params[:data][:a] + assert_equal false, params[:data][:b] + assert_equal true, params[:data][:c] + assert_equal Date.new(2005,3,17), params[:data][:d] + assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e] + assert_equal "unparsed", params[:data][:f] + assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g] + end + + def test_entities_unescaped_as_xml_simple + ActionController::Base.param_parsers[Mime::XML] = :xml_simple + process('POST', 'application/xml', <<-XML) + <data><foo "bar's" & friends></data> + XML + assert_equal %(<foo "bar's" & friends>), @controller.params[:data] + end + + def test_dasherized_keys_as_yaml + ActionController::Base.param_parsers[Mime::YAML] = :yaml + process('POST', 'application/x-yaml', "---\nfirst-key:\n sub-key: ...\n", true) + assert_equal 'action, controller, first_key(sub_key), full', @controller.response.body + assert_equal "...", @controller.params[:first_key][:sub_key] + end + + def test_typecast_as_yaml + ActionController::Base.param_parsers[Mime::YAML] = :yaml + process('POST', 'application/x-yaml', <<-YAML) + --- + data: + a: 15 + b: false + c: true + d: 2005-03-17 + e: 2005-03-17T21:41:07Z + f: unparsed + g: + - 1 + - hello + - 1974-07-25 + YAML + params = @controller.params + assert_equal 15, params[:data][:a] + assert_equal false, params[:data][:b] + assert_equal true, params[:data][:c] + assert_equal Date.new(2005,3,17), params[:data][:d] + assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e] + assert_equal "unparsed", params[:data][:f] + assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g] + end + + private + + def process(verb, content_type = 'application/x-www-form-urlencoded', data = '', full=false) + + cgi = MockCGI.new({ + 'REQUEST_METHOD' => verb, + 'CONTENT_TYPE' => content_type, + 'QUERY_STRING' => "action=assign_parameters&controller=webservicetest/test#{"&full=1" if full}", + "REQUEST_URI" => "/", + "HTTP_HOST" => 'testdomain.com', + "CONTENT_LENGTH" => data.size, + "SERVER_PORT" => "80", + "HTTPS" => "off"}, data) + + @controller.send(:process, ActionController::CgiRequest.new(cgi, {}), ActionController::CgiResponse.new(cgi)) + end + +end + + +class XmlNodeTest < Test::Unit::TestCase + def test_all + xn = XmlNode.from_xml(%{<?xml version="1.0" encoding="UTF-8"?> + <response success='true'> + <page title='Ajax Summit' id='1133' email_address='ry87ib@backpackit.com'> + <description>With O'Reilly and Adaptive Path</description> + <notes> + <note title='Hotel' id='1020' created_at='2005-05-14 16:41:11'> + Staying at the Savoy + </note> + </notes> + <tags> + <tag name='Technology' id='4' /> + <tag name='Travel' id='5' /> + </tags> + </page> + </response> + } + ) + assert_equal 'UTF-8', xn.node.document.encoding + assert_equal '1.0', xn.node.document.version + assert_equal 'true', xn['success'] + assert_equal 'response', xn.node_name + assert_equal 'Ajax Summit', xn.page['title'] + assert_equal '1133', xn.page['id'] + assert_equal "With O'Reilly and Adaptive Path", xn.page.description.node_value + assert_equal nil, xn.nonexistent + assert_equal "Staying at the Savoy", xn.page.notes.note.node_value.strip + assert_equal 'Technology', xn.page.tags.tag[0]['name'] + assert_equal 'Travel', xn.page.tags.tag[1][:name] + matches = xn.xpath('//@id').map{ |id| id.to_i } + assert_equal [4, 5, 1020, 1133], matches.sort + matches = xn.xpath('//tag').map{ |tag| tag['name'] } + assert_equal ['Technology', 'Travel'], matches.sort + assert_equal "Ajax Summit", xn.page['title'] + xn.page['title'] = 'Ajax Summit V2' + assert_equal "Ajax Summit V2", xn.page['title'] + assert_equal "Staying at the Savoy", xn.page.notes.note.node_value.strip + xn.page.notes.note.node_value = "Staying at the Ritz" + assert_equal "Staying at the Ritz", xn.page.notes.note.node_value.strip + assert_equal '5', xn.page.tags.tag[1][:id] + xn.page.tags.tag[1]['id'] = '7' + assert_equal '7', xn.page.tags.tag[1]['id'] + end + + + def test_small_entry + node = XmlNode.from_xml('<entry>hi</entry>') + assert_equal 'hi', node.node_value + end + +end +class AClassThatContainsAController::PoorlyPlacedController < ActionController::Base + + def self.is_evil? + :decidedly_so + end + +endclass ModuleThatHoldsControllers::NestedController < ActionController::Base + +endclass AClassThatContainsAController #often < ActiveRecord::Base + + def self.is_special? + :you_know_it + end + +endclass Company < ActiveRecord::Base + attr_protected :rating + set_sequence_name :companies_nonstd_seq + + validates_presence_of :name + def validate + errors.add('rating', 'rating should not be 2') if rating == 2 + end +endclass Developer < ActiveRecord::Base + has_and_belongs_to_many :projects +end + +class DeVeLoPeR < ActiveRecord::Base + set_table_name "developers" +end +# see routing/controller component tests + +raise Exception, "I should never be loaded"module AbcHelper + def bare_a() end + def bare_b() end + def bare_c() end +end +module Fun::GamesHelper + def stratego() "Iz guuut!" end +endmodule Fun::PDFHelper + def foobar() 'baz' end +end +class Project < ActiveRecord::Base + has_and_belongs_to_many :developers, :uniq => true +end +class Reply < ActiveRecord::Base + belongs_to :topic, :include => [:replies] + + validates_presence_of :content +end +class Topic < ActiveRecord::Base + has_many :replies, :include => [:user], :dependent => true +endrequire 'test/unit' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/date_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/form_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/text_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/tag_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/url_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/form_tag_helper' +# require File.dirname(__FILE__) + '/../../lib/action_view/helpers/active_record_helper' + +class ActiveRecordHelperTest < Test::Unit::TestCase + include ActionView::Helpers::FormHelper + include ActionView::Helpers::ActiveRecordHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::FormTagHelper + + silence_warnings do + Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on) + Post.class_eval do + alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast) + alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast) + alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast) + end + Column = Struct.new("Column", :type, :name, :human_name) + end + + def setup + @post = Post.new + def @post.errors + Class.new { + def on(field) field == "author_name" || field == "body" end + def empty?() false end + def count() 1 end + def full_messages() [ "Author name can't be empty" ] end + }.new + end + + def @post.new_record?() true end + def @post.to_param() nil end + + def @post.column_for_attribute(attr_name) + Post.content_columns.select { |column| column.name == attr_name }.first + end + + def Post.content_columns() [ Column.new(:string, "title", "Title"), Column.new(:text, "body", "Body") ] end + + @post.title = "Hello World" + @post.author_name = "" + @post.body = "Back to the hill and over it again!" + @post.secret = 1 + @post.written_on = Date.new(2004, 6, 15) + + @controller = Object.new + def @controller.url_for(options, *parameters_for_method_reference) + options = options.symbolize_keys + + [options[:action], options[:id].to_param].compact.join('/') + end + end + + def test_generic_input_tag + assert_dom_equal( + %(<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />), input("post", "title") + ) + end + + def test_text_area_with_errors + assert_dom_equal( + %(<div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div>), + text_area("post", "body") + ) + end + + def test_text_field_with_errors + assert_dom_equal( + %(<div class="fieldWithErrors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>), + text_field("post", "author_name") + ) + end + + def test_form_with_string + assert_dom_equal( + %(<form action="create" method="post"><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>), + form("post") + ) + + class << @post + def new_record?() false end + def to_param() id end + def id() 1 end + end + assert_dom_equal( + %(<form action="update/1" method="post"><input id="post_id" name="post[id]" type="hidden" value="1" /><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Update" /></form>), + form("post") + ) + end + + def test_form_with_date + def Post.content_columns() [ Column.new(:date, "written_on", "Written on") ] end + + assert_dom_equal( + %(<form action="create" method="post"><p><label for="post_written_on">Written on</label><br /><select name="post[written_on(1i)]">\n<option value="1999">1999</option>\n<option value="2000">2000</option>\n<option value="2001">2001</option>\n<option value="2002">2002</option>\n<option value="2003">2003</option>\n<option value="2004" selected="selected">2004</option>\n<option value="2005">2005</option>\n<option value="2006">2006</option>\n<option value="2007">2007</option>\n<option value="2008">2008</option>\n<option value="2009">2009</option>\n</select>\n<select name="post[written_on(2i)]">\n<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6" selected="selected">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n</select>\n<select name="post[written_on(3i)]">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15" selected="selected">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n</select>\n</p><input name="commit" type="submit" value="Create" /></form>), + form("post") + ) + end + + def test_form_with_datetime + def Post.content_columns() [ Column.new(:datetime, "written_on", "Written on") ] end + @post.written_on = Time.gm(2004, 6, 15, 16, 30) + + assert_dom_equal( + %(<form action="create" method="post"><p><label for="post_written_on">Written on</label><br /><select name="post[written_on(1i)]">\n<option value="1999">1999</option>\n<option value="2000">2000</option>\n<option value="2001">2001</option>\n<option value="2002">2002</option>\n<option value="2003">2003</option>\n<option value="2004" selected="selected">2004</option>\n<option value="2005">2005</option>\n<option value="2006">2006</option>\n<option value="2007">2007</option>\n<option value="2008">2008</option>\n<option value="2009">2009</option>\n</select>\n<select name="post[written_on(2i)]">\n<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6" selected="selected">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n</select>\n<select name="post[written_on(3i)]">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15" selected="selected">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n</select>\n — <select name="post[written_on(4i)]">\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n</select>\n : <select name="post[written_on(5i)]">\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30" selected="selected">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n</select>\n</p><input name="commit" type="submit" value="Create" /></form>), + form("post") + ) + end + + def test_error_for_block + assert_dom_equal %(<div class="errorExplanation" id="errorExplanation"><h2>1 error prohibited this post from being saved</h2><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>), error_messages_for("post") + assert_equal %(<div class="errorDeathByClass" id="errorDeathById"><h1>1 error prohibited this post from being saved</h1><p>There were problems with the following fields:</p><ul><li>Author name can't be empty</li></ul></div>), error_messages_for("post", :class => "errorDeathByClass", :id => "errorDeathById", :header_tag => "h1") + end + + def test_error_messages_for_handles_nil + assert_equal "", error_messages_for("notthere") + end + + def test_form_with_string_multipart + assert_dom_equal( + %(<form action="create" enctype="multipart/form-data" method="post"><p><label for="post_title">Title</label><br /><input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /></p>\n<p><label for="post_body">Body</label><br /><div class="fieldWithErrors"><textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea></div></p><input name="commit" type="submit" value="Create" /></form>), + form("post", :multipart => true) + ) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class AssetTagHelperTest < Test::Unit::TestCase + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::AssetTagHelper + + def setup + @controller = Class.new do + + attr_accessor :request + + def url_for(options, *parameters_for_method_reference) + "http://www.example.com" + end + + end.new + + @request = Class.new do + def relative_url_root + "" + end + end.new + + @controller.request = @request + + ActionView::Helpers::AssetTagHelper::reset_javascript_include_default + end + + def teardown + Object.send(:remove_const, :RAILS_ROOT) if defined?(RAILS_ROOT) + ENV["RAILS_ASSET_ID"] = nil + end + + AutoDiscoveryToTag = { + %(auto_discovery_link_tag) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />), + %(auto_discovery_link_tag(:atom)) => %(<link href="http://www.example.com" rel="alternate" title="ATOM" type="application/atom+xml" />), + %(auto_discovery_link_tag(:rss, :action => "feed")) => %(<link href="http://www.example.com" rel="alternate" title="RSS" type="application/rss+xml" />), + %(auto_discovery_link_tag(:rss, "http://localhost/feed")) => %(<link href="http://localhost/feed" rel="alternate" title="RSS" type="application/rss+xml" />), + %(auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My RSS"})) => %(<link href="http://www.example.com" rel="alternate" title="My RSS" type="application/rss+xml" />), + %(auto_discovery_link_tag(:rss, {}, {:title => "My RSS"})) => %(<link href="http://www.example.com" rel="alternate" title="My RSS" type="application/rss+xml" />), + %(auto_discovery_link_tag(nil, {}, {:type => "text/html"})) => %(<link href="http://www.example.com" rel="alternate" title="" type="text/html" />), + %(auto_discovery_link_tag(nil, {}, {:title => "No stream.. really", :type => "text/html"})) => %(<link href="http://www.example.com" rel="alternate" title="No stream.. really" type="text/html" />), + %(auto_discovery_link_tag(:rss, {}, {:title => "My RSS", :type => "text/html"})) => %(<link href="http://www.example.com" rel="alternate" title="My RSS" type="text/html" />), + %(auto_discovery_link_tag(:atom, {}, {:rel => "Not so alternate"})) => %(<link href="http://www.example.com" rel="Not so alternate" title="ATOM" type="application/atom+xml" />), + } + + JavascriptPathToTag = { + %(javascript_path("xmlhr")) => %(/javascripts/xmlhr.js), + %(javascript_path("super/xmlhr")) => %(/javascripts/super/xmlhr.js) + } + + JavascriptIncludeToTag = { + %(javascript_include_tag("xmlhr")) => %(<script src="/javascripts/xmlhr.js" type="text/javascript"></script>), + %(javascript_include_tag("xmlhr", :lang => "vbscript")) => %(<script lang="vbscript" src="/javascripts/xmlhr.js" type="text/javascript"></script>), + %(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/javascripts/common.javascript" type="text/javascript"></script>\n<script src="/elsewhere/cools.js" type="text/javascript"></script>), + %(javascript_include_tag(:defaults)) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>), + %(javascript_include_tag(:defaults, "test")) => %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/test.js" type="text/javascript"></script>), + %(javascript_include_tag("test", :defaults)) => %(<script src="/javascripts/test.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>) + } + + StylePathToTag = { + %(stylesheet_path("style")) => %(/stylesheets/style.css), + %(stylesheet_path('dir/file')) => %(/stylesheets/dir/file.css), + %(stylesheet_path('/dir/file')) => %(/dir/file.css) + } + + StyleLinkToTag = { + %(stylesheet_link_tag("style")) => %(<link href="/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />), + %(stylesheet_link_tag("/dir/file")) => %(<link href="/dir/file.css" media="screen" rel="Stylesheet" type="text/css" />), + %(stylesheet_link_tag("dir/file")) => %(<link href="/stylesheets/dir/file.css" media="screen" rel="Stylesheet" type="text/css" />), + %(stylesheet_link_tag("style", :media => "all")) => %(<link href="/stylesheets/style.css" media="all" rel="Stylesheet" type="text/css" />), + %(stylesheet_link_tag("random.styles", "/css/stylish")) => %(<link href="/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />\n<link href="/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />) + } + + ImagePathToTag = { + %(image_path("xml")) => %(/images/xml.png), + } + + ImageLinkToTag = { + %(image_tag("xml")) => %(<img alt="Xml" src="/images/xml.png" />), + %(image_tag("rss", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/images/rss.png" />), + %(image_tag("gold", :size => "45x70")) => %(<img alt="Gold" height="70" src="/images/gold.png" width="45" />), + %(image_tag("symbolize", "size" => "45x70")) => %(<img alt="Symbolize" height="70" src="/images/symbolize.png" width="45" />), + %(image_tag("http://www.rubyonrails.com/images/rails")) => %(<img alt="Rails" src="http://www.rubyonrails.com/images/rails.png" />) + } + + def test_auto_discovery + AutoDiscoveryToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_javascript_path + JavascriptPathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_javascript_include + JavascriptIncludeToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_register_javascript_include_default + ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider' + assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/slider.js" type="text/javascript"></script>), javascript_include_tag(:defaults) + ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'lib1', '/elsewhere/blub/lib2' + assert_dom_equal %(<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/slider.js" type="text/javascript"></script>\n<script src="/javascripts/lib1.js" type="text/javascript"></script>\n<script src="/elsewhere/blub/lib2.js" type="text/javascript"></script>), javascript_include_tag(:defaults) + end + + def test_style_path + StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_style_link + StyleLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_image_path + ImagePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_image_tag + ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_timebased_asset_id + Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") + expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s + assert_equal %(<img alt="Rails" src="/images/rails.png?#{expected_time}" />), image_tag("rails.png") + end + + def test_skipping_asset_id_on_complete_url + Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") + assert_equal %(<img alt="Rails" src="http://www.example.com/rails.png" />), image_tag("http://www.example.com/rails.png") + end + + def test_preset_asset_id + Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") + ENV["RAILS_ASSET_ID"] = "4500" + assert_equal %(<img alt="Rails" src="/images/rails.png?4500" />), image_tag("rails.png") + end +end + +class AssetTagHelperNonVhostTest < Test::Unit::TestCase + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::AssetTagHelper + + def setup + @controller = Class.new do + + attr_accessor :request + + def url_for(options, *parameters_for_method_reference) + "http://www.example.com/calloboration/hieraki" + end + + end.new + + @request = Class.new do + def relative_url_root + "/calloboration/hieraki" + end + end.new + + @controller.request = @request + + ActionView::Helpers::AssetTagHelper::reset_javascript_include_default + end + + AutoDiscoveryToTag = { + %(auto_discovery_link_tag(:rss, :action => "feed")) => %(<link href="http://www.example.com/calloboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), + %(auto_discovery_link_tag(:atom)) => %(<link href="http://www.example.com/calloboration/hieraki" rel="alternate" title="ATOM" type="application/atom+xml" />), + %(auto_discovery_link_tag) => %(<link href="http://www.example.com/calloboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), + } + + JavascriptPathToTag = { + %(javascript_path("xmlhr")) => %(/calloboration/hieraki/javascripts/xmlhr.js), + } + + JavascriptIncludeToTag = { + %(javascript_include_tag("xmlhr")) => %(<script src="/calloboration/hieraki/javascripts/xmlhr.js" type="text/javascript"></script>), + %(javascript_include_tag("common.javascript", "/elsewhere/cools")) => %(<script src="/calloboration/hieraki/javascripts/common.javascript" type="text/javascript"></script>\n<script src="/calloboration/hieraki/elsewhere/cools.js" type="text/javascript"></script>), + %(javascript_include_tag(:defaults)) => %(<script src="/calloboration/hieraki/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/effects.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/controls.js" type="text/javascript"></script>) + } + + StylePathToTag = { + %(stylesheet_path("style")) => %(/calloboration/hieraki/stylesheets/style.css), + } + + StyleLinkToTag = { + %(stylesheet_link_tag("style")) => %(<link href="/calloboration/hieraki/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />), + %(stylesheet_link_tag("random.styles", "/css/stylish")) => %(<link href="/calloboration/hieraki/stylesheets/random.styles" media="screen" rel="Stylesheet" type="text/css" />\n<link href="/calloboration/hieraki/css/stylish.css" media="screen" rel="Stylesheet" type="text/css" />) + } + + ImagePathToTag = { + %(image_path("xml")) => %(/calloboration/hieraki/images/xml.png), + } + + ImageLinkToTag = { + %(image_tag("xml")) => %(<img alt="Xml" src="/calloboration/hieraki/images/xml.png" />), + %(image_tag("rss", :alt => "rss syndication")) => %(<img alt="rss syndication" src="/calloboration/hieraki/images/rss.png" />), + %(image_tag("gold", :size => "45x70")) => %(<img alt="Gold" height="70" src="/calloboration/hieraki/images/gold.png" width="45" />), + %(image_tag("http://www.example.com/images/icon.gif")) => %(<img alt="Icon" src="http://www.example.com/images/icon.gif" />), + %(image_tag("symbolize", "size" => "45x70")) => %(<img alt="Symbolize" height="70" src="/calloboration/hieraki/images/symbolize.png" width="45" />) + } + + def test_auto_discovery + AutoDiscoveryToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_javascript_path + JavascriptPathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_javascript_include + JavascriptIncludeToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_register_javascript_include_default + ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'slider' + assert_dom_equal %(<script src="/calloboration/hieraki/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/effects.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/controls.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/slider.js" type="text/javascript"></script>), javascript_include_tag(:defaults) + ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'lib1', '/elsewhere/blub/lib2' + assert_dom_equal %(<script src="/calloboration/hieraki/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/effects.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/controls.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/slider.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/javascripts/lib1.js" type="text/javascript"></script>\n<script src="/calloboration/hieraki/elsewhere/blub/lib2.js" type="text/javascript"></script>), javascript_include_tag(:defaults) + end + + def test_style_path + StylePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_style_link + StyleLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_image_path + ImagePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + end + + def test_image_tag + ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) } + # Assigning a default alt tag should not cause an exception to be raised + assert_nothing_raised { image_tag('') } + end + + def test_stylesheet_with_asset_host_already_encoded + ActionController::Base.asset_host = "http://foo.example.com" + result = stylesheet_link_tag("http://bar.example.com/stylesheets/style.css") + assert_dom_equal( + %(<link href="http://bar.example.com/stylesheets/style.css" media="screen" rel="Stylesheet" type="text/css" />), + result) + ensure + ActionController::Base.asset_host = "" + end + +end +require 'test/unit' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/benchmark_helper' + +class BenchmarkHelperTest < Test::Unit::TestCase + include ActionView::Helpers::BenchmarkHelper + + class MockLogger + attr_reader :logged + + def initialize + @logged = [] + end + + def method_missing(method, *args) + @logged << [method, args] + end + end + + def setup + @logger = MockLogger.new + end + + def test_without_logger_or_block + @logger = nil + assert_nothing_raised { benchmark } + end + + def test_without_block + assert_raise(LocalJumpError) { benchmark } + assert @logger.logged.empty? + end + + def test_without_logger + @logger = nil + i_was_run = false + benchmark { i_was_run = true } + assert !i_was_run + end + + def test_defaults + i_was_run = false + benchmark { i_was_run = true } + assert i_was_run + assert 1, @logger.logged.size + assert_last_logged + end + + def test_with_message + i_was_run = false + benchmark('test_run') { i_was_run = true } + assert i_was_run + assert 1, @logger.logged.size + assert_last_logged 'test_run' + end + + def test_with_message_and_level + i_was_run = false + benchmark('debug_run', :debug) { i_was_run = true } + assert i_was_run + assert 1, @logger.logged.size + assert_last_logged 'debug_run', :debug + end + + private + def assert_last_logged(message = 'Benchmarking', level = :info) + last = @logger.logged.last + assert 2, last.size + assert_equal level, last.first + assert 1, last[1].size + assert last[1][0] =~ /^#{message} \(.*\)$/ + end +end +require 'test/unit' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/date_helper' +require File.dirname(__FILE__) + "/../abstract_unit" + +class CompiledTemplateTests < Test::Unit::TestCase + + def setup + @ct = ActionView::CompiledTemplates.new + @v = Class.new + @v.send :include, @ct + @a = './test_compile_template_a.rhtml' + @b = './test_compile_template_b.rhtml' + @s = './test_compile_template_link.rhtml' + end + def teardown + [@a, @b, @s].each do |f| + `rm #{f}` if File.exist?(f) || File.symlink?(f) + end + end + attr_reader :ct, :v + + def test_name_allocation + hi_world = ct.method_names['hi world'] + hi_sexy = ct.method_names['hi sexy'] + wish_upon_a_star = ct.method_names['I love seeing decent error messages'] + + assert_equal hi_world, ct.method_names['hi world'] + assert_equal hi_sexy, ct.method_names['hi sexy'] + assert_equal wish_upon_a_star, ct.method_names['I love seeing decent error messages'] + assert_equal 3, [hi_world, hi_sexy, wish_upon_a_star].uniq.length + end + + def test_wrap_source + assert_equal( + "def aliased_assignment(value)\nself.value = value\nend", + @ct.wrap_source(:aliased_assignment, [:value], 'self.value = value') + ) + + assert_equal( + "def simple()\nnil\nend", + @ct.wrap_source(:simple, [], 'nil') + ) + end + + def test_compile_source_single_method + selector = ct.compile_source('doubling method', [:a], 'a + a') + assert_equal 2, @v.new.send(selector, 1) + assert_equal 4, @v.new.send(selector, 2) + assert_equal -4, @v.new.send(selector, -2) + assert_equal 0, @v.new.send(selector, 0) + selector + end + + def test_compile_source_two_method + sel1 = test_compile_source_single_method # compile the method in the other test + sel2 = ct.compile_source('doubling method', [:a, :b], 'a + b + a + b') + assert_not_equal sel1, sel2 + + assert_equal 2, @v.new.send(sel1, 1) + assert_equal 4, @v.new.send(sel1, 2) + + assert_equal 6, @v.new.send(sel2, 1, 2) + assert_equal 32, @v.new.send(sel2, 15, 1) + end + + def test_mtime + t1 = Time.now + test_compile_source_single_method + assert (t1..Time.now).include?(ct.mtime('doubling method', [:a])) + end + + def test_compile_time + `echo '#{@a}' > #{@a}; echo '#{@b}' > #{@b}; ln -s #{@a} #{@s}` + + v = ActionView::Base.new + v.base_path = '.' + v.cache_template_loading = false; + + sleep 1 + t = Time.now + v.compile_and_render_template(:rhtml, '', @a) + v.compile_and_render_template(:rhtml, '', @b) + v.compile_and_render_template(:rhtml, '', @s) + a_n = v.method_names[@a] + b_n = v.method_names[@b] + s_n = v.method_names[@s] + # all of the files have changed since last compile + assert v.compile_time[a_n] > t + assert v.compile_time[b_n] > t + assert v.compile_time[s_n] > t + + sleep 1 + t = Time.now + v.compile_and_render_template(:rhtml, '', @a) + v.compile_and_render_template(:rhtml, '', @b) + v.compile_and_render_template(:rhtml, '', @s) + # none of the files have changed since last compile + assert v.compile_time[a_n] < t + assert v.compile_time[b_n] < t + assert v.compile_time[s_n] < t + + `rm #{@s}; ln -s #{@b} #{@s}` + v.compile_and_render_template(:rhtml, '', @a) + v.compile_and_render_template(:rhtml, '', @b) + v.compile_and_render_template(:rhtml, '', @s) + # the symlink has changed since last compile + assert v.compile_time[a_n] < t + assert v.compile_time[b_n] < t + assert v.compile_time[s_n] > t + + sleep 1 + `touch #{@b}` + t = Time.now + v.compile_and_render_template(:rhtml, '', @a) + v.compile_and_render_template(:rhtml, '', @b) + v.compile_and_render_template(:rhtml, '', @s) + # the file at the end of the symlink has changed since last compile + # both the symlink and the file at the end of it should be recompiled + assert v.compile_time[a_n] < t + assert v.compile_time[b_n] > t + assert v.compile_time[s_n] > t + end +end + +module ActionView + class Base + def compile_time + @@compile_time + end + def method_names + @@method_names + end + end +end +require 'test/unit' +require File.dirname(__FILE__) + "/../abstract_unit" + +class DateHelperTest < Test::Unit::TestCase + include ActionView::Helpers::DateHelper + include ActionView::Helpers::FormHelper + + silence_warnings do + Post = Struct.new("Post", :written_on, :updated_at) + end + + def test_distance_in_words + from = Time.mktime(2004, 3, 6, 21, 41, 18) + + assert_equal "less than a minute", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 41, 25)) + assert_equal "5 minutes", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 46, 25)) + assert_equal "about 1 hour", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 22, 47, 25)) + assert_equal "about 3 hours", distance_of_time_in_words(from, Time.mktime(2004, 3, 7, 0, 41)) + assert_equal "about 4 hours", distance_of_time_in_words(from, Time.mktime(2004, 3, 7, 1, 20)) + assert_equal "2 days", distance_of_time_in_words(from, Time.mktime(2004, 3, 9, 15, 40)) + + # include seconds + assert_equal "less than a minute", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 41, 19), false) + assert_equal "less than 5 seconds", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 41, 19), true) + assert_equal "less than 10 seconds", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 41, 28), true) + assert_equal "less than 20 seconds", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 41, 38), true) + assert_equal "half a minute", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 41, 48), true) + assert_equal "less than a minute", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 42, 17), true) + + assert_equal "1 minute", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 42, 18), true) + assert_equal "1 minute", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 42, 28), true) + assert_equal "2 minutes", distance_of_time_in_words(from, Time.mktime(2004, 3, 6, 21, 42, 48), true) + + # test to < from + assert_equal "about 4 hours", distance_of_time_in_words(Time.mktime(2004, 3, 7, 1, 20), from) + assert_equal "less than 20 seconds", distance_of_time_in_words(Time.mktime(2004, 3, 6, 21, 41, 38), from, true) + + # test with integers + assert_equal "less than a minute", distance_of_time_in_words(50) + assert_equal "about 1 hour", distance_of_time_in_words(60*60) + + # more cumbersome test with integers + assert_equal "less than a minute", distance_of_time_in_words(0, 50) + assert_equal "about 1 hour", distance_of_time_in_words(60*60, 0) + + end + + def test_distance_in_words_date + start_date = Date.new 1975, 1, 31 + end_date = Date.new 1977, 4, 17 + assert_not_equal("13 minutes", + distance_of_time_in_words(start_date, end_date)) + end + + def test_select_day + expected = %(<select name="date[day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_day(Time.mktime(2003, 8, 16)) + assert_equal expected, select_day(16) + end + + def test_select_day_with_blank + expected = %(<select name="date[day]">\n) + expected << +%(<option value=""></option>\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_day(Time.mktime(2003, 8, 16), :include_blank => true) + assert_equal expected, select_day(16, :include_blank => true) + end + + def test_select_day_nil_with_blank + expected = %(<select name="date[day]">\n) + expected << +%(<option value=""></option>\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_day(nil, :include_blank => true) + end + + def test_select_month + expected = %(<select name="date[month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16)) + assert_equal expected, select_month(8) + end + + def test_select_month_with_disabled + expected = %(<select name="date[month]" disabled="disabled">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :disabled => true) + assert_equal expected, select_month(8, :disabled => true) + end + + def test_select_month_with_field_name_override + expected = %(<select name="date[mois]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :field_name => 'mois') + assert_equal expected, select_month(8, :field_name => 'mois') + end + + def test_select_month_with_blank + expected = %(<select name="date[month]">\n) + expected << %(<option value=""></option>\n<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :include_blank => true) + assert_equal expected, select_month(8, :include_blank => true) + end + + def test_select_month_nil_with_blank + expected = %(<select name="date[month]">\n) + expected << %(<option value=""></option>\n<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(nil, :include_blank => true) + end + + def test_select_month_with_numbers + expected = %(<select name="date[month]">\n) + expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8" selected="selected">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :use_month_numbers => true) + assert_equal expected, select_month(8, :use_month_numbers => true) + end + + def test_select_month_with_numbers_and_names + expected = %(<select name="date[month]">\n) + expected << %(<option value="1">1 - January</option>\n<option value="2">2 - February</option>\n<option value="3">3 - March</option>\n<option value="4">4 - April</option>\n<option value="5">5 - May</option>\n<option value="6">6 - June</option>\n<option value="7">7 - July</option>\n<option value="8" selected="selected">8 - August</option>\n<option value="9">9 - September</option>\n<option value="10">10 - October</option>\n<option value="11">11 - November</option>\n<option value="12">12 - December</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :add_month_numbers => true) + assert_equal expected, select_month(8, :add_month_numbers => true) + end + + def test_select_month_with_numbers_and_names_with_abbv + expected = %(<select name="date[month]">\n) + expected << %(<option value="1">1 - Jan</option>\n<option value="2">2 - Feb</option>\n<option value="3">3 - Mar</option>\n<option value="4">4 - Apr</option>\n<option value="5">5 - May</option>\n<option value="6">6 - Jun</option>\n<option value="7">7 - Jul</option>\n<option value="8" selected="selected">8 - Aug</option>\n<option value="9">9 - Sep</option>\n<option value="10">10 - Oct</option>\n<option value="11">11 - Nov</option>\n<option value="12">12 - Dec</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :add_month_numbers => true, :use_short_month => true) + assert_equal expected, select_month(8, :add_month_numbers => true, :use_short_month => true) + end + + def test_select_month_with_abbv + expected = %(<select name="date[month]">\n) + expected << %(<option value="1">Jan</option>\n<option value="2">Feb</option>\n<option value="3">Mar</option>\n<option value="4">Apr</option>\n<option value="5">May</option>\n<option value="6">Jun</option>\n<option value="7">Jul</option>\n<option value="8" selected="selected">Aug</option>\n<option value="9">Sep</option>\n<option value="10">Oct</option>\n<option value="11">Nov</option>\n<option value="12">Dec</option>\n) + expected << "</select>\n" + + assert_equal expected, select_month(Time.mktime(2003, 8, 16), :use_short_month => true) + assert_equal expected, select_month(8, :use_short_month => true) + end + + def test_select_year + expected = %(<select name="date[year]">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + assert_equal expected, select_year(Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005) + assert_equal expected, select_year(2003, :start_year => 2003, :end_year => 2005) + end + + def test_select_year_with_disabled + expected = %(<select name="date[year]" disabled="disabled">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + assert_equal expected, select_year(Time.mktime(2003, 8, 16), :disabled => true, :start_year => 2003, :end_year => 2005) + assert_equal expected, select_year(2003, :disabled => true, :start_year => 2003, :end_year => 2005) + end + + def test_select_year_with_field_name_override + expected = %(<select name="date[annee]">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + assert_equal expected, select_year(Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005, :field_name => 'annee') + assert_equal expected, select_year(2003, :start_year => 2003, :end_year => 2005, :field_name => 'annee') + end + + def test_select_year_with_type_discarding + expected = %(<select name="date_year">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + assert_equal expected, select_year( + Time.mktime(2003, 8, 16), :prefix => "date_year", :discard_type => true, :start_year => 2003, :end_year => 2005) + assert_equal expected, select_year( + 2003, :prefix => "date_year", :discard_type => true, :start_year => 2003, :end_year => 2005) + end + + def test_select_year_descending + expected = %(<select name="date[year]">\n) + expected << %(<option value="2005" selected="selected">2005</option>\n<option value="2004">2004</option>\n<option value="2003">2003</option>\n) + expected << "</select>\n" + + assert_equal expected, select_year(Time.mktime(2005, 8, 16), :start_year => 2005, :end_year => 2003) + assert_equal expected, select_year(2005, :start_year => 2005, :end_year => 2003) + end + + def test_select_hour + expected = %(<select name="date[hour]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + assert_equal expected, select_hour(Time.mktime(2003, 8, 16, 8, 4, 18)) + end + + def test_select_hour_with_disabled + expected = %(<select name="date[hour]" disabled="disabled">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + assert_equal expected, select_hour(Time.mktime(2003, 8, 16, 8, 4, 18), :disabled => true) + end + + def test_select_hour_with_field_name_override + expected = %(<select name="date[heure]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + assert_equal expected, select_hour(Time.mktime(2003, 8, 16, 8, 4, 18), :field_name => 'heure') + end + + def test_select_hour_with_blank + expected = %(<select name="date[hour]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + assert_equal expected, select_hour(Time.mktime(2003, 8, 16, 8, 4, 18), :include_blank => true) + end + + def test_select_hour_nil_with_blank + expected = %(<select name="date[hour]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + assert_equal expected, select_hour(nil, :include_blank => true) + end + + def test_select_minute + expected = %(<select name="date[minute]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18)) + end + + def test_select_minute_with_disabled + expected = %(<select name="date[minute]" disabled="disabled">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), :disabled => true) + end + + def test_select_minute_with_field_name_override + expected = %(<select name="date[minuto]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), :field_name => 'minuto') + end + + def test_select_minute_with_blank + expected = %(<select name="date[minute]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), :include_blank => true) + end + + def test_select_minute_with_blank_and_step + expected = %(<select name="date[minute]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="15">15</option>\n<option value="30">30</option>\n<option value="45">45</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(Time.mktime(2003, 8, 16, 8, 4, 18), { :include_blank => true , :minute_step => 15 }) + end + + def test_select_minute_nil_with_blank + expected = %(<select name="date[minute]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(nil, :include_blank => true) + end + + def test_select_minute_nil_with_blank_and_step + expected = %(<select name="date[minute]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="15">15</option>\n<option value="30">30</option>\n<option value="45">45</option>\n) + expected << "</select>\n" + + assert_equal expected, select_minute(nil, { :include_blank => true , :minute_step => 15 }) + end + + def test_select_second + expected = %(<select name="date[second]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18" selected="selected">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18)) + end + + def test_select_second_with_disabled + expected = %(<select name="date[second]" disabled="disabled">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18" selected="selected">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18), :disabled => true) + end + + def test_select_second_with_field_name_override + expected = %(<select name="date[segundo]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18" selected="selected">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18), :field_name => 'segundo') + end + + def test_select_second_with_blank + expected = %(<select name="date[second]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18" selected="selected">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_second(Time.mktime(2003, 8, 16, 8, 4, 18), :include_blank => true) + end + + def test_select_second_nil_with_blank + expected = %(<select name="date[second]">\n) + expected << %(<option value=""></option>\n<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_second(nil, :include_blank => true) + end + + def test_select_date + expected = %(<select name="date[first][year]">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date( + Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005, :prefix => "date[first]" + ) + end + + def test_select_date_with_disabled + expected = %(<select name="date[first][year]" disabled="disabled">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][month]" disabled="disabled">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]" disabled="disabled">\n) + expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date(Time.mktime(2003, 8, 16), :start_year => 2003, :end_year => 2005, :prefix => "date[first]", :disabled => true) + end + + + def test_select_date_with_no_start_year + expected = %(<select name="date[first][year]">\n) + (Date.today.year-5).upto(Date.today.year+1) do |y| + if y == Date.today.year + expected << %(<option value="#{y}" selected="selected">#{y}</option>\n) + else + expected << %(<option value="#{y}">#{y}</option>\n) + end + end + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date( + Time.mktime(Date.today.year, 8, 16), :end_year => Date.today.year+1, :prefix => "date[first]" + ) + end + + def test_select_date_with_no_end_year + expected = %(<select name="date[first][year]">\n) + 2003.upto(2008) do |y| + if y == 2003 + expected << %(<option value="#{y}" selected="selected">#{y}</option>\n) + else + expected << %(<option value="#{y}">#{y}</option>\n) + end + end + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date( + Time.mktime(2003, 8, 16), :start_year => 2003, :prefix => "date[first]" + ) + end + + def test_select_date_with_no_start_or_end_year + expected = %(<select name="date[first][year]">\n) + (Date.today.year-5).upto(Date.today.year+5) do |y| + if y == Date.today.year + expected << %(<option value="#{y}" selected="selected">#{y}</option>\n) + else + expected << %(<option value="#{y}">#{y}</option>\n) + end + end + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date( + Time.mktime(Date.today.year, 8, 16), :prefix => "date[first]" + ) + end + + def test_select_time_with_seconds + expected = %(<select name="date[hour]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[minute]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[second]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18" selected="selected">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :include_seconds => true) + end + + def test_select_time_without_seconds + expected = %(<select name="date[hour]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08" selected="selected">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[minute]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04" selected="selected">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18)) + assert_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), :include_seconds => false) + end + + def test_date_select_with_zero_value + expected = %(<select name="date[first][year]">\n) + expected << %(<option value="2003">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date(0, :start_year => 2003, :end_year => 2005, :prefix => "date[first]") + end + + def test_date_select_within_fields_for + @post = Post.new + @post.written_on = Date.new(2004, 6, 15) + + _erbout = '' + + fields_for :post, @post do |f| + _erbout.concat f.date_select(:written_on) + end + + expected = "<select name='post[written_on(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n" + + "<select name='post[written_on(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n" + + "<select name='post[written_on(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n" + + assert_dom_equal(expected, _erbout) + end + + def test_datetime_select_within_fields_for + @post = Post.new + @post.updated_at = Time.local(2004, 6, 15, 16, 35) + + _erbout = '' + + fields_for :post, @post do |f| + _erbout.concat f.datetime_select(:updated_at) + end + + expected = "<select name='post[updated_at(1i)]'>\n<option value='1999'>1999</option>\n<option value='2000'>2000</option>\n<option value='2001'>2001</option>\n<option value='2002'>2002</option>\n<option value='2003'>2003</option>\n<option selected='selected' value='2004'>2004</option>\n<option value='2005'>2005</option>\n<option value='2006'>2006</option>\n<option value='2007'>2007</option>\n<option value='2008'>2008</option>\n<option value='2009'>2009</option>\n</select>\n<select name='post[updated_at(2i)]'>\n<option value='1'>January</option>\n<option value='2'>February</option>\n<option value='3'>March</option>\n<option value='4'>April</option>\n<option value='5'>May</option>\n<option selected='selected' value='6'>June</option>\n<option value='7'>July</option>\n<option value='8'>August</option>\n<option value='9'>September</option>\n<option value='10'>October</option>\n<option value='11'>November</option>\n<option value='12'>December</option>\n</select>\n<select name='post[updated_at(3i)]'>\n<option value='1'>1</option>\n<option value='2'>2</option>\n<option value='3'>3</option>\n<option value='4'>4</option>\n<option value='5'>5</option>\n<option value='6'>6</option>\n<option value='7'>7</option>\n<option value='8'>8</option>\n<option value='9'>9</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option selected='selected' value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n</select>\n — <select name='post[updated_at(4i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option selected='selected' value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n</select>\n : <select name='post[updated_at(5i)]'>\n<option value='00'>00</option>\n<option value='01'>01</option>\n<option value='02'>02</option>\n<option value='03'>03</option>\n<option value='04'>04</option>\n<option value='05'>05</option>\n<option value='06'>06</option>\n<option value='07'>07</option>\n<option value='08'>08</option>\n<option value='09'>09</option>\n<option value='10'>10</option>\n<option value='11'>11</option>\n<option value='12'>12</option>\n<option value='13'>13</option>\n<option value='14'>14</option>\n<option value='15'>15</option>\n<option value='16'>16</option>\n<option value='17'>17</option>\n<option value='18'>18</option>\n<option value='19'>19</option>\n<option value='20'>20</option>\n<option value='21'>21</option>\n<option value='22'>22</option>\n<option value='23'>23</option>\n<option value='24'>24</option>\n<option value='25'>25</option>\n<option value='26'>26</option>\n<option value='27'>27</option>\n<option value='28'>28</option>\n<option value='29'>29</option>\n<option value='30'>30</option>\n<option value='31'>31</option>\n<option value='32'>32</option>\n<option value='33'>33</option>\n<option value='34'>34</option>\n<option selected='selected' value='35'>35</option>\n<option value='36'>36</option>\n<option value='37'>37</option>\n<option value='38'>38</option>\n<option value='39'>39</option>\n<option value='40'>40</option>\n<option value='41'>41</option>\n<option value='42'>42</option>\n<option value='43'>43</option>\n<option value='44'>44</option>\n<option value='45'>45</option>\n<option value='46'>46</option>\n<option value='47'>47</option>\n<option value='48'>48</option>\n<option value='49'>49</option>\n<option value='50'>50</option>\n<option value='51'>51</option>\n<option value='52'>52</option>\n<option value='53'>53</option>\n<option value='54'>54</option>\n<option value='55'>55</option>\n<option value='56'>56</option>\n<option value='57'>57</option>\n<option value='58'>58</option>\n<option value='59'>59</option>\n</select>\n" + + assert_dom_equal(expected, _erbout) + end + + def test_date_select_with_zero_value_and_no_start_year + expected = %(<select name="date[first][year]">\n) + (Date.today.year-5).upto(Date.today.year+1) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date(0, :end_year => Date.today.year+1, :prefix => "date[first]") + end + + def test_date_select_with_zero_value_and_no_end_year + expected = %(<select name="date[first][year]">\n) + last_year = Time.now.year + 5 + 2003.upto(last_year) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date(0, :start_year => 2003, :prefix => "date[first]") + end + + def test_date_select_with_zero_value_and_no_start_and_end_year + expected = %(<select name="date[first][year]">\n) + (Date.today.year-5).upto(Date.today.year+5) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date(0, :prefix => "date[first]") + end + + def test_date_select_with_nil_value_and_no_start_and_end_year + expected = %(<select name="date[first][year]">\n) + (Date.today.year-5).upto(Date.today.year+5) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_equal expected, select_date(nil, :prefix => "date[first]") + end + + def test_datetime_select_with_nil_value_and_no_start_and_end_year + expected = %(<select name="date[first][year]">\n) + (Date.today.year-5).upto(Date.today.year+5) { |y| expected << %(<option value="#{y}">#{y}</option>\n) } + expected << "</select>\n" + + expected << %(<select name="date[first][month]">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][day]">\n) + expected << +%(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][hour]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n) + expected << "</select>\n" + + expected << %(<select name="date[first][minute]">\n) + expected << %(<option value="00">00</option>\n<option value="01">01</option>\n<option value="02">02</option>\n<option value="03">03</option>\n<option value="04">04</option>\n<option value="05">05</option>\n<option value="06">06</option>\n<option value="07">07</option>\n<option value="08">08</option>\n<option value="09">09</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n<option value="32">32</option>\n<option value="33">33</option>\n<option value="34">34</option>\n<option value="35">35</option>\n<option value="36">36</option>\n<option value="37">37</option>\n<option value="38">38</option>\n<option value="39">39</option>\n<option value="40">40</option>\n<option value="41">41</option>\n<option value="42">42</option>\n<option value="43">43</option>\n<option value="44">44</option>\n<option value="45">45</option>\n<option value="46">46</option>\n<option value="47">47</option>\n<option value="48">48</option>\n<option value="49">49</option>\n<option value="50">50</option>\n<option value="51">51</option>\n<option value="52">52</option>\n<option value="53">53</option>\n<option value="54">54</option>\n<option value="55">55</option>\n<option value="56">56</option>\n<option value="57">57</option>\n<option value="58">58</option>\n<option value="59">59</option>\n) + expected << "</select>\n" + + assert_equal expected, select_datetime(nil, :prefix => "date[first]") + end + +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class FormHelperTest < Test::Unit::TestCase + include ActionView::Helpers::FormHelper + include ActionView::Helpers::FormTagHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + + silence_warnings do + Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on, :cost) + Post.class_eval do + alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast) + alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast) + alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast) + end + end + + def setup + @post = Post.new + def @post.errors() Class.new{ def on(field) field == "author_name" end }.new end + + def @post.id; 123; end + def @post.id_before_type_cast; 123; end + + @post.title = "Hello World" + @post.author_name = "" + @post.body = "Back to the hill and over it again!" + @post.secret = 1 + @post.written_on = Date.new(2004, 6, 15) + + @controller = Class.new do + attr_reader :url_for_options + def url_for(options, *parameters_for_method_reference) + @url_for_options = options + "http://www.example.com" + end + end + @controller = @controller.new + end + + def test_text_field + assert_dom_equal( + '<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title") + ) + assert_dom_equal( + '<input id="post_title" name="post[title]" size="30" type="password" value="Hello World" />', password_field("post", "title") + ) + assert_dom_equal( + '<input id="person_name" name="person[name]" size="30" type="password" />', password_field("person", "name") + ) + end + + def test_text_field_with_escapes + @post.title = "<b>Hello World</b>" + assert_dom_equal( + '<input id="post_title" name="post[title]" size="30" type="text" value="<b>Hello World</b>" />', text_field("post", "title") + ) + end + + def test_text_field_with_options + expected = '<input id="post_title" name="post[title]" size="35" type="text" value="Hello World" />' + assert_dom_equal expected, text_field("post", "title", "size" => 35) + assert_dom_equal expected, text_field("post", "title", :size => 35) + end + + def test_text_field_assuming_size + expected = '<input id="post_title" maxlength="35" name="post[title]" size="35" type="text" value="Hello World" />' + assert_dom_equal expected, text_field("post", "title", "maxlength" => 35) + assert_dom_equal expected, text_field("post", "title", :maxlength => 35) + end + + def test_text_field_doesnt_change_param_values + object_name = 'post[]' + expected = '<input id="post_123_title" name="post[123][title]" size="30" type="text" value="Hello World" />' + assert_equal expected, text_field(object_name, "title") + assert_equal object_name, "post[]" + end + + def test_check_box + assert_dom_equal( + '<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />', + check_box("post", "secret") + ) + @post.secret = 0 + assert_dom_equal( + '<input id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />', + check_box("post", "secret") + ) + assert_dom_equal( + '<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />', + check_box("post", "secret" ,{"checked"=>"checked"}) + ) + @post.secret = true + assert_dom_equal( + '<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />', + check_box("post", "secret") + ) + end + + def test_check_box_with_explicit_checked_and_unchecked_values + @post.secret = "on" + assert_dom_equal( + '<input checked="checked" id="post_secret" name="post[secret]" type="checkbox" value="on" /><input name="post[secret]" type="hidden" value="off" />', + check_box("post", "secret", {}, "on", "off") + ) + end + + def test_radio_button + assert_dom_equal('<input checked="checked" id="post_title_hello_world" name="post[title]" type="radio" value="Hello World" />', + radio_button("post", "title", "Hello World") + ) + assert_dom_equal('<input id="post_title_goodbye_world" name="post[title]" type="radio" value="Goodbye World" />', + radio_button("post", "title", "Goodbye World") + ) + end + + def test_radio_button_is_checked_with_integers + assert_dom_equal('<input checked="checked" id="post_secret_1" name="post[secret]" type="radio" value="1" />', + radio_button("post", "secret", "1") + ) + end + + def test_text_area + assert_dom_equal( + '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + text_area("post", "body") + ) + end + + def test_text_area_with_escapes + @post.body = "Back to <i>the</i> hill and over it again!" + assert_dom_equal( + '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to <i>the</i> hill and over it again!</textarea>', + text_area("post", "body") + ) + end + + def test_text_area_with_alternate_value + assert_dom_equal( + '<textarea cols="40" id="post_body" name="post[body]" rows="20">Testing alternate values.</textarea>', + text_area("post", "body", :value => 'Testing alternate values.') + ) + end + + def test_date_selects + assert_dom_equal( + '<textarea cols="40" id="post_body" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + text_area("post", "body") + ) + end + + def test_explicit_name + assert_dom_equal( + '<input id="post_title" name="dont guess" size="30" type="text" value="Hello World" />', text_field("post", "title", "name" => "dont guess") + ) + assert_dom_equal( + '<textarea cols="40" id="post_body" name="really!" rows="20">Back to the hill and over it again!</textarea>', + text_area("post", "body", "name" => "really!") + ) + assert_dom_equal( + '<input checked="checked" id="post_secret" name="i mean it" type="checkbox" value="1" /><input name="i mean it" type="hidden" value="0" />', + check_box("post", "secret", "name" => "i mean it") + ) + assert_dom_equal text_field("post", "title", "name" => "dont guess"), + text_field("post", "title", :name => "dont guess") + assert_dom_equal text_area("post", "body", "name" => "really!"), + text_area("post", "body", :name => "really!") + assert_dom_equal check_box("post", "secret", "name" => "i mean it"), + check_box("post", "secret", :name => "i mean it") + end + + def test_explicit_id + assert_dom_equal( + '<input id="dont guess" name="post[title]" size="30" type="text" value="Hello World" />', text_field("post", "title", "id" => "dont guess") + ) + assert_dom_equal( + '<textarea cols="40" id="really!" name="post[body]" rows="20">Back to the hill and over it again!</textarea>', + text_area("post", "body", "id" => "really!") + ) + assert_dom_equal( + '<input checked="checked" id="i mean it" name="post[secret]" type="checkbox" value="1" /><input name="post[secret]" type="hidden" value="0" />', + check_box("post", "secret", "id" => "i mean it") + ) + assert_dom_equal text_field("post", "title", "id" => "dont guess"), + text_field("post", "title", :id => "dont guess") + assert_dom_equal text_area("post", "body", "id" => "really!"), + text_area("post", "body", :id => "really!") + assert_dom_equal check_box("post", "secret", "id" => "i mean it"), + check_box("post", "secret", :id => "i mean it") + end + + def test_auto_index + pid = @post.id + assert_dom_equal( + "<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title") + ) + assert_dom_equal( + "<textarea cols=\"40\" id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\" rows=\"20\">Back to the hill and over it again!</textarea>", + text_area("post[]", "body") + ) + assert_dom_equal( + "<input checked=\"checked\" id=\"post_#{pid}_secret\" name=\"post[#{pid}][secret]\" type=\"checkbox\" value=\"1\" /><input name=\"post[#{pid}][secret]\" type=\"hidden\" value=\"0\" />", + check_box("post[]", "secret") + ) + assert_dom_equal( +"<input checked=\"checked\" id=\"post_#{pid}_title_hello_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Hello World\" />", + radio_button("post[]", "title", "Hello World") + ) + assert_dom_equal("<input id=\"post_#{pid}_title_goodbye_world\" name=\"post[#{pid}][title]\" type=\"radio\" value=\"Goodbye World\" />", + radio_button("post[]", "title", "Goodbye World") + ) + end + + def test_form_for + _erbout = '' + + form_for(:post, @post, :html => { :id => 'create-post' }) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + "<form action='http://www.example.com' id='create-post' method='post'>" + + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' />" + + "</form>" + + assert_dom_equal expected, _erbout + end + + def test_form_for_without_object + _erbout = '' + + form_for(:post, :html => { :id => 'create-post' }) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + "<form action='http://www.example.com' id='create-post' method='post'>" + + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' />" + + "</form>" + + assert_dom_equal expected, _erbout + end + + def test_fields_for + _erbout = '' + + fields_for(:post, @post) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' />" + + assert_dom_equal expected, _erbout + end + + def test_fields_for_without_object + _erbout = '' + fields_for(:post) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' />" + + assert_dom_equal expected, _erbout + end + + def test_form_builder_does_not_have_form_for_method + assert ! ActionView::Helpers::FormBuilder.instance_methods.include?('form_for') + end + + def test_form_for_and_fields_for + _erbout = '' + + form_for(:post, @post, :html => { :id => 'create-post' }) do |post_form| + _erbout.concat post_form.text_field(:title) + _erbout.concat post_form.text_area(:body) + + fields_for(:parent_post, @post) do |parent_fields| + _erbout.concat parent_fields.check_box(:secret) + end + end + + expected = + "<form action='http://www.example.com' id='create-post' method='post'>" + + "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" + + "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='parent_post[secret]' checked='checked' type='checkbox' id='parent_post_secret' value='1' />" + + "<input name='parent_post[secret]' type='hidden' value='0' />" + + "</form>" + + assert_dom_equal expected, _erbout + end + + class LabelledFormBuilder < ActionView::Helpers::FormBuilder + (field_helpers - %w(hidden_field)).each do |selector| + src = <<-END_SRC + def #{selector}(field, *args, &proc) + "<label for='\#{field}'>\#{field.to_s.humanize}:</label> " + super + "<br/>" + end + END_SRC + class_eval src, __FILE__, __LINE__ + end + end + + def test_form_for_with_labelled_builder + _erbout = '' + + form_for(:post, @post, :builder => LabelledFormBuilder) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + "<form action='http://www.example.com' method='post'>" + + "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + "<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' /><br/>" + + "</form>" + + assert_dom_equal expected, _erbout + end + + # Perhaps this test should be moved to prototype helper tests. + def test_remote_form_for_with_labelled_builder + self.extend ActionView::Helpers::PrototypeHelper + _erbout = '' + + remote_form_for(:post, @post, :builder => LabelledFormBuilder) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + %(<form action="http://www.example.com" onsubmit="new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;" method="post">) + + "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + "<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' /><br/>" + + "</form>" + + assert_dom_equal expected, _erbout + end + + def test_fields_for_with_labelled_builder + _erbout = '' + + fields_for(:post, @post, :builder => LabelledFormBuilder) do |f| + _erbout.concat f.text_field(:title) + _erbout.concat f.text_area(:body) + _erbout.concat f.check_box(:secret) + end + + expected = + "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" + + "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" + + "<label for='secret'>Secret:</label> <input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" + + "<input name='post[secret]' type='hidden' value='0' /><br/>" + + assert_dom_equal expected, _erbout + end + + def test_form_for_with_html_options_adds_options_to_form_tag + _erbout = '' + + form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end + expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\"></form>" + + assert_dom_equal expected, _erbout + end + + def test_form_for_with_string_url_option + _erbout = '' + + form_for(:post, @post, :url => 'http://www.otherdomain.com') do |f| end + + assert_equal 'http://www.otherdomain.com', @controller.url_for_options + end + + def test_form_for_with_hash_url_option + _erbout = '' + + form_for(:post, @post, :url => {:controller => 'controller', :action => 'action'}) do |f| end + + assert_equal 'controller', @controller.url_for_options[:controller] + assert_equal 'action', @controller.url_for_options[:action] + end + + def test_remote_form_for_with_html_options_adds_options_to_form_tag + self.extend ActionView::Helpers::PrototypeHelper + _erbout = '' + + remote_form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end + expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\" onsubmit=\"new Ajax.Request('http://www.example.com', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\"></form>" + + assert_dom_equal expected, _erbout + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class MockTimeZone + attr_reader :name + + def initialize( name ) + @name = name + end + + def self.all + [ "A", "B", "C", "D", "E" ].map { |s| new s } + end + + def ==( z ) + z && @name == z.name + end + + def to_s + @name + end +end + +ActionView::Helpers::FormOptionsHelper::TimeZone = MockTimeZone + +class FormOptionsHelperTest < Test::Unit::TestCase + include ActionView::Helpers::FormHelper + include ActionView::Helpers::FormOptionsHelper + + silence_warnings do + Post = Struct.new('Post', :title, :author_name, :body, :secret, :written_on, :category, :origin) + Continent = Struct.new('Continent', :continent_name, :countries) + Country = Struct.new('Country', :country_id, :country_name) + Firm = Struct.new('Firm', :time_zone) + end + + def test_collection_options + @posts = [ + Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") + ] + + assert_dom_equal( + "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>", + options_from_collection_for_select(@posts, "author_name", "title") + ) + end + + + def test_collection_options_with_preselected_value + @posts = [ + Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") + ] + + assert_dom_equal( + "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\" selected=\"selected\">Babe went home</option>\n<option value=\"Cabe\">Cabe went home</option>", + options_from_collection_for_select(@posts, "author_name", "title", "Babe") + ) + end + + def test_collection_options_with_preselected_value_array + @posts = [ + Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") + ] + + assert_dom_equal( + "<option value=\"<Abe>\"><Abe> went home</option>\n<option value=\"Babe\" selected=\"selected\">Babe went home</option>\n<option value=\"Cabe\" selected=\"selected\">Cabe went home</option>", + options_from_collection_for_select(@posts, "author_name", "title", [ "Babe", "Cabe" ]) + ) + end + + def test_array_options_for_select + assert_dom_equal( + "<option value=\"<Denmark>\"><Denmark></option>\n<option value=\"USA\">USA</option>\n<option value=\"Sweden\">Sweden</option>", + options_for_select([ "<Denmark>", "USA", "Sweden" ]) + ) + end + + def test_array_options_for_select_with_selection + assert_dom_equal( + "<option value=\"Denmark\">Denmark</option>\n<option value=\"<USA>\" selected=\"selected\"><USA></option>\n<option value=\"Sweden\">Sweden</option>", + options_for_select([ "Denmark", "<USA>", "Sweden" ], "<USA>") + ) + end + + def test_array_options_for_select_with_selection_array + assert_dom_equal( + "<option value=\"Denmark\">Denmark</option>\n<option value=\"<USA>\" selected=\"selected\"><USA></option>\n<option value=\"Sweden\" selected=\"selected\">Sweden</option>", + options_for_select([ "Denmark", "<USA>", "Sweden" ], [ "<USA>", "Sweden" ]) + ) + end + + def test_array_options_for_string_include_in_other_string_bug_fix + assert_dom_equal( + "<option value=\"ruby\">ruby</option>\n<option value=\"rubyonrails\" selected=\"selected\">rubyonrails</option>", + options_for_select([ "ruby", "rubyonrails" ], "rubyonrails") + ) + assert_dom_equal( + "<option value=\"ruby\" selected=\"selected\">ruby</option>\n<option value=\"rubyonrails\">rubyonrails</option>", + options_for_select([ "ruby", "rubyonrails" ], "ruby") + ) + end + + def test_hash_options_for_select + assert_dom_equal( + "<option value=\"<Kroner>\"><DKR></option>\n<option value=\"Dollar\">$</option>", + options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }) + ) + assert_dom_equal( + "<option value=\"<Kroner>\"><DKR></option>\n<option value=\"Dollar\" selected=\"selected\">$</option>", + options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }, "Dollar") + ) + assert_dom_equal( + "<option value=\"<Kroner>\" selected=\"selected\"><DKR></option>\n<option value=\"Dollar\" selected=\"selected\">$</option>", + options_for_select({ "$" => "Dollar", "<DKR>" => "<Kroner>" }, [ "Dollar", "<Kroner>" ]) + ) + end + + def test_ducktyped_options_for_select + quack = Struct.new(:first, :last) + assert_dom_equal( + "<option value=\"<Kroner>\"><DKR></option>\n<option value=\"Dollar\">$</option>", + options_for_select([quack.new("<DKR>", "<Kroner>"), quack.new("$", "Dollar")]) + ) + assert_dom_equal( + "<option value=\"<Kroner>\"><DKR></option>\n<option value=\"Dollar\" selected=\"selected\">$</option>", + options_for_select([quack.new("<DKR>", "<Kroner>"), quack.new("$", "Dollar")], "Dollar") + ) + assert_dom_equal( + "<option value=\"<Kroner>\" selected=\"selected\"><DKR></option>\n<option value=\"Dollar\" selected=\"selected\">$</option>", + options_for_select([quack.new("<DKR>", "<Kroner>"), quack.new("$", "Dollar")], ["Dollar", "<Kroner>"]) + ) + end + + def test_html_option_groups_from_collection + @continents = [ + Continent.new("<Africa>", [Country.new("<sa>", "<South Africa>"), Country.new("so", "Somalia")] ), + Continent.new("Europe", [Country.new("dk", "Denmark"), Country.new("ie", "Ireland")] ) + ] + + assert_dom_equal( + "<optgroup label=\"<Africa>\"><option value=\"<sa>\"><South Africa></option>\n<option value=\"so\">Somalia</option></optgroup><optgroup label=\"Europe\"><option value=\"dk\" selected=\"selected\">Denmark</option>\n<option value=\"ie\">Ireland</option></optgroup>", + option_groups_from_collection_for_select(@continents, "countries", "continent_name", "country_id", "country_name", "dk") + ) + end + + def test_time_zone_options_no_parms + opts = time_zone_options_for_select + assert_dom_equal "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\">D</option>\n" + + "<option value=\"E\">E</option>", + opts + end + + def test_time_zone_options_with_selected + opts = time_zone_options_for_select( "D" ) + assert_dom_equal "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>\n" + + "<option value=\"E\">E</option>", + opts + end + + def test_time_zone_options_with_unknown_selected + opts = time_zone_options_for_select( "K" ) + assert_dom_equal "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\">D</option>\n" + + "<option value=\"E\">E</option>", + opts + end + + def test_time_zone_options_with_priority_zones + zones = [ TimeZone.new( "B" ), TimeZone.new( "E" ) ] + opts = time_zone_options_for_select( nil, zones ) + assert_dom_equal "<option value=\"B\">B</option>\n" + + "<option value=\"E\">E</option>" + + "<option value=\"\">-------------</option>\n" + + "<option value=\"A\">A</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\">D</option>", + opts + end + + def test_time_zone_options_with_selected_priority_zones + zones = [ TimeZone.new( "B" ), TimeZone.new( "E" ) ] + opts = time_zone_options_for_select( "E", zones ) + assert_dom_equal "<option value=\"B\">B</option>\n" + + "<option value=\"E\" selected=\"selected\">E</option>" + + "<option value=\"\">-------------</option>\n" + + "<option value=\"A\">A</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\">D</option>", + opts + end + + def test_time_zone_options_with_unselected_priority_zones + zones = [ TimeZone.new( "B" ), TimeZone.new( "E" ) ] + opts = time_zone_options_for_select( "C", zones ) + assert_dom_equal "<option value=\"B\">B</option>\n" + + "<option value=\"E\">E</option>" + + "<option value=\"\">-------------</option>\n" + + "<option value=\"A\">A</option>\n" + + "<option value=\"C\" selected=\"selected\">C</option>\n" + + "<option value=\"D\">D</option>", + opts + end + + def test_select + @post = Post.new + @post.category = "<mus>" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest)) + ) + end + + def test_select_under_fields_for + @post = Post.new + @post.category = "<mus>" + + _erbout = '' + + fields_for :post, @post do |f| + _erbout.concat f.select(:category, %w( abe <mus> hest)) + end + + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>", + _erbout + ) + end + + def test_select_with_blank + @post = Post.new + @post.category = "<mus>" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\"></option>\n<option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :include_blank => true) + ) + end + + def test_select_with_default_prompt + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"abe\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :prompt => true) + ) + end + + def test_select_no_prompt_when_select_has_value + @post = Post.new + @post.category = "<mus>" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\" selected=\"selected\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :prompt => true) + ) + end + + def test_select_with_given_prompt + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">The prompt</option>\n<option value=\"abe\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :prompt => 'The prompt') + ) + end + + def test_select_with_prompt_and_blank + @post = Post.new + @post.category = "" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"\">Please select</option>\n<option value=\"\"></option>\n<option value=\"abe\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest), :prompt => true, :include_blank => true) + ) + end + + def test_select_with_selected_value + @post = Post.new + @post.category = "<mus>" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\" selected=\"selected\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest ), :selected => 'abe') + ) + end + + def test_select_with_selected_nil + @post = Post.new + @post.category = "<mus>" + assert_dom_equal( + "<select id=\"post_category\" name=\"post[category]\"><option value=\"abe\">abe</option>\n<option value=\"<mus>\"><mus></option>\n<option value=\"hest\">hest</option></select>", + select("post", "category", %w( abe <mus> hest ), :selected => nil) + ) + end + + def test_collection_select + @posts = [ + Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") + ] + + @post = Post.new + @post.author_name = "Babe" + + assert_dom_equal( + "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>", + collection_select("post", "author_name", @posts, "author_name", "author_name") + ) + end + + def test_collection_select_under_fields_for + @posts = [ + Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") + ] + + @post = Post.new + @post.author_name = "Babe" + + _erbout = '' + + fields_for :post, @post do |f| + _erbout.concat f.collection_select(:author_name, @posts, :author_name, :author_name) + end + + assert_dom_equal( + "<select id=\"post_author_name\" name=\"post[author_name]\"><option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>", + _erbout + ) + end + + def test_collection_select_with_blank_and_style + @posts = [ + Post.new("<Abe> went home", "<Abe>", "To a little house", "shh!"), + Post.new("Babe went home", "Babe", "To a little house", "shh!"), + Post.new("Cabe went home", "Cabe", "To a little house", "shh!") + ] + + @post = Post.new + @post.author_name = "Babe" + + assert_dom_equal( + "<select id=\"post_author_name\" name=\"post[author_name]\" style=\"width: 200px\"><option value=\"\"></option>\n<option value=\"<Abe>\"><Abe></option>\n<option value=\"Babe\" selected=\"selected\">Babe</option>\n<option value=\"Cabe\">Cabe</option></select>", + collection_select("post", "author_name", @posts, "author_name", "author_name", { :include_blank => true }, "style" => "width: 200px") + ) + end + + def test_country_select + @post = Post.new + @post.origin = "Denmark" + assert_dom_equal( + "<select id=\"post_origin\" name=\"post[origin]\"><option value=\"Afghanistan\">Afghanistan</option>\n<option value=\"Albania\">Albania</option>\n<option value=\"Algeria\">Algeria</option>\n<option value=\"American Samoa\">American Samoa</option>\n<option value=\"Andorra\">Andorra</option>\n<option value=\"Angola\">Angola</option>\n<option value=\"Anguilla\">Anguilla</option>\n<option value=\"Antarctica\">Antarctica</option>\n<option value=\"Antigua And Barbuda\">Antigua And Barbuda</option>\n<option value=\"Argentina\">Argentina</option>\n<option value=\"Armenia\">Armenia</option>\n<option value=\"Aruba\">Aruba</option>\n<option value=\"Australia\">Australia</option>\n<option value=\"Austria\">Austria</option>\n<option value=\"Azerbaijan\">Azerbaijan</option>\n<option value=\"Bahamas\">Bahamas</option>\n<option value=\"Bahrain\">Bahrain</option>\n<option value=\"Bangladesh\">Bangladesh</option>\n<option value=\"Barbados\">Barbados</option>\n<option value=\"Belarus\">Belarus</option>\n<option value=\"Belgium\">Belgium</option>\n<option value=\"Belize\">Belize</option>\n<option value=\"Benin\">Benin</option>\n<option value=\"Bermuda\">Bermuda</option>\n<option value=\"Bhutan\">Bhutan</option>\n<option value=\"Bolivia\">Bolivia</option>\n<option value=\"Bosnia and Herzegowina\">Bosnia and Herzegowina</option>\n<option value=\"Botswana\">Botswana</option>\n<option value=\"Bouvet Island\">Bouvet Island</option>\n<option value=\"Brazil\">Brazil</option>\n<option value=\"British Indian Ocean Territory\">British Indian Ocean Territory</option>\n<option value=\"Brunei Darussalam\">Brunei Darussalam</option>\n<option value=\"Bulgaria\">Bulgaria</option>\n<option value=\"Burkina Faso\">Burkina Faso</option>\n<option value=\"Burma\">Burma</option>\n<option value=\"Burundi\">Burundi</option>\n<option value=\"Cambodia\">Cambodia</option>\n<option value=\"Cameroon\">Cameroon</option>\n<option value=\"Canada\">Canada</option>\n<option value=\"Cape Verde\">Cape Verde</option>\n<option value=\"Cayman Islands\">Cayman Islands</option>\n<option value=\"Central African Republic\">Central African Republic</option>\n<option value=\"Chad\">Chad</option>\n<option value=\"Chile\">Chile</option>\n<option value=\"China\">China</option>\n<option value=\"Christmas Island\">Christmas Island</option>\n<option value=\"Cocos (Keeling) Islands\">Cocos (Keeling) Islands</option>\n<option value=\"Colombia\">Colombia</option>\n<option value=\"Comoros\">Comoros</option>\n<option value=\"Congo\">Congo</option>\n<option value=\"Congo, the Democratic Republic of the\">Congo, the Democratic Republic of the</option>\n<option value=\"Cook Islands\">Cook Islands</option>\n<option value=\"Costa Rica\">Costa Rica</option>\n<option value=\"Cote d'Ivoire\">Cote d'Ivoire</option>\n<option value=\"Croatia\">Croatia</option>\n<option value=\"Cuba\">Cuba</option>\n<option value=\"Cyprus\">Cyprus</option>\n<option value=\"Czech Republic\">Czech Republic</option>\n<option value=\"Denmark\" selected=\"selected\">Denmark</option>\n<option value=\"Djibouti\">Djibouti</option>\n<option value=\"Dominica\">Dominica</option>\n<option value=\"Dominican Republic\">Dominican Republic</option>\n<option value=\"East Timor\">East Timor</option>\n<option value=\"Ecuador\">Ecuador</option>\n<option value=\"Egypt\">Egypt</option>\n<option value=\"El Salvador\">El Salvador</option>\n<option value=\"England\">England" + + "</option>\n<option value=\"Equatorial Guinea\">Equatorial Guinea</option>\n<option value=\"Eritrea\">Eritrea</option>\n<option value=\"Espana\">Espana</option>\n<option value=\"Estonia\">Estonia</option>\n<option value=\"Ethiopia\">Ethiopia</option>\n<option value=\"Falkland Islands\">Falkland Islands</option>\n<option value=\"Faroe Islands\">Faroe Islands</option>\n<option value=\"Fiji\">Fiji</option>\n<option value=\"Finland\">Finland</option>\n<option value=\"France\">France</option>\n<option value=\"French Guiana\">French Guiana</option>\n<option value=\"French Polynesia\">French Polynesia</option>\n<option value=\"French Southern Territories\">French Southern Territories</option>\n<option value=\"Gabon\">Gabon</option>\n<option value=\"Gambia\">Gambia</option>\n<option value=\"Georgia\">Georgia</option>\n<option value=\"Germany\">Germany</option>\n<option value=\"Ghana\">Ghana</option>\n<option value=\"Gibraltar\">Gibraltar</option>\n<option value=\"Great Britain\">Great Britain</option>\n<option value=\"Greece\">Greece</option>\n<option value=\"Greenland\">Greenland</option>\n<option value=\"Grenada\">Grenada</option>\n<option value=\"Guadeloupe\">Guadeloupe</option>\n<option value=\"Guam\">Guam</option>\n<option value=\"Guatemala\">Guatemala</option>\n<option value=\"Guinea\">Guinea</option>\n<option value=\"Guinea-Bissau\">Guinea-Bissau</option>\n<option value=\"Guyana\">Guyana</option>\n<option value=\"Haiti\">Haiti</option>\n<option value=\"Heard and Mc Donald Islands\">Heard and Mc Donald Islands</option>\n<option value=\"Honduras\">Honduras</option>\n<option value=\"Hong Kong\">Hong Kong</option>\n<option value=\"Hungary\">Hungary</option>\n<option value=\"Iceland\">Iceland</option>\n<option value=\"India\">India</option>\n<option value=\"Indonesia\">Indonesia</option>\n<option value=\"Ireland\">Ireland</option>\n<option value=\"Israel\">Israel</option>\n<option value=\"Italy\">Italy</option>\n<option value=\"Iran\">Iran</option>\n<option value=\"Iraq\">Iraq</option>\n<option value=\"Jamaica\">Jamaica</option>\n<option value=\"Japan\">Japan</option>\n<option value=\"Jordan\">Jordan</option>\n<option value=\"Kazakhstan\">Kazakhstan</option>\n<option value=\"Kenya\">Kenya</option>\n<option value=\"Kiribati\">Kiribati</option>\n<option value=\"Korea, Republic of\">Korea, Republic of</option>\n<option value=\"Korea (South)\">Korea (South)</option>\n<option value=\"Kuwait\">Kuwait</option>\n<option value=\"Kyrgyzstan\">Kyrgyzstan</option>\n<option value=\"Lao People's Democratic Republic\">Lao People's Democratic Republic</option>\n<option value=\"Latvia\">Latvia</option>\n<option value=\"Lebanon\">Lebanon</option>\n<option value=\"Lesotho\">Lesotho</option>\n<option value=\"Liberia\">Liberia</option>\n<option value=\"Liechtenstein\">Liechtenstein</option>\n<option value=\"Lithuania\">Lithuania</option>\n<option value=\"Luxembourg\">Luxembourg</option>\n<option value=\"Macau\">Macau</option>\n<option value=\"Macedonia\">Macedonia</option>\n<option value=\"Madagascar\">Madagascar</option>\n<option value=\"Malawi\">Malawi</option>\n<option value=\"Malaysia\">Malaysia</option>\n<option value=\"Maldives\">Maldives</option>\n<option value=\"Mali\">Mali</option>\n<option value=\"Malta\">Malta</option>\n<option value=\"Marshall Islands\">Marshall Islands</option>\n<option value=\"Martinique\">Martinique</option>\n<option value=\"Mauritania\">Mauritania</option>\n<option value=\"Mauritius\">Mauritius</option>\n<option value=\"Mayotte\">Mayotte</option>\n<option value=\"Mexico\">Mexico</option>\n<option value=\"Micronesia, Federated States of\">Micronesia, Federated States of</option>\n<option value=\"Moldova, Republic of\">Moldova, Republic of</option>\n<option value=\"Monaco\">Monaco</option>\n<option value=\"Mongolia\">Mongolia</option>\n<option value=\"Montserrat\">Montserrat</option>\n<option value=\"Morocco\">Morocco</option>\n<option value=\"Mozambique\">Mozambique</option>\n<option value=\"Myanmar\">Myanmar</option>\n<option value=\"Namibia\">Namibia</option>\n<option value=\"Nauru\">Nauru</option>\n<option value=\"Nepal\">Nepal</option>\n<option value=\"Netherlands\">Netherlands</option>\n<option value=\"Netherlands Antilles\">Netherlands Antilles</option>\n<option value=\"New Caledonia\">New Caledonia</option>" + + "\n<option value=\"New Zealand\">New Zealand</option>\n<option value=\"Nicaragua\">Nicaragua</option>\n<option value=\"Niger\">Niger</option>\n<option value=\"Nigeria\">Nigeria</option>\n<option value=\"Niue\">Niue</option>\n<option value=\"Norfolk Island\">Norfolk Island</option>\n<option value=\"Northern Ireland\">Northern Ireland</option>\n<option value=\"Northern Mariana Islands\">Northern Mariana Islands</option>\n<option value=\"Norway\">Norway</option>\n<option value=\"Oman\">Oman</option>\n<option value=\"Pakistan\">Pakistan</option>\n<option value=\"Palau\">Palau</option>\n<option value=\"Panama\">Panama</option>\n<option value=\"Papua New Guinea\">Papua New Guinea</option>\n<option value=\"Paraguay\">Paraguay</option>\n<option value=\"Peru\">Peru</option>\n<option value=\"Philippines\">Philippines</option>\n<option value=\"Pitcairn\">Pitcairn</option>\n<option value=\"Poland\">Poland</option>\n<option value=\"Portugal\">Portugal</option>\n<option value=\"Puerto Rico\">Puerto Rico</option>\n<option value=\"Qatar\">Qatar</option>\n<option value=\"Reunion\">Reunion</option>\n<option value=\"Romania\">Romania</option>\n<option value=\"Russia\">Russia</option>\n<option value=\"Rwanda\">Rwanda</option>\n<option value=\"Saint Kitts and Nevis\">Saint Kitts and Nevis</option>\n<option value=\"Saint Lucia\">Saint Lucia</option>\n<option value=\"Saint Vincent and the Grenadines\">Saint Vincent and the Grenadines</option>\n<option value=\"Samoa (Independent)\">Samoa (Independent)</option>\n<option value=\"San Marino\">San Marino</option>\n<option value=\"Sao Tome and Principe\">Sao Tome and Principe</option>\n<option value=\"Saudi Arabia\">Saudi Arabia</option>\n<option value=\"Scotland\">Scotland</option>\n<option value=\"Senegal\">Senegal</option>\n<option value=\"Serbia and Montenegro\">Serbia and Montenegro</option>\n<option value=\"Seychelles\">Seychelles</option>\n<option value=\"Sierra Leone\">Sierra Leone</option>\n<option value=\"Singapore\">Singapore</option>\n<option value=\"Slovakia\">Slovakia</option>\n<option value=\"Slovenia\">Slovenia</option>\n<option value=\"Solomon Islands\">Solomon Islands</option>\n<option value=\"Somalia\">Somalia</option>\n<option value=\"South Africa\">South Africa</option>\n<option value=\"South Georgia and the South Sandwich Islands\">South Georgia and the South Sandwich Islands</option>\n<option value=\"South Korea\">South Korea</option>\n<option value=\"Spain\">Spain</option>\n<option value=\"Sri Lanka\">Sri Lanka</option>\n<option value=\"St. Helena\">St. Helena</option>\n<option value=\"St. Pierre and Miquelon\">St. Pierre and Miquelon</option>\n<option value=\"Suriname\">Suriname</option>\n<option value=\"Svalbard and Jan Mayen Islands\">Svalbard and Jan Mayen Islands</option>\n<option value=\"Swaziland\">Swaziland</option>\n<option value=\"Sweden\">Sweden</option>\n<option value=\"Switzerland\">Switzerland</option>\n<option value=\"Taiwan\">Taiwan</option>\n<option value=\"Tajikistan\">Tajikistan</option>\n<option value=\"Tanzania\">Tanzania</option>\n<option value=\"Thailand\">Thailand</option>\n<option value=\"Togo\">Togo</option>\n<option value=\"Tokelau\">Tokelau</option>\n<option value=\"Tonga\">Tonga</option>\n<option value=\"Trinidad\">Trinidad</option>\n<option value=\"Trinidad and Tobago\">Trinidad and Tobago</option>\n<option value=\"Tunisia\">Tunisia</option>\n<option value=\"Turkey\">Turkey</option>\n<option value=\"Turkmenistan\">" + + "Turkmenistan</option>\n<option value=\"Turks and Caicos Islands\">Turks and Caicos Islands</option>\n<option value=\"Tuvalu\">Tuvalu</option>\n<option value=\"Uganda\">Uganda</option>\n<option value=\"Ukraine\">Ukraine</option>\n<option value=\"United Arab Emirates\">United Arab Emirates</option>\n<option value=\"United Kingdom\">United Kingdom</option>\n<option value=\"United States\">United States</option>\n<option value=\"United States Minor Outlying Islands\">United States Minor Outlying Islands</option>\n<option value=\"Uruguay\">Uruguay</option>\n<option value=\"Uzbekistan\">Uzbekistan</option>\n<option value=\"Vanuatu\">Vanuatu</option>\n<option value=\"Vatican City State (Holy See)\">Vatican City State (Holy See)</option>\n<option value=\"Venezuela\">Venezuela</option>\n<option value=\"Viet Nam\">Viet Nam</option>\n<option value=\"Virgin Islands (British)\">Virgin Islands (British)</option>\n<option value=\"Virgin Islands (U.S.)\">Virgin Islands (U.S.)</option>\n<option value=\"Wales\">Wales</option>\n<option value=\"Wallis and Futuna Islands\">Wallis and Futuna Islands</option>\n<option value=\"Western Sahara\">Western Sahara</option>\n<option value=\"Yemen\">Yemen</option>\n<option value=\"Zambia\">Zambia</option>\n<option value=\"Zimbabwe\">Zimbabwe</option></select>", + country_select("post", "origin") + ) + end + + def test_time_zone_select + @firm = Firm.new("D") + html = time_zone_select( "firm", "time_zone" ) + assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" + + "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>\n" + + "<option value=\"E\">E</option>" + + "</select>", + html + end + + def test_time_zone_select_under_fields_for + @firm = Firm.new("D") + + _erbout = '' + + fields_for :firm, @firm do |f| + _erbout.concat f.time_zone_select(:time_zone) + end + + assert_dom_equal( + "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" + + "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>\n" + + "<option value=\"E\">E</option>" + + "</select>", + _erbout + ) + end + + def test_time_zone_select_with_blank + @firm = Firm.new("D") + html = time_zone_select("firm", "time_zone", nil, :include_blank => true) + assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" + + "<option value=\"\"></option>\n" + + "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>\n" + + "<option value=\"E\">E</option>" + + "</select>", + html + end + + def test_time_zone_select_with_style + @firm = Firm.new("D") + html = time_zone_select("firm", "time_zone", nil, {}, + "style" => "color: red") + assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\" style=\"color: red\">" + + "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>\n" + + "<option value=\"E\">E</option>" + + "</select>", + html + assert_dom_equal html, time_zone_select("firm", "time_zone", nil, {}, + :style => "color: red") + end + + def test_time_zone_select_with_blank_and_style + @firm = Firm.new("D") + html = time_zone_select("firm", "time_zone", nil, + { :include_blank => true }, "style" => "color: red") + assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\" style=\"color: red\">" + + "<option value=\"\"></option>\n" + + "<option value=\"A\">A</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>\n" + + "<option value=\"E\">E</option>" + + "</select>", + html + assert_dom_equal html, time_zone_select("firm", "time_zone", nil, + { :include_blank => true }, :style => "color: red") + end + + def test_time_zone_select_with_priority_zones + @firm = Firm.new("D") + zones = [ TimeZone.new("A"), TimeZone.new("D") ] + html = time_zone_select("firm", "time_zone", zones ) + assert_dom_equal "<select id=\"firm_time_zone\" name=\"firm[time_zone]\">" + + "<option value=\"A\">A</option>\n" + + "<option value=\"D\" selected=\"selected\">D</option>" + + "<option value=\"\">-------------</option>\n" + + "<option value=\"B\">B</option>\n" + + "<option value=\"C\">C</option>\n" + + "<option value=\"E\">E</option>" + + "</select>", + html + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class FormTagHelperTest < Test::Unit::TestCase + + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::FormTagHelper + + def setup + @controller = Class.new do + def url_for(options, *parameters_for_method_reference) + "http://www.example.com" + end + end + @controller = @controller.new + end + + def test_check_box_tag + actual = check_box_tag "admin" + expected = %(<input id="admin" name="admin" type="checkbox" value="1" />) + assert_dom_equal expected, actual + end + + def test_form_tag + actual = form_tag + expected = %(<form action="http://www.example.com" method="post">) + assert_dom_equal expected, actual + end + + def test_form_tag_multipart + actual = form_tag({}, { 'multipart' => true }) + expected = %(<form action="http://www.example.com" enctype="multipart/form-data" method="post">) + assert_dom_equal expected, actual + end + + def test_hidden_field_tag + actual = hidden_field_tag "id", 3 + expected = %(<input id="id" name="id" type="hidden" value="3" />) + assert_dom_equal expected, actual + end + + def test_password_field_tag + actual = password_field_tag + expected = %(<input id="password" name="password" type="password" />) + assert_dom_equal expected, actual + end + + def test_radio_button_tag + actual = radio_button_tag "people", "david" + expected = %(<input id="people" name="people" type="radio" value="david" />) + assert_dom_equal expected, actual + end + + def test_select_tag + actual = select_tag "people", "<option>david</option>" + expected = %(<select id="people" name="people"><option>david</option></select>) + assert_dom_equal expected, actual + end + + def test_text_area_tag_size_string + actual = text_area_tag "body", "hello world", "size" => "20x40" + expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>) + assert_dom_equal expected, actual + end + + def test_text_area_tag_size_symbol + actual = text_area_tag "body", "hello world", :size => "20x40" + expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>) + assert_dom_equal expected, actual + end + + def test_text_field_tag + actual = text_field_tag "title", "Hello!" + expected = %(<input id="title" name="title" type="text" value="Hello!" />) + assert_dom_equal expected, actual + end + + def test_text_field_tag_class_string + actual = text_field_tag "title", "Hello!", "class" => "admin" + expected = %(<input class="admin" id="title" name="title" type="text" value="Hello!" />) + assert_dom_equal expected, actual + end + + def test_boolean_optios + assert_dom_equal %(<input checked="checked" disabled="disabled" id="admin" name="admin" readonly="readonly" type="checkbox" value="1" />), check_box_tag("admin", 1, true, 'disabled' => true, :readonly => "yes") + assert_dom_equal %(<input checked="checked" id="admin" name="admin" type="checkbox" value="1" />), check_box_tag("admin", 1, true, :disabled => false, :readonly => nil) + assert_dom_equal %(<select id="people" multiple="multiple" name="people"><option>david</option></select>), select_tag("people", "<option>david</option>", :multiple => true) + assert_dom_equal %(<select id="people" name="people"><option>david</option></select>), select_tag("people", "<option>david</option>", :multiple => nil) + end + + def test_stringify_symbol_keys + actual = text_field_tag "title", "Hello!", :id => "admin" + expected = %(<input id="admin" name="title" type="text" value="Hello!" />) + assert_dom_equal expected, actual + end + + def test_submit_tag + assert_dom_equal( + %(<input name='commit' type='submit' value='Save' onclick="this.disabled=true;this.value='Saving...';this.form.submit();alert('hello!')" />), + submit_tag("Save", :disable_with => "Saving...", :onclick => "alert('hello!')") + ) + end + + def test_pass + assert_equal 1, 1 + end +end + +require File.dirname(__FILE__) + '/../abstract_unit' + +class JavaScriptMacrosHelperTest < Test::Unit::TestCase + include ActionView::Helpers::JavaScriptHelper + include ActionView::Helpers::JavaScriptMacrosHelper + + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::FormHelper + include ActionView::Helpers::CaptureHelper + + def setup + @controller = Class.new do + def url_for(options, *parameters_for_method_reference) + url = "http://www.example.com/" + url << options[:action].to_s if options and options[:action] + url + end + end + @controller = @controller.new + end + + + def test_auto_complete_field + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }); + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:','})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => ','); + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {tokens:[',']})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }, :tokens => [',']); + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {minChars:3})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }, :min_chars => 3); + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {onHide:function(element, update){alert('me');}})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }, :on_hide => "function(element, update){alert('me');}"); + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {frequency:2})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }, :frequency => 2); + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nvar some_input_auto_completer = new Ajax.Autocompleter('some_input', 'some_input_auto_complete', 'http://www.example.com/autocomplete', {afterUpdateElement:function(element,value){alert('You have chosen: '+value)}})\n//]]>\n</script>), + auto_complete_field("some_input", :url => { :action => "autocomplete" }, + :after_update_element => "function(element,value){alert('You have chosen: '+value)}"); + end + + def test_auto_complete_result + result = [ { :title => 'test1' }, { :title => 'test2' } ] + assert_equal %(<ul><li>test1</li><li>test2</li></ul>), + auto_complete_result(result, :title) + assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li><li>t<strong class=\"highlight\">est</strong>2</li></ul>), + auto_complete_result(result, :title, "est") + + resultuniq = [ { :title => 'test1' }, { :title => 'test1' } ] + assert_equal %(<ul><li>t<strong class=\"highlight\">est</strong>1</li></ul>), + auto_complete_result(resultuniq, :title, "est") + end + + def test_text_field_with_auto_complete + assert_match "<style>", + text_field_with_auto_complete(:message, :recipient) + assert_dom_equal %(<input id=\"message_recipient\" name=\"message[recipient]\" size=\"30\" type=\"text\" /><div class=\"auto_complete\" id=\"message_recipient_auto_complete\"></div><script type=\"text/javascript\">\n//<![CDATA[\nvar message_recipient_auto_completer = new Ajax.Autocompleter('message_recipient', 'message_recipient_auto_complete', 'http://www.example.com/auto_complete_for_message_recipient', {})\n//]]>\n</script>), + text_field_with_auto_complete(:message, :recipient, {}, :skip_style => true) + end + + def test_in_place_editor_external_control + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {externalControl:'blah'})\n//]]>\n</script>), + in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :external_control => 'blah'}) + end + + def test_in_place_editor_size + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {size:4})\n//]]>\n</script>), + in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :size => 4}) + end + + def test_in_place_editor_cols_no_rows + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {cols:4})\n//]]>\n</script>), + in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :cols => 4}) + end + + def test_in_place_editor_cols_with_rows + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {cols:40, rows:5})\n//]]>\n</script>), + in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :rows => 5, :cols => 40}) + end + + def test_inplace_editor_loading_text + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Ajax.InPlaceEditor('some_input', 'http://www.example.com/inplace_edit', {loadingText:'Why are we waiting?'})\n//]]>\n</script>), + in_place_editor('some_input', {:url => {:action => 'inplace_edit'}, :loading_text => 'Why are we waiting?'}) + end + + def test_in_place_editor_url + assert_match "Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value')", + in_place_editor( 'id-goes-here', :url => { :action => "action_to_set_value" }) + end + + def test_in_place_editor_load_text_url + assert_match "Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value', {loadTextURL:'http://www.example.com/action_to_get_value'})", + in_place_editor( 'id-goes-here', + :url => { :action => "action_to_set_value" }, + :load_text_url => { :action => "action_to_get_value" }) + end + + def test_in_place_editor_eval_scripts + assert_match "Ajax.InPlaceEditor('id-goes-here', 'http://www.example.com/action_to_set_value', {evalScripts:true})", + in_place_editor( 'id-goes-here', + :url => { :action => "action_to_set_value" }, + :script => true ) + end + +end +require File.dirname(__FILE__) + '/../abstract_unit' + +class JavaScriptHelperTest < Test::Unit::TestCase + include ActionView::Helpers::JavaScriptHelper + + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::FormHelper + include ActionView::Helpers::CaptureHelper + + def test_define_javascript_functions + # check if prototype.js is included first + assert_not_nil define_javascript_functions.split("\n")[1].match(/Prototype JavaScript framework/) + + # check that scriptaculous.js is not in here, only needed if loaded remotely + assert_nil define_javascript_functions.split("\n")[1].match(/var Scriptaculous = \{/) + end + + def test_escape_javascript + assert_equal %(This \\"thing\\" is really\\n netos\\'), escape_javascript(%(This "thing" is really\n netos')) + end + + def test_link_to_function + assert_dom_equal %(<a href="#" onclick="alert('Hello world!'); return false;">Greeting</a>), + link_to_function("Greeting", "alert('Hello world!')") + end + + def test_link_to_function_with_existing_onclick + assert_dom_equal %(<a href="#" onclick="confirm('Sanity!'); alert('Hello world!'); return false;">Greeting</a>), + link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')") + end + + def test_button_to_function + assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />), + button_to_function("Greeting", "alert('Hello world!')") + end +end +require 'test/unit' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/number_helper' +require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/hash' # for stringify_keys +require File.dirname(__FILE__) + '/../../../activesupport/lib/active_support/core_ext/numeric' # for human_size + +class NumberHelperTest < Test::Unit::TestCase + include ActionView::Helpers::NumberHelper + include ActiveSupport::CoreExtensions::Hash + + def test_number_to_phone + assert_equal("123-555-1234", number_to_phone(1235551234)) + assert_equal("(123) 555-1234", number_to_phone(1235551234, {:area_code => true})) + assert_equal("123 555 1234", number_to_phone(1235551234, {:delimiter => " "})) + assert_equal("(123) 555-1234 x 555", number_to_phone(1235551234, {:area_code => true, :extension => 555})) + assert_equal("123-555-1234", number_to_phone(1235551234, :extension => " ")) + end + + def test_number_to_currency + assert_equal("$1,234,567,890.50", number_to_currency(1234567890.50)) + assert_equal("$1,234,567,890.51", number_to_currency(1234567890.506)) + assert_equal("$1,234,567,890", number_to_currency(1234567890.50, {:precision => 0})) + assert_equal("$1,234,567,890.5", number_to_currency(1234567890.50, {:precision => 1})) + assert_equal("£1234567890,50", number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""})) + end + + def test_number_to_percentage + assert_equal("100.000%", number_to_percentage(100)) + assert_equal("100%", number_to_percentage(100, {:precision => 0})) + assert_equal("302.06%", number_to_percentage(302.0574, {:precision => 2})) + end + + def test_number_with_delimiter + assert_equal("12,345,678", number_with_delimiter(12345678)) + end + + def test_number_to_human_size + assert_equal '0 Bytes', human_size(0) + assert_equal '3 Bytes', human_size(3.14159265) + assert_equal '123 Bytes', human_size(123.0) + assert_equal '123 Bytes', human_size(123) + assert_equal '1.2 KB', human_size(1234) + assert_equal '12.1 KB', human_size(12345) + assert_equal '1.2 MB', human_size(1234567) + assert_equal '1.1 GB', human_size(1234567890) + assert_equal '1.1 TB', human_size(1234567890123) + assert_equal '444 KB', human_size(444.kilobytes) + assert_equal '1023 MB', human_size(1023.megabytes) + assert_equal '3 TB', human_size(3.terabytes) + assert_nil human_size('x') + assert_nil human_size(nil) + end + + def test_number_with_precision + assert_equal("111.235", number_with_precision(111.2346)) + end +end +require File.dirname(__FILE__) + '/../abstract_unit' + +module BaseTest + include ActionView::Helpers::JavaScriptHelper + include ActionView::Helpers::PrototypeHelper + include ActionView::Helpers::ScriptaculousHelper + + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::FormHelper + include ActionView::Helpers::CaptureHelper + + def setup + @controller = Class.new do + def url_for(options, *parameters_for_method_reference) + url = "http://www.example.com/" + url << options[:action].to_s if options and options[:action] + url << "?a=#{options[:a]}" if options && options[:a] + url << "&b=#{options[:b]}" if options && options[:a] && options[:b] + url + end + end.new + end + +protected + def create_generator + block = Proc.new { |*args| yield *args if block_given? } + JavaScriptGenerator.new self, &block + end +end + +class PrototypeHelperTest < Test::Unit::TestCase + include BaseTest + + def test_link_to_remote + assert_dom_equal %(<a class=\"fine\" href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true}); return false;\">Remote outpost</a>), + link_to_remote("Remote outpost", { :url => { :action => "whatnot" }}, { :class => "fine" }) + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onComplete:function(request){alert(request.reponseText)}}); return false;\">Remote outpost</a>), + link_to_remote("Remote outpost", :complete => "alert(request.reponseText)", :url => { :action => "whatnot" }) + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onSuccess:function(request){alert(request.reponseText)}}); return false;\">Remote outpost</a>), + link_to_remote("Remote outpost", :success => "alert(request.reponseText)", :url => { :action => "whatnot" }) + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}}); return false;\">Remote outpost</a>), + link_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot" }) + assert_dom_equal %(<a href=\"#\" onclick=\"new Ajax.Request('http://www.example.com/whatnot?a=10&b=20', {asynchronous:true, evalScripts:true, onFailure:function(request){alert(request.reponseText)}}); return false;\">Remote outpost</a>), + link_to_remote("Remote outpost", :failure => "alert(request.reponseText)", :url => { :action => "whatnot", :a => '10', :b => '20' }) + end + + def test_periodically_call_remote + assert_dom_equal %(<script type="text/javascript">\n//<![CDATA[\nnew PeriodicalExecuter(function() {new Ajax.Updater('schremser_bier', 'http://www.example.com/mehr_bier', {asynchronous:true, evalScripts:true})}, 10)\n//]]>\n</script>), + periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" }) + end + + def test_form_remote_tag + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }) + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">), + form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast }) + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">), + form_remote_tag(:update => { :failure => "glass_of_water" }, :url => { :action => :fast }) + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;\">), + form_remote_tag(:update => { :success => 'glass_of_beer', :failure => "glass_of_water" }, :url => { :action => :fast }) + end + + def test_on_callbacks + callbacks = [:uninitialized, :loading, :loaded, :interactive, :complete, :success, :failure] + callbacks.each do |callback| + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();") + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => { :success => "glass_of_beer" }, :url => { :action => :fast }, callback=>"monkeys();") + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({failure:'glass_of_beer'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => { :failure => "glass_of_beer" }, :url => { :action => :fast }, callback=>"monkeys();") + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater({success:'glass_of_beer',failure:'glass_of_water'}, 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => { :success => "glass_of_beer", :failure => "glass_of_water" }, :url => { :action => :fast }, callback=>"monkeys();") + end + + #HTTP status codes 200 up to 599 have callbacks + #these should work + 100.upto(599) do |callback| + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on#{callback.to_s.capitalize}:function(request){monkeys();}, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();") + end + + #test 200 and 404 + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, 200=>"monkeys();", 404=>"bananas();") + + #these shouldn't + 1.upto(99) do |callback| + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();") + end + 600.upto(999) do |callback| + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, callback=>"monkeys();") + end + + #test ultimate combo + assert_dom_equal %(<form action=\"http://www.example.com/fast\" method=\"post\" onsubmit=\"new Ajax.Updater('glass_of_beer', 'http://www.example.com/fast', {asynchronous:true, evalScripts:true, on200:function(request){monkeys();}, on404:function(request){bananas();}, onComplete:function(request){c();}, onFailure:function(request){f();}, onLoading:function(request){c1()}, onSuccess:function(request){s()}, parameters:Form.serialize(this)}); return false;\">), + form_remote_tag(:update => "glass_of_beer", :url => { :action => :fast }, :loading => "c1()", :success => "s()", :failure => "f();", :complete => "c();", 200=>"monkeys();", 404=>"bananas();") + + end + + def test_submit_to_remote + assert_dom_equal %(<input name=\"More beer!\" onclick=\"new Ajax.Updater('empty_bottle', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)}); return false;\" type=\"button\" value=\"1000000\" />), + submit_to_remote("More beer!", 1_000_000, :update => "empty_bottle") + end + + def test_observe_field + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true})})\n//]]>\n</script>), + observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" }) + end + + def test_observe_field_using_function_for_callback + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {alert('Element changed')})\n//]]>\n</script>), + observe_field("glass", :frequency => 5.minutes, :function => "alert('Element changed')") + end + + def test_observe_form + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true})})\n//]]>\n</script>), + observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" }) + end + + def test_observe_form_using_function_for_callback + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {alert('Form changed')})\n//]]>\n</script>), + observe_form("cart", :frequency => 2, :function => "alert('Form changed')") + end + + def test_update_element_function + assert_equal %($('myelement').innerHTML = 'blub';\n), + update_element_function('myelement', :content => 'blub') + assert_equal %($('myelement').innerHTML = 'blub';\n), + update_element_function('myelement', :action => :update, :content => 'blub') + assert_equal %($('myelement').innerHTML = '';\n), + update_element_function('myelement', :action => :empty) + assert_equal %(Element.remove('myelement');\n), + update_element_function('myelement', :action => :remove) + + assert_equal %(new Insertion.Bottom('myelement','blub');\n), + update_element_function('myelement', :position => 'bottom', :content => 'blub') + assert_equal %(new Insertion.Bottom('myelement','blub');\n), + update_element_function('myelement', :action => :update, :position => :bottom, :content => 'blub') + + _erbout = "" + assert_equal %($('myelement').innerHTML = 'test';\n), + update_element_function('myelement') { _erbout << "test" } + + _erbout = "" + assert_equal %($('myelement').innerHTML = 'blockstuff';\n), + update_element_function('myelement', :content => 'paramstuff') { _erbout << "blockstuff" } + end + + def test_update_page + block = Proc.new { |page| page.replace_html('foo', 'bar') } + assert_equal create_generator(&block).to_s, update_page(&block) + end + + def test_update_page_tag + block = Proc.new { |page| page.replace_html('foo', 'bar') } + assert_equal javascript_tag(create_generator(&block).to_s), update_page_tag(&block) + end +end + +class JavaScriptGeneratorTest < Test::Unit::TestCase + include BaseTest + + def setup + super + @generator = create_generator + end + + def test_insert_html_with_string + assert_equal 'new Insertion.Top("element", "<p>This is a test</p>");', + @generator.insert_html(:top, 'element', '<p>This is a test</p>') + assert_equal 'new Insertion.Bottom("element", "<p>This is a test</p>");', + @generator.insert_html(:bottom, 'element', '<p>This is a test</p>') + assert_equal 'new Insertion.Before("element", "<p>This is a test</p>");', + @generator.insert_html(:before, 'element', '<p>This is a test</p>') + assert_equal 'new Insertion.After("element", "<p>This is a test</p>");', + @generator.insert_html(:after, 'element', '<p>This is a test</p>') + end + + def test_replace_html_with_string + assert_equal 'Element.update("element", "<p>This is a test</p>");', + @generator.replace_html('element', '<p>This is a test</p>') + end + + def test_replace_element_with_string + assert_equal 'Element.replace("element", "<div id=\"element\"><p>This is a test</p></div>");', + @generator.replace('element', '<div id="element"><p>This is a test</p></div>') + end + + def test_remove + assert_equal '["foo"].each(Element.remove);', + @generator.remove('foo') + assert_equal '["foo", "bar", "baz"].each(Element.remove);', + @generator.remove('foo', 'bar', 'baz') + end + + def test_show + assert_equal 'Element.show("foo");', + @generator.show('foo') + assert_equal 'Element.show("foo", "bar", "baz");', + @generator.show('foo', 'bar', 'baz') + end + + def test_hide + assert_equal 'Element.hide("foo");', + @generator.hide('foo') + assert_equal 'Element.hide("foo", "bar", "baz");', + @generator.hide('foo', 'bar', 'baz') + end + + def test_alert + assert_equal 'alert("hello");', @generator.alert('hello') + end + + def test_redirect_to + assert_equal 'window.location.href = "http://www.example.com/welcome";', + @generator.redirect_to(:action => 'welcome') + end + + def test_delay + @generator.delay(20) do + @generator.hide('foo') + end + + assert_equal "setTimeout(function() {\n;\nElement.hide(\"foo\");\n}, 20000);", @generator.to_s + end + + def test_to_s + @generator.insert_html(:top, 'element', '<p>This is a test</p>') + @generator.insert_html(:bottom, 'element', '<p>This is a test</p>') + @generator.remove('foo', 'bar') + @generator.replace_html('baz', '<p>This is a test</p>') + + assert_equal <<-EOS.chomp, @generator.to_s +new Insertion.Top("element", "<p>This is a test</p>"); +new Insertion.Bottom("element", "<p>This is a test</p>"); +["foo", "bar"].each(Element.remove); +Element.update("baz", "<p>This is a test</p>"); + EOS + end + + def test_element_access + assert_equal %($("hello");), @generator['hello'] + end + + def test_element_proxy_one_deep + @generator['hello'].hide + assert_equal %($("hello").hide();), @generator.to_s + end + + def test_element_proxy_assignment + @generator['hello'].width = 400 + assert_equal %($("hello").width = 400;), @generator.to_s + end + + def test_element_proxy_two_deep + @generator['hello'].hide("first").clean_whitespace + assert_equal %($("hello").hide("first").cleanWhitespace();), @generator.to_s + end + + def test_select_access + assert_equal %($$("div.hello");), @generator.select('div.hello') + end + + def test_select_proxy_one_deep + @generator.select('p.welcome b').first.hide + assert_equal %($$("p.welcome b").first().hide();), @generator.to_s + end + + def test_visual_effect + assert_equal %(new Effect.Puff("blah",{});), + @generator.visual_effect(:puff,'blah') + end + + def test_visual_effect_toggle + assert_equal %(Effect.toggle("blah",'appear',{});), + @generator.visual_effect(:toggle_appear,'blah') + end + + def test_sortable + assert_equal %(Sortable.create("blah", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize("blah")})}});), + @generator.sortable('blah', :url => { :action => "order" }) + end + + def test_draggable + assert_equal %(new Draggable("blah", {});), + @generator.draggable('blah') + end + + def test_drop_receiving + assert_equal %(Droppables.add("blah", {onDrop:function(element){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}});), + @generator.drop_receiving('blah', :url => { :action => "order" }) + end + + def test_collection_first_and_last + @generator.select('p.welcome b').first.hide() + @generator.select('p.welcome b').last.show() + assert_equal <<-EOS.strip, @generator.to_s +$$("p.welcome b").first().hide(); +$$("p.welcome b").last().show(); + EOS + end + + def test_collection_proxy_with_each + @generator.select('p.welcome b').each do |value| + value.remove_class_name 'selected' + end + @generator.select('p.welcome b').each do |value, index| + @generator.visual_effect :highlight, value + end + assert_equal <<-EOS.strip, @generator.to_s +$$("p.welcome b").each(function(value, index) { +value.removeClassName("selected"); +}); +$$("p.welcome b").each(function(value, index) { +new Effect.Highlight(value,{}); +}); + EOS + end + + def test_collection_proxy_on_collect + @generator.select('p').collect('a') { |para| para.show } + @generator.select('p').collect { |para| para.hide } + assert_equal <<-EOS.strip, @generator.to_s +var a = $$("p").collect(function(value, index) { +return value.show(); +}); +$$("p").collect(function(value, index) { +return value.hide(); +}); + EOS + @generator = create_generator + end + + def test_collection_proxy_with_grep + @generator.select('p').grep 'a', /^a/ do |value| + @generator << '(value.className == "welcome")' + end + @generator.select('p').grep 'b', /b$/ do |value, index| + @generator.call 'alert', value + @generator << '(value.className == "welcome")' + end + + assert_equal <<-EOS.strip, @generator.to_s +var a = $$("p").grep(/^a/, function(value, index) { +return (value.className == "welcome"); +}); +var b = $$("p").grep(/b$/, function(value, index) { +alert(value); +return (value.className == "welcome"); +}); + EOS + end + + def test_collection_proxy_with_inject + @generator.select('p').inject 'a', [] do |memo, value| + @generator << '(value.className == "welcome")' + end + @generator.select('p').inject 'b', nil do |memo, value, index| + @generator.call 'alert', memo + @generator << '(value.className == "welcome")' + end + + assert_equal <<-EOS.strip, @generator.to_s +var a = $$("p").inject([], function(memo, value, index) { +return (value.className == "welcome"); +}); +var b = $$("p").inject(null, function(memo, value, index) { +alert(memo); +return (value.className == "welcome"); +}); + EOS + end + + def test_collection_proxy_with_pluck + @generator.select('p').pluck('a', 'className') + assert_equal %(var a = $$("p").pluck("className");), @generator.to_s + end + + def test_collection_proxy_with_zip + ActionView::Helpers::JavaScriptCollectionProxy.new(@generator, '[1, 2, 3]').zip('a', [4, 5, 6], [7, 8, 9]) + ActionView::Helpers::JavaScriptCollectionProxy.new(@generator, '[1, 2, 3]').zip('b', [4, 5, 6], [7, 8, 9]) do |array| + @generator.call 'array.reverse' + end + + assert_equal <<-EOS.strip, @generator.to_s +var a = [1, 2, 3].zip([4, 5, 6], [7, 8, 9]); +var b = [1, 2, 3].zip([4, 5, 6], [7, 8, 9], function(array) { +return array.reverse(); +}); + EOS + end + + def test_collection_proxy_with_find_all + @generator.select('p').find_all 'a' do |value, index| + @generator << '(value.className == "welcome")' + end + + assert_equal <<-EOS.strip, @generator.to_s +var a = $$("p").findAll(function(value, index) { +return (value.className == "welcome"); +}); + EOS + end + + def test_debug_rjs + ActionView::Base.debug_rjs = true + @generator['welcome'].replace_html 'Welcome' + assert_equal "try {\n$(\"welcome\").update(\"Welcome\");\n} catch (e) { alert('RJS error:\\n\\n' + e.toString()); alert('$(\\\"welcome\\\").update(\\\"Welcome\\\");'); throw e }", @generator.to_s + ensure + ActionView::Base.debug_rjs = false + end + + def test_class_proxy + @generator.form.focus('my_field') + assert_equal "Form.focus(\"my_field\");", @generator.to_s + end +end + +require File.dirname(__FILE__) + '/../abstract_unit' + +class ScriptaculousHelperTest < Test::Unit::TestCase + include ActionView::Helpers::JavaScriptHelper + include ActionView::Helpers::PrototypeHelper + include ActionView::Helpers::ScriptaculousHelper + + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::TextHelper + include ActionView::Helpers::FormHelper + include ActionView::Helpers::CaptureHelper + + def setup + @controller = Class.new do + def url_for(options, *parameters_for_method_reference) + url = "http://www.example.com/" + url << options[:action].to_s if options and options[:action] + url + end + end.new + end + + def test_effect + assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect(:highlight, "posts") + assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect("highlight", :posts) + assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect(:highlight, :posts) + assert_equal "new Effect.Fade(\"fademe\",{duration:4.0});", visual_effect(:fade, "fademe", :duration => 4.0) + assert_equal "new Effect.Shake(element,{});", visual_effect(:shake) + assert_equal "new Effect.DropOut(\"dropme\",{queue:'end'});", visual_effect(:drop_out, 'dropme', :queue => :end) + + # chop the queue params into a comma separated list + beginning, ending = 'new Effect.DropOut("dropme",{queue:{', '}});' + ve = [ + visual_effect(:drop_out, 'dropme', :queue => {:position => "end", :scope => "test", :limit => 2}), + visual_effect(:drop_out, 'dropme', :queue => {:scope => :list, :limit => 2}), + visual_effect(:drop_out, 'dropme', :queue => {:position => :end, :scope => :test, :limit => 2}) + ].collect { |v| v[beginning.length..-ending.length-1].split(',') } + + assert ve[0].include?("limit:2") + assert ve[0].include?("scope:'test'") + assert ve[0].include?("position:'end'") + + assert ve[1].include?("limit:2") + assert ve[1].include?("scope:'list'") + + assert ve[2].include?("limit:2") + assert ve[2].include?("scope:'test'") + assert ve[2].include?("position:'end'") + end + + def test_toggle_effects + assert_equal "Effect.toggle(\"posts\",'appear',{});", visual_effect(:toggle_appear, "posts") + assert_equal "Effect.toggle(\"posts\",'slide',{});", visual_effect(:toggle_slide, "posts") + assert_equal "Effect.toggle(\"posts\",'blind',{});", visual_effect(:toggle_blind, "posts") + assert_equal "Effect.toggle(\"posts\",'appear',{});", visual_effect("toggle_appear", "posts") + assert_equal "Effect.toggle(\"posts\",'slide',{});", visual_effect("toggle_slide", "posts") + assert_equal "Effect.toggle(\"posts\",'blind',{});", visual_effect("toggle_blind", "posts") + end + + + def test_sortable_element + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>), + sortable_element("mylist", :url => { :action => "order" }) + assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}, tag:'div'})\n//]]>\n</script>), + sortable_element("mylist", :tag => "div", :constraint => "horizontal", :url => { :action => "order" }) + assert_dom_equal %|<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', containment:['list1','list2'], onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>|, + sortable_element("mylist", :containment => ['list1','list2'], :constraint => "horizontal", :url => { :action => "order" }) + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', containment:'list1', onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>), + sortable_element("mylist", :containment => 'list1', :constraint => "horizontal", :url => { :action => "order" }) + end + + def test_draggable_element + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Draggable(\"product_13\", {})\n//]]>\n</script>), + draggable_element("product_13") + assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Draggable(\"product_13\", {revert:true})\n//]]>\n</script>), + draggable_element("product_13", :revert => true) + end + + def test_drop_receiving_element + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nDroppables.add(\"droptarget1\", {onDrop:function(element){new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}})\n//]]>\n</script>), + drop_receiving_element("droptarget1") + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nDroppables.add(\"droptarget1\", {accept:'products', onDrop:function(element){new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}})\n//]]>\n</script>), + drop_receiving_element("droptarget1", :accept => 'products') + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nDroppables.add(\"droptarget1\", {accept:'products', onDrop:function(element){new Ajax.Updater('infobox', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}})\n//]]>\n</script>), + drop_receiving_element("droptarget1", :accept => 'products', :update => 'infobox') + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nDroppables.add(\"droptarget1\", {accept:['tshirts','mugs'], onDrop:function(element){new Ajax.Updater('infobox', 'http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}})\n//]]>\n</script>), + drop_receiving_element("droptarget1", :accept => ['tshirts','mugs'], :update => 'infobox') + end +endrequire File.dirname(__FILE__) + '/../abstract_unit' + +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/tag_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/url_helper' + +class TagHelperTest < Test::Unit::TestCase + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + + def test_tag + assert_equal "<p class=\"show\" />", tag("p", "class" => "show") + assert_equal tag("p", "class" => "show"), tag("p", :class => "show") + end + + def test_tag_options + assert_equal "<p class=\"elsewhere\" />", tag("p", "class" => "show", :class => "elsewhere") + end + + def test_tag_options_rejects_nil_option + assert_equal "<p />", tag("p", :ignored => nil) + end + + def test_tag_options_accepts_blank_option + assert_equal "<p included=\"\" />", tag("p", :included => '') + end + + def test_tag_options_converts_boolean_option + assert_equal '<p disabled="disabled" multiple="multiple" readonly="readonly" />', + tag("p", :disabled => true, :multiple => true, :readonly => true) + end + + def test_content_tag + assert_equal "<a href=\"create\">Create</a>", content_tag("a", "Create", "href" => "create") + assert_equal content_tag("a", "Create", "href" => "create"), + content_tag("a", "Create", :href => "create") + end + + def test_cdata_section + assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>") + end +end +require File.dirname(__FILE__) + '/../abstract_unit' +require "#{File.dirname(__FILE__)}/../testing_sandbox" + +class TextHelperTest < Test::Unit::TestCase + include ActionView::Helpers::TextHelper + include ActionView::Helpers::TagHelper + include TestingSandbox + + def setup + # This simulates the fact that instance variables are reset every time + # a view is rendered. The cycle helper depends on this behavior. + @_cycles = nil if (defined? @_cycles) + end + + def test_simple_format + assert_equal "<p>crazy\n<br /> cross\n<br /> platform linebreaks</p>", simple_format("crazy\r\n cross\r platform linebreaks") + assert_equal "<p>A paragraph</p>\n\n<p>and another one!</p>", simple_format("A paragraph\n\nand another one!") + assert_equal "<p>A paragraph\n<br /> With a newline</p>", simple_format("A paragraph\n With a newline") + end + + def test_truncate + assert_equal "Hello World!", truncate("Hello World!", 12) + assert_equal "Hello Wor...", truncate("Hello World!!", 12) + end + + def test_truncate_multibyte_without_kcode + result = execute_in_sandbox(<<-'CODE') + require File.dirname(__FILE__) + '/../../activesupport/lib/active_support/core_ext/kernel' + require "#{File.dirname(__FILE__)}/../lib/action_view/helpers/text_helper" + include ActionView::Helpers::TextHelper + truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", 10) + CODE + + assert_equal "\354\225\210\353\205\225\355...", result + end + + def test_truncate_multibyte_with_kcode + result = execute_in_sandbox(<<-'CODE') + $KCODE = "u" + require 'jcode' + + require File.dirname(__FILE__) + '/../../activesupport/lib/active_support/core_ext/kernel' + require "#{File.dirname(__FILE__)}/../lib/action_view/helpers/text_helper" + include ActionView::Helpers::TextHelper + truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254\353\236 \354\225\204\353\235\274\353\246\254\354\230\244", 10) + CODE + + assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254\353\236 ...", result + end + + def test_strip_links + assert_equal "on my mind", strip_links("<a href='almost'>on my mind</a>") + end + + def test_highlighter + assert_equal( + "This is a <strong class=\"highlight\">beautiful</strong> morning", + highlight("This is a beautiful morning", "beautiful") + ) + + assert_equal( + "This is a <strong class=\"highlight\">beautiful</strong> morning, but also a <strong class=\"highlight\">beautiful</strong> day", + highlight("This is a beautiful morning, but also a beautiful day", "beautiful") + ) + + assert_equal( + "This is a <b>beautiful</b> morning, but also a <b>beautiful</b> day", + highlight("This is a beautiful morning, but also a beautiful day", "beautiful", '<b>\1</b>') + ) + + assert_equal( + "This text is not changed because we supplied an empty phrase", + highlight("This text is not changed because we supplied an empty phrase", nil) + ) + end + + def test_highlighter_with_regexp + assert_equal( + "This is a <strong class=\"highlight\">beautiful!</strong> morning", + highlight("This is a beautiful! morning", "beautiful!") + ) + + assert_equal( + "This is a <strong class=\"highlight\">beautiful! morning</strong>", + highlight("This is a beautiful! morning", "beautiful! morning") + ) + + assert_equal( + "This is a <strong class=\"highlight\">beautiful? morning</strong>", + highlight("This is a beautiful? morning", "beautiful? morning") + ) + end + + def test_excerpt + assert_equal("...is a beautiful morni...", excerpt("This is a beautiful morning", "beautiful", 5)) + assert_equal("This is a...", excerpt("This is a beautiful morning", "this", 5)) + assert_equal("...iful morning", excerpt("This is a beautiful morning", "morning", 5)) + assert_equal("...iful morning", excerpt("This is a beautiful morning", "morning", 5)) + assert_nil excerpt("This is a beautiful morning", "day") + end + + def test_excerpt_with_regex + assert_equal('...is a beautiful! morn...', excerpt('This is a beautiful! morning', 'beautiful', 5)) + assert_equal('...is a beautiful? morn...', excerpt('This is a beautiful? morning', 'beautiful', 5)) + end + + + def test_word_wrap + assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", 15)) + end + + def test_pluralization + assert_equal("1 count", pluralize(1, "count")) + assert_equal("2 counts", pluralize(2, "count")) + end + + def test_auto_linking + email_raw = 'david@loudthinking.com' + email_result = %{<a href="mailto:#{email_raw}">#{email_raw}</a>} + link_raw = 'http://www.rubyonrails.com' + link_result = %{<a href="#{link_raw}">#{link_raw}</a>} + link_result_with_options = %{<a href="#{link_raw}" target="_blank">#{link_raw}</a>} + link2_raw = 'www.rubyonrails.com' + link2_result = %{<a href="http://#{link2_raw}">#{link2_raw}</a>} + link3_raw = 'http://manuals.ruby-on-rails.com/read/chapter.need_a-period/103#page281' + link3_result = %{<a href="#{link3_raw}">#{link3_raw}</a>} + link4_raw = 'http://foo.example.com/controller/action?parm=value&p2=v2#anchor123' + link4_result = %{<a href="#{link4_raw}">#{link4_raw}</a>} + link5_raw = 'http://foo.example.com:3000/controller/action' + link5_result = %{<a href="#{link5_raw}">#{link5_raw}</a>} + + assert_equal %(hello #{email_result}), auto_link("hello #{email_raw}", :email_addresses) + assert_equal %(Go to #{link_result}), auto_link("Go to #{link_raw}", :urls) + assert_equal %(Go to #{link_raw}), auto_link("Go to #{link_raw}", :email_addresses) + assert_equal %(Go to #{link_result} and say hello to #{email_result}), auto_link("Go to #{link_raw} and say hello to #{email_raw}") + assert_equal %(<p>Link #{link_result}</p>), auto_link("<p>Link #{link_raw}</p>") + assert_equal %(<p>#{link_result} Link</p>), auto_link("<p>#{link_raw} Link</p>") + assert_equal %(<p>Link #{link_result_with_options}</p>), auto_link("<p>Link #{link_raw}</p>", :all, {:target => "_blank"}) + assert_equal %(Go to #{link_result}.), auto_link(%(Go to #{link_raw}.)) + assert_equal %(<p>Go to #{link_result}, then say hello to #{email_result}.</p>), auto_link(%(<p>Go to #{link_raw}, then say hello to #{email_raw}.</p>)) + assert_equal %(Go to #{link2_result}), auto_link("Go to #{link2_raw}", :urls) + assert_equal %(Go to #{link2_raw}), auto_link("Go to #{link2_raw}", :email_addresses) + assert_equal %(<p>Link #{link2_result}</p>), auto_link("<p>Link #{link2_raw}</p>") + assert_equal %(<p>#{link2_result} Link</p>), auto_link("<p>#{link2_raw} Link</p>") + assert_equal %(Go to #{link2_result}.), auto_link(%(Go to #{link2_raw}.)) + assert_equal %(<p>Say hello to #{email_result}, then go to #{link2_result}.</p>), auto_link(%(<p>Say hello to #{email_raw}, then go to #{link2_raw}.</p>)) + assert_equal %(Go to #{link3_result}), auto_link("Go to #{link3_raw}", :urls) + assert_equal %(Go to #{link3_raw}), auto_link("Go to #{link3_raw}", :email_addresses) + assert_equal %(<p>Link #{link3_result}</p>), auto_link("<p>Link #{link3_raw}</p>") + assert_equal %(<p>#{link3_result} Link</p>), auto_link("<p>#{link3_raw} Link</p>") + assert_equal %(Go to #{link3_result}.), auto_link(%(Go to #{link3_raw}.)) + assert_equal %(<p>Go to #{link3_result}. seriously, #{link3_result}? i think I'll say hello to #{email_result}. instead.</p>), auto_link(%(<p>Go to #{link3_raw}. seriously, #{link3_raw}? i think I'll say hello to #{email_raw}. instead.</p>)) + assert_equal %(<p>Link #{link4_result}</p>), auto_link("<p>Link #{link4_raw}</p>") + assert_equal %(<p>#{link4_result} Link</p>), auto_link("<p>#{link4_raw} Link</p>") + assert_equal %(<p>#{link5_result} Link</p>), auto_link("<p>#{link5_raw} Link</p>") + assert_equal '', auto_link(nil) + assert_equal '', auto_link('') + end + + def test_auto_link_at_eol + url1 = "http://api.rubyonrails.com/Foo.html" + url2 = "http://www.ruby-doc.org/core/Bar.html" + + assert_equal %(<p><a href="#{url1}">#{url1}</a><br /><a href="#{url2}">#{url2}</a><br /></p>), auto_link("<p>#{url1}<br />#{url2}<br /></p>") + end + + def test_auto_link_with_block + url = "http://api.rubyonrails.com/Foo.html" + email = "fantabulous@shiznadel.ic" + + assert_equal %(<p><a href="#{url}">#{url[0...7]}...</a><br /><a href="mailto:#{email}">#{email[0...7]}...</a><br /></p>), auto_link("<p>#{url}<br />#{email}<br /></p>") { |url| truncate(url, 10) } + end + + def test_sanitize_form + raw = "<form action=\"/foo/bar\" method=\"post\"><input></form>" + result = sanitize(raw) + assert_equal "<form action='/foo/bar' method='post'><input></form>", result + end + + def test_sanitize_script + raw = "<script language=\"Javascript\">blah blah blah</script>" + result = sanitize(raw) + assert_equal "<script language='Javascript'>blah blah blah</script>", result + end + + def test_sanitize_js_handlers + raw = %{onthis="do that" <a href="#" onclick="hello" name="foo" onbogus="remove me">hello</a>} + result = sanitize(raw) + assert_equal %{onthis="do that" <a name='foo' href='#'>hello</a>}, result + end + + def test_sanitize_javascript_href + raw = %{href="javascript:bang" <a href="javascript:bang" name="hello">foo</a>, <span href="javascript:bang">bar</span>} + result = sanitize(raw) + assert_equal %{href="javascript:bang" <a name='hello'>foo</a>, <span>bar</span>}, result + end + + def test_cycle_class + value = Cycle.new("one", 2, "3") + assert_equal("one", value.to_s) + assert_equal("2", value.to_s) + assert_equal("3", value.to_s) + assert_equal("one", value.to_s) + value.reset + assert_equal("one", value.to_s) + assert_equal("2", value.to_s) + assert_equal("3", value.to_s) + end + + def test_cycle_class_with_no_arguments + assert_raise(ArgumentError) { value = Cycle.new() } + end + + def test_cycle + assert_equal("one", cycle("one", 2, "3")) + assert_equal("2", cycle("one", 2, "3")) + assert_equal("3", cycle("one", 2, "3")) + assert_equal("one", cycle("one", 2, "3")) + assert_equal("2", cycle("one", 2, "3")) + assert_equal("3", cycle("one", 2, "3")) + end + + def test_cycle_with_no_arguments + assert_raise(ArgumentError) { value = cycle() } + end + + def test_cycle_resets_with_new_values + assert_equal("even", cycle("even", "odd")) + assert_equal("odd", cycle("even", "odd")) + assert_equal("even", cycle("even", "odd")) + assert_equal("1", cycle(1, 2, 3)) + assert_equal("2", cycle(1, 2, 3)) + assert_equal("3", cycle(1, 2, 3)) + assert_equal("1", cycle(1, 2, 3)) + end + + def test_named_cycles + assert_equal("1", cycle(1, 2, 3, :name => "numbers")) + assert_equal("red", cycle("red", "blue", :name => "colors")) + assert_equal("2", cycle(1, 2, 3, :name => "numbers")) + assert_equal("blue", cycle("red", "blue", :name => "colors")) + assert_equal("3", cycle(1, 2, 3, :name => "numbers")) + assert_equal("red", cycle("red", "blue", :name => "colors")) + end + + def test_default_named_cycle + assert_equal("1", cycle(1, 2, 3)) + assert_equal("2", cycle(1, 2, 3, :name => "default")) + assert_equal("3", cycle(1, 2, 3)) + end + + def test_reset_cycle + assert_equal("1", cycle(1, 2, 3)) + assert_equal("2", cycle(1, 2, 3)) + reset_cycle + assert_equal("1", cycle(1, 2, 3)) + end + + def test_reset_unknown_cycle + reset_cycle("colors") + end + + def test_recet_named_cycle + assert_equal("1", cycle(1, 2, 3, :name => "numbers")) + assert_equal("red", cycle("red", "blue", :name => "colors")) + reset_cycle("numbers") + assert_equal("1", cycle(1, 2, 3, :name => "numbers")) + assert_equal("blue", cycle("red", "blue", :name => "colors")) + assert_equal("2", cycle(1, 2, 3, :name => "numbers")) + assert_equal("red", cycle("red", "blue", :name => "colors")) + end + + def test_cycle_no_instance_variable_clashes + @cycles = %w{Specialized Fuji Giant} + assert_equal("red", cycle("red", "blue")) + assert_equal("blue", cycle("red", "blue")) + assert_equal("red", cycle("red", "blue")) + assert_equal(%w{Specialized Fuji Giant}, @cycles) + end + + def test_strip_tags + assert_equal("This is a test.", strip_tags("<p>This <u>is<u> a <a href='test.html'><strong>test</strong></a>.</p>")) + assert_equal("This is a test.", strip_tags("This is a test.")) + assert_equal( + %{This is a test.\n\n\nIt no longer contains any HTML.\n}, strip_tags( + %{<title>This is <b>a <a href="" target="_blank">test</a></b>.</title>\n\n<!-- it has a comment -->\n\n<p>It no <b>longer <strong>contains <em>any <strike>HTML</strike></em>.</strong></b></p>\n})) + assert_equal("This has a here.", strip_tags("This has a <!-- comment --> here.")) + end + +end +require File.dirname(__FILE__) + '/../abstract_unit' + +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/url_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/asset_tag_helper' +require File.dirname(__FILE__) + '/../../lib/action_view/helpers/tag_helper' + +RequestMock = Struct.new("Request", :request_uri) + +class UrlHelperTest < Test::Unit::TestCase + include ActionView::Helpers::AssetTagHelper + include ActionView::Helpers::UrlHelper + include ActionView::Helpers::TagHelper + + def setup + @controller = Class.new do + attr_accessor :url + def url_for(options, *parameters_for_method_reference) + url + end + end + @controller = @controller.new + @controller.url = "http://www.example.com" + end + + def test_url_for_escapes_urls + @controller.url = "http://www.example.com?a=b&c=d" + assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd') + assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => true) + assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => false) + end + + # todo: missing test cases + def test_button_to_with_straight_url + assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com") + end + + def test_button_to_with_query + assert_dom_equal "<form method=\"post\" action=\"http://www.example.com/q1=v1&q2=v2\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com/q1=v1&q2=v2") + end + + def test_button_to_with_query_and_no_name + assert_dom_equal "<form method=\"post\" action=\"http://www.example.com?q1=v1&q2=v2\" class=\"button-to\"><div><input type=\"submit\" value=\"http://www.example.com?q1=v1&q2=v2\" /></div></form>", button_to(nil, "http://www.example.com?q1=v1&q2=v2") + end + + def test_button_to_with_javascript_confirm + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input onclick=\"return confirm('Are you sure?');\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :confirm => "Are you sure?") + ) + end + + def test_button_to_enabled_disabled + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :disabled => false) + ) + assert_dom_equal( + "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input disabled=\"disabled\" type=\"submit\" value=\"Hello\" /></div></form>", + button_to("Hello", "http://www.example.com", :disabled => true) + ) + end + + def test_link_tag_with_straight_url + assert_dom_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", "http://www.example.com") + end + + def test_link_tag_with_query + assert_dom_equal "<a href=\"http://www.example.com?q1=v1&q2=v2\">Hello</a>", link_to("Hello", "http://www.example.com?q1=v1&q2=v2") + end + + def test_link_tag_with_query_and_no_name + assert_dom_equal "<a href=\"http://www.example.com?q1=v1&q2=v2\">http://www.example.com?q1=v1&q2=v2</a>", link_to(nil, "http://www.example.com?q1=v1&q2=v2") + end + + def test_link_tag_with_img + assert_dom_equal "<a href=\"http://www.example.com\"><img src='/favicon.jpg' /></a>", link_to("<img src='/favicon.jpg' />", "http://www.example.com") + end + + def test_link_with_nil_html_options + assert_dom_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", {:action => 'myaction'}, nil) + end + + def test_link_tag_with_custom_onclick + assert_dom_equal "<a href=\"http://www.example.com\" onclick=\"alert('yay!')\">Hello</a>", link_to("Hello", "http://www.example.com", :onclick => "alert('yay!')") + end + + def test_link_tag_with_javascript_confirm + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"return confirm('Are you sure?');\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "Are you sure?") + ) + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"return confirm('You can\\'t possibly be sure, can you?');\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "You can't possibly be sure, can you?") + ) + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"return confirm('You can\\'t possibly be sure,\\n can you?');\">Hello</a>", + link_to("Hello", "http://www.example.com", :confirm => "You can't possibly be sure,\n can you?") + ) + end + + def test_link_tag_with_popup + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"window.open(this.href);return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", :popup => true) + ) + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"window.open(this.href);return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", :popup => 'true') + ) + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"window.open(this.href,'window_name','width=300,height=300');return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", :popup => ['window_name', 'width=300,height=300']) + ) + end + + def test_link_tag_with_popup_and_javascript_confirm + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"if (confirm('Fo\\' sho\\'?')) { window.open(this.href); };return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", { :popup => true, :confirm => "Fo' sho'?" }) + ) + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"if (confirm('Are you serious?')) { window.open(this.href,'window_name','width=300,height=300'); };return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", { :popup => ['window_name', 'width=300,height=300'], :confirm => "Are you serious?" }) + ) + end + + def test_link_tag_using_post_javascript + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"var f = document.createElement('form'); this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit();return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", :post => true) + ) + end + + def test_link_tag_using_post_javascript_and_confirm + assert_dom_equal( + "<a href=\"http://www.example.com\" onclick=\"if (confirm('Are you serious?')) { var f = document.createElement('form'); this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; f.submit(); };return false;\">Hello</a>", + link_to("Hello", "http://www.example.com", :post => true, :confirm => "Are you serious?") + ) + end + + def test_link_tag_using_post_javascript_and_popup + assert_raises(ActionView::ActionViewError) { link_to("Hello", "http://www.example.com", :popup => true, :post => true, :confirm => "Are you serious?") } + end + + def test_link_to_unless + assert_equal "Showing", link_to_unless(true, "Showing", :action => "show", :controller => "weblog") + assert_dom_equal "<a href=\"http://www.example.com\">Listing</a>", link_to_unless(false, "Listing", :action => "list", :controller => "weblog") + assert_equal "Showing", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) + assert_equal "<strong>Showing</strong>", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) { |name, options, html_options, *parameters_for_method_reference| + "<strong>#{name}</strong>" + } + assert_equal "<strong>Showing</strong>", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) { |name| + "<strong>#{name}</strong>" + } + assert_equal "test", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) { + "test" + } + end + + def test_link_to_if + assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog") + assert_dom_equal "<a href=\"http://www.example.com\">Listing</a>", link_to_if(true, "Listing", :action => "list", :controller => "weblog") + assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog", :id => 1) + end + + def xtest_link_unless_current + @request = RequestMock.new("http://www.example.com") + assert_equal "Showing", link_to_unless_current("Showing", :action => "show", :controller => "weblog") + @request = RequestMock.new("http://www.example.org") + assert "<a href=\"http://www.example.com\">Listing</a>", link_to_unless_current("Listing", :action => "list", :controller => "weblog") + + @request = RequestMock.new("http://www.example.com") + assert_equal "Showing", link_to_unless_current("Showing", :action => "show", :controller => "weblog", :id => 1) + end + + def test_mail_to + assert_dom_equal "<a href=\"mailto:david@loudthinking.com\">david@loudthinking.com</a>", mail_to("david@loudthinking.com") + assert_dom_equal "<a href=\"mailto:david@loudthinking.com\">David Heinemeier Hansson</a>", mail_to("david@loudthinking.com", "David Heinemeier Hansson") + assert_dom_equal( + "<a class=\"admin\" href=\"mailto:david@loudthinking.com\">David Heinemeier Hansson</a>", + mail_to("david@loudthinking.com", "David Heinemeier Hansson", "class" => "admin") + ) + assert_equal mail_to("david@loudthinking.com", "David Heinemeier Hansson", "class" => "admin"), + mail_to("david@loudthinking.com", "David Heinemeier Hansson", :class => "admin") + end + + def test_mail_to_with_javascript + assert_dom_equal "<script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript") + end + + def test_mail_with_options + assert_dom_equal( + %(<a href="mailto:me@example.com?cc=ccaddress%40example.com&bcc=bccaddress%40example.com&body=This%20is%20the%20body%20of%20the%20message.&subject=This%20is%20an%20example%20email">My email</a>), + mail_to("me@example.com", "My email", :cc => "ccaddress@example.com", :bcc => "bccaddress@example.com", :subject => "This is an example email", :body => "This is the body of the message.") + ) + end + + def test_mail_to_with_img + assert_dom_equal %(<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>), mail_to('feedback@example.com', '<img src="/feedback.png" />') + end + + def test_mail_to_with_hex + assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex") + end + + def test_mail_to_with_replace_options + assert_dom_equal "<a href=\"mailto:wolfgang@stufenlos.net\">wolfgang(at)stufenlos(dot)net</a>", mail_to("wolfgang@stufenlos.net", nil, :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain.com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)") + assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex", :replace_at => "(at)") + assert_dom_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">me(at)domain(dot)com</a>", mail_to("me@domain.com", nil, :encode => "hex", :replace_at => "(at)", :replace_dot => "(dot)") + assert_dom_equal "<script type=\"text/javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)") + end +end +module TestingSandbox + + # This whole thing *could* be much simpler, but I don't think Tempfile, + # popen and others exist on all platforms (like Windows). + def execute_in_sandbox(code) + test_name = "#{File.dirname(__FILE__)}/test.#{$$}.rb" + res_name = "#{File.dirname(__FILE__)}/test.#{$$}.out" + + File.open(test_name, "w+") do |file| + file.write(<<-CODE) + $:.unshift "../lib" + block = Proc.new do + #{code} + end + print block.call + CODE + end + + system("ruby #{test_name} > #{res_name}") or raise "could not run test in sandbox" + File.read(res_name) + ensure + File.delete(test_name) rescue nil + File.delete(res_name) rescue nil + end + +end +class DirectoryCategory < ActionWebService::Struct + member :fullViewableName, :string + member :specialEncoding, :string +end + +class ResultElement < ActionWebService::Struct + member :summary, :string + member :URL, :string + member :snippet, :string + member :title, :string + member :cachedSize, :string + member :relatedInformationPresent, :bool + member :hostName, :string + member :directoryCategory, DirectoryCategory + member :directoryTitle, :string +end + +class GoogleSearchResult < ActionWebService::Struct + member :documentFiltering, :bool + member :searchComments, :string + member :estimatedTotalResultsCount, :int + member :estimateIsExact, :bool + member :resultElements, [ResultElement] + member :searchQuery, :string + member :startIndex, :int + member :endIndex, :int + member :searchTips, :string + member :directoryCategories, [DirectoryCategory] + member :searchTime, :float +end + +class GoogleSearchAPI < ActionWebService::API::Base + inflect_names false + + api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}] + api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}] + + api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [ + {:key=>:string}, + {:q=>:string}, + {:start=>:int}, + {:maxResults=>:int}, + {:filter=>:bool}, + {:restrict=>:string}, + {:safeSearch=>:bool}, + {:lr=>:string}, + {:ie=>:string}, + {:oe=>:string} + ] +end +class GoogleSearchController < ApplicationController + wsdl_service_name 'GoogleSearch' + + def doGetCachedPage + "<html><body>i am a cached page. my key was %s, url was %s</body></html>" % [@params['key'], @params['url']] + end + + def doSpellingSuggestion + "%s: Did you mean '%s'?" % [@params['key'], @params['phrase']] + end + + def doGoogleSearch + resultElement = ResultElement.new + resultElement.summary = "ONlamp.com: Rolling with Ruby on Rails" + resultElement.URL = "http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" + resultElement.snippet = "Curt Hibbs shows off Ruby on Rails by building a simple application that requires " + + "almost no Ruby experience. ... Rolling with Ruby on Rails. ..." + resultElement.title = "Teh Railz0r" + resultElement.cachedSize = "Almost no lines of code!" + resultElement.relatedInformationPresent = true + resultElement.hostName = "rubyonrails.com" + resultElement.directoryCategory = category("Web Development", "UTF-8") + + result = GoogleSearchResult.new + result.documentFiltering = @params['filter'] + result.searchComments = "" + result.estimatedTotalResultsCount = 322000 + result.estimateIsExact = false + result.resultElements = [resultElement] + result.searchQuery = "http://www.google.com/search?q=ruby+on+rails" + result.startIndex = @params['start'] + result.endIndex = @params['start'] + @params['maxResults'] + result.searchTips = "\"on\" is a very common word and was not included in your search [details]" + result.searchTime = 0.000001 + + # For Mono, we have to clone objects if they're referenced by more than one place, otherwise + # the Ruby SOAP collapses them into one instance and uses references all over the + # place, confusing Mono. + # + # This has recently been fixed: + # http://bugzilla.ximian.com/show_bug.cgi?id=72265 + result.directoryCategories = [ + category("Web Development", "UTF-8"), + category("Programming", "US-ASCII"), + ] + + result + end + + private + def category(name, encoding) + cat = DirectoryCategory.new + cat.fullViewableName = name.dup + cat.specialEncoding = encoding.dup + cat + end +end +class DirectoryCategory < ActionWebService::Struct + member :fullViewableName, :string + member :specialEncoding, :string +end + +class ResultElement < ActionWebService::Struct + member :summary, :string + member :URL, :string + member :snippet, :string + member :title, :string + member :cachedSize, :string + member :relatedInformationPresent, :bool + member :hostName, :string + member :directoryCategory, DirectoryCategory + member :directoryTitle, :string +end + +class GoogleSearchResult < ActionWebService::Struct + member :documentFiltering, :bool + member :searchComments, :string + member :estimatedTotalResultsCount, :int + member :estimateIsExact, :bool + member :resultElements, [ResultElement] + member :searchQuery, :string + member :startIndex, :int + member :endIndex, :int + member :searchTips, :string + member :directoryCategories, [DirectoryCategory] + member :searchTime, :float +end + +class GoogleSearchAPI < ActionWebService::API::Base + inflect_names false + + api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}] + api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}] + + api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [ + {:key=>:string}, + {:q=>:string}, + {:start=>:int}, + {:maxResults=>:int}, + {:filter=>:bool}, + {:restrict=>:string}, + {:safeSearch=>:bool}, + {:lr=>:string}, + {:ie=>:string}, + {:oe=>:string} + ] +end + +class GoogleSearchService < ActionWebService::Base + web_service_api GoogleSearchAPI + + def doGetCachedPage(key, url) + "<html><body>i am a cached page</body></html>" + end + + def doSpellingSuggestion(key, phrase) + "Did you mean 'teh'?" + end + + def doGoogleSearch(key, q, start, maxResults, filter, restrict, safeSearch, lr, ie, oe) + resultElement = ResultElement.new + resultElement.summary = "ONlamp.com: Rolling with Ruby on Rails" + resultElement.URL = "http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" + resultElement.snippet = "Curt Hibbs shows off Ruby on Rails by building a simple application that requires " + + "almost no Ruby experience. ... Rolling with Ruby on Rails. ..." + resultElement.title = "Teh Railz0r" + resultElement.cachedSize = "Almost no lines of code!" + resultElement.relatedInformationPresent = true + resultElement.hostName = "rubyonrails.com" + resultElement.directoryCategory = category("Web Development", "UTF-8") + + result = GoogleSearchResult.new + result.documentFiltering = filter + result.searchComments = "" + result.estimatedTotalResultsCount = 322000 + result.estimateIsExact = false + result.resultElements = [resultElement] + result.searchQuery = "http://www.google.com/search?q=ruby+on+rails" + result.startIndex = start + result.endIndex = start + maxResults + result.searchTips = "\"on\" is a very common word and was not included in your search [details]" + result.searchTime = 0.000001 + + # For Mono, we have to clone objects if they're referenced by more than one place, otherwise + # the Ruby SOAP collapses them into one instance and uses references all over the + # place, confusing Mono. + # + # This has recently been fixed: + # http://bugzilla.ximian.com/show_bug.cgi?id=72265 + result.directoryCategories = [ + category("Web Development", "UTF-8"), + category("Programming", "US-ASCII"), + ] + + result + end + + private + def category(name, encoding) + cat = DirectoryCategory.new + cat.fullViewableName = name.dup + cat.specialEncoding = encoding.dup + cat + end +end +require 'google_search_service' + +class SearchController < ApplicationController + wsdl_service_name 'GoogleSearch' + web_service_dispatching_mode :delegated + web_service :beta3, GoogleSearchService.new +end +class DirectoryCategory < ActionWebService::Struct + member :fullViewableName, :string + member :specialEncoding, :string +end + +class ResultElement < ActionWebService::Struct + member :summary, :string + member :URL, :string + member :snippet, :string + member :title, :string + member :cachedSize, :string + member :relatedInformationPresent, :bool + member :hostName, :string + member :directoryCategory, DirectoryCategory + member :directoryTitle, :string +end + +class GoogleSearchResult < ActionWebService::Struct + member :documentFiltering, :bool + member :searchComments, :string + member :estimatedTotalResultsCount, :int + member :estimateIsExact, :bool + member :resultElements, [ResultElement] + member :searchQuery, :string + member :startIndex, :int + member :endIndex, :int + member :searchTips, :string + member :directoryCategories, [DirectoryCategory] + member :searchTime, :float +end + +class GoogleSearchAPI < ActionWebService::API::Base + inflect_names false + + api_method :doGetCachedPage, :returns => [:string], :expects => [{:key=>:string}, {:url=>:string}] + api_method :doGetSpellingSuggestion, :returns => [:string], :expects => [{:key=>:string}, {:phrase=>:string}] + + api_method :doGoogleSearch, :returns => [GoogleSearchResult], :expects => [ + {:key=>:string}, + {:q=>:string}, + {:start=>:int}, + {:maxResults=>:int}, + {:filter=>:bool}, + {:restrict=>:string}, + {:safeSearch=>:bool}, + {:lr=>:string}, + {:ie=>:string}, + {:oe=>:string} + ] +end +class SearchController < ApplicationController + web_service_api :google_search + wsdl_service_name 'GoogleSearch' + + def doGetCachedPage + "<html><body>i am a cached page. my key was %s, url was %s</body></html>" % [@params['key'], @params['url']] + end + + def doSpellingSuggestion + "%s: Did you mean '%s'?" % [@params['key'], @params['phrase']] + end + + def doGoogleSearch + resultElement = ResultElement.new + resultElement.summary = "ONlamp.com: Rolling with Ruby on Rails" + resultElement.URL = "http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html" + resultElement.snippet = "Curt Hibbs shows off Ruby on Rails by building a simple application that requires " + + "almost no Ruby experience. ... Rolling with Ruby on Rails. ..." + resultElement.title = "Teh Railz0r" + resultElement.cachedSize = "Almost no lines of code!" + resultElement.relatedInformationPresent = true + resultElement.hostName = "rubyonrails.com" + resultElement.directoryCategory = category("Web Development", "UTF-8") + + result = GoogleSearchResult.new + result.documentFiltering = @params['filter'] + result.searchComments = "" + result.estimatedTotalResultsCount = 322000 + result.estimateIsExact = false + result.resultElements = [resultElement] + result.searchQuery = "http://www.google.com/search?q=ruby+on+rails" + result.startIndex = @params['start'] + result.endIndex = @params['start'] + @params['maxResults'] + result.searchTips = "\"on\" is a very common word and was not included in your search [details]" + result.searchTime = 0.000001 + + # For Mono, we have to clone objects if they're referenced by more than one place, otherwise + # the Ruby SOAP collapses them into one instance and uses references all over the + # place, confusing Mono. + # + # This has recently been fixed: + # http://bugzilla.ximian.com/show_bug.cgi?id=72265 + result.directoryCategories = [ + category("Web Development", "UTF-8"), + category("Programming", "US-ASCII"), + ] + + result + end + + private + def category(name, encoding) + cat = DirectoryCategory.new + cat.fullViewableName = name.dup + cat.specialEncoding = encoding.dup + cat + end +end +# +# see the blogger API spec at http://www.blogger.com/developers/api/1_docs/ +# note that the method signatures are subtly different to metaWeblog, they +# are not identical. take care to ensure you handle the different semantics +# properly if you want to support blogger API too, to get maximum compatibility. +# + +module Blog + class Blog < ActionWebService::Struct + member :url, :string + member :blogid, :string + member :blogName, :string + end + + class User < ActionWebService::Struct + member :nickname, :string + member :userid, :string + member :url, :string + member :email, :string + member :lastname, :string + member :firstname, :string + end +end + +# +# blogger +# +class BloggerAPI < ActionWebService::API::Base + inflect_names false + + api_method :newPost, :returns => [:string], :expects => [ + {:appkey=>:string}, + {:blogid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:content=>:string}, + {:publish=>:bool} + ] + + api_method :editPost, :returns => [:bool], :expects => [ + {:appkey=>:string}, + {:postid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:content=>:string}, + {:publish=>:bool} + ] + + api_method :getUsersBlogs, :returns => [[Blog::Blog]], :expects => [ + {:appkey=>:string}, + {:username=>:string}, + {:password=>:string} + ] + + api_method :getUserInfo, :returns => [Blog::User], :expects => [ + {:appkey=>:string}, + {:username=>:string}, + {:password=>:string} + ] +end +require 'blogger_api' + +class BloggerService < ActionWebService::Base + web_service_api BloggerAPI + + def initialize + @postid = 0 + end + + def newPost(key, id, user, pw, content, publish) + $stderr.puts "id=#{id} user=#{user} pw=#{pw}, content=#{content.inspect} [#{publish}]" + (@postid += 1).to_s + end + + def editPost(key, post_id, user, pw, content, publish) + $stderr.puts "id=#{post_id} user=#{user} pw=#{pw} content=#{content.inspect} [#{publish}]" + true + end + + def getUsersBlogs(key, user, pw) + $stderr.puts "getting blogs for #{user}" + blog = Blog::Blog.new( + :url =>'http://blog', + :blogid => 'myblog', + :blogName => 'My Blog' + ) + [blog] + end + + def getUserInfo(key, user, pw) + $stderr.puts "getting user info for #{user}" + Blog::User.new(:nickname => 'user', :email => 'user@test.com') + end +end +# +# here lie structures, cousins of those on http://www.xmlrpc.com/metaWeblog +# but they don't necessarily the real world reflect +# so if you do, find that your client complains: +# please tell, of problems you suffered through +# + +module Blog + class Post < ActionWebService::Struct + member :title, :string + member :link, :string + member :description, :string + member :author, :string + member :category, :string + member :comments, :string + member :guid, :string + member :pubDate, :string + end + + class Category < ActionWebService::Struct + member :description, :string + member :htmlUrl, :string + member :rssUrl, :string + end +end + +# +# metaWeblog +# +class MetaWeblogAPI < ActionWebService::API::Base + inflect_names false + + api_method :newPost, :returns => [:string], :expects => [ + {:blogid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:struct=>Blog::Post}, + {:publish=>:bool} + ] + + api_method :editPost, :returns => [:bool], :expects => [ + {:postid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:struct=>Blog::Post}, + {:publish=>:bool}, + ] + + api_method :getPost, :returns => [Blog::Post], :expects => [ + {:postid=>:string}, + {:username=>:string}, + {:password=>:string}, + ] + + api_method :getCategories, :returns => [[Blog::Category]], :expects => [ + {:blogid=>:string}, + {:username=>:string}, + {:password=>:string}, + ] + + api_method :getRecentPosts, :returns => [[Blog::Post]], :expects => [ + {:blogid=>:string}, + {:username=>:string}, + {:password=>:string}, + {:numberOfPosts=>:int}, + ] +end +require 'meta_weblog_api' + +class MetaWeblogService < ActionWebService::Base + web_service_api MetaWeblogAPI + + def initialize + @postid = 0 + end + + def newPost(id, user, pw, struct, publish) + $stderr.puts "id=#{id} user=#{user} pw=#{pw}, struct=#{struct.inspect} [#{publish}]" + (@postid += 1).to_s + end + + def editPost(post_id, user, pw, struct, publish) + $stderr.puts "id=#{post_id} user=#{user} pw=#{pw} struct=#{struct.inspect} [#{publish}]" + true + end + + def getPost(post_id, user, pw) + $stderr.puts "get post #{post_id}" + Blog::Post.new(:title => 'hello world', :description => 'first post!') + end + + def getCategories(id, user, pw) + $stderr.puts "categories for #{user}" + cat = Blog::Category.new( + :description => 'Tech', + :htmlUrl => 'http://blog/tech', + :rssUrl => 'http://blog/tech.rss') + [cat] + end + + def getRecentPosts(id, user, pw, num) + $stderr.puts "recent #{num} posts for #{user} on blog #{id}" + post1 = Blog::Post.new( + :title => 'first post!', + :link => 'http://blog.xeraph.org/testOne.html', + :description => 'this is the first post' + ) + post2 = Blog::Post.new( + :title => 'second post!', + :link => 'http://blog.xeraph.org/testTwo.html', + :description => 'this is the second post' + ) + [post1, post2] + end +end +# +# example controller implementing both blogger and metaWeblog APIs +# in a way that should be compatible with clients supporting both/either. +# +# test by pointing your client at http://URL/xmlrpc/api +# + +require 'meta_weblog_service' +require 'blogger_service' + +class XmlrpcController < ApplicationController + web_service_dispatching_mode :layered + + web_service :metaWeblog, MetaWeblogService.new + web_service :blogger, BloggerService.new +end +module ActionWebService # :nodoc: + module API # :nodoc: + # A web service API class specifies the methods that will be available for + # invocation for an API. It also contains metadata such as the method type + # signature hints. + # + # It is not intended to be instantiated. + # + # It is attached to web service implementation classes like + # ActionWebService::Base and ActionController::Base derivatives by using + # <tt>container.web_service_api</tt>, where <tt>container</tt> is an + # ActionController::Base or a ActionWebService::Base. + # + # See ActionWebService::Container::Direct::ClassMethods for an example + # of use. + class Base + # Action WebService API subclasses should be reloaded by the dispatcher in Rails + # when Dependencies.mechanism = :load. + include Reloadable::Subclasses + + # Whether to transform the public API method names into camel-cased names + class_inheritable_option :inflect_names, true + + # Whether to allow ActiveRecord::Base models in <tt>:expects</tt>. + # The default is +false+; you should be aware of the security implications + # of allowing this, and ensure that you don't allow remote callers to + # easily overwrite data they should not have access to. + class_inheritable_option :allow_active_record_expects, false + + # If present, the name of a method to call when the remote caller + # tried to call a nonexistent method. Semantically equivalent to + # +method_missing+. + class_inheritable_option :default_api_method + + # Disallow instantiation + private_class_method :new, :allocate + + class << self + include ActionWebService::SignatureTypes + + # API methods have a +name+, which must be the Ruby method name to use when + # performing the invocation on the web service object. + # + # The signatures for the method input parameters and return value can + # by specified in +options+. + # + # A signature is an array of one or more parameter specifiers. + # A parameter specifier can be one of the following: + # + # * A symbol or string representing one of the Action Web Service base types. + # See ActionWebService::SignatureTypes for a canonical list of the base types. + # * The Class object of the parameter type + # * A single-element Array containing one of the two preceding items. This + # will cause Action Web Service to treat the parameter at that position + # as an array containing only values of the given type. + # * A Hash containing as key the name of the parameter, and as value + # one of the three preceding items + # + # If no method input parameter or method return value signatures are given, + # the method is assumed to take no parameters and/or return no values of + # interest, and any values that are received by the server will be + # discarded and ignored. + # + # Valid options: + # [<tt>:expects</tt>] Signature for the method input parameters + # [<tt>:returns</tt>] Signature for the method return value + # [<tt>:expects_and_returns</tt>] Signature for both input parameters and return value + def api_method(name, options={}) + unless options.is_a?(Hash) + raise(ActionWebServiceError, "Expected a Hash for options") + end + validate_options([:expects, :returns, :expects_and_returns], options.keys) + if options[:expects_and_returns] + expects = options[:expects_and_returns] + returns = options[:expects_and_returns] + else + expects = options[:expects] + returns = options[:returns] + end + expects = canonical_signature(expects) + returns = canonical_signature(returns) + if expects + expects.each do |type| + type = type.element_type if type.is_a?(ArrayType) + if type.type_class.ancestors.include?(ActiveRecord::Base) && !allow_active_record_expects + raise(ActionWebServiceError, "ActiveRecord model classes not allowed in :expects") + end + end + end + name = name.to_sym + public_name = public_api_method_name(name) + method = Method.new(name, public_name, expects, returns) + write_inheritable_hash("api_methods", name => method) + write_inheritable_hash("api_public_method_names", public_name => name) + end + + # Whether the given method name is a service method on this API + def has_api_method?(name) + api_methods.has_key?(name) + end + + # Whether the given public method name has a corresponding service method + # on this API + def has_public_api_method?(public_name) + api_public_method_names.has_key?(public_name) + end + + # The corresponding public method name for the given service method name + def public_api_method_name(name) + if inflect_names + name.to_s.camelize + else + name.to_s + end + end + + # The corresponding service method name for the given public method name + def api_method_name(public_name) + api_public_method_names[public_name] + end + + # A Hash containing all service methods on this API, and their + # associated metadata. + def api_methods + read_inheritable_attribute("api_methods") || {} + end + + # The Method instance for the given public API method name, if any + def public_api_method_instance(public_method_name) + api_method_instance(api_method_name(public_method_name)) + end + + # The Method instance for the given API method name, if any + def api_method_instance(method_name) + api_methods[method_name] + end + + # The Method instance for the default API method, if any + def default_api_method_instance + return nil unless name = default_api_method + instance = read_inheritable_attribute("default_api_method_instance") + if instance && instance.name == name + return instance + end + instance = Method.new(name, public_api_method_name(name), nil, nil) + write_inheritable_attribute("default_api_method_instance", instance) + instance + end + + private + def api_public_method_names + read_inheritable_attribute("api_public_method_names") || {} + end + + def validate_options(valid_option_keys, supplied_option_keys) + unknown_option_keys = supplied_option_keys - valid_option_keys + unless unknown_option_keys.empty? + raise(ActionWebServiceError, "Unknown options: #{unknown_option_keys}") + end + end + end + end + + # Represents an API method and its associated metadata, and provides functionality + # to assist in commonly performed API method tasks. + class Method + attr :name + attr :public_name + attr :expects + attr :returns + + def initialize(name, public_name, expects, returns) + @name = name + @public_name = public_name + @expects = expects + @returns = returns + @caster = ActionWebService::Casting::BaseCaster.new(self) + end + + # The list of parameter names for this method + def param_names + return [] unless @expects + @expects.map{ |type| type.name } + end + + # Casts a set of Ruby values into the expected Ruby values + def cast_expects(params) + @caster.cast_expects(params) + end + + # Cast a Ruby return value into the expected Ruby value + def cast_returns(return_value) + @caster.cast_returns(return_value) + end + + # Returns the index of the first expected parameter + # with the given name + def expects_index_of(param_name) + return -1 if @expects.nil? + (0..(@expects.length-1)).each do |i| + return i if @expects[i].name.to_s == param_name.to_s + end + -1 + end + + # Returns a hash keyed by parameter name for the given + # parameter list + def expects_to_hash(params) + return {} if @expects.nil? + h = {} + @expects.zip(params){ |type, param| h[type.name] = param } + h + end + + # Backwards compatibility with previous API + def [](sig_type) + case sig_type + when :expects + @expects.map{|x| compat_signature_entry(x)} + when :returns + @returns.map{|x| compat_signature_entry(x)} + end + end + + # String representation of this method + def to_s + fqn = "" + fqn << (@returns ? (@returns[0].human_name(false) + " ") : "void ") + fqn << "#{@public_name}(" + fqn << @expects.map{ |p| p.human_name }.join(", ") if @expects + fqn << ")" + fqn + end + + private + def compat_signature_entry(entry) + if entry.array? + [compat_signature_entry(entry.element_type)] + else + if entry.spec.is_a?(Hash) + {entry.spec.keys.first => entry.type_class} + else + entry.type_class + end + end + end + end + end +end +module ActionWebService # :nodoc: + class ActionWebServiceError < StandardError # :nodoc: + end + + # An Action Web Service object implements a specified API. + # + # Used by controllers operating in _Delegated_ dispatching mode. + # + # ==== Example + # + # class PersonService < ActionWebService::Base + # web_service_api PersonAPI + # + # def find_person(criteria) + # Person.find_all [...] + # end + # + # def delete_person(id) + # Person.find_by_id(id).destroy + # end + # end + # + # class PersonAPI < ActionWebService::API::Base + # api_method :find_person, :expects => [SearchCriteria], :returns => [[Person]] + # api_method :delete_person, :expects => [:int] + # end + # + # class SearchCriteria < ActionWebService::Struct + # member :firstname, :string + # member :lastname, :string + # member :email, :string + # end + class Base + # Action WebService subclasses should be reloaded by the dispatcher in Rails + # when Dependencies.mechanism = :load. + include Reloadable::Subclasses + + # Whether to report exceptions back to the caller in the protocol's exception + # format + class_inheritable_option :web_service_exception_reporting, true + end +end +require 'time' +require 'date' +require 'xmlrpc/datetime' + +module ActionWebService # :nodoc: + module Casting # :nodoc: + class CastingError < ActionWebServiceError # :nodoc: + end + + # Performs casting of arbitrary values into the correct types for the signature + class BaseCaster # :nodoc: + def initialize(api_method) + @api_method = api_method + end + + # Coerces the parameters in +params+ (an Enumerable) into the types + # this method expects + def cast_expects(params) + self.class.cast_expects(@api_method, params) + end + + # Coerces the given +return_value+ into the type returned by this + # method + def cast_returns(return_value) + self.class.cast_returns(@api_method, return_value) + end + + class << self + include ActionWebService::SignatureTypes + + def cast_expects(api_method, params) # :nodoc: + return [] if api_method.expects.nil? + api_method.expects.zip(params).map{ |type, param| cast(param, type) } + end + + def cast_returns(api_method, return_value) # :nodoc: + return nil if api_method.returns.nil? + cast(return_value, api_method.returns[0]) + end + + def cast(value, signature_type) # :nodoc: + return value if signature_type.nil? # signature.length != params.length + return nil if value.nil? + # XMLRPC protocol doesn't support nil values. It uses false instead. + # It should never happen for SOAP. + if signature_type.structured? && value.equal?(false) + return nil + end + unless signature_type.array? || signature_type.structured? + return value if canonical_type(value.class) == signature_type.type + end + if signature_type.array? + unless value.respond_to?(:entries) && !value.is_a?(String) + raise CastingError, "Don't know how to cast #{value.class} into #{signature_type.type.inspect}" + end + value.entries.map do |entry| + cast(entry, signature_type.element_type) + end + elsif signature_type.structured? + cast_to_structured_type(value, signature_type) + elsif !signature_type.custom? + cast_base_type(value, signature_type) + end + end + + def cast_base_type(value, signature_type) # :nodoc: + # This is a work-around for the fact that XML-RPC special-cases DateTime values into its own DateTime type + # in order to support iso8601 dates. This doesn't work too well for us, so we'll convert it into a Time, + # with the caveat that we won't be able to handle pre-1970 dates that are sent to us. + # + # See http://dev.rubyonrails.com/ticket/2516 + value = value.to_time if value.is_a?(XMLRPC::DateTime) + + case signature_type.type + when :int + Integer(value) + when :string + value.to_s + when :base64 + if value.is_a?(ActionWebService::Base64) + value + else + ActionWebService::Base64.new(value.to_s) + end + when :bool + return false if value.nil? + return value if value == true || value == false + case value.to_s.downcase + when '1', 'true', 'y', 'yes' + true + when '0', 'false', 'n', 'no' + false + else + raise CastingError, "Don't know how to cast #{value.class} into Boolean" + end + when :float + Float(value) + when :time + value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash) + Time.parse(value.to_s) + when :date + value = "#{value['2']}/#{value['3']}/#{value['1']}" if value.kind_of?(Hash) + Date.parse(value.to_s) + when :datetime + value = "#{value['2']}/#{value['3']}/#{value['1']} #{value['4']}:#{value['5']}:#{value['6']}" if value.kind_of?(Hash) + DateTime.parse(value.to_s) + end + end + + def cast_to_structured_type(value, signature_type) # :nodoc: + obj = nil + obj = value if canonical_type(value.class) == canonical_type(signature_type.type) + obj ||= signature_type.type_class.new + if value.respond_to?(:each_pair) + klass = signature_type.type_class + value.each_pair do |name, val| + type = klass.respond_to?(:member_type) ? klass.member_type(name) : nil + val = cast(val, type) if type + # See http://dev.rubyonrails.com/ticket/3567 + val = val.to_time if val.is_a?(XMLRPC::DateTime) + obj.__send__("#{name}=", val) if obj.respond_to?(name) + end + elsif value.respond_to?(:attributes) + signature_type.each_member do |name, type| + val = value.__send__(name) + obj.__send__("#{name}=", cast(val, type)) if obj.respond_to?(name) + end + else + raise CastingError, "Don't know how to cast #{value.class} to #{signature_type.type_class}" + end + obj + end + end + end + end +end +module ActionWebService # :nodoc: + module Client # :nodoc: + class ClientError < StandardError # :nodoc: + end + + class Base # :nodoc: + def initialize(api, endpoint_uri) + @api = api + @endpoint_uri = endpoint_uri + end + + def method_missing(name, *args) # :nodoc: + call_name = method_name(name) + return super(name, *args) if call_name.nil? + self.perform_invocation(call_name, args) + end + + private + def method_name(name) + if @api.has_api_method?(name.to_sym) + name.to_s + elsif @api.has_public_api_method?(name.to_s) + @api.api_method_name(name.to_s).to_s + end + end + end + end +end +require 'soap/rpc/driver' +require 'uri' + +module ActionWebService # :nodoc: + module Client # :nodoc: + + # Implements SOAP client support (using RPC encoding for the messages). + # + # ==== Example Usage + # + # class PersonAPI < ActionWebService::API::Base + # api_method :find_all, :returns => [[Person]] + # end + # + # soap_client = ActionWebService::Client::Soap.new(PersonAPI, "http://...") + # persons = soap_client.find_all + # + class Soap < Base + + # Creates a new web service client using the SOAP RPC protocol. + # + # +api+ must be an ActionWebService::API::Base derivative, and + # +endpoint_uri+ must point at the relevant URL to which protocol requests + # will be sent with HTTP POST. + # + # Valid options: + # [<tt>:namespace</tt>] If the remote server has used a custom namespace to + # declare its custom types, you can specify it here. This would + # be the namespace declared with a [WebService(Namespace = "http://namespace")] attribute + # in .NET, for example. + # [<tt>:driver_options</tt>] If you want to supply any custom SOAP RPC driver + # options, you can provide them as a Hash here + # + # The <tt>:driver_options</tt> option can be used to configure the backend SOAP + # RPC driver. An example of configuring the SOAP backend to do + # client-certificate authenticated SSL connections to the server: + # + # opts = {} + # opts['protocol.http.ssl_config.verify_mode'] = 'OpenSSL::SSL::VERIFY_PEER' + # opts['protocol.http.ssl_config.client_cert'] = client_cert_file_path + # opts['protocol.http.ssl_config.client_key'] = client_key_file_path + # opts['protocol.http.ssl_config.ca_file'] = ca_cert_file_path + # client = ActionWebService::Client::Soap.new(api, 'https://some/service', :driver_options => opts) + def initialize(api, endpoint_uri, options={}) + super(api, endpoint_uri) + @namespace = options[:namespace] || 'urn:ActionWebService' + @driver_options = options[:driver_options] || {} + @protocol = ActionWebService::Protocol::Soap::SoapProtocol.new @namespace + @soap_action_base = options[:soap_action_base] + @soap_action_base ||= URI.parse(endpoint_uri).path + @driver = create_soap_rpc_driver(api, endpoint_uri) + @driver_options.each do |name, value| + @driver.options[name.to_s] = value + end + end + + protected + def perform_invocation(method_name, args) + method = @api.api_methods[method_name.to_sym] + args = method.cast_expects(args.dup) rescue args + return_value = @driver.send(method_name, *args) + method.cast_returns(return_value.dup) rescue return_value + end + + def soap_action(method_name) + "#{@soap_action_base}/#{method_name}" + end + + private + def create_soap_rpc_driver(api, endpoint_uri) + @protocol.register_api(api) + driver = SoapDriver.new(endpoint_uri, nil) + driver.mapping_registry = @protocol.marshaler.registry + api.api_methods.each do |name, method| + qname = XSD::QName.new(@namespace, method.public_name) + action = soap_action(method.public_name) + expects = method.expects + returns = method.returns + param_def = [] + if expects + expects.each do |type| + type_binding = @protocol.marshaler.lookup_type(type) + if SOAP::Version >= "1.5.5" + param_def << ['in', type.name.to_s, [type_binding.type.type_class.to_s]] + else + param_def << ['in', type.name, type_binding.mapping] + end + end + end + if returns + type_binding = @protocol.marshaler.lookup_type(returns[0]) + if SOAP::Version >= "1.5.5" + param_def << ['retval', 'return', [type_binding.type.type_class.to_s]] + else + param_def << ['retval', 'return', type_binding.mapping] + end + end + driver.add_method(qname, action, method.name.to_s, param_def) + end + driver + end + + class SoapDriver < SOAP::RPC::Driver # :nodoc: + def add_method(qname, soapaction, name, param_def) + @proxy.add_rpc_method(qname, soapaction, name, param_def) + add_rpc_method_interface(name, param_def) + end + end + end + end +end +require 'uri' +require 'xmlrpc/client' + +module ActionWebService # :nodoc: + module Client # :nodoc: + + # Implements XML-RPC client support + # + # ==== Example Usage + # + # class BloggerAPI < ActionWebService::API::Base + # inflect_names false + # api_method :getRecentPosts, :returns => [[Blog::Post]] + # end + # + # blog = ActionWebService::Client::XmlRpc.new(BloggerAPI, "http://.../RPC", :handler_name => "blogger") + # posts = blog.getRecentPosts + class XmlRpc < Base + + # Creates a new web service client using the XML-RPC protocol. + # + # +api+ must be an ActionWebService::API::Base derivative, and + # +endpoint_uri+ must point at the relevant URL to which protocol requests + # will be sent with HTTP POST. + # + # Valid options: + # [<tt>:handler_name</tt>] If the remote server defines its services inside special + # handler (the Blogger API uses a <tt>"blogger"</tt> handler name for example), + # provide it here, or your method calls will fail + def initialize(api, endpoint_uri, options={}) + @api = api + @handler_name = options[:handler_name] + @protocol = ActionWebService::Protocol::XmlRpc::XmlRpcProtocol.new + @client = XMLRPC::Client.new2(endpoint_uri, options[:proxy], options[:timeout]) + end + + protected + def perform_invocation(method_name, args) + method = @api.api_methods[method_name.to_sym] + if method.expects && method.expects.length != args.length + raise(ArgumentError, "#{method.public_name}: wrong number of arguments (#{args.length} for #{method.expects.length})") + end + args = method.cast_expects(args.dup) rescue args + if method.expects + method.expects.each_with_index{ |type, i| args[i] = @protocol.value_to_xmlrpc_wire_format(args[i], type) } + end + ok, return_value = @client.call2(public_name(method_name), *args) + return (method.cast_returns(return_value.dup) rescue return_value) if ok + raise(ClientError, "#{return_value.faultCode}: #{return_value.faultString}") + end + + def public_name(method_name) + public_name = @api.public_api_method_name(method_name) + @handler_name ? "#{@handler_name}.#{public_name}" : public_name + end + end + end +end +require 'action_web_service/client/base' +require 'action_web_service/client/soap_client' +require 'action_web_service/client/xmlrpc_client' +module ActionWebService # :nodoc: + module Container # :nodoc: + module ActionController # :nodoc: + def self.append_features(base) # :nodoc: + class << base + include ClassMethods + alias_method :inherited_without_api, :inherited + alias_method :inherited, :inherited_with_api + alias_method :web_service_api_without_require, :web_service_api + alias_method :web_service_api, :web_service_api_with_require + end + end + + module ClassMethods + # Creates a client for accessing remote web services, using the + # given +protocol+ to communicate with the +endpoint_uri+. + # + # ==== Example + # + # class MyController < ActionController::Base + # web_client_api :blogger, :xmlrpc, "http://blogger.com/myblog/api/RPC2", :handler_name => 'blogger' + # end + # + # In this example, a protected method named <tt>blogger</tt> will + # now exist on the controller, and calling it will return the + # XML-RPC client object for working with that remote service. + # + # +options+ is the set of protocol client specific options (see + # a protocol client class for details). + # + # If your API definition does not exist on the load path with the + # correct rules for it to be found using +name+, you can pass in + # the API definition class via +options+, using a key of <tt>:api</tt> + def web_client_api(name, protocol, endpoint_uri, options={}) + unless method_defined?(name) + api_klass = options.delete(:api) || require_web_service_api(name) + class_eval do + define_method(name) do + create_web_service_client(api_klass, protocol, endpoint_uri, options) + end + protected name + end + end + end + + def web_service_api_with_require(definition=nil) # :nodoc: + return web_service_api_without_require if definition.nil? + case definition + when String, Symbol + klass = require_web_service_api(definition) + else + klass = definition + end + web_service_api_without_require(klass) + end + + def require_web_service_api(name) # :nodoc: + case name + when String, Symbol + file_name = name.to_s.underscore + "_api" + class_name = file_name.camelize + class_names = [class_name, class_name.sub(/Api$/, 'API')] + begin + require_dependency(file_name) + rescue LoadError => load_error + requiree = / -- (.*?)(\.rb)?$/.match(load_error).to_a[1] + msg = requiree == file_name ? "Missing API definition file in apis/#{file_name}.rb" : "Can't load file: #{requiree}" + raise LoadError.new(msg).copy_blame!(load_error) + end + klass = nil + class_names.each do |name| + klass = name.constantize rescue nil + break unless klass.nil? + end + unless klass + raise(NameError, "neither #{class_names[0]} or #{class_names[1]} found") + end + klass + else + raise(ArgumentError, "expected String or Symbol argument") + end + end + + private + def inherited_with_api(child) + inherited_without_api(child) + begin child.web_service_api(child.controller_path) + rescue MissingSourceFile => e + raise unless e.is_missing?("apis/#{child.controller_path}_api") + end + end + end + end + end +end +module ActionWebService # :nodoc: + module Container # :nodoc: + module Delegated # :nodoc: + class ContainerError < ActionWebServiceError # :nodoc: + end + + def self.append_features(base) # :nodoc: + super + base.extend(ClassMethods) + base.send(:include, ActionWebService::Container::Delegated::InstanceMethods) + end + + module ClassMethods + # Declares a web service that will provide access to the API of the given + # +object+. +object+ must be an ActionWebService::Base derivative. + # + # Web service object creation can either be _immediate_, where the object + # instance is given at class definition time, or _deferred_, where + # object instantiation is delayed until request time. + # + # ==== Immediate web service object example + # + # class ApiController < ApplicationController + # web_service_dispatching_mode :delegated + # + # web_service :person, PersonService.new + # end + # + # For deferred instantiation, a block should be given instead of an + # object instance. This block will be executed in controller instance + # context, so it can rely on controller instance variables being present. + # + # ==== Deferred web service object example + # + # class ApiController < ApplicationController + # web_service_dispatching_mode :delegated + # + # web_service(:person) { PersonService.new(request.env) } + # end + def web_service(name, object=nil, &block) + if (object && block_given?) || (object.nil? && block.nil?) + raise(ContainerError, "either service, or a block must be given") + end + name = name.to_sym + if block_given? + info = { name => { :block => block } } + else + info = { name => { :object => object } } + end + write_inheritable_hash("web_services", info) + call_web_service_definition_callbacks(self, name, info) + end + + # Whether this service contains a service with the given +name+ + def has_web_service?(name) + web_services.has_key?(name.to_sym) + end + + def web_services # :nodoc: + read_inheritable_attribute("web_services") || {} + end + + def add_web_service_definition_callback(&block) # :nodoc: + write_inheritable_array("web_service_definition_callbacks", [block]) + end + + private + def call_web_service_definition_callbacks(container_class, web_service_name, service_info) + (read_inheritable_attribute("web_service_definition_callbacks") || []).each do |block| + block.call(container_class, web_service_name, service_info) + end + end + end + + module InstanceMethods # :nodoc: + def web_service_object(web_service_name) + info = self.class.web_services[web_service_name.to_sym] + unless info + raise(ContainerError, "no such web service '#{web_service_name}'") + end + service = info[:block] + service ? self.instance_eval(&service) : info[:object] + end + end + end + end +end +module ActionWebService # :nodoc: + module Container # :nodoc: + module Direct # :nodoc: + class ContainerError < ActionWebServiceError # :nodoc: + end + + def self.append_features(base) # :nodoc: + super + base.extend(ClassMethods) + end + + module ClassMethods + # Attaches ActionWebService API +definition+ to the calling class. + # + # Action Controllers can have a default associated API, removing the need + # to call this method if you follow the Action Web Service naming conventions. + # + # A controller with a class name of GoogleSearchController will + # implicitly load <tt>app/apis/google_search_api.rb</tt>, and expect the + # API definition class to be named <tt>GoogleSearchAPI</tt> or + # <tt>GoogleSearchApi</tt>. + # + # ==== Service class example + # + # class MyService < ActionWebService::Base + # web_service_api MyAPI + # end + # + # class MyAPI < ActionWebService::API::Base + # ... + # end + # + # ==== Controller class example + # + # class MyController < ActionController::Base + # web_service_api MyAPI + # end + # + # class MyAPI < ActionWebService::API::Base + # ... + # end + def web_service_api(definition=nil) + if definition.nil? + read_inheritable_attribute("web_service_api") + else + if definition.is_a?(Symbol) + raise(ContainerError, "symbols can only be used for #web_service_api inside of a controller") + end + unless definition.respond_to?(:ancestors) && definition.ancestors.include?(ActionWebService::API::Base) + raise(ContainerError, "#{definition.to_s} is not a valid API definition") + end + write_inheritable_attribute("web_service_api", definition) + call_web_service_api_callbacks(self, definition) + end + end + + def add_web_service_api_callback(&block) # :nodoc: + write_inheritable_array("web_service_api_callbacks", [block]) + end + + private + def call_web_service_api_callbacks(container_class, definition) + (read_inheritable_attribute("web_service_api_callbacks") || []).each do |block| + block.call(container_class, definition) + end + end + end + end + end +end +require 'action_web_service/container/direct_container' +require 'action_web_service/container/delegated_container' +require 'action_web_service/container/action_controller_container' +require 'benchmark' + +module ActionWebService # :nodoc: + module Dispatcher # :nodoc: + class DispatcherError < ActionWebService::ActionWebServiceError # :nodoc: + end + + def self.append_features(base) # :nodoc: + super + base.class_inheritable_option(:web_service_dispatching_mode, :direct) + base.class_inheritable_option(:web_service_exception_reporting, true) + base.send(:include, ActionWebService::Dispatcher::InstanceMethods) + end + + module InstanceMethods # :nodoc: + private + def invoke_web_service_request(protocol_request) + invocation = web_service_invocation(protocol_request) + if invocation.is_a?(Array) && protocol_request.protocol.is_a?(Protocol::XmlRpc::XmlRpcProtocol) + xmlrpc_multicall_invoke(invocation) + else + web_service_invoke(invocation) + end + end + + def web_service_direct_invoke(invocation) + @method_params = invocation.method_ordered_params + arity = method(invocation.api_method.name).arity rescue 0 + if arity < 0 || arity > 0 + params = @method_params + else + params = [] + end + web_service_filtered_invoke(invocation, params) + end + + def web_service_delegated_invoke(invocation) + web_service_filtered_invoke(invocation, invocation.method_ordered_params) + end + + def web_service_filtered_invoke(invocation, params) + cancellation_reason = nil + return_value = invocation.service.perform_invocation(invocation.api_method.name, params) do |x| + cancellation_reason = x + end + if cancellation_reason + raise(DispatcherError, "request canceled: #{cancellation_reason}") + end + return_value + end + + def web_service_invoke(invocation) + case web_service_dispatching_mode + when :direct + return_value = web_service_direct_invoke(invocation) + when :delegated, :layered + return_value = web_service_delegated_invoke(invocation) + end + web_service_create_response(invocation.protocol, invocation.protocol_options, invocation.api, invocation.api_method, return_value) + end + + def xmlrpc_multicall_invoke(invocations) + responses = [] + invocations.each do |invocation| + if invocation.is_a?(Hash) + responses << invocation + next + end + begin + case web_service_dispatching_mode + when :direct + return_value = web_service_direct_invoke(invocation) + when :delegated, :layered + return_value = web_service_delegated_invoke(invocation) + end + api_method = invocation.api_method + if invocation.api.has_api_method?(api_method.name) + return_value = api_method.cast_returns(return_value) + end + responses << [return_value] + rescue Exception => e + responses << { 'faultCode' => 3, 'faultString' => e.message } + end + end + invocation = invocations[0] + invocation.protocol.encode_response('system.multicall', responses, nil, invocation.protocol_options) + end + + def web_service_invocation(request, level = 0) + public_method_name = request.method_name + invocation = Invocation.new + invocation.protocol = request.protocol + invocation.protocol_options = request.protocol_options + invocation.service_name = request.service_name + if web_service_dispatching_mode == :layered + case invocation.protocol + when Protocol::Soap::SoapProtocol + soap_action = request.protocol_options[:soap_action] + if soap_action && soap_action =~ /^\/\w+\/(\w+)\// + invocation.service_name = $1 + end + when Protocol::XmlRpc::XmlRpcProtocol + if request.method_name =~ /^([^\.]+)\.(.*)$/ + public_method_name = $2 + invocation.service_name = $1 + end + end + end + if invocation.protocol.is_a? Protocol::XmlRpc::XmlRpcProtocol + if public_method_name == 'multicall' && invocation.service_name == 'system' + if level > 0 + raise(DispatcherError, "Recursive system.multicall invocations not allowed") + end + multicall = request.method_params.dup + unless multicall.is_a?(Array) && multicall[0].is_a?(Array) + raise(DispatcherError, "Malformed multicall (expected array of Hash elements)") + end + multicall = multicall[0] + return multicall.map do |item| + raise(DispatcherError, "Multicall elements must be Hash") unless item.is_a?(Hash) + raise(DispatcherError, "Multicall elements must contain a 'methodName' key") unless item.has_key?('methodName') + method_name = item['methodName'] + params = item.has_key?('params') ? item['params'] : [] + multicall_request = request.dup + multicall_request.method_name = method_name + multicall_request.method_params = params + begin + web_service_invocation(multicall_request, level + 1) + rescue Exception => e + {'faultCode' => 4, 'faultMessage' => e.message} + end + end + end + end + case web_service_dispatching_mode + when :direct + invocation.api = self.class.web_service_api + invocation.service = self + when :delegated, :layered + invocation.service = web_service_object(invocation.service_name) + invocation.api = invocation.service.class.web_service_api + end + if invocation.api.nil? + raise(DispatcherError, "no API attached to #{invocation.service.class}") + end + invocation.protocol.register_api(invocation.api) + request.api = invocation.api + if invocation.api.has_public_api_method?(public_method_name) + invocation.api_method = invocation.api.public_api_method_instance(public_method_name) + else + if invocation.api.default_api_method.nil? + raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api}") + else + invocation.api_method = invocation.api.default_api_method_instance + end + end + if invocation.service.nil? + raise(DispatcherError, "no service available for service name #{invocation.service_name}") + end + unless invocation.service.respond_to?(invocation.api_method.name) + raise(DispatcherError, "no such method '#{public_method_name}' on API #{invocation.api} (#{invocation.api_method.name})") + end + request.api_method = invocation.api_method + begin + invocation.method_ordered_params = invocation.api_method.cast_expects(request.method_params.dup) + rescue + logger.warn "Casting of method parameters failed" unless logger.nil? + invocation.method_ordered_params = request.method_params + end + request.method_params = invocation.method_ordered_params + invocation.method_named_params = {} + invocation.api_method.param_names.inject(0) do |m, n| + invocation.method_named_params[n] = invocation.method_ordered_params[m] + m + 1 + end + invocation + end + + def web_service_create_response(protocol, protocol_options, api, api_method, return_value) + if api.has_api_method?(api_method.name) + return_type = api_method.returns ? api_method.returns[0] : nil + return_value = api_method.cast_returns(return_value) + else + return_type = ActionWebService::SignatureTypes.canonical_signature_entry(return_value.class, 0) + end + protocol.encode_response(api_method.public_name + 'Response', return_value, return_type, protocol_options) + end + + class Invocation # :nodoc: + attr_accessor :protocol + attr_accessor :protocol_options + attr_accessor :service_name + attr_accessor :api + attr_accessor :api_method + attr_accessor :method_ordered_params + attr_accessor :method_named_params + attr_accessor :service + end + end + end +end +require 'benchmark' +require 'builder/xmlmarkup' + +module ActionWebService # :nodoc: + module Dispatcher # :nodoc: + module ActionController # :nodoc: + def self.append_features(base) # :nodoc: + super + class << base + include ClassMethods + alias_method :inherited_without_action_controller, :inherited + alias_method :inherited, :inherited_with_action_controller + end + base.class_eval do + alias_method :web_service_direct_invoke_without_controller, :web_service_direct_invoke + end + base.add_web_service_api_callback do |klass, api| + if klass.web_service_dispatching_mode == :direct + klass.class_eval 'def api; dispatch_web_service_request; end' + end + end + base.add_web_service_definition_callback do |klass, name, info| + if klass.web_service_dispatching_mode == :delegated + klass.class_eval "def #{name}; dispatch_web_service_request; end" + elsif klass.web_service_dispatching_mode == :layered + klass.class_eval 'def api; dispatch_web_service_request; end' + end + end + base.send(:include, ActionWebService::Dispatcher::ActionController::InstanceMethods) + end + + module ClassMethods # :nodoc: + def inherited_with_action_controller(child) + inherited_without_action_controller(child) + child.send(:include, ActionWebService::Dispatcher::ActionController::WsdlAction) + end + end + + module InstanceMethods # :nodoc: + private + def dispatch_web_service_request + exception = nil + begin + ws_request = discover_web_service_request(request) + rescue Exception => e + exception = e + end + if ws_request + ws_response = nil + exception = nil + bm = Benchmark.measure do + begin + ws_response = invoke_web_service_request(ws_request) + rescue Exception => e + exception = e + end + end + log_request(ws_request, request.raw_post) + if exception + log_error(exception) unless logger.nil? + send_web_service_error_response(ws_request, exception) + else + send_web_service_response(ws_response, bm.real) + end + else + exception ||= DispatcherError.new("Malformed SOAP or XML-RPC protocol message") + log_error(exception) unless logger.nil? + send_web_service_error_response(ws_request, exception) + end + rescue Exception => e + log_error(e) unless logger.nil? + send_web_service_error_response(ws_request, e) + end + + def send_web_service_response(ws_response, elapsed=nil) + log_response(ws_response, elapsed) + options = { :type => ws_response.content_type, :disposition => 'inline' } + send_data(ws_response.body, options) + end + + def send_web_service_error_response(ws_request, exception) + if ws_request + unless self.class.web_service_exception_reporting + exception = DispatcherError.new("Internal server error (exception raised)") + end + api_method = ws_request.api_method + public_method_name = api_method ? api_method.public_name : ws_request.method_name + return_type = ActionWebService::SignatureTypes.canonical_signature_entry(Exception, 0) + ws_response = ws_request.protocol.encode_response(public_method_name + 'Response', exception, return_type, ws_request.protocol_options) + send_web_service_response(ws_response) + else + if self.class.web_service_exception_reporting + message = exception.message + backtrace = "\nBacktrace:\n#{exception.backtrace.join("\n")}" + else + message = "Exception raised" + backtrace = "" + end + render_text("Internal protocol error: #{message}#{backtrace}", "500 Internal Protocol Error") + end + end + + def web_service_direct_invoke(invocation) + invocation.method_named_params.each do |name, value| + params[name] = value + end + params['action'] = invocation.api_method.name.to_s + if before_action == false + raise(DispatcherError, "Method filtered") + end + return_value = web_service_direct_invoke_without_controller(invocation) + after_action + return_value + end + + def log_request(ws_request, body) + unless logger.nil? + name = ws_request.method_name + api_method = ws_request.api_method + params = ws_request.method_params + if api_method && api_method.expects + params = api_method.expects.zip(params).map{ |type, param| "#{type.name}=>#{param.inspect}" } + else + params = params.map{ |param| param.inspect } + end + service = ws_request.service_name + logger.debug("\nWeb Service Request: #{name}(#{params.join(", ")}) Entrypoint: #{service}") + logger.debug(indent(body)) + end + end + + def log_response(ws_response, elapsed=nil) + unless logger.nil? + elapsed = (elapsed ? " (%f):" % elapsed : ":") + logger.debug("\nWeb Service Response" + elapsed + " => #{ws_response.return_value.inspect}") + logger.debug(indent(ws_response.body)) + end + end + + def indent(body) + body.split(/\n/).map{|x| " #{x}"}.join("\n") + end + end + + module WsdlAction # :nodoc: + XsdNs = 'http://www.w3.org/2001/XMLSchema' + WsdlNs = 'http://schemas.xmlsoap.org/wsdl/' + SoapNs = 'http://schemas.xmlsoap.org/wsdl/soap/' + SoapEncodingNs = 'http://schemas.xmlsoap.org/soap/encoding/' + SoapHttpTransport = 'http://schemas.xmlsoap.org/soap/http' + + def wsdl + case request.method + when :get + begin + options = { :type => 'text/xml', :disposition => 'inline' } + send_data(to_wsdl, options) + rescue Exception => e + log_error(e) unless logger.nil? + end + when :post + render_text('POST not supported', '500 POST not supported') + end + end + + private + def base_uri + host = request.env['HTTP_HOST'] || request.env['SERVER_NAME'] || 'localhost' + relative_url_root = request.relative_url_root + scheme = request.ssl? ? 'https' : 'http' + '%s://%s%s/%s/' % [scheme, host, relative_url_root, self.class.controller_path] + end + + def to_wsdl + xml = '' + dispatching_mode = web_service_dispatching_mode + global_service_name = wsdl_service_name + namespace = wsdl_namespace || 'urn:ActionWebService' + soap_action_base = "/#{controller_name}" + + marshaler = ActionWebService::Protocol::Soap::SoapMarshaler.new(namespace) + apis = {} + case dispatching_mode + when :direct + api = self.class.web_service_api + web_service_name = controller_class_name.sub(/Controller$/, '').underscore + apis[web_service_name] = [api, register_api(api, marshaler)] + when :delegated, :layered + self.class.web_services.each do |web_service_name, info| + service = web_service_object(web_service_name) + api = service.class.web_service_api + apis[web_service_name] = [api, register_api(api, marshaler)] + end + end + custom_types = [] + apis.values.each do |api, bindings| + bindings.each do |b| + custom_types << b unless custom_types.include?(b) + end + end + + xm = Builder::XmlMarkup.new(:target => xml, :indent => 2) + xm.instruct! + xm.definitions('name' => wsdl_service_name, + 'targetNamespace' => namespace, + 'xmlns:typens' => namespace, + 'xmlns:xsd' => XsdNs, + 'xmlns:soap' => SoapNs, + 'xmlns:soapenc' => SoapEncodingNs, + 'xmlns:wsdl' => WsdlNs, + 'xmlns' => WsdlNs) do + # Generate XSD + if custom_types.size > 0 + xm.types do + xm.xsd(:schema, 'xmlns' => XsdNs, 'targetNamespace' => namespace) do + custom_types.each do |binding| + case + when binding.type.array? + xm.xsd(:complexType, 'name' => binding.type_name) do + xm.xsd(:complexContent) do + xm.xsd(:restriction, 'base' => 'soapenc:Array') do + xm.xsd(:attribute, 'ref' => 'soapenc:arrayType', + 'wsdl:arrayType' => binding.element_binding.qualified_type_name('typens') + '[]') + end + end + end + when binding.type.structured? + xm.xsd(:complexType, 'name' => binding.type_name) do + xm.xsd(:all) do + binding.type.each_member do |name, type| + b = marshaler.register_type(type) + xm.xsd(:element, 'name' => name, 'type' => b.qualified_type_name('typens')) + end + end + end + end + end + end + end + end + + # APIs + apis.each do |api_name, values| + api = values[0] + api.api_methods.each do |name, method| + gen = lambda do |msg_name, direction| + xm.message('name' => message_name_for(api_name, msg_name)) do + sym = nil + if direction == :out + returns = method.returns + if returns + binding = marshaler.register_type(returns[0]) + xm.part('name' => 'return', 'type' => binding.qualified_type_name('typens')) + end + else + expects = method.expects + expects.each do |type| + binding = marshaler.register_type(type) + xm.part('name' => type.name, 'type' => binding.qualified_type_name('typens')) + end if expects + end + end + end + public_name = method.public_name + gen.call(public_name, :in) + gen.call("#{public_name}Response", :out) + end + + # Port + port_name = port_name_for(global_service_name, api_name) + xm.portType('name' => port_name) do + api.api_methods.each do |name, method| + xm.operation('name' => method.public_name) do + xm.input('message' => "typens:" + message_name_for(api_name, method.public_name)) + xm.output('message' => "typens:" + message_name_for(api_name, "#{method.public_name}Response")) + end + end + end + + # Bind it + binding_name = binding_name_for(global_service_name, api_name) + xm.binding('name' => binding_name, 'type' => "typens:#{port_name}") do + xm.soap(:binding, 'style' => 'rpc', 'transport' => SoapHttpTransport) + api.api_methods.each do |name, method| + xm.operation('name' => method.public_name) do + case web_service_dispatching_mode + when :direct + soap_action = soap_action_base + "/api/" + method.public_name + when :delegated, :layered + soap_action = soap_action_base \ + + "/" + api_name.to_s \ + + "/" + method.public_name + end + xm.soap(:operation, 'soapAction' => soap_action) + xm.input do + xm.soap(:body, + 'use' => 'encoded', + 'namespace' => namespace, + 'encodingStyle' => SoapEncodingNs) + end + xm.output do + xm.soap(:body, + 'use' => 'encoded', + 'namespace' => namespace, + 'encodingStyle' => SoapEncodingNs) + end + end + end + end + end + + # Define it + xm.service('name' => "#{global_service_name}Service") do + apis.each do |api_name, values| + port_name = port_name_for(global_service_name, api_name) + binding_name = binding_name_for(global_service_name, api_name) + case web_service_dispatching_mode + when :direct, :layered + binding_target = 'api' + when :delegated + binding_target = api_name.to_s + end + xm.port('name' => port_name, 'binding' => "typens:#{binding_name}") do + xm.soap(:address, 'location' => "#{base_uri}#{binding_target}") + end + end + end + end + end + + def port_name_for(global_service, service) + "#{global_service}#{service.to_s.camelize}Port" + end + + def binding_name_for(global_service, service) + "#{global_service}#{service.to_s.camelize}Binding" + end + + def message_name_for(api_name, message_name) + mode = web_service_dispatching_mode + if mode == :layered || mode == :delegated + api_name.to_s + '-' + message_name + else + message_name + end + end + + def register_api(api, marshaler) + bindings = {} + traverse_custom_types(api, marshaler, bindings) do |binding| + bindings[binding] = nil unless bindings.has_key?(binding) + element_binding = binding.element_binding + bindings[element_binding] = nil if element_binding && !bindings.has_key?(element_binding) + end + bindings.keys + end + + def traverse_custom_types(api, marshaler, bindings, &block) + api.api_methods.each do |name, method| + expects, returns = method.expects, method.returns + expects.each{ |type| traverse_type(marshaler, type, bindings, &block) if type.custom? } if expects + returns.each{ |type| traverse_type(marshaler, type, bindings, &block) if type.custom? } if returns + end + end + + def traverse_type(marshaler, type, bindings, &block) + binding = marshaler.register_type(type) + return if bindings.has_key?(binding) + bindings[binding] = nil + yield binding + if type.array? + yield marshaler.register_type(type.element_type) + type = type.element_type + end + type.each_member{ |name, type| traverse_type(marshaler, type, bindings, &block) } if type.structured? + end + end + end + end +end +require 'action_web_service/dispatcher/abstract' +require 'action_web_service/dispatcher/action_controller_dispatcher' +module ActionWebService # :nodoc: + module Invocation # :nodoc: + class InvocationError < ActionWebService::ActionWebServiceError # :nodoc: + end + + def self.append_features(base) # :nodoc: + super + base.extend(ClassMethods) + base.send(:include, ActionWebService::Invocation::InstanceMethods) + end + + # Invocation interceptors provide a means to execute custom code before + # and after method invocations on ActionWebService::Base objects. + # + # When running in _Direct_ dispatching mode, ActionController filters + # should be used for this functionality instead. + # + # The semantics of invocation interceptors are the same as ActionController + # filters, and accept the same parameters and options. + # + # A _before_ interceptor can also cancel execution by returning +false+, + # or returning a <tt>[false, "cancel reason"]</tt> array if it wishes to supply + # a reason for canceling the request. + # + # === Example + # + # class CustomService < ActionWebService::Base + # before_invocation :intercept_add, :only => [:add] + # + # def add(a, b) + # a + b + # end + # + # private + # def intercept_add + # return [false, "permission denied"] # cancel it + # end + # end + # + # Options: + # [<tt>:except</tt>] A list of methods for which the interceptor will NOT be called + # [<tt>:only</tt>] A list of methods for which the interceptor WILL be called + module ClassMethods + # Appends the given +interceptors+ to be called + # _before_ method invocation. + def append_before_invocation(*interceptors, &block) + conditions = extract_conditions!(interceptors) + interceptors << block if block_given? + add_interception_conditions(interceptors, conditions) + append_interceptors_to_chain("before", interceptors) + end + + # Prepends the given +interceptors+ to be called + # _before_ method invocation. + def prepend_before_invocation(*interceptors, &block) + conditions = extract_conditions!(interceptors) + interceptors << block if block_given? + add_interception_conditions(interceptors, conditions) + prepend_interceptors_to_chain("before", interceptors) + end + + alias :before_invocation :append_before_invocation + + # Appends the given +interceptors+ to be called + # _after_ method invocation. + def append_after_invocation(*interceptors, &block) + conditions = extract_conditions!(interceptors) + interceptors << block if block_given? + add_interception_conditions(interceptors, conditions) + append_interceptors_to_chain("after", interceptors) + end + + # Prepends the given +interceptors+ to be called + # _after_ method invocation. + def prepend_after_invocation(*interceptors, &block) + conditions = extract_conditions!(interceptors) + interceptors << block if block_given? + add_interception_conditions(interceptors, conditions) + prepend_interceptors_to_chain("after", interceptors) + end + + alias :after_invocation :append_after_invocation + + def before_invocation_interceptors # :nodoc: + read_inheritable_attribute("before_invocation_interceptors") + end + + def after_invocation_interceptors # :nodoc: + read_inheritable_attribute("after_invocation_interceptors") + end + + def included_intercepted_methods # :nodoc: + read_inheritable_attribute("included_intercepted_methods") || {} + end + + def excluded_intercepted_methods # :nodoc: + read_inheritable_attribute("excluded_intercepted_methods") || {} + end + + private + def append_interceptors_to_chain(condition, interceptors) + write_inheritable_array("#{condition}_invocation_interceptors", interceptors) + end + + def prepend_interceptors_to_chain(condition, interceptors) + interceptors = interceptors + read_inheritable_attribute("#{condition}_invocation_interceptors") + write_inheritable_attribute("#{condition}_invocation_interceptors", interceptors) + end + + def extract_conditions!(interceptors) + return nil unless interceptors.last.is_a? Hash + interceptors.pop + end + + def add_interception_conditions(interceptors, conditions) + return unless conditions + included, excluded = conditions[:only], conditions[:except] + write_inheritable_hash("included_intercepted_methods", condition_hash(interceptors, included)) && return if included + write_inheritable_hash("excluded_intercepted_methods", condition_hash(interceptors, excluded)) if excluded + end + + def condition_hash(interceptors, *methods) + interceptors.inject({}) {|hash, interceptor| hash.merge(interceptor => methods.flatten.map {|method| method.to_s})} + end + end + + module InstanceMethods # :nodoc: + def self.append_features(base) + super + base.class_eval do + alias_method :perform_invocation_without_interception, :perform_invocation + alias_method :perform_invocation, :perform_invocation_with_interception + end + end + + def perform_invocation_with_interception(method_name, params, &block) + return if before_invocation(method_name, params, &block) == false + return_value = perform_invocation_without_interception(method_name, params) + after_invocation(method_name, params, return_value) + return_value + end + + def perform_invocation(method_name, params) + send(method_name, *params) + end + + def before_invocation(name, args, &block) + call_interceptors(self.class.before_invocation_interceptors, [name, args], &block) + end + + def after_invocation(name, args, result) + call_interceptors(self.class.after_invocation_interceptors, [name, args, result]) + end + + private + + def call_interceptors(interceptors, interceptor_args, &block) + if interceptors and not interceptors.empty? + interceptors.each do |interceptor| + next if method_exempted?(interceptor, interceptor_args[0].to_s) + result = case + when interceptor.is_a?(Symbol) + self.send(interceptor, *interceptor_args) + when interceptor_block?(interceptor) + interceptor.call(self, *interceptor_args) + when interceptor_class?(interceptor) + interceptor.intercept(self, *interceptor_args) + else + raise( + InvocationError, + "Interceptors need to be either a symbol, proc/method, or a class implementing a static intercept method" + ) + end + reason = nil + if result.is_a?(Array) + reason = result[1] if result[1] + result = result[0] + end + if result == false + block.call(reason) if block && reason + return false + end + end + end + end + + def interceptor_block?(interceptor) + interceptor.respond_to?("call") && (interceptor.arity == 3 || interceptor.arity == -1) + end + + def interceptor_class?(interceptor) + interceptor.respond_to?("intercept") + end + + def method_exempted?(interceptor, method_name) + case + when self.class.included_intercepted_methods[interceptor] + !self.class.included_intercepted_methods[interceptor].include?(method_name) + when self.class.excluded_intercepted_methods[interceptor] + self.class.excluded_intercepted_methods[interceptor].include?(method_name) + end + end + end + end +end +module ActionWebService # :nodoc: + module Protocol # :nodoc: + class ProtocolError < ActionWebServiceError # :nodoc: + end + + class AbstractProtocol # :nodoc: + def setup(controller) + end + + def decode_action_pack_request(action_pack_request) + end + + def encode_action_pack_request(service_name, public_method_name, raw_body, options={}) + klass = options[:request_class] || SimpleActionPackRequest + request = klass.new + request.request_parameters['action'] = service_name.to_s + request.env['RAW_POST_DATA'] = raw_body + request.env['REQUEST_METHOD'] = 'POST' + request.env['HTTP_CONTENT_TYPE'] = 'text/xml' + request + end + + def decode_request(raw_request, service_name, protocol_options={}) + end + + def encode_request(method_name, params, param_types) + end + + def decode_response(raw_response) + end + + def encode_response(method_name, return_value, return_type, protocol_options={}) + end + + def protocol_client(api, protocol_name, endpoint_uri, options) + end + + def register_api(api) + end + end + + class Request # :nodoc: + attr :protocol + attr_accessor :method_name + attr_accessor :method_params + attr :service_name + attr_accessor :api + attr_accessor :api_method + attr :protocol_options + + def initialize(protocol, method_name, method_params, service_name, api=nil, api_method=nil, protocol_options=nil) + @protocol = protocol + @method_name = method_name + @method_params = method_params + @service_name = service_name + @api = api + @api_method = api_method + @protocol_options = protocol_options || {} + end + end + + class Response # :nodoc: + attr :body + attr :content_type + attr :return_value + + def initialize(body, content_type, return_value) + @body = body + @content_type = content_type + @return_value = return_value + end + end + + class SimpleActionPackRequest < ActionController::AbstractRequest # :nodoc: + def initialize + @env = {} + @qparams = {} + @rparams = {} + @cookies = {} + reset_session + end + + def query_parameters + @qparams + end + + def request_parameters + @rparams + end + + def env + @env + end + + def host + '' + end + + def cookies + @cookies + end + + def session + @session + end + + def reset_session + @session = {} + end + end + end +end +module ActionWebService # :nodoc: + module Protocol # :nodoc: + module Discovery # :nodoc: + def self.included(base) + base.extend(ClassMethods) + base.send(:include, ActionWebService::Protocol::Discovery::InstanceMethods) + end + + module ClassMethods # :nodoc: + def register_protocol(klass) + write_inheritable_array("web_service_protocols", [klass]) + end + end + + module InstanceMethods # :nodoc: + private + def discover_web_service_request(action_pack_request) + (self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol| + protocol = protocol.create(self) + request = protocol.decode_action_pack_request(action_pack_request) + return request unless request.nil? + end + nil + end + + def create_web_service_client(api, protocol_name, endpoint_uri, options) + (self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol| + protocol = protocol.create(self) + client = protocol.protocol_client(api, protocol_name, endpoint_uri, options) + return client unless client.nil? + end + nil + end + end + end + end +end +require 'soap/mapping' + +module ActionWebService + module Protocol + module Soap + # Workaround for SOAP4R return values changing + class Registry < SOAP::Mapping::Registry + if SOAP::Version >= "1.5.4" + def find_mapped_soap_class(obj_class) + return @map.instance_eval { @obj2soap[obj_class][0] } + end + + def find_mapped_obj_class(soap_class) + return @map.instance_eval { @soap2obj[soap_class][0] } + end + end + end + + class SoapMarshaler + attr :namespace + attr :registry + + def initialize(namespace=nil) + @namespace = namespace || 'urn:ActionWebService' + @registry = Registry.new + @type2binding = {} + register_static_factories + end + + def soap_to_ruby(obj) + SOAP::Mapping.soap2obj(obj, @registry) + end + + def ruby_to_soap(obj) + soap = SOAP::Mapping.obj2soap(obj, @registry) + soap.elename = XSD::QName.new if SOAP::Version >= "1.5.5" && soap.elename == XSD::QName::EMPTY + soap + end + + def register_type(type) + return @type2binding[type] if @type2binding.has_key?(type) + + if type.array? + array_mapping = @registry.find_mapped_soap_class(Array) + qname = XSD::QName.new(@namespace, soap_type_name(type.element_type.type_class.name) + 'Array') + element_type_binding = register_type(type.element_type) + @type2binding[type] = SoapBinding.new(self, qname, type, array_mapping, element_type_binding) + elsif (mapping = @registry.find_mapped_soap_class(type.type_class) rescue nil) + qname = mapping[2] ? mapping[2][:type] : nil + qname ||= soap_base_type_name(mapping[0]) + @type2binding[type] = SoapBinding.new(self, qname, type, mapping) + else + qname = XSD::QName.new(@namespace, soap_type_name(type.type_class.name)) + @registry.add(type.type_class, + SOAP::SOAPStruct, + typed_struct_factory(type.type_class), + { :type => qname }) + mapping = @registry.find_mapped_soap_class(type.type_class) + @type2binding[type] = SoapBinding.new(self, qname, type, mapping) + end + + if type.structured? + type.each_member do |m_name, m_type| + register_type(m_type) + end + end + + @type2binding[type] + end + alias :lookup_type :register_type + + def annotate_arrays(binding, value) + if value.nil? + return + elsif binding.type.array? + mark_typed_array(value, binding.element_binding.qname) + if binding.element_binding.type.custom? + value.each do |element| + annotate_arrays(binding.element_binding, element) + end + end + elsif binding.type.structured? + binding.type.each_member do |name, type| + member_binding = register_type(type) + member_value = value.respond_to?('[]') ? value[name] : value.send(name) + annotate_arrays(member_binding, member_value) if type.custom? + end + end + end + + private + def typed_struct_factory(type_class) + if Object.const_defined?('ActiveRecord') + if type_class.ancestors.include?(ActiveRecord::Base) + qname = XSD::QName.new(@namespace, soap_type_name(type_class.name)) + type_class.instance_variable_set('@qname', qname) + return SoapActiveRecordStructFactory.new + end + end + SOAP::Mapping::Registry::TypedStructFactory + end + + def mark_typed_array(array, qname) + (class << array; self; end).class_eval do + define_method(:arytype) do + qname + end + end + end + + def soap_base_type_name(type) + xsd_type = type.ancestors.find{ |c| c.const_defined? 'Type' } + xsd_type ? xsd_type.const_get('Type') : XSD::XSDAnySimpleType::Type + end + + def soap_type_name(type_name) + type_name.gsub(/::/, '..') + end + + def register_static_factories + @registry.add(ActionWebService::Base64, + SOAP::SOAPBase64, + SoapBase64Factory.new, + nil) + mapping = @registry.find_mapped_soap_class(ActionWebService::Base64) + @type2binding[ActionWebService::Base64] = + SoapBinding.new(self, SOAP::SOAPBase64::Type, + ActionWebService::Base64, mapping) + @registry.add(Array, + SOAP::SOAPArray, + SoapTypedArrayFactory.new, + nil) + end + end + + class SoapBinding + attr :qname + attr :type + attr :mapping + attr :element_binding + + def initialize(marshaler, qname, type, mapping, element_binding=nil) + @marshaler = marshaler + @qname = qname + @type = type + @mapping = mapping + @element_binding = element_binding + end + + def type_name + @type.custom? ? @qname.name : nil + end + + def qualified_type_name(ns=nil) + if @type.custom? + "#{ns ? ns : @qname.namespace}:#{@qname.name}" + else + ns = XSD::NS.new + ns.assign(XSD::Namespace, SOAP::XSDNamespaceTag) + ns.assign(SOAP::EncodingNamespace, "soapenc") + xsd_klass = mapping[0].ancestors.find{|c| c.const_defined?('Type')} + return ns.name(XSD::AnyTypeName) unless xsd_klass + ns.name(xsd_klass.const_get('Type')) + end + end + + def eql?(other) + @qname == other.qname + end + alias :== :eql? + + def hash + @qname.hash + end + end + + class SoapActiveRecordStructFactory < SOAP::Mapping::Factory + def obj2soap(soap_class, obj, info, map) + unless obj.is_a?(ActiveRecord::Base) + return nil + end + soap_obj = soap_class.new(obj.class.instance_variable_get('@qname')) + obj.class.columns.each do |column| + key = column.name.to_s + value = obj.send(key) + soap_obj[key] = SOAP::Mapping._obj2soap(value, map) + end + soap_obj + end + + def soap2obj(obj_class, node, info, map) + unless node.type == obj_class.instance_variable_get('@qname') + return false + end + obj = obj_class.new + node.each do |key, value| + obj[key] = value.data + end + obj.instance_variable_set('@new_record', false) + return true, obj + end + end + + class SoapTypedArrayFactory < SOAP::Mapping::Factory + def obj2soap(soap_class, obj, info, map) + unless obj.respond_to?(:arytype) + return nil + end + soap_obj = soap_class.new(SOAP::ValueArrayName, 1, obj.arytype) + mark_marshalled_obj(obj, soap_obj) + obj.each do |item| + child = SOAP::Mapping._obj2soap(item, map) + soap_obj.add(child) + end + soap_obj + end + + def soap2obj(obj_class, node, info, map) + return false + end + end + + class SoapBase64Factory < SOAP::Mapping::Factory + def obj2soap(soap_class, obj, info, map) + unless obj.is_a?(ActionWebService::Base64) + return nil + end + return soap_class.new(obj) + end + + def soap2obj(obj_class, node, info, map) + unless node.type == SOAP::SOAPBase64::Type + return false + end + return true, obj_class.new(node.string) + end + end + + end + end +end +require 'action_web_service/protocol/soap_protocol/marshaler' +require 'soap/streamHandler' +require 'action_web_service/client/soap_client' + +module ActionWebService # :nodoc: + module API # :nodoc: + class Base # :nodoc: + def self.soap_client(endpoint_uri, options={}) + ActionWebService::Client::Soap.new self, endpoint_uri, options + end + end + end + + module Protocol # :nodoc: + module Soap # :nodoc: + def self.included(base) + base.register_protocol(SoapProtocol) + base.class_inheritable_option(:wsdl_service_name) + base.class_inheritable_option(:wsdl_namespace) + end + + class SoapProtocol < AbstractProtocol # :nodoc: + AWSEncoding = 'UTF-8' + XSDEncoding = 'UTF8' + + attr :marshaler + + def initialize(namespace=nil) + namespace ||= 'urn:ActionWebService' + @marshaler = SoapMarshaler.new namespace + end + + def self.create(controller) + SoapProtocol.new(controller.wsdl_namespace) + end + + def decode_action_pack_request(action_pack_request) + return nil unless soap_action = has_valid_soap_action?(action_pack_request) + service_name = action_pack_request.parameters['action'] + input_encoding = parse_charset(action_pack_request.env['HTTP_CONTENT_TYPE']) + protocol_options = { + :soap_action => soap_action, + :charset => input_encoding + } + decode_request(action_pack_request.raw_post, service_name, protocol_options) + end + + def encode_action_pack_request(service_name, public_method_name, raw_body, options={}) + request = super + request.env['HTTP_SOAPACTION'] = '/soap/%s/%s' % [service_name, public_method_name] + request + end + + def decode_request(raw_request, service_name, protocol_options={}) + envelope = SOAP::Processor.unmarshal(raw_request, :charset => protocol_options[:charset]) + unless envelope + raise ProtocolError, "Failed to parse SOAP request message" + end + request = envelope.body.request + method_name = request.elename.name + params = request.collect{ |k, v| marshaler.soap_to_ruby(request[k]) } + Request.new(self, method_name, params, service_name, nil, nil, protocol_options) + end + + def encode_request(method_name, params, param_types) + param_types.each{ |type| marshaler.register_type(type) } if param_types + qname = XSD::QName.new(marshaler.namespace, method_name) + param_def = [] + if param_types + params = param_types.zip(params).map do |type, param| + param_def << ['in', type.name, marshaler.lookup_type(type).mapping] + [type.name, marshaler.ruby_to_soap(param)] + end + else + params = [] + end + request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def) + request.set_param(params) + envelope = create_soap_envelope(request) + SOAP::Processor.marshal(envelope) + end + + def decode_response(raw_response) + envelope = SOAP::Processor.unmarshal(raw_response) + unless envelope + raise ProtocolError, "Failed to parse SOAP request message" + end + method_name = envelope.body.request.elename.name + return_value = envelope.body.response + return_value = marshaler.soap_to_ruby(return_value) unless return_value.nil? + [method_name, return_value] + end + + def encode_response(method_name, return_value, return_type, protocol_options={}) + if return_type + return_binding = marshaler.register_type(return_type) + marshaler.annotate_arrays(return_binding, return_value) + end + qname = XSD::QName.new(marshaler.namespace, method_name) + if return_value.nil? + response = SOAP::RPC::SOAPMethodResponse.new(qname, nil) + else + if return_value.is_a?(Exception) + detail = SOAP::Mapping::SOAPException.new(return_value) + response = SOAP::SOAPFault.new( + SOAP::SOAPQName.new('%s:%s' % [SOAP::SOAPNamespaceTag, 'Server']), + SOAP::SOAPString.new(return_value.to_s), + SOAP::SOAPString.new(self.class.name), + marshaler.ruby_to_soap(detail)) + else + if return_type + param_def = [['retval', 'return', marshaler.lookup_type(return_type).mapping]] + response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def) + response.retval = marshaler.ruby_to_soap(return_value) + else + response = SOAP::RPC::SOAPMethodResponse.new(qname, nil) + end + end + end + envelope = create_soap_envelope(response) + + # FIXME: This is not thread-safe, but StringFactory_ in SOAP4R only + # reads target encoding from the XSD::Charset.encoding variable. + # This is required to ensure $KCODE strings are converted + # correctly to UTF-8 for any values of $KCODE. + previous_encoding = XSD::Charset.encoding + XSD::Charset.encoding = XSDEncoding + response_body = SOAP::Processor.marshal(envelope, :charset => AWSEncoding) + XSD::Charset.encoding = previous_encoding + + Response.new(response_body, "text/xml; charset=#{AWSEncoding}", return_value) + end + + def protocol_client(api, protocol_name, endpoint_uri, options={}) + return nil unless protocol_name == :soap + ActionWebService::Client::Soap.new(api, endpoint_uri, options) + end + + def register_api(api) + api.api_methods.each do |name, method| + method.expects.each{ |type| marshaler.register_type(type) } if method.expects + method.returns.each{ |type| marshaler.register_type(type) } if method.returns + end + end + + private + def has_valid_soap_action?(request) + return nil unless request.method == :post + soap_action = request.env['HTTP_SOAPACTION'] + return nil unless soap_action + soap_action = soap_action.dup + soap_action.gsub!(/^"/, '') + soap_action.gsub!(/"$/, '') + soap_action.strip! + return nil if soap_action.empty? + soap_action + end + + def create_soap_envelope(body) + header = SOAP::SOAPHeader.new + body = SOAP::SOAPBody.new(body) + SOAP::SOAPEnvelope.new(header, body) + end + + def parse_charset(content_type) + return AWSEncoding if content_type.nil? + if /^text\/xml(?:\s*;\s*charset=([^"]+|"[^"]+"))$/i =~ content_type + $1 + else + AWSEncoding + end + end + end + end + end +end +require 'xmlrpc/marshal' +require 'action_web_service/client/xmlrpc_client' + +module XMLRPC # :nodoc: + class FaultException # :nodoc: + alias :message :faultString + end +end + +module ActionWebService # :nodoc: + module API # :nodoc: + class Base # :nodoc: + def self.xmlrpc_client(endpoint_uri, options={}) + ActionWebService::Client::XmlRpc.new self, endpoint_uri, options + end + end + end + + module Protocol # :nodoc: + module XmlRpc # :nodoc: + def self.included(base) + base.register_protocol(XmlRpcProtocol) + end + + class XmlRpcProtocol < AbstractProtocol # :nodoc: + def self.create(controller) + XmlRpcProtocol.new + end + + def decode_action_pack_request(action_pack_request) + service_name = action_pack_request.parameters['action'] + decode_request(action_pack_request.raw_post, service_name) + end + + def decode_request(raw_request, service_name) + method_name, params = XMLRPC::Marshal.load_call(raw_request) + Request.new(self, method_name, params, service_name) + end + + def encode_request(method_name, params, param_types) + if param_types + params = params.dup + param_types.each_with_index{ |type, i| params[i] = value_to_xmlrpc_wire_format(params[i], type) } + end + XMLRPC::Marshal.dump_call(method_name, *params) + end + + def decode_response(raw_response) + [nil, XMLRPC::Marshal.load_response(raw_response)] + end + + def encode_response(method_name, return_value, return_type, protocol_options={}) + if return_value && return_type + return_value = value_to_xmlrpc_wire_format(return_value, return_type) + end + return_value = false if return_value.nil? + raw_response = XMLRPC::Marshal.dump_response(return_value) + Response.new(raw_response, 'text/xml', return_value) + end + + def protocol_client(api, protocol_name, endpoint_uri, options={}) + return nil unless protocol_name == :xmlrpc + ActionWebService::Client::XmlRpc.new(api, endpoint_uri, options) + end + + def value_to_xmlrpc_wire_format(value, value_type) + if value_type.array? + value.map{ |val| value_to_xmlrpc_wire_format(val, value_type.element_type) } + else + if value.is_a?(ActionWebService::Struct) + struct = {} + value.class.members.each do |name, type| + member_value = value[name] + next if member_value.nil? + struct[name.to_s] = value_to_xmlrpc_wire_format(member_value, type) + end + struct + elsif value.is_a?(ActiveRecord::Base) + struct = {} + value.attributes.each do |key, member_value| + next if member_value.nil? + struct[key.to_s] = member_value + end + struct + elsif value.is_a?(ActionWebService::Base64) + XMLRPC::Base64.new(value) + elsif value.is_a?(Exception) && !value.is_a?(XMLRPC::FaultException) + XMLRPC::FaultException.new(2, value.message) + else + value + end + end + end + end + end + end +end +require 'action_web_service/protocol/abstract' +require 'action_web_service/protocol/discovery' +require 'action_web_service/protocol/soap_protocol' +require 'action_web_service/protocol/xmlrpc_protocol' +require 'benchmark' +require 'pathname' + +module ActionWebService + module Scaffolding # :nodoc: + class ScaffoldingError < ActionWebServiceError # :nodoc: + end + + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # Web service invocation scaffolding provides a way to quickly invoke web service methods in a controller. The + # generated scaffold actions have default views to let you enter the method parameters and view the + # results. + # + # Example: + # + # class ApiController < ActionController + # web_service_scaffold :invoke + # end + # + # This example generates an +invoke+ action in the +ApiController+ that you can navigate to from + # your browser, select the API method, enter its parameters, and perform the invocation. + # + # If you want to customize the default views, create the following views in "app/views": + # + # * <tt>action_name/methods.rhtml</tt> + # * <tt>action_name/parameters.rhtml</tt> + # * <tt>action_name/result.rhtml</tt> + # * <tt>action_name/layout.rhtml</tt> + # + # Where <tt>action_name</tt> is the name of the action you gave to ClassMethods#web_service_scaffold. + # + # You can use the default views in <tt>RAILS_DIR/lib/action_web_service/templates/scaffolds</tt> as + # a guide. + module ClassMethods + # Generates web service invocation scaffolding for the current controller. The given action name + # can then be used as the entry point for invoking API methods from a web browser. + def web_service_scaffold(action_name) + add_template_helper(Helpers) + module_eval <<-"end_eval", __FILE__, __LINE__ + def #{action_name} + if request.method == :get + setup_invocation_assigns + render_invocation_scaffold 'methods' + end + end + + def #{action_name}_method_params + if request.method == :get + setup_invocation_assigns + render_invocation_scaffold 'parameters' + end + end + + def #{action_name}_submit + if request.method == :post + setup_invocation_assigns + protocol_name = params['protocol'] ? params['protocol'].to_sym : :soap + case protocol_name + when :soap + @protocol = Protocol::Soap::SoapProtocol.create(self) + when :xmlrpc + @protocol = Protocol::XmlRpc::XmlRpcProtocol.create(self) + end + bm = Benchmark.measure do + @protocol.register_api(@scaffold_service.api) + post_params = params['method_params'] ? params['method_params'].dup : nil + params = [] + @scaffold_method.expects.each_with_index do |spec, i| + params << post_params[i.to_s] + end if @scaffold_method.expects + params = @scaffold_method.cast_expects(params) + method_name = public_method_name(@scaffold_service.name, @scaffold_method.public_name) + @method_request_xml = @protocol.encode_request(method_name, params, @scaffold_method.expects) + new_request = @protocol.encode_action_pack_request(@scaffold_service.name, @scaffold_method.public_name, @method_request_xml) + prepare_request(new_request, @scaffold_service.name, @scaffold_method.public_name) + @request = new_request + if @scaffold_container.dispatching_mode != :direct + request.parameters['action'] = @scaffold_service.name + end + dispatch_web_service_request + @method_response_xml = @response.body + method_name, obj = @protocol.decode_response(@method_response_xml) + return if handle_invocation_exception(obj) + @method_return_value = @scaffold_method.cast_returns(obj) + end + @method_elapsed = bm.real + add_instance_variables_to_assigns + reset_invocation_response + render_invocation_scaffold 'result' + end + end + + private + def setup_invocation_assigns + @scaffold_class = self.class + @scaffold_action_name = "#{action_name}" + @scaffold_container = WebServiceModel::Container.new(self) + if params['service'] && params['method'] + @scaffold_service = @scaffold_container.services.find{ |x| x.name == params['service'] } + @scaffold_method = @scaffold_service.api_methods[params['method']] + end + add_instance_variables_to_assigns + end + + def render_invocation_scaffold(action) + customized_template = "\#{self.class.controller_path}/#{action_name}/\#{action}" + default_template = scaffold_path(action) + if template_exists?(customized_template) + content = @template.render_file(customized_template) + else + content = @template.render_file(default_template, false) + end + @template.instance_variable_set("@content_for_layout", content) + if self.active_layout.nil? + render_file(scaffold_path("layout")) + else + render_file(self.active_layout, "200 OK", true) + end + end + + def scaffold_path(template_name) + File.dirname(__FILE__) + "/templates/scaffolds/" + template_name + ".rhtml" + end + + def reset_invocation_response + erase_render_results + @response.headers = ::ActionController::AbstractResponse::DEFAULT_HEADERS.merge("cookie" => []) + end + + def public_method_name(service_name, method_name) + if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::XmlRpc::XmlRpcProtocol) + service_name + '.' + method_name + else + method_name + end + end + + def prepare_request(new_request, service_name, method_name) + new_request.parameters.update(request.parameters) + request.env.each{ |k, v| new_request.env[k] = v unless new_request.env.has_key?(k) } + if web_service_dispatching_mode == :layered && @protocol.is_a?(ActionWebService::Protocol::Soap::SoapProtocol) + new_request.env['HTTP_SOAPACTION'] = "/\#{controller_name()}/\#{service_name}/\#{method_name}" + end + end + + def handle_invocation_exception(obj) + exception = nil + if obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && obj.detail.cause.is_a?(Exception) + exception = obj.detail.cause + elsif obj.is_a?(XMLRPC::FaultException) + exception = obj + end + return unless exception + reset_invocation_response + rescue_action(exception) + true + end + end_eval + end + end + + module Helpers # :nodoc: + def method_parameter_input_fields(method, type, field_name_base, idx, was_structured=false) + if type.array? + return content_tag('em', "Typed array input fields not supported yet (#{type.name})") + end + if type.structured? + return content_tag('em', "Nested structural types not supported yet (#{type.name})") if was_structured + parameters = "" + type.each_member do |member_name, member_type| + label = method_parameter_label(member_name, member_type) + nested_content = method_parameter_input_fields( + method, + member_type, + "#{field_name_base}[#{idx}][#{member_name}]", + idx, + true) + if member_type.custom? + parameters << content_tag('li', label) + parameters << content_tag('ul', nested_content) + else + parameters << content_tag('li', label + ' ' + nested_content) + end + end + content_tag('ul', parameters) + else + # If the data source was structured previously we already have the index set + field_name_base = "#{field_name_base}[#{idx}]" unless was_structured + + case type.type + when :int + text_field_tag "#{field_name_base}" + when :string + text_field_tag "#{field_name_base}" + when :base64 + text_area_tag "#{field_name_base}", nil, :size => "40x5" + when :bool + radio_button_tag("#{field_name_base}", "true") + " True" + + radio_button_tag("#{field_name_base}", "false") + "False" + when :float + text_field_tag "#{field_name_base}" + when :time, :datetime + time = Time.now + i = 0 + %w|year month day hour minute second|.map do |name| + i += 1 + send("select_#{name}", time, :prefix => "#{field_name_base}[#{i}]", :discard_type => true) + end.join + when :date + date = Date.today + i = 0 + %w|year month day|.map do |name| + i += 1 + send("select_#{name}", date, :prefix => "#{field_name_base}[#{i}]", :discard_type => true) + end.join + end + end + end + + def method_parameter_label(name, type) + name.to_s.capitalize + ' (' + type.human_name(false) + ')' + end + + def service_method_list(service) + action = @scaffold_action_name + '_method_params' + methods = service.api_methods_full.map do |desc, name| + content_tag("li", link_to(desc, :action => action, :service => service.name, :method => name)) + end + content_tag("ul", methods.join("\n")) + end + end + + module WebServiceModel # :nodoc: + class Container # :nodoc: + attr :services + attr :dispatching_mode + + def initialize(real_container) + @real_container = real_container + @dispatching_mode = @real_container.class.web_service_dispatching_mode + @services = [] + if @dispatching_mode == :direct + @services << Service.new(@real_container.controller_name, @real_container) + else + @real_container.class.web_services.each do |name, obj| + @services << Service.new(name, @real_container.instance_eval{ web_service_object(name) }) + end + end + end + end + + class Service # :nodoc: + attr :name + attr :object + attr :api + attr :api_methods + attr :api_methods_full + + def initialize(name, real_service) + @name = name.to_s + @object = real_service + @api = @object.class.web_service_api + if @api.nil? + raise ScaffoldingError, "No web service API attached to #{object.class}" + end + @api_methods = {} + @api_methods_full = [] + @api.api_methods.each do |name, method| + @api_methods[method.public_name.to_s] = method + @api_methods_full << [method.to_s, method.public_name.to_s] + end + end + + def to_s + self.name.camelize + end + end + end + end +end +module ActionWebService + # To send structured types across the wire, derive from ActionWebService::Struct, + # and use +member+ to declare structure members. + # + # ActionWebService::Struct should be used in method signatures when you want to accept or return + # structured types that have no Active Record model class representations, or you don't + # want to expose your entire Active Record model to remote callers. + # + # === Example + # + # class Person < ActionWebService::Struct + # member :id, :int + # member :firstnames, [:string] + # member :lastname, :string + # member :email, :string + # end + # person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe') + # + # Active Record model classes are already implicitly supported in method + # signatures. + class Struct + # Action WebService Struct subclasses should be reloaded by the dispatcher in Rails + # when Dependencies.mechanism = :load. + include Reloadable::Subclasses + + # If a Hash is given as argument to an ActionWebService::Struct constructor, + # it can contain initial values for the structure member. + def initialize(values={}) + if values.is_a?(Hash) + values.map{|k,v| __send__('%s=' % k.to_s, v)} + end + end + + # The member with the given name + def [](name) + send(name.to_s) + end + + # Iterates through each member + def each_pair(&block) + self.class.members.each do |name, type| + yield name, self.__send__(name) + end + end + + class << self + # Creates a structure member with the specified +name+ and +type+. Generates + # accessor methods for reading and writing the member value. + def member(name, type) + name = name.to_sym + type = ActionWebService::SignatureTypes.canonical_signature_entry({ name => type }, 0) + write_inheritable_hash("struct_members", name => type) + class_eval <<-END + def #{name}; @#{name}; end + def #{name}=(value); @#{name} = value; end + END + end + + def members # :nodoc: + read_inheritable_attribute("struct_members") || {} + end + + def member_type(name) # :nodoc: + members[name.to_sym] + end + end + end +end +class Class # :nodoc: + def class_inheritable_option(sym, default_value=nil) + write_inheritable_attribute sym, default_value + class_eval <<-EOS + def self.#{sym}(value=nil) + if !value.nil? + write_inheritable_attribute(:#{sym}, value) + else + read_inheritable_attribute(:#{sym}) + end + end + + def self.#{sym}=(value) + write_inheritable_attribute(:#{sym}, value) + end + + def #{sym} + self.class.#{sym} + end + + def #{sym}=(value) + self.class.#{sym} = value + end + EOS + end +end +module ActionWebService # :nodoc: + # Action Web Service supports the following base types in a signature: + # + # [<tt>:int</tt>] Represents an integer value, will be cast to an integer using <tt>Integer(value)</tt> + # [<tt>:string</tt>] Represents a string value, will be cast to an string using the <tt>to_s</tt> method on an object + # [<tt>:base64</tt>] Represents a Base 64 value, will contain the binary bytes of a Base 64 value sent by the caller + # [<tt>:bool</tt>] Represents a boolean value, whatever is passed will be cast to boolean (<tt>true</tt>, '1', 'true', 'y', 'yes' are taken to represent true; <tt>false</tt>, '0', 'false', 'n', 'no' and <tt>nil</tt> represent false) + # [<tt>:float</tt>] Represents a floating point value, will be cast to a float using <tt>Float(value)</tt> + # [<tt>:time</tt>] Represents a timestamp, will be cast to a <tt>Time</tt> object + # [<tt>:datetime</tt>] Represents a timestamp, will be cast to a <tt>DateTime</tt> object + # [<tt>:date</tt>] Represents a date, will be cast to a <tt>Date</tt> object + # + # For structured types, you'll need to pass in the Class objects of + # ActionWebService::Struct and ActiveRecord::Base derivatives. + module SignatureTypes + def canonical_signature(signature) # :nodoc: + return nil if signature.nil? + unless signature.is_a?(Array) + raise(ActionWebServiceError, "Expected signature to be an Array") + end + i = -1 + signature.map{ |spec| canonical_signature_entry(spec, i += 1) } + end + + def canonical_signature_entry(spec, i) # :nodoc: + orig_spec = spec + name = "param#{i}" + if spec.is_a?(Hash) + name, spec = spec.keys.first, spec.values.first + end + type = spec + if spec.is_a?(Array) + ArrayType.new(orig_spec, canonical_signature_entry(spec[0], 0), name) + else + type = canonical_type(type) + if type.is_a?(Symbol) + BaseType.new(orig_spec, type, name) + else + StructuredType.new(orig_spec, type, name) + end + end + end + + def canonical_type(type) # :nodoc: + type_name = symbol_name(type) || class_to_type_name(type) + type = type_name || type + return canonical_type_name(type) if type.is_a?(Symbol) + type + end + + def canonical_type_name(name) # :nodoc: + name = name.to_sym + case name + when :int, :integer, :fixnum, :bignum + :int + when :string, :text + :string + when :base64, :binary + :base64 + when :bool, :boolean + :bool + when :float, :double + :float + when :time, :timestamp + :time + when :datetime + :datetime + when :date + :date + else + raise(TypeError, "#{name} is not a valid base type") + end + end + + def canonical_type_class(type) # :nodoc: + type = canonical_type(type) + type.is_a?(Symbol) ? type_name_to_class(type) : type + end + + def symbol_name(name) # :nodoc: + return name.to_sym if name.is_a?(Symbol) || name.is_a?(String) + nil + end + + def class_to_type_name(klass) # :nodoc: + klass = klass.class unless klass.is_a?(Class) + if derived_from?(Integer, klass) || derived_from?(Fixnum, klass) || derived_from?(Bignum, klass) + :int + elsif klass == String + :string + elsif klass == Base64 + :base64 + elsif klass == TrueClass || klass == FalseClass + :bool + elsif derived_from?(Float, klass) || derived_from?(Precision, klass) || derived_from?(Numeric, klass) + :float + elsif klass == Time + :time + elsif klass == DateTime + :datetime + elsif klass == Date + :date + else + nil + end + end + + def type_name_to_class(name) # :nodoc: + case canonical_type_name(name) + when :int + Integer + when :string + String + when :base64 + Base64 + when :bool + TrueClass + when :float + Float + when :time + Time + when :date + Date + when :datetime + DateTime + else + nil + end + end + + def derived_from?(ancestor, child) # :nodoc: + child.ancestors.include?(ancestor) + end + + module_function :type_name_to_class + module_function :class_to_type_name + module_function :symbol_name + module_function :canonical_type_class + module_function :canonical_type_name + module_function :canonical_type + module_function :canonical_signature_entry + module_function :canonical_signature + module_function :derived_from? + end + + class BaseType # :nodoc: + include SignatureTypes + + attr :spec + attr :type + attr :type_class + attr :name + + def initialize(spec, type, name) + @spec = spec + @type = canonical_type(type) + @type_class = canonical_type_class(@type) + @name = name + end + + def custom? + false + end + + def array? + false + end + + def structured? + false + end + + def human_name(show_name=true) + type_type = array? ? element_type.type.to_s : self.type.to_s + str = array? ? (type_type + '[]') : type_type + show_name ? (str + " " + name.to_s) : str + end + end + + class ArrayType < BaseType # :nodoc: + attr :element_type + + def initialize(spec, element_type, name) + super(spec, Array, name) + @element_type = element_type + end + + def custom? + true + end + + def array? + true + end + end + + class StructuredType < BaseType # :nodoc: + def each_member + if @type_class.respond_to?(:members) + @type_class.members.each do |name, type| + yield name, type + end + elsif @type_class.respond_to?(:columns) + i = -1 + @type_class.columns.each do |column| + yield column.name, canonical_signature_entry(column.type, i += 1) + end + end + end + + def custom? + true + end + + def structured? + true + end + end + + class Base64 < String # :nodoc: + end +end +require 'test/unit' + +module Test # :nodoc: + module Unit # :nodoc: + class TestCase # :nodoc: + private + # invoke the specified API method + def invoke_direct(method_name, *args) + prepare_request('api', 'api', method_name, *args) + @controller.process(@request, @response) + decode_rpc_response + end + alias_method :invoke, :invoke_direct + + # invoke the specified API method on the specified service + def invoke_delegated(service_name, method_name, *args) + prepare_request(service_name.to_s, service_name, method_name, *args) + @controller.process(@request, @response) + decode_rpc_response + end + + # invoke the specified layered API method on the correct service + def invoke_layered(service_name, method_name, *args) + prepare_request('api', service_name, method_name, *args) + @controller.process(@request, @response) + decode_rpc_response + end + + # ---------------------- internal --------------------------- + + def prepare_request(action, service_name, api_method_name, *args) + @request.recycle! + @request.request_parameters['action'] = action + @request.env['REQUEST_METHOD'] = 'POST' + @request.env['HTTP_CONTENT_TYPE'] = 'text/xml' + @request.env['RAW_POST_DATA'] = encode_rpc_call(service_name, api_method_name, *args) + case protocol + when ActionWebService::Protocol::Soap::SoapProtocol + soap_action = "/#{@controller.controller_name}/#{service_name}/#{public_method_name(service_name, api_method_name)}" + @request.env['HTTP_SOAPACTION'] = soap_action + when ActionWebService::Protocol::XmlRpc::XmlRpcProtocol + @request.env.delete('HTTP_SOAPACTION') + end + end + + def encode_rpc_call(service_name, api_method_name, *args) + case @controller.web_service_dispatching_mode + when :direct + api = @controller.class.web_service_api + when :delegated, :layered + api = @controller.web_service_object(service_name.to_sym).class.web_service_api + end + protocol.register_api(api) + method = api.api_methods[api_method_name.to_sym] + raise ArgumentError, "wrong number of arguments for rpc call (#{args.length} for #{method.expects.length})" unless args.length == method.expects.length + protocol.encode_request(public_method_name(service_name, api_method_name), args.dup, method.expects) + end + + def decode_rpc_response + public_method_name, return_value = protocol.decode_response(@response.body) + exception = is_exception?(return_value) + raise exception if exception + return_value + end + + def public_method_name(service_name, api_method_name) + public_name = service_api(service_name).public_api_method_name(api_method_name) + if @controller.web_service_dispatching_mode == :layered && protocol.is_a?(ActionWebService::Protocol::XmlRpc::XmlRpcProtocol) + '%s.%s' % [service_name.to_s, public_name] + else + public_name + end + end + + def service_api(service_name) + case @controller.web_service_dispatching_mode + when :direct + @controller.class.web_service_api + when :delegated, :layered + @controller.web_service_object(service_name.to_sym).class.web_service_api + end + end + + def protocol + if @protocol.nil? + @protocol ||= ActionWebService::Protocol::Soap::SoapProtocol.create(@controller) + else + case @protocol + when :xmlrpc + @protocol = ActionWebService::Protocol::XmlRpc::XmlRpcProtocol.create(@controller) + when :soap + @protocol = ActionWebService::Protocol::Soap::SoapProtocol.create(@controller) + else + @protocol + end + end + end + + def is_exception?(obj) + case protocol + when :soap, ActionWebService::Protocol::Soap::SoapProtocol + (obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \ + obj.detail.cause.is_a?(Exception)) ? obj.detail.cause : nil + when :xmlrpc, ActionWebService::Protocol::XmlRpc::XmlRpcProtocol + obj.is_a?(XMLRPC::FaultException) ? obj : nil + end + end + end + end +end +module ActionWebService + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 1 + TINY = 6 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end +#-- +# Copyright (C) 2005 Leon Breedt +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +begin + require 'active_support' + require 'action_controller' + require 'active_record' +rescue LoadError + require 'rubygems' + require_gem 'activesupport', '>= 1.0.2' + require_gem 'actionpack', '>= 1.6.0' + require_gem 'activerecord', '>= 1.9.0' +end + +$:.unshift(File.dirname(__FILE__) + "/action_web_service/vendor/") + +require 'action_web_service/support/class_inheritable_options' +require 'action_web_service/support/signature_types' +require 'action_web_service/base' +require 'action_web_service/client' +require 'action_web_service/invocation' +require 'action_web_service/api' +require 'action_web_service/casting' +require 'action_web_service/struct' +require 'action_web_service/container' +require 'action_web_service/protocol' +require 'action_web_service/dispatcher' +require 'action_web_service/scaffolding' + +ActionWebService::Base.class_eval do + include ActionWebService::Container::Direct + include ActionWebService::Invocation +end + +ActionController::Base.class_eval do + include ActionWebService::Protocol::Discovery + include ActionWebService::Protocol::Soap + include ActionWebService::Protocol::XmlRpc + include ActionWebService::Container::Direct + include ActionWebService::Container::Delegated + include ActionWebService::Container::ActionController + include ActionWebService::Invocation + include ActionWebService::Dispatcher + include ActionWebService::Dispatcher::ActionController + include ActionWebService::Scaffolding +end +# +# setup.rb +# +# Copyright (c) 2000-2004 Minero Aoki +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Note: Originally licensed under LGPL v2+. Using MIT license for Rails +# with permission of Minero Aoki. + +# + +unless Enumerable.method_defined?(:map) # Ruby 1.4.6 + module Enumerable + alias map collect + end +end + +unless File.respond_to?(:read) # Ruby 1.6 + def File.read(fname) + open(fname) {|f| + return f.read + } + end +end + +def File.binread(fname) + open(fname, 'rb') {|f| + return f.read + } +end + +# for corrupted windows stat(2) +def File.dir?(path) + File.directory?((path[-1,1] == '/') ? path : path + '/') +end + + +class SetupError < StandardError; end + +def setup_rb_error(msg) + raise SetupError, msg +end + +# +# Config +# + +if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } + ARGV.delete(arg) + require arg.split(/=/, 2)[1] + $".push 'rbconfig.rb' +else + require 'rbconfig' +end + +def multipackage_install? + FileTest.directory?(File.dirname($0) + '/packages') +end + + +class ConfigItem + def initialize(name, template, default, desc) + @name = name.freeze + @template = template + @value = default + @default = default.dup.freeze + @description = desc + end + + attr_reader :name + attr_reader :description + + attr_accessor :default + alias help_default default + + def help_opt + "--#{@name}=#{@template}" + end + + def value + @value + end + + def eval(table) + @value.gsub(%r<\$([^/]+)>) { table[$1] } + end + + def set(val) + @value = check(val) + end + + private + + def check(val) + setup_rb_error "config: --#{name} requires argument" unless val + val + end +end + +class BoolItem < ConfigItem + def config_type + 'bool' + end + + def help_opt + "--#{@name}" + end + + private + + def check(val) + return 'yes' unless val + unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val + setup_rb_error "config: --#{@name} accepts only yes/no for argument" + end + (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no' + end +end + +class PathItem < ConfigItem + def config_type + 'path' + end + + private + + def check(path) + setup_rb_error "config: --#{@name} requires argument" unless path + path[0,1] == '$' ? path : File.expand_path(path) + end +end + +class ProgramItem < ConfigItem + def config_type + 'program' + end +end + +class SelectItem < ConfigItem + def initialize(name, template, default, desc) + super + @ok = template.split('/') + end + + def config_type + 'select' + end + + private + + def check(val) + unless @ok.include?(val.strip) + setup_rb_error "config: use --#{@name}=#{@template} (#{val})" + end + val.strip + end +end + +class PackageSelectionItem < ConfigItem + def initialize(name, template, default, help_default, desc) + super name, template, default, desc + @help_default = help_default + end + + attr_reader :help_default + + def config_type + 'package' + end + + private + + def check(val) + unless File.dir?("packages/#{val}") + setup_rb_error "config: no such package: #{val}" + end + val + end +end + +class ConfigTable_class + + def initialize(items) + @items = items + @table = {} + items.each do |i| + @table[i.name] = i + end + ALIASES.each do |ali, name| + @table[ali] = @table[name] + end + end + + include Enumerable + + def each(&block) + @items.each(&block) + end + + def key?(name) + @table.key?(name) + end + + def lookup(name) + @table[name] or raise ArgumentError, "no such config item: #{name}" + end + + def add(item) + @items.push item + @table[item.name] = item + end + + def remove(name) + item = lookup(name) + @items.delete_if {|i| i.name == name } + @table.delete_if {|name, i| i.name == name } + item + end + + def new + dup() + end + + def savefile + '.config' + end + + def load + begin + t = dup() + File.foreach(savefile()) do |line| + k, v = *line.split(/=/, 2) + t[k] = v.strip + end + t + rescue Errno::ENOENT + setup_rb_error $!.message + "#{File.basename($0)} config first" + end + end + + def save + @items.each {|i| i.value } + File.open(savefile(), 'w') {|f| + @items.each do |i| + f.printf "%s=%s\n", i.name, i.value if i.value + end + } + end + + def [](key) + lookup(key).eval(self) + end + + def []=(key, val) + lookup(key).set val + end + +end + +c = ::Config::CONFIG + +rubypath = c['bindir'] + '/' + c['ruby_install_name'] + +major = c['MAJOR'].to_i +minor = c['MINOR'].to_i +teeny = c['TEENY'].to_i +version = "#{major}.#{minor}" + +# ruby ver. >= 1.4.4? +newpath_p = ((major >= 2) or + ((major == 1) and + ((minor >= 5) or + ((minor == 4) and (teeny >= 4))))) + +if c['rubylibdir'] + # V < 1.6.3 + _stdruby = c['rubylibdir'] + _siteruby = c['sitedir'] + _siterubyver = c['sitelibdir'] + _siterubyverarch = c['sitearchdir'] +elsif newpath_p + # 1.4.4 <= V <= 1.6.3 + _stdruby = "$prefix/lib/ruby/#{version}" + _siteruby = c['sitedir'] + _siterubyver = "$siteruby/#{version}" + _siterubyverarch = "$siterubyver/#{c['arch']}" +else + # V < 1.4.4 + _stdruby = "$prefix/lib/ruby/#{version}" + _siteruby = "$prefix/lib/ruby/#{version}/site_ruby" + _siterubyver = _siteruby + _siterubyverarch = "$siterubyver/#{c['arch']}" +end +libdir = '-* dummy libdir *-' +stdruby = '-* dummy rubylibdir *-' +siteruby = '-* dummy site_ruby *-' +siterubyver = '-* dummy site_ruby version *-' +parameterize = lambda {|path| + path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\ + .sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\ + .sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\ + .sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\ + .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver') +} +libdir = parameterize.call(c['libdir']) +stdruby = parameterize.call(_stdruby) +siteruby = parameterize.call(_siteruby) +siterubyver = parameterize.call(_siterubyver) +siterubyverarch = parameterize.call(_siterubyverarch) + +if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } + makeprog = arg.sub(/'/, '').split(/=/, 2)[1] +else + makeprog = 'make' +end + +common_conf = [ + PathItem.new('prefix', 'path', c['prefix'], + 'path prefix of target environment'), + PathItem.new('bindir', 'path', parameterize.call(c['bindir']), + 'the directory for commands'), + PathItem.new('libdir', 'path', libdir, + 'the directory for libraries'), + PathItem.new('datadir', 'path', parameterize.call(c['datadir']), + 'the directory for shared data'), + PathItem.new('mandir', 'path', parameterize.call(c['mandir']), + 'the directory for man pages'), + PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), + 'the directory for man pages'), + PathItem.new('stdruby', 'path', stdruby, + 'the directory for standard ruby libraries'), + PathItem.new('siteruby', 'path', siteruby, + 'the directory for version-independent aux ruby libraries'), + PathItem.new('siterubyver', 'path', siterubyver, + 'the directory for aux ruby libraries'), + PathItem.new('siterubyverarch', 'path', siterubyverarch, + 'the directory for aux ruby binaries'), + PathItem.new('rbdir', 'path', '$siterubyver', + 'the directory for ruby scripts'), + PathItem.new('sodir', 'path', '$siterubyverarch', + 'the directory for ruby extentions'), + PathItem.new('rubypath', 'path', rubypath, + 'the path to set to #! line'), + ProgramItem.new('rubyprog', 'name', rubypath, + 'the ruby program using for installation'), + ProgramItem.new('makeprog', 'name', makeprog, + 'the make program to compile ruby extentions'), + SelectItem.new('shebang', 'all/ruby/never', 'ruby', + 'shebang line (#!) editing mode'), + BoolItem.new('without-ext', 'yes/no', 'no', + 'does not compile/install ruby extentions') +] +class ConfigTable_class # open again + ALIASES = { + 'std-ruby' => 'stdruby', + 'site-ruby-common' => 'siteruby', # For backward compatibility + 'site-ruby' => 'siterubyver', # For backward compatibility + 'bin-dir' => 'bindir', + 'bin-dir' => 'bindir', + 'rb-dir' => 'rbdir', + 'so-dir' => 'sodir', + 'data-dir' => 'datadir', + 'ruby-path' => 'rubypath', + 'ruby-prog' => 'rubyprog', + 'ruby' => 'rubyprog', + 'make-prog' => 'makeprog', + 'make' => 'makeprog' + } +end +multipackage_conf = [ + PackageSelectionItem.new('with', 'name,name...', '', 'ALL', + 'package names that you want to install'), + PackageSelectionItem.new('without', 'name,name...', '', 'NONE', + 'package names that you do not want to install') +] +if multipackage_install? + ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf) +else + ConfigTable = ConfigTable_class.new(common_conf) +end + + +module MetaConfigAPI + + def eval_file_ifexist(fname) + instance_eval File.read(fname), fname, 1 if File.file?(fname) + end + + def config_names + ConfigTable.map {|i| i.name } + end + + def config?(name) + ConfigTable.key?(name) + end + + def bool_config?(name) + ConfigTable.lookup(name).config_type == 'bool' + end + + def path_config?(name) + ConfigTable.lookup(name).config_type == 'path' + end + + def value_config?(name) + case ConfigTable.lookup(name).config_type + when 'bool', 'path' + true + else + false + end + end + + def add_config(item) + ConfigTable.add item + end + + def add_bool_config(name, default, desc) + ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) + end + + def add_path_config(name, default, desc) + ConfigTable.add PathItem.new(name, 'path', default, desc) + end + + def set_config_default(name, default) + ConfigTable.lookup(name).default = default + end + + def remove_config(name) + ConfigTable.remove(name) + end + +end + + +# +# File Operations +# + +module FileOperations + + def mkdir_p(dirname, prefix = nil) + dirname = prefix + File.expand_path(dirname) if prefix + $stderr.puts "mkdir -p #{dirname}" if verbose? + return if no_harm? + + # does not check '/'... it's too abnormal case + dirs = File.expand_path(dirname).split(%r<(?=/)>) + if /\A[a-z]:\z/i =~ dirs[0] + disk = dirs.shift + dirs[0] = disk + dirs[0] + end + dirs.each_index do |idx| + path = dirs[0..idx].join('') + Dir.mkdir path unless File.dir?(path) + end + end + + def rm_f(fname) + $stderr.puts "rm -f #{fname}" if verbose? + return if no_harm? + + if File.exist?(fname) or File.symlink?(fname) + File.chmod 0777, fname + File.unlink fname + end + end + + def rm_rf(dn) + $stderr.puts "rm -rf #{dn}" if verbose? + return if no_harm? + + Dir.chdir dn + Dir.foreach('.') do |fn| + next if fn == '.' + next if fn == '..' + if File.dir?(fn) + verbose_off { + rm_rf fn + } + else + verbose_off { + rm_f fn + } + end + end + Dir.chdir '..' + Dir.rmdir dn + end + + def move_file(src, dest) + File.unlink dest if File.exist?(dest) + begin + File.rename src, dest + rescue + File.open(dest, 'wb') {|f| f.write File.binread(src) } + File.chmod File.stat(src).mode, dest + File.unlink src + end + end + + def install(from, dest, mode, prefix = nil) + $stderr.puts "install #{from} #{dest}" if verbose? + return if no_harm? + + realdest = prefix ? prefix + File.expand_path(dest) : dest + realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) + str = File.binread(from) + if diff?(str, realdest) + verbose_off { + rm_f realdest if File.exist?(realdest) + } + File.open(realdest, 'wb') {|f| + f.write str + } + File.chmod mode, realdest + + File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| + if prefix + f.puts realdest.sub(prefix, '') + else + f.puts realdest + end + } + end + end + + def diff?(new_content, path) + return true unless File.exist?(path) + new_content != File.binread(path) + end + + def command(str) + $stderr.puts str if verbose? + system str or raise RuntimeError, "'system #{str}' failed" + end + + def ruby(str) + command config('rubyprog') + ' ' + str + end + + def make(task = '') + command config('makeprog') + ' ' + task + end + + def extdir?(dir) + File.exist?(dir + '/MANIFEST') + end + + def all_files_in(dirname) + Dir.open(dirname) {|d| + return d.select {|ent| File.file?("#{dirname}/#{ent}") } + } + end + + REJECT_DIRS = %w( + CVS SCCS RCS CVS.adm .svn + ) + + def all_dirs_in(dirname) + Dir.open(dirname) {|d| + return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS + } + end + +end + + +# +# Main Installer +# + +module HookUtils + + def run_hook(name) + try_run_hook "#{curr_srcdir()}/#{name}" or + try_run_hook "#{curr_srcdir()}/#{name}.rb" + end + + def try_run_hook(fname) + return false unless File.file?(fname) + begin + instance_eval File.read(fname), fname, 1 + rescue + setup_rb_error "hook #{fname} failed:\n" + $!.message + end + true + end + +end + + +module HookScriptAPI + + def get_config(key) + @config[key] + end + + alias config get_config + + def set_config(key, val) + @config[key] = val + end + + # + # srcdir/objdir (works only in the package directory) + # + + #abstract srcdir_root + #abstract objdir_root + #abstract relpath + + def curr_srcdir + "#{srcdir_root()}/#{relpath()}" + end + + def curr_objdir + "#{objdir_root()}/#{relpath()}" + end + + def srcfile(path) + "#{curr_srcdir()}/#{path}" + end + + def srcexist?(path) + File.exist?(srcfile(path)) + end + + def srcdirectory?(path) + File.dir?(srcfile(path)) + end + + def srcfile?(path) + File.file? srcfile(path) + end + + def srcentries(path = '.') + Dir.open("#{curr_srcdir()}/#{path}") {|d| + return d.to_a - %w(. ..) + } + end + + def srcfiles(path = '.') + srcentries(path).select {|fname| + File.file?(File.join(curr_srcdir(), path, fname)) + } + end + + def srcdirectories(path = '.') + srcentries(path).select {|fname| + File.dir?(File.join(curr_srcdir(), path, fname)) + } + end + +end + + +class ToplevelInstaller + + Version = '3.3.1' + Copyright = 'Copyright (c) 2000-2004 Minero Aoki' + + TASKS = [ + [ 'all', 'do config, setup, then install' ], + [ 'config', 'saves your configurations' ], + [ 'show', 'shows current configuration' ], + [ 'setup', 'compiles ruby extentions and others' ], + [ 'install', 'installs files' ], + [ 'clean', "does `make clean' for each extention" ], + [ 'distclean',"does `make distclean' for each extention" ] + ] + + def ToplevelInstaller.invoke + instance().invoke + end + + @singleton = nil + + def ToplevelInstaller.instance + @singleton ||= new(File.dirname($0)) + @singleton + end + + include MetaConfigAPI + + def initialize(ardir_root) + @config = nil + @options = { 'verbose' => true } + @ardir = File.expand_path(ardir_root) + end + + def inspect + "#<#{self.class} #{__id__()}>" + end + + def invoke + run_metaconfigs + case task = parsearg_global() + when nil, 'all' + @config = load_config('config') + parsearg_config + init_installers + exec_config + exec_setup + exec_install + else + @config = load_config(task) + __send__ "parsearg_#{task}" + init_installers + __send__ "exec_#{task}" + end + end + + def run_metaconfigs + eval_file_ifexist "#{@ardir}/metaconfig" + end + + def load_config(task) + case task + when 'config' + ConfigTable.new + when 'clean', 'distclean' + if File.exist?(ConfigTable.savefile) + then ConfigTable.load + else ConfigTable.new + end + else + ConfigTable.load + end + end + + def init_installers + @installer = Installer.new(@config, @options, @ardir, File.expand_path('.')) + end + + # + # Hook Script API bases + # + + def srcdir_root + @ardir + end + + def objdir_root + '.' + end + + def relpath + '.' + end + + # + # Option Parsing + # + + def parsearg_global + valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/ + + while arg = ARGV.shift + case arg + when /\A\w+\z/ + setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg + return arg + + when '-q', '--quiet' + @options['verbose'] = false + + when '--verbose' + @options['verbose'] = true + + when '-h', '--help' + print_usage $stdout + exit 0 + + when '-v', '--version' + puts "#{File.basename($0)} version #{Version}" + exit 0 + + when '--copyright' + puts Copyright + exit 0 + + else + setup_rb_error "unknown global option '#{arg}'" + end + end + + nil + end + + + def parsearg_no_options + unless ARGV.empty? + setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}" + end + end + + alias parsearg_show parsearg_no_options + alias parsearg_setup parsearg_no_options + alias parsearg_clean parsearg_no_options + alias parsearg_distclean parsearg_no_options + + def parsearg_config + re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/ + @options['config-opt'] = [] + + while i = ARGV.shift + if /\A--?\z/ =~ i + @options['config-opt'] = ARGV.dup + break + end + m = re.match(i) or setup_rb_error "config: unknown option #{i}" + name, value = *m.to_a[1,2] + @config[name] = value + end + end + + def parsearg_install + @options['no-harm'] = false + @options['install-prefix'] = '' + while a = ARGV.shift + case a + when /\A--no-harm\z/ + @options['no-harm'] = true + when /\A--prefix=(.*)\z/ + path = $1 + path = File.expand_path(path) unless path[0,1] == '/' + @options['install-prefix'] = path + else + setup_rb_error "install: unknown option #{a}" + end + end + end + + def print_usage(out) + out.puts 'Typical Installation Procedure:' + out.puts " $ ruby #{File.basename $0} config" + out.puts " $ ruby #{File.basename $0} setup" + out.puts " # ruby #{File.basename $0} install (may require root privilege)" + out.puts + out.puts 'Detailed Usage:' + out.puts " ruby #{File.basename $0} <global option>" + out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]" + + fmt = " %-24s %s\n" + out.puts + out.puts 'Global options:' + out.printf fmt, '-q,--quiet', 'suppress message outputs' + out.printf fmt, ' --verbose', 'output messages verbosely' + out.printf fmt, '-h,--help', 'print this message' + out.printf fmt, '-v,--version', 'print version and quit' + out.printf fmt, ' --copyright', 'print copyright and quit' + out.puts + out.puts 'Tasks:' + TASKS.each do |name, desc| + out.printf fmt, name, desc + end + + fmt = " %-24s %s [%s]\n" + out.puts + out.puts 'Options for CONFIG or ALL:' + ConfigTable.each do |item| + out.printf fmt, item.help_opt, item.description, item.help_default + end + out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" + out.puts + out.puts 'Options for INSTALL:' + out.printf fmt, '--no-harm', 'only display what to do if given', 'off' + out.printf fmt, '--prefix=path', 'install path prefix', '$prefix' + out.puts + end + + # + # Task Handlers + # + + def exec_config + @installer.exec_config + @config.save # must be final + end + + def exec_setup + @installer.exec_setup + end + + def exec_install + @installer.exec_install + end + + def exec_show + ConfigTable.each do |i| + printf "%-20s %s\n", i.name, i.value + end + end + + def exec_clean + @installer.exec_clean + end + + def exec_distclean + @installer.exec_distclean + end + +end + + +class ToplevelInstallerMulti < ToplevelInstaller + + include HookUtils + include HookScriptAPI + include FileOperations + + def initialize(ardir) + super + @packages = all_dirs_in("#{@ardir}/packages") + raise 'no package exists' if @packages.empty? + end + + def run_metaconfigs + eval_file_ifexist "#{@ardir}/metaconfig" + @packages.each do |name| + eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig" + end + end + + def init_installers + @installers = {} + @packages.each do |pack| + @installers[pack] = Installer.new(@config, @options, + "#{@ardir}/packages/#{pack}", + "packages/#{pack}") + end + + with = extract_selection(config('with')) + without = extract_selection(config('without')) + @selected = @installers.keys.select {|name| + (with.empty? or with.include?(name)) \ + and not without.include?(name) + } + end + + def extract_selection(list) + a = list.split(/,/) + a.each do |name| + setup_rb_error "no such package: #{name}" unless @installers.key?(name) + end + a + end + + def print_usage(f) + super + f.puts 'Inluded packages:' + f.puts ' ' + @packages.sort.join(' ') + f.puts + end + + # + # multi-package metaconfig API + # + + attr_reader :packages + + def declare_packages(list) + raise 'package list is empty' if list.empty? + list.each do |name| + raise "directory packages/#{name} does not exist"\ + unless File.dir?("#{@ardir}/packages/#{name}") + end + @packages = list + end + + # + # Task Handlers + # + + def exec_config + run_hook 'pre-config' + each_selected_installers {|inst| inst.exec_config } + run_hook 'post-config' + @config.save # must be final + end + + def exec_setup + run_hook 'pre-setup' + each_selected_installers {|inst| inst.exec_setup } + run_hook 'post-setup' + end + + def exec_install + run_hook 'pre-install' + each_selected_installers {|inst| inst.exec_install } + run_hook 'post-install' + end + + def exec_clean + rm_f ConfigTable.savefile + run_hook 'pre-clean' + each_selected_installers {|inst| inst.exec_clean } + run_hook 'post-clean' + end + + def exec_distclean + rm_f ConfigTable.savefile + run_hook 'pre-distclean' + each_selected_installers {|inst| inst.exec_distclean } + run_hook 'post-distclean' + end + + # + # lib + # + + def each_selected_installers + Dir.mkdir 'packages' unless File.dir?('packages') + @selected.each do |pack| + $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose'] + Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") + Dir.chdir "packages/#{pack}" + yield @installers[pack] + Dir.chdir '../..' + end + end + + def verbose? + @options['verbose'] + end + + def no_harm? + @options['no-harm'] + end + +end + + +class Installer + + FILETYPES = %w( bin lib ext data ) + + include HookScriptAPI + include HookUtils + include FileOperations + + def initialize(config, opt, srcroot, objroot) + @config = config + @options = opt + @srcdir = File.expand_path(srcroot) + @objdir = File.expand_path(objroot) + @currdir = '.' + end + + def inspect + "#<#{self.class} #{File.basename(@srcdir)}>" + end + + # + # Hook Script API base methods + # + + def srcdir_root + @srcdir + end + + def objdir_root + @objdir + end + + def relpath + @currdir + end + + # + # configs/options + # + + def no_harm? + @options['no-harm'] + end + + def verbose? + @options['verbose'] + end + + def verbose_off + begin + save, @options['verbose'] = @options['verbose'], false + yield + ensure + @options['verbose'] = save + end + end + + # + # TASK config + # + + def exec_config + exec_task_traverse 'config' + end + + def config_dir_bin(rel) + end + + def config_dir_lib(rel) + end + + def config_dir_ext(rel) + extconf if extdir?(curr_srcdir()) + end + + def extconf + opt = @options['config-opt'].join(' ') + command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}" + end + + def config_dir_data(rel) + end + + # + # TASK setup + # + + def exec_setup + exec_task_traverse 'setup' + end + + def setup_dir_bin(rel) + all_files_in(curr_srcdir()).each do |fname| + adjust_shebang "#{curr_srcdir()}/#{fname}" + end + end + + def adjust_shebang(path) + return if no_harm? + tmpfile = File.basename(path) + '.tmp' + begin + File.open(path, 'rb') {|r| + first = r.gets + return unless File.basename(config('rubypath')) == 'ruby' + return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby' + $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose? + File.open(tmpfile, 'wb') {|w| + w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath')) + w.write r.read + } + move_file tmpfile, File.basename(path) + } + ensure + File.unlink tmpfile if File.exist?(tmpfile) + end + end + + def setup_dir_lib(rel) + end + + def setup_dir_ext(rel) + make if extdir?(curr_srcdir()) + end + + def setup_dir_data(rel) + end + + # + # TASK install + # + + def exec_install + rm_f 'InstalledFiles' + exec_task_traverse 'install' + end + + def install_dir_bin(rel) + install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755 + end + + def install_dir_lib(rel) + install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644 + end + + def install_dir_ext(rel) + return unless extdir?(curr_srcdir()) + install_files ruby_extentions('.'), + "#{config('sodir')}/#{File.dirname(rel)}", + 0555 + end + + def install_dir_data(rel) + install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644 + end + + def install_files(list, dest, mode) + mkdir_p dest, @options['install-prefix'] + list.each do |fname| + install fname, dest, mode, @options['install-prefix'] + end + end + + def ruby_scripts + collect_filenames_auto().select {|n| /\.rb\z/ =~ n } + end + + # picked up many entries from cvs-1.11.1/src/ignore.c + reject_patterns = %w( + core RCSLOG tags TAGS .make.state + .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb + *~ *.old *.bak *.BAK *.orig *.rej _$* *$ + + *.org *.in .* + ) + mapping = { + '.' => '\.', + '$' => '\$', + '#' => '\#', + '*' => '.*' + } + REJECT_PATTERNS = Regexp.new('\A(?:' + + reject_patterns.map {|pat| + pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] } + }.join('|') + + ')\z') + + def collect_filenames_auto + mapdir((existfiles() - hookfiles()).reject {|fname| + REJECT_PATTERNS =~ fname + }) + end + + def existfiles + all_files_in(curr_srcdir()) | all_files_in('.') + end + + def hookfiles + %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| + %w( config setup install clean ).map {|t| sprintf(fmt, t) } + }.flatten + end + + def mapdir(filelist) + filelist.map {|fname| + if File.exist?(fname) # objdir + fname + else # srcdir + File.join(curr_srcdir(), fname) + end + } + end + + def ruby_extentions(dir) + Dir.open(dir) {|d| + ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname } + if ents.empty? + setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" + end + return ents + } + end + + # + # TASK clean + # + + def exec_clean + exec_task_traverse 'clean' + rm_f ConfigTable.savefile + rm_f 'InstalledFiles' + end + + def clean_dir_bin(rel) + end + + def clean_dir_lib(rel) + end + + def clean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'clean' if File.file?('Makefile') + end + + def clean_dir_data(rel) + end + + # + # TASK distclean + # + + def exec_distclean + exec_task_traverse 'distclean' + rm_f ConfigTable.savefile + rm_f 'InstalledFiles' + end + + def distclean_dir_bin(rel) + end + + def distclean_dir_lib(rel) + end + + def distclean_dir_ext(rel) + return unless extdir?(curr_srcdir()) + make 'distclean' if File.file?('Makefile') + end + + # + # lib + # + + def exec_task_traverse(task) + run_hook "pre-#{task}" + FILETYPES.each do |type| + if config('without-ext') == 'yes' and type == 'ext' + $stderr.puts 'skipping ext/* by user option' if verbose? + next + end + traverse task, type, "#{task}_dir_#{type}" + end + run_hook "post-#{task}" + end + + def traverse(task, rel, mid) + dive_into(rel) { + run_hook "pre-#{task}" + __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') + all_dirs_in(curr_srcdir()).each do |d| + traverse task, "#{rel}/#{d}", mid + end + run_hook "post-#{task}" + } + end + + def dive_into(rel) + return unless File.dir?("#{@srcdir}/#{rel}") + + dir = File.basename(rel) + Dir.mkdir dir unless File.dir?(dir) + prevdir = Dir.pwd + Dir.chdir dir + $stderr.puts '---> ' + rel if verbose? + @currdir = rel + yield + Dir.chdir prevdir + $stderr.puts '<--- ' + rel if verbose? + @currdir = File.dirname(rel) + end + +end + + +if $0 == __FILE__ + begin + if multipackage_install? + ToplevelInstallerMulti.invoke + else + ToplevelInstaller.invoke + end + rescue SetupError + raise if $DEBUG + $stderr.puts $!.message + $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." + exit 1 + end +end +require File.dirname(__FILE__) + '/abstract_unit' +require 'webrick' +require 'webrick/log' +require 'singleton' + +module ClientTest + class Person < ActionWebService::Struct + member :firstnames, [:string] + member :lastname, :string + + def ==(other) + firstnames == other.firstnames && lastname == other.lastname + end + end + + class Inner < ActionWebService::Struct + member :name, :string + end + + class Outer < ActionWebService::Struct + member :name, :string + member :inner, Inner + end + + class User < ActiveRecord::Base + end + + module Accounting + class User < ActiveRecord::Base + end + end + + class WithModel < ActionWebService::Struct + member :user, User + member :users, [User] + end + + class WithMultiDimArray < ActionWebService::Struct + member :pref, [[:string]] + end + + class API < ActionWebService::API::Base + api_method :void + api_method :normal, :expects => [:int, :int], :returns => [:int] + api_method :array_return, :returns => [[Person]] + api_method :struct_pass, :expects => [[Person]], :returns => [:bool] + api_method :nil_struct_return, :returns => [Person] + api_method :inner_nil, :returns => [Outer] + api_method :client_container, :returns => [:int] + api_method :named_parameters, :expects => [{:key=>:string}, {:id=>:int}] + api_method :thrower + api_method :user_return, :returns => [User] + api_method :with_model_return, :returns => [WithModel] + api_method :scoped_model_return, :returns => [Accounting::User] + api_method :multi_dim_return, :returns => [WithMultiDimArray] + end + + class NullLogOut + def <<(*args); end + end + + class Container < ActionController::Base + web_service_api API + + attr_accessor :value_void + attr_accessor :value_normal + attr_accessor :value_array_return + attr_accessor :value_struct_pass + attr_accessor :value_named_parameters + + def initialize + @session = @assigns = {} + @value_void = nil + @value_normal = nil + @value_array_return = nil + @value_struct_pass = nil + @value_named_parameters = nil + end + + def void + @value_void = @method_params + end + + def normal + @value_normal = @method_params + 5 + end + + def array_return + person = Person.new + person.firstnames = ["one", "two"] + person.lastname = "last" + @value_array_return = [person] + end + + def struct_pass + @value_struct_pass = @method_params + true + end + + def nil_struct_return + nil + end + + def inner_nil + Outer.new :name => 'outer', :inner => nil + end + + def client_container + 50 + end + + def named_parameters + @value_named_parameters = @method_params + end + + def thrower + raise "Hi" + end + + def user_return + User.find(1) + end + + def with_model_return + WithModel.new :user => User.find(1), :users => User.find(:all) + end + + def scoped_model_return + Accounting::User.find(1) + end + + def multi_dim_return + WithMultiDimArray.new :pref => [%w{pref1 value1}, %w{pref2 value2}] + end + end + + class AbstractClientLet < WEBrick::HTTPServlet::AbstractServlet + def initialize(controller) + @controller = controller + end + + def get_instance(*args) + self + end + + def require_path_info? + false + end + + def do_GET(req, res) + raise WEBrick::HTTPStatus::MethodNotAllowed, "GET request not allowed." + end + + def do_POST(req, res) + raise NotImplementedError + end + end + + class AbstractServer + include ClientTest + include Singleton + attr :container + def initialize + @container = Container.new + @clientlet = create_clientlet(@container) + log = WEBrick::BasicLog.new(NullLogOut.new) + @server = WEBrick::HTTPServer.new(:Port => server_port, :Logger => log, :AccessLog => log) + @server.mount('/', @clientlet) + @thr = Thread.new { @server.start } + until @server.status == :Running; end + at_exit { @server.stop; @thr.join } + end + + protected + def create_clientlet + raise NotImplementedError + end + + def server_port + raise NotImplementedError + end + end +end +require File.dirname(__FILE__) + '/abstract_unit' +require 'stringio' + +class ActionController::Base; def rescue_action(e) raise e end; end + +module DispatcherTest + Utf8String = "One World Caf\303\251" + WsdlNamespace = 'http://rubyonrails.com/some/namespace' + + class Node < ActiveRecord::Base + def initialize(*args) + super(*args) + @new_record = false + end + + class << self + def name + "DispatcherTest::Node" + end + + def columns(*args) + [ + ActiveRecord::ConnectionAdapters::Column.new('id', 0, 'int'), + ActiveRecord::ConnectionAdapters::Column.new('name', nil, 'string'), + ActiveRecord::ConnectionAdapters::Column.new('description', nil, 'string'), + ] + end + + def connection + self + end + end + end + + class Person < ActionWebService::Struct + member :id, :int + member :name, :string + + def ==(other) + self.id == other.id && self.name == other.name + end + end + + class API < ActionWebService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + api_method :interceptee + api_method :struct_return, :returns => [[Node]] + api_method :void + end + + class DirectAPI < ActionWebService::API::Base + api_method :add, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int] + api_method :add2, :expects => [{:a=>:int}, {:b=>:int}], :returns => [:int] + api_method :before_filtered + api_method :after_filtered, :returns => [[:int]] + api_method :struct_return, :returns => [[Node]] + api_method :struct_pass, :expects => [{:person => Person}] + api_method :base_struct_return, :returns => [[Person]] + api_method :hash_struct_return, :returns => [[Person]] + api_method :thrower + api_method :void + api_method :test_utf8, :returns => [:string] + api_method :hex, :expects => [:base64], :returns => [:string] + api_method :unhex, :expects => [:string], :returns => [:base64] + api_method :time, :expects => [:time], :returns => [:time] + end + + class VirtualAPI < ActionWebService::API::Base + default_api_method :fallback + end + + class Service < ActionWebService::Base + web_service_api API + + before_invocation :do_intercept, :only => [:interceptee] + + attr :added + attr :intercepted + attr :void_called + + def initialize + @void_called = false + end + + def add(a, b) + @added = a + b + end + + def interceptee + @intercepted = false + end + + def struct_return + n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1') + n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2') + [n1, n2] + end + + def void(*args) + @void_called = args + end + + def do_intercept(name, args) + [false, "permission denied"] + end + end + + class MTAPI < ActionWebService::API::Base + inflect_names false + api_method :getCategories, :returns => [[:string]] + api_method :bool, :returns => [:bool] + api_method :alwaysFail + end + + class BloggerAPI < ActionWebService::API::Base + inflect_names false + api_method :getCategories, :returns => [[:string]] + api_method :str, :expects => [:int], :returns => [:string] + api_method :alwaysFail + end + + class MTService < ActionWebService::Base + web_service_api MTAPI + + def getCategories + ["mtCat1", "mtCat2"] + end + + def bool + 'y' + end + + def alwaysFail + raise "MT AlwaysFail" + end + end + + class BloggerService < ActionWebService::Base + web_service_api BloggerAPI + + def getCategories + ["bloggerCat1", "bloggerCat2"] + end + + def str(int) + unless int.is_a?(Integer) + raise "Not an integer!" + end + 500 + int + end + + def alwaysFail + raise "Blogger AlwaysFail" + end + end + + class AbstractController < ActionController::Base + def generate_wsdl + @request ||= ::ActionController::TestRequest.new + to_wsdl + end + end + + class DelegatedController < AbstractController + web_service_dispatching_mode :delegated + wsdl_namespace WsdlNamespace + + web_service(:test_service) { @service ||= Service.new; @service } + end + + class LayeredController < AbstractController + web_service_dispatching_mode :layered + wsdl_namespace WsdlNamespace + + web_service(:mt) { @mt_service ||= MTService.new; @mt_service } + web_service(:blogger) { @blogger_service ||= BloggerService.new; @blogger_service } + end + + class DirectController < AbstractController + web_service_api DirectAPI + web_service_dispatching_mode :direct + wsdl_namespace WsdlNamespace + + before_invocation :alwaysfail, :only => [:before_filtered] + after_invocation :alwaysok, :only => [:after_filtered] + + attr :added + attr :added2 + attr :before_filter_called + attr :before_filter_target_called + attr :after_filter_called + attr :after_filter_target_called + attr :void_called + attr :struct_pass_value + + def initialize + @before_filter_called = false + @before_filter_target_called = false + @after_filter_called = false + @after_filter_target_called = false + @void_called = false + @struct_pass_value = false + end + + def add + @added = @params['a'] + @params['b'] + end + + def add2(a, b) + @added2 = a + b + end + + def before_filtered + @before_filter_target_called = true + end + + def after_filtered + @after_filter_target_called = true + [5, 6, 7] + end + + def thrower + raise "Hi, I'm an exception" + end + + def struct_return + n1 = Node.new('id' => 1, 'name' => 'node1', 'description' => 'Node 1') + n2 = Node.new('id' => 2, 'name' => 'node2', 'description' => 'Node 2') + [n1, n2] + end + + def struct_pass(person) + @struct_pass_value = person + end + + def base_struct_return + p1 = Person.new('id' => 1, 'name' => 'person1') + p2 = Person.new('id' => 2, 'name' => 'person2') + [p1, p2] + end + + def hash_struct_return + p1 = { :id => '1', 'name' => 'test' } + p2 = { 'id' => '2', :name => 'person2' } + [p1, p2] + end + + def void + @void_called = @method_params + end + + def test_utf8 + Utf8String + end + + def hex(s) + return s.unpack("H*")[0] + end + + def unhex(s) + return [s].pack("H*") + end + + def time(t) + t + end + + protected + def alwaysfail(method_name, params) + @before_filter_called = true + false + end + + def alwaysok(method_name, params, return_value) + @after_filter_called = true + end + end + + class VirtualController < AbstractController + web_service_api VirtualAPI + wsdl_namespace WsdlNamespace + + def fallback + "fallback!" + end + end +end + +module DispatcherCommonTests + def test_direct_dispatching + assert_equal(70, do_method_call(@direct_controller, 'Add', 20, 50)) + assert_equal(70, @direct_controller.added) + assert_equal(50, do_method_call(@direct_controller, 'Add2', 25, 25)) + assert_equal(50, @direct_controller.added2) + assert(@direct_controller.void_called == false) + assert(do_method_call(@direct_controller, 'Void', 3, 4, 5).nil?) + assert(@direct_controller.void_called == []) + result = do_method_call(@direct_controller, 'BaseStructReturn') + assert(result[0].is_a?(DispatcherTest::Person)) + assert(result[1].is_a?(DispatcherTest::Person)) + assert_equal("cafe", do_method_call(@direct_controller, 'Hex', "\xca\xfe")) + assert_equal("\xca\xfe", do_method_call(@direct_controller, 'Unhex', "cafe")) + time = Time.gm(1998, "Feb", 02, 15, 12, 01) + assert_equal(time, do_method_call(@direct_controller, 'Time', time)) + end + + def test_direct_entrypoint + assert(@direct_controller.respond_to?(:api)) + end + + def test_virtual_dispatching + assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualOne')) + assert_equal("fallback!", do_method_call(@virtual_controller, 'VirtualTwo')) + end + + def test_direct_filtering + assert_equal(false, @direct_controller.before_filter_called) + assert_equal(false, @direct_controller.before_filter_target_called) + do_method_call(@direct_controller, 'BeforeFiltered') + assert_equal(true, @direct_controller.before_filter_called) + assert_equal(false, @direct_controller.before_filter_target_called) + assert_equal(false, @direct_controller.after_filter_called) + assert_equal(false, @direct_controller.after_filter_target_called) + assert_equal([5, 6, 7], do_method_call(@direct_controller, 'AfterFiltered')) + assert_equal(true, @direct_controller.after_filter_called) + assert_equal(true, @direct_controller.after_filter_target_called) + end + + def test_delegated_dispatching + assert_equal(130, do_method_call(@delegated_controller, 'Add', 50, 80)) + service = @delegated_controller.web_service_object(:test_service) + assert_equal(130, service.added) + @delegated_controller.web_service_exception_reporting = true + assert(service.intercepted.nil?) + result = do_method_call(@delegated_controller, 'Interceptee') + assert(service.intercepted.nil?) + assert(is_exception?(result)) + assert_match(/permission denied/, exception_message(result)) + result = do_method_call(@delegated_controller, 'NonExistentMethod') + assert(is_exception?(result)) + assert_match(/NonExistentMethod/, exception_message(result)) + assert(service.void_called == false) + assert(do_method_call(@delegated_controller, 'Void', 3, 4, 5).nil?) + assert(service.void_called == []) + end + + def test_garbage_request + [@direct_controller, @delegated_controller].each do |controller| + controller.class.web_service_exception_reporting = true + send_garbage_request = lambda do + service_name = service_name(controller) + request = protocol.encode_action_pack_request(service_name, 'broken, method, name!', 'broken request body', :request_class => ActionController::TestRequest) + response = ActionController::TestResponse.new + controller.process(request, response) + # puts response.body + assert(response.headers['Status'] =~ /^500/) + end + send_garbage_request.call + controller.class.web_service_exception_reporting = false + send_garbage_request.call + end + end + + def test_exception_marshaling + @direct_controller.web_service_exception_reporting = true + result = do_method_call(@direct_controller, 'Thrower') + assert(is_exception?(result)) + assert_equal("Hi, I'm an exception", exception_message(result)) + @direct_controller.web_service_exception_reporting = false + result = do_method_call(@direct_controller, 'Thrower') + assert(exception_message(result) != "Hi, I'm an exception") + end + + def test_ar_struct_return + [@direct_controller, @delegated_controller].each do |controller| + result = do_method_call(controller, 'StructReturn') + assert(result[0].is_a?(DispatcherTest::Node)) + assert(result[1].is_a?(DispatcherTest::Node)) + assert_equal('node1', result[0].name) + assert_equal('node2', result[1].name) + end + end + + def test_casting + assert_equal 70, do_method_call(@direct_controller, 'Add', "50", "20") + assert_equal false, @direct_controller.struct_pass_value + person = DispatcherTest::Person.new(:id => 1, :name => 'test') + result = do_method_call(@direct_controller, 'StructPass', person) + assert(nil == result || true == result) + assert_equal person, @direct_controller.struct_pass_value + assert !person.equal?(@direct_controller.struct_pass_value) + result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test'}) + case + when soap? + assert_equal(person, @direct_controller.struct_pass_value) + assert !person.equal?(@direct_controller.struct_pass_value) + when xmlrpc? + assert_equal(person, @direct_controller.struct_pass_value) + assert !person.equal?(@direct_controller.struct_pass_value) + end + assert_equal person, do_method_call(@direct_controller, 'HashStructReturn')[0] + result = do_method_call(@direct_controller, 'StructPass', {'id' => '1', 'name' => 'test', 'nonexistent_attribute' => 'value'}) + case + when soap? + assert_equal(person, @direct_controller.struct_pass_value) + assert !person.equal?(@direct_controller.struct_pass_value) + when xmlrpc? + assert_equal(person, @direct_controller.struct_pass_value) + assert !person.equal?(@direct_controller.struct_pass_value) + end + end + + def test_logging + buf = "" + ActionController::Base.logger = Logger.new(StringIO.new(buf)) + test_casting + test_garbage_request + test_exception_marshaling + ActionController::Base.logger = nil + assert_match /Web Service Response/, buf + assert_match /Web Service Request/, buf + end + + protected + def service_name(container) + raise NotImplementedError + end + + def exception_message(obj) + raise NotImplementedError + end + + def is_exception?(obj) + raise NotImplementedError + end + + def protocol + @protocol + end + + def soap? + protocol.is_a? ActionWebService::Protocol::Soap::SoapProtocol + end + + def xmlrpc? + protocol.is_a? ActionWebService::Protocol::XmlRpc::XmlRpcProtocol + end + + def do_method_call(container, public_method_name, *params) + request_env = {} + mode = container.web_service_dispatching_mode + case mode + when :direct + service_name = service_name(container) + api = container.class.web_service_api + method = api.public_api_method_instance(public_method_name) + when :delegated + service_name = service_name(container) + api = container.web_service_object(service_name).class.web_service_api + method = api.public_api_method_instance(public_method_name) + when :layered + service_name = nil + real_method_name = nil + if public_method_name =~ /^([^\.]+)\.(.*)$/ + service_name = $1 + real_method_name = $2 + end + if soap? + public_method_name = real_method_name + request_env['HTTP_SOAPACTION'] = "/soap/#{service_name}/#{real_method_name}" + end + api = container.web_service_object(service_name.to_sym).class.web_service_api rescue nil + method = api.public_api_method_instance(real_method_name) rescue nil + service_name = self.service_name(container) + end + protocol.register_api(api) + virtual = false + unless method + virtual = true + method ||= ActionWebService::API::Method.new(public_method_name.underscore.to_sym, public_method_name, nil, nil) + end + body = protocol.encode_request(public_method_name, params.dup, method.expects) + # puts body + ap_request = protocol.encode_action_pack_request(service_name, public_method_name, body, :request_class => ActionController::TestRequest) + ap_request.env.update(request_env) + ap_response = ActionController::TestResponse.new + container.process(ap_request, ap_response) + # puts ap_response.body + @response_body = ap_response.body + public_method_name, return_value = protocol.decode_response(ap_response.body) + unless is_exception?(return_value) || virtual + return_value = method.cast_returns(return_value) + end + if soap? + # http://dev.rubyonrails.com/changeset/920 + assert_match(/Response$/, public_method_name) unless public_method_name == "fault" + end + return_value + end +end +ENV["RAILS_ENV"] = "test" +$:.unshift(File.dirname(__FILE__) + '/../lib') +$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') +$:.unshift(File.dirname(__FILE__) + '/../../actionpack/lib') +$:.unshift(File.dirname(__FILE__) + '/../../activerecord/lib') + +require 'test/unit' +require 'action_web_service' +require 'action_controller' +require 'action_controller/test_process' + +ActionController::Base.logger = nil +ActionController::Base.ignore_missing_templates = true + +begin + PATH_TO_AR = File.dirname(__FILE__) + '/../../activerecord' + require "#{PATH_TO_AR}/lib/active_record" unless Object.const_defined?(:ActiveRecord) + require "#{PATH_TO_AR}/lib/active_record/fixtures" unless Object.const_defined?(:Fixtures) +rescue Object => e + fail "\nFailed to load activerecord: #{e}" +end + +ActiveRecord::Base.establish_connection( + :adapter => "mysql", + :username => "rails", + :encoding => "utf8", + :database => "activewebservice_unittest" +) +ActiveRecord::Base.connection + +Test::Unit::TestCase.fixture_path = "#{File.dirname(__FILE__)}/fixtures/" + +# restore default raw_post functionality +class ActionController::TestRequest + def raw_post + super + end +endrequire File.dirname(__FILE__) + '/abstract_unit' + +module APITest + class API < ActionWebService::API::Base + api_method :void + api_method :expects_and_returns, :expects_and_returns => [:string] + api_method :expects, :expects => [:int, :bool] + api_method :returns, :returns => [:int, [:string]] + api_method :named_signature, :expects => [{:appkey=>:int}, {:publish=>:bool}] + api_method :string_types, :expects => ['int', 'string', 'bool', 'base64'] + api_method :class_types, :expects => [TrueClass, Bignum, String] + end +end + +class TC_API < Test::Unit::TestCase + API = APITest::API + + def test_api_method_declaration + %w( + void + expects_and_returns + expects + returns + named_signature + string_types + class_types + ).each do |name| + name = name.to_sym + public_name = API.public_api_method_name(name) + assert(API.has_api_method?(name)) + assert(API.has_public_api_method?(public_name)) + assert(API.api_method_name(public_name) == name) + assert(API.api_methods.has_key?(name)) + end + end + + def test_signature_canonicalization + assert_equal(nil, API.api_methods[:void].expects) + assert_equal(nil, API.api_methods[:void].returns) + assert_equal([String], API.api_methods[:expects_and_returns].expects.map{|x| x.type_class}) + assert_equal([String], API.api_methods[:expects_and_returns].returns.map{|x| x.type_class}) + assert_equal([Integer, TrueClass], API.api_methods[:expects].expects.map{|x| x.type_class}) + assert_equal(nil, API.api_methods[:expects].returns) + assert_equal(nil, API.api_methods[:returns].expects) + assert_equal([Integer, [String]], API.api_methods[:returns].returns.map{|x| x.array?? [x.element_type.type_class] : x.type_class}) + assert_equal([[:appkey, Integer], [:publish, TrueClass]], API.api_methods[:named_signature].expects.map{|x| [x.name, x.type_class]}) + assert_equal(nil, API.api_methods[:named_signature].returns) + assert_equal([Integer, String, TrueClass, ActionWebService::Base64], API.api_methods[:string_types].expects.map{|x| x.type_class}) + assert_equal(nil, API.api_methods[:string_types].returns) + assert_equal([TrueClass, Integer, String], API.api_methods[:class_types].expects.map{|x| x.type_class}) + assert_equal(nil, API.api_methods[:class_types].returns) + end + + def test_not_instantiable + assert_raises(NoMethodError) do + API.new + end + end + + def test_api_errors + assert_raises(ActionWebService::ActionWebServiceError) do + klass = Class.new(ActionWebService::API::Base) do + api_method :test, :expects => [ActiveRecord::Base] + end + end + klass = Class.new(ActionWebService::API::Base) do + allow_active_record_expects true + api_method :test2, :expects => [ActiveRecord::Base] + end + assert_raises(ActionWebService::ActionWebServiceError) do + klass = Class.new(ActionWebService::API::Base) do + api_method :test, :invalid => [:int] + end + end + end + + def test_parameter_names + method = API.api_methods[:named_signature] + assert_equal 0, method.expects_index_of(:appkey) + assert_equal 1, method.expects_index_of(:publish) + assert_equal 1, method.expects_index_of('publish') + assert_equal 0, method.expects_index_of('appkey') + assert_equal -1, method.expects_index_of('blah') + assert_equal -1, method.expects_index_of(:missing) + assert_equal -1, API.api_methods[:void].expects_index_of('test') + end + + def test_parameter_hash + method = API.api_methods[:named_signature] + hash = method.expects_to_hash([5, false]) + assert_equal({:appkey => 5, :publish => false}, hash) + end + + def test_api_methods_compat + sig = API.api_methods[:named_signature][:expects] + assert_equal [{:appkey=>Integer}, {:publish=>TrueClass}], sig + end + + def test_to_s + assert_equal 'void Expects(int param0, bool param1)', APITest::API.api_methods[:expects].to_s + end +end +class AutoLoadAPI < ActionWebService::API::Base + api_method :void +end + + +require File.dirname(__FILE__) + '/abstract_unit' + +module BaseTest + class API < ActionWebService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + api_method :void + end + + class PristineAPI < ActionWebService::API::Base + inflect_names false + + api_method :add + api_method :under_score + end + + class Service < ActionWebService::Base + web_service_api API + + def add(a, b) + end + + def void + end + end + + class PristineService < ActionWebService::Base + web_service_api PristineAPI + + def add + end + + def under_score + end + end +end + +class TC_Base < Test::Unit::TestCase + def test_options + assert(BaseTest::PristineService.web_service_api.inflect_names == false) + assert(BaseTest::Service.web_service_api.inflect_names == true) + end +end +require File.dirname(__FILE__) + '/abstract_unit' + +module CastingTest + class API < ActionWebService::API::Base + api_method :int, :expects => [:int] + api_method :str, :expects => [:string] + api_method :base64, :expects => [:base64] + api_method :bool, :expects => [:bool] + api_method :float, :expects => [:float] + api_method :time, :expects => [:time] + api_method :datetime, :expects => [:datetime] + api_method :date, :expects => [:date] + + api_method :int_array, :expects => [[:int]] + api_method :str_array, :expects => [[:string]] + api_method :bool_array, :expects => [[:bool]] + end +end + +class TC_Casting < Test::Unit::TestCase + include CastingTest + + def test_base_type_casting_valid + assert_equal 10000, cast_expects(:int, '10000')[0] + assert_equal '10000', cast_expects(:str, 10000)[0] + base64 = cast_expects(:base64, 10000)[0] + assert_equal '10000', base64 + assert_instance_of ActionWebService::Base64, base64 + [1, '1', 'true', 'y', 'yes'].each do |val| + assert_equal true, cast_expects(:bool, val)[0] + end + [0, '0', 'false', 'n', 'no'].each do |val| + assert_equal false, cast_expects(:bool, val)[0] + end + assert_equal 3.14159, cast_expects(:float, '3.14159')[0] + now = Time.at(Time.now.tv_sec) + casted = cast_expects(:time, now.to_s)[0] + assert_equal now, casted + now = DateTime.now + assert_equal now.to_s, cast_expects(:datetime, now.to_s)[0].to_s + today = Date.today + assert_equal today, cast_expects(:date, today.to_s)[0] + end + + def test_base_type_casting_invalid + assert_raises ArgumentError do + cast_expects(:int, 'this is not a number') + end + assert_raises ActionWebService::Casting::CastingError do + # neither true or false ;) + cast_expects(:bool, 'i always lie') + end + assert_raises ArgumentError do + cast_expects(:float, 'not a float') + end + assert_raises ArgumentError do + cast_expects(:time, '111111111111111111111111111111111') + end + assert_raises ArgumentError do + cast_expects(:datetime, '-1') + end + assert_raises ArgumentError do + cast_expects(:date, '') + end + end + + def test_array_type_casting + assert_equal [1, 2, 3213992, 4], cast_expects(:int_array, ['1', '2', '3213992', '4'])[0] + assert_equal ['one', 'two', '5.0', '200', nil, 'true'], cast_expects(:str_array, [:one, 'two', 5.0, 200, nil, true])[0] + assert_equal [true, nil, true, true, false], cast_expects(:bool_array, ['1', nil, 'y', true, 'false'])[0] + end + + def test_array_type_casting_failure + assert_raises ActionWebService::Casting::CastingError do + cast_expects(:bool_array, ['false', 'blahblah']) + end + assert_raises ArgumentError do + cast_expects(:int_array, ['1', '2.021', '4']) + end + end + + private + def cast_expects(method_name, *args) + API.api_method_instance(method_name.to_sym).cast_expects([*args]) + end +end +require File.dirname(__FILE__) + '/abstract_client' + + +module ClientSoapTest + PORT = 8998 + + class SoapClientLet < ClientTest::AbstractClientLet + def do_POST(req, res) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1] + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENTTYPE'] = 'text/xml' + test_request.env['HTTP_SOAPACTION'] = req.header['soapaction'][0] + test_request.env['RAW_POST_DATA'] = req.body + response = ActionController::TestResponse.new + @controller.process(test_request, response) + res.header['content-type'] = 'text/xml' + res.body = response.body + rescue Exception => e + $stderr.puts e.message + $stderr.puts e.backtrace.join("\n") + end + end + + class ClientContainer < ActionController::Base + web_client_api :client, :soap, "http://localhost:#{PORT}/client/api", :api => ClientTest::API + web_client_api :invalid, :null, "", :api => true + + def get_client + client + end + + def get_invalid + invalid + end + end + + class SoapServer < ClientTest::AbstractServer + def create_clientlet(controller) + SoapClientLet.new(controller) + end + + def server_port + PORT + end + end +end + +class TC_ClientSoap < Test::Unit::TestCase + include ClientTest + include ClientSoapTest + + fixtures :users + + def setup + @server = SoapServer.instance + @container = @server.container + @client = ActionWebService::Client::Soap.new(API, "http://localhost:#{@server.server_port}/client/api") + end + + def test_void + assert(@container.value_void.nil?) + @client.void + assert(!@container.value_void.nil?) + end + + def test_normal + assert(@container.value_normal.nil?) + assert_equal(5, @client.normal(5, 6)) + assert_equal([5, 6], @container.value_normal) + assert_equal(5, @client.normal("7", "8")) + assert_equal([7, 8], @container.value_normal) + assert_equal(5, @client.normal(true, false)) + end + + def test_array_return + assert(@container.value_array_return.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal([new_person], @client.array_return) + assert_equal([new_person], @container.value_array_return) + end + + def test_struct_pass + assert(@container.value_struct_pass.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal(true, @client.struct_pass([new_person])) + assert_equal([[new_person]], @container.value_struct_pass) + end + + def test_nil_struct_return + assert_nil @client.nil_struct_return + end + + def test_inner_nil + outer = @client.inner_nil + assert_equal 'outer', outer.name + assert_nil outer.inner + end + + def test_client_container + assert_equal(50, ClientContainer.new.get_client.client_container) + assert(ClientContainer.new.get_invalid.nil?) + end + + def test_named_parameters + assert(@container.value_named_parameters.nil?) + assert(@client.named_parameters("key", 5).nil?) + assert_equal(["key", 5], @container.value_named_parameters) + end + + def test_capitalized_method_name + @container.value_normal = nil + assert_equal(5, @client.Normal(5, 6)) + assert_equal([5, 6], @container.value_normal) + @container.value_normal = nil + end + + def test_model_return + user = @client.user_return + assert_equal 1, user.id + assert_equal 'Kent', user.name + assert user.active? + assert_kind_of Date, user.created_on + assert_equal Date.today, user.created_on + end + + def test_with_model + with_model = @client.with_model_return + assert_equal 'Kent', with_model.user.name + assert_equal 2, with_model.users.size + with_model.users.each do |user| + assert_kind_of User, user + end + end + + def test_scoped_model_return + scoped_model = @client.scoped_model_return + assert_kind_of Accounting::User, scoped_model + assert_equal 'Kent', scoped_model.name + end + + def test_multi_dim_return + md_struct = @client.multi_dim_return + assert_kind_of Array, md_struct.pref + assert_equal 2, md_struct.pref.size + assert_kind_of Array, md_struct.pref[0] + end +end +require File.dirname(__FILE__) + '/abstract_client' + + +module ClientXmlRpcTest + PORT = 8999 + + class XmlRpcClientLet < ClientTest::AbstractClientLet + def do_POST(req, res) + test_request = ActionController::TestRequest.new + test_request.request_parameters['action'] = req.path.gsub(/^\//, '').split(/\//)[1] + test_request.env['REQUEST_METHOD'] = "POST" + test_request.env['HTTP_CONTENT_TYPE'] = 'text/xml' + test_request.env['RAW_POST_DATA'] = req.body + response = ActionController::TestResponse.new + @controller.process(test_request, response) + res.header['content-type'] = 'text/xml' + res.body = response.body + # puts res.body + rescue Exception => e + $stderr.puts e.message + $stderr.puts e.backtrace.join("\n") + end + end + + class ClientContainer < ActionController::Base + web_client_api :client, :xmlrpc, "http://localhost:#{PORT}/client/api", :api => ClientTest::API + + def get_client + client + end + end + + class XmlRpcServer < ClientTest::AbstractServer + def create_clientlet(controller) + XmlRpcClientLet.new(controller) + end + + def server_port + PORT + end + end +end + +class TC_ClientXmlRpc < Test::Unit::TestCase + include ClientTest + include ClientXmlRpcTest + + fixtures :users + + def setup + @server = XmlRpcServer.instance + @container = @server.container + @client = ActionWebService::Client::XmlRpc.new(API, "http://localhost:#{@server.server_port}/client/api") + end + + def test_void + assert(@container.value_void.nil?) + @client.void + assert(!@container.value_void.nil?) + end + + def test_normal + assert(@container.value_normal.nil?) + assert_equal(5, @client.normal(5, 6)) + assert_equal([5, 6], @container.value_normal) + assert_equal(5, @client.normal("7", "8")) + assert_equal([7, 8], @container.value_normal) + assert_equal(5, @client.normal(true, false)) + end + + def test_array_return + assert(@container.value_array_return.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal([new_person], @client.array_return) + assert_equal([new_person], @container.value_array_return) + end + + def test_struct_pass + assert(@container.value_struct_pass.nil?) + new_person = Person.new + new_person.firstnames = ["one", "two"] + new_person.lastname = "last" + assert_equal(true, @client.struct_pass([new_person])) + assert_equal([[new_person]], @container.value_struct_pass) + end + + def test_nil_struct_return + assert_equal false, @client.nil_struct_return + end + + def test_inner_nil + outer = @client.inner_nil + assert_equal 'outer', outer.name + assert_nil outer.inner + end + + def test_client_container + assert_equal(50, ClientContainer.new.get_client.client_container) + end + + def test_named_parameters + assert(@container.value_named_parameters.nil?) + assert_equal(false, @client.named_parameters("xxx", 7)) + assert_equal(["xxx", 7], @container.value_named_parameters) + end + + def test_exception + assert_raises(ActionWebService::Client::ClientError) do + assert(@client.thrower) + end + end + + def test_invalid_signature + assert_raises(ArgumentError) do + @client.normal + end + end + + def test_model_return + user = @client.user_return + assert_equal 1, user.id + assert_equal 'Kent', user.name + assert user.active? + assert_kind_of Time, user.created_on + assert_equal Time.utc(Time.now.year, Time.now.month, Time.now.day), user.created_on + end + + def test_with_model + with_model = @client.with_model_return + assert_equal 'Kent', with_model.user.name + assert_equal 2, with_model.users.size + with_model.users.each do |user| + assert_kind_of User, user + end + end + + def test_scoped_model_return + scoped_model = @client.scoped_model_return + assert_kind_of Accounting::User, scoped_model + assert_equal 'Kent', scoped_model.name + end + + def test_multi_dim_return + md_struct = @client.multi_dim_return + assert_kind_of Array, md_struct.pref + assert_equal 2, md_struct.pref.size + assert_kind_of Array, md_struct.pref[0] + end +end +require File.dirname(__FILE__) + '/abstract_unit' + +module ContainerTest + $immediate_service = Object.new + $deferred_service = Object.new + + class DelegateContainer < ActionController::Base + web_service_dispatching_mode :delegated + + attr :flag + attr :previous_flag + + def initialize + @previous_flag = nil + @flag = true + end + + web_service :immediate_service, $immediate_service + web_service(:deferred_service) { @previous_flag = @flag; @flag = false; $deferred_service } + end + + class DirectContainer < ActionController::Base + web_service_dispatching_mode :direct + end + + class InvalidContainer + include ActionWebService::Container::Direct + end +end + +class TC_Container < Test::Unit::TestCase + include ContainerTest + + def setup + @delegate_container = DelegateContainer.new + @direct_container = DirectContainer.new + end + + def test_registration + assert(DelegateContainer.has_web_service?(:immediate_service)) + assert(DelegateContainer.has_web_service?(:deferred_service)) + assert(!DelegateContainer.has_web_service?(:fake_service)) + assert_raises(ActionWebService::Container::Delegated::ContainerError) do + DelegateContainer.web_service('invalid') + end + end + + def test_service_object + assert_raises(ActionWebService::Container::Delegated::ContainerError) do + @delegate_container.web_service_object(:nonexistent) + end + assert(@delegate_container.flag == true) + assert(@delegate_container.web_service_object(:immediate_service) == $immediate_service) + assert(@delegate_container.previous_flag.nil?) + assert(@delegate_container.flag == true) + assert(@delegate_container.web_service_object(:deferred_service) == $deferred_service) + assert(@delegate_container.previous_flag == true) + assert(@delegate_container.flag == false) + end + + def test_direct_container + assert(DirectContainer.web_service_dispatching_mode == :direct) + end + + def test_validity + assert_raises(ActionWebService::Container::Direct::ContainerError) do + InvalidContainer.web_service_api :test + end + assert_raises(ActionWebService::Container::Direct::ContainerError) do + InvalidContainer.web_service_api 50.0 + end + end +end +$:.unshift(File.dirname(__FILE__) + '/apis') +require File.dirname(__FILE__) + '/abstract_dispatcher' +require 'wsdl/parser' + +class ActionController::Base + class << self + alias :inherited_without_name_error :inherited + def inherited(child) + begin + inherited_without_name_error(child) + rescue NameError => e + end + end + end +end + +class AutoLoadController < ActionController::Base; end +class FailingAutoLoadController < ActionController::Base; end +class BrokenAutoLoadController < ActionController::Base; end + +class TC_DispatcherActionControllerSoap < Test::Unit::TestCase + include DispatcherTest + include DispatcherCommonTests + + def setup + @direct_controller = DirectController.new + @delegated_controller = DelegatedController.new + @virtual_controller = VirtualController.new + @layered_controller = LayeredController.new + @protocol = ActionWebService::Protocol::Soap::SoapProtocol.create(@direct_controller) + end + + def test_wsdl_generation + ensure_valid_wsdl_generation DelegatedController.new, DispatcherTest::WsdlNamespace + ensure_valid_wsdl_generation DirectController.new, DispatcherTest::WsdlNamespace + end + + def test_wsdl_action + delegated_types = ensure_valid_wsdl_action DelegatedController.new + delegated_names = delegated_types.map{|x| x.name.name} + assert(delegated_names.include?('DispatcherTest..NodeArray')) + assert(delegated_names.include?('DispatcherTest..Node')) + direct_types = ensure_valid_wsdl_action DirectController.new + direct_names = direct_types.map{|x| x.name.name} + assert(direct_names.include?('DispatcherTest..NodeArray')) + assert(direct_names.include?('DispatcherTest..Node')) + assert(direct_names.include?('IntegerArray')) + end + + def test_autoloading + assert(!AutoLoadController.web_service_api.nil?) + assert(AutoLoadController.web_service_api.has_public_api_method?('Void')) + assert(FailingAutoLoadController.web_service_api.nil?) + assert_raises(MissingSourceFile) do + FailingAutoLoadController.require_web_service_api :blah + end + assert_raises(ArgumentError) do + FailingAutoLoadController.require_web_service_api 50.0 + end + assert(BrokenAutoLoadController.web_service_api.nil?) + end + + def test_layered_dispatching + mt_cats = do_method_call(@layered_controller, 'mt.getCategories') + assert_equal(["mtCat1", "mtCat2"], mt_cats) + blogger_cats = do_method_call(@layered_controller, 'blogger.getCategories') + assert_equal(["bloggerCat1", "bloggerCat2"], blogger_cats) + end + + def test_utf8 + @direct_controller.web_service_exception_reporting = true + $KCODE = 'u' + assert_equal(Utf8String, do_method_call(@direct_controller, 'TestUtf8')) + retval = SOAP::Processor.unmarshal(@response_body).body.response + assert retval.is_a?(SOAP::SOAPString) + + # If $KCODE is not set to UTF-8, any strings with non-ASCII UTF-8 data + # will be sent back as base64 by SOAP4R. By the time we get it here though, + # it will be decoded back into a string. So lets read the base64 value + # from the message body directly. + $KCODE = 'NONE' + do_method_call(@direct_controller, 'TestUtf8') + retval = SOAP::Processor.unmarshal(@response_body).body.response + assert retval.is_a?(SOAP::SOAPBase64) + assert_equal "T25lIFdvcmxkIENhZsOp", retval.data.to_s + end + + protected + def exception_message(soap_fault_exception) + soap_fault_exception.detail.cause.message + end + + def is_exception?(obj) + obj.respond_to?(:detail) && obj.detail.respond_to?(:cause) && \ + obj.detail.cause.is_a?(Exception) + end + + def service_name(container) + container.is_a?(DelegatedController) ? 'test_service' : 'api' + end + + def ensure_valid_wsdl_generation(controller, expected_namespace) + wsdl = controller.generate_wsdl + ensure_valid_wsdl(controller, wsdl, expected_namespace) + end + + def ensure_valid_wsdl(controller, wsdl, expected_namespace) + definitions = WSDL::Parser.new.parse(wsdl) + assert(definitions.is_a?(WSDL::Definitions)) + definitions.bindings.each do |binding| + assert(binding.name.name.index(':').nil?) + end + definitions.services.each do |service| + service.ports.each do |port| + assert(port.name.name.index(':').nil?) + end + end + types = definitions.collect_complextypes.map{|x| x.name} + types.each do |type| + assert(type.namespace == expected_namespace) + end + location = definitions.services[0].ports[0].soap_address.location + if controller.is_a?(DelegatedController) + assert_match %r{http://localhost/dispatcher_test/delegated/test_service$}, location + elsif controller.is_a?(DirectController) + assert_match %r{http://localhost/dispatcher_test/direct/api$}, location + end + definitions.collect_complextypes + end + + def ensure_valid_wsdl_action(controller) + test_request = ActionController::TestRequest.new({ 'action' => 'wsdl' }) + test_request.env['REQUEST_METHOD'] = 'GET' + test_request.env['HTTP_HOST'] = 'localhost' + test_response = ActionController::TestResponse.new + wsdl = controller.process(test_request, test_response).body + ensure_valid_wsdl(controller, wsdl, DispatcherTest::WsdlNamespace) + end +end +require File.dirname(__FILE__) + '/abstract_dispatcher' + +class TC_DispatcherActionControllerXmlRpc < Test::Unit::TestCase + include DispatcherTest + include DispatcherCommonTests + + def setup + @direct_controller = DirectController.new + @delegated_controller = DelegatedController.new + @layered_controller = LayeredController.new + @virtual_controller = VirtualController.new + @protocol = ActionWebService::Protocol::XmlRpc::XmlRpcProtocol.create(@direct_controller) + end + + def test_layered_dispatching + mt_cats = do_method_call(@layered_controller, 'mt.getCategories') + assert_equal(["mtCat1", "mtCat2"], mt_cats) + blogger_cats = do_method_call(@layered_controller, 'blogger.getCategories') + assert_equal(["bloggerCat1", "bloggerCat2"], blogger_cats) + end + + def test_multicall + response = do_method_call(@layered_controller, 'system.multicall', [ + {'methodName' => 'mt.getCategories'}, + {'methodName' => 'blogger.getCategories'}, + {'methodName' => 'mt.bool'}, + {'methodName' => 'blogger.str', 'params' => ['2000']}, + {'methodName' => 'mt.alwaysFail'}, + {'methodName' => 'blogger.alwaysFail'}, + {'methodName' => 'mt.blah'}, + {'methodName' => 'blah.blah'} + ]) + assert_equal [ + [["mtCat1", "mtCat2"]], + [["bloggerCat1", "bloggerCat2"]], + [true], + ["2500"], + {"faultCode" => 3, "faultString" => "MT AlwaysFail"}, + {"faultCode" => 3, "faultString" => "Blogger AlwaysFail"}, + {"faultCode" => 4, "faultMessage" => "no such method 'blah' on API DispatcherTest::MTAPI"}, + {"faultCode" => 4, "faultMessage" => "no such web service 'blah'"} + ], response + end + + protected + def exception_message(xmlrpc_fault_exception) + xmlrpc_fault_exception.faultString + end + + def is_exception?(obj) + obj.is_a?(XMLRPC::FaultException) + end + + def service_name(container) + container.is_a?(DelegatedController) ? 'test_service' : 'api' + end +end +require File.dirname(__FILE__) + '/abstract_unit' + +module InvocationTest + class API < ActionWebService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] + api_method :transmogrify, :expects_and_returns => [:string] + api_method :fail_with_reason + api_method :fail_generic + api_method :no_before + api_method :no_after + api_method :only_one + api_method :only_two + end + + class Interceptor + attr :args + + def initialize + @args = nil + end + + def intercept(*args) + @args = args + end + end + + InterceptorClass = Interceptor.new + + class Service < ActionController::Base + web_service_api API + + before_invocation :intercept_before, :except => [:no_before] + after_invocation :intercept_after, :except => [:no_after] + prepend_after_invocation :intercept_after_first, :except => [:no_after] + prepend_before_invocation :intercept_only, :only => [:only_one, :only_two] + after_invocation(:only => [:only_one]) do |*args| + args[0].instance_variable_set('@block_invoked', args[1]) + end + after_invocation InterceptorClass, :only => [:only_one] + + attr_accessor :before_invoked + attr_accessor :after_invoked + attr_accessor :after_first_invoked + attr_accessor :only_invoked + attr_accessor :block_invoked + attr_accessor :invocation_result + + def initialize + @before_invoked = nil + @after_invoked = nil + @after_first_invoked = nil + @only_invoked = nil + @invocation_result = nil + @block_invoked = nil + end + + def add(a, b) + a + b + end + + def transmogrify(str) + str.upcase + end + + def fail_with_reason + end + + def fail_generic + end + + def no_before + 5 + end + + def no_after + end + + def only_one + end + + def only_two + end + + protected + def intercept_before(name, args) + @before_invoked = name + return [false, "permission denied"] if name == :fail_with_reason + return false if name == :fail_generic + end + + def intercept_after(name, args, result) + @after_invoked = name + @invocation_result = result + end + + def intercept_after_first(name, args, result) + @after_first_invoked = name + end + + def intercept_only(name, args) + raise "Interception error" unless name == :only_one || name == :only_two + @only_invoked = name + end + end +end + +class TC_Invocation < Test::Unit::TestCase + include ActionWebService::Invocation + + def setup + @service = InvocationTest::Service.new + end + + def test_invocation + assert(perform_invocation(:add, 5, 10) == 15) + assert(perform_invocation(:transmogrify, "hello") == "HELLO") + assert_raises(NoMethodError) do + perform_invocation(:nonexistent_method_xyzzy) + end + end + + def test_interceptor_registration + assert(InvocationTest::Service.before_invocation_interceptors.length == 2) + assert(InvocationTest::Service.after_invocation_interceptors.length == 4) + assert_equal(:intercept_only, InvocationTest::Service.before_invocation_interceptors[0]) + assert_equal(:intercept_after_first, InvocationTest::Service.after_invocation_interceptors[0]) + end + + def test_interception + assert(@service.before_invoked.nil?) + assert(@service.after_invoked.nil?) + assert(@service.only_invoked.nil?) + assert(@service.block_invoked.nil?) + assert(@service.invocation_result.nil?) + perform_invocation(:add, 20, 50) + assert(@service.before_invoked == :add) + assert(@service.after_invoked == :add) + assert(@service.invocation_result == 70) + end + + def test_interception_canceling + reason = nil + perform_invocation(:fail_with_reason){|r| reason = r} + assert(@service.before_invoked == :fail_with_reason) + assert(@service.after_invoked.nil?) + assert(@service.invocation_result.nil?) + assert(reason == "permission denied") + reason = true + @service.before_invoked = @service.after_invoked = @service.invocation_result = nil + perform_invocation(:fail_generic){|r| reason = r} + assert(@service.before_invoked == :fail_generic) + assert(@service.after_invoked.nil?) + assert(@service.invocation_result.nil?) + assert(reason == true) + end + + def test_interception_except_conditions + perform_invocation(:no_before) + assert(@service.before_invoked.nil?) + assert(@service.after_first_invoked == :no_before) + assert(@service.after_invoked == :no_before) + assert(@service.invocation_result == 5) + @service.before_invoked = @service.after_invoked = @service.invocation_result = nil + perform_invocation(:no_after) + assert(@service.before_invoked == :no_after) + assert(@service.after_invoked.nil?) + assert(@service.invocation_result.nil?) + end + + def test_interception_only_conditions + assert(@service.only_invoked.nil?) + perform_invocation(:only_one) + assert(@service.only_invoked == :only_one) + assert(@service.block_invoked == :only_one) + assert(InvocationTest::InterceptorClass.args[1] == :only_one) + @service.only_invoked = nil + perform_invocation(:only_two) + assert(@service.only_invoked == :only_two) + end + + private + def perform_invocation(method_name, *args, &block) + @service.perform_invocation(method_name, args, &block) + end +end +require File.dirname(__FILE__) + '/abstract_unit' + +ActionController::Routing::Routes.draw do |map| + map.connect '', :controller => 'scaffolded' + map.connect ':controller/:action/:id' +end + +ActionController::Base.template_root = '.' + +class ScaffoldPerson < ActionWebService::Struct + member :id, :int + member :name, :string + member :birth, :date + + def ==(other) + self.id == other.id && self.name == other.name + end +end + +class ScaffoldedControllerTestAPI < ActionWebService::API::Base + api_method :hello, :expects => [{:integer=>:int}, :string], :returns => [:bool] + api_method :hello_struct_param, :expects => [{:person => ScaffoldPerson}], :returns => [:bool] + api_method :date_of_birth, :expects => [ScaffoldPerson], :returns => [:string] + api_method :bye, :returns => [[ScaffoldPerson]] + api_method :date_diff, :expects => [{:start_date => :date}, {:end_date => :date}], :returns => [:int] + api_method :time_diff, :expects => [{:start_time => :time}, {:end_time => :time}], :returns => [:int] + api_method :base64_upcase, :expects => [:base64], :returns => [:base64] +end + +class ScaffoldedController < ActionController::Base + web_service_api ScaffoldedControllerTestAPI + web_service_scaffold :scaffold_invoke + + def hello(int, string) + 0 + end + + def hello_struct_param(person) + 0 + end + + def date_of_birth(person) + person.birth.to_s + end + + def bye + [ScaffoldPerson.new(:id => 1, :name => "leon"), ScaffoldPerson.new(:id => 2, :name => "paul")] + end + + def rescue_action(e) + raise e + end + + def date_diff(start_date, end_date) + end_date - start_date + end + + def time_diff(start_time, end_time) + end_time - start_time + end + + def base64_upcase(data) + data.upcase + end +end + +class ScaffoldedControllerTest < Test::Unit::TestCase + def setup + @controller = ScaffoldedController.new + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_scaffold_invoke + get :scaffold_invoke + assert_rendered_file 'methods.rhtml' + end + + def test_scaffold_invoke_method_params + get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'Hello' + assert_rendered_file 'parameters.rhtml' + end + + def test_scaffold_invoke_method_params_with_struct + get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'HelloStructParam' + assert_rendered_file 'parameters.rhtml' + assert_tag :tag => 'input', :attributes => {:name => "method_params[0][name]"} + end + + def test_scaffold_invoke_submit_hello + post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Hello', :method_params => {'0' => '5', '1' => 'hello world'} + assert_rendered_file 'result.rhtml' + assert_equal false, @controller.instance_eval{ @method_return_value } + end + + def test_scaffold_invoke_submit_bye + post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Bye' + assert_rendered_file 'result.rhtml' + persons = [ScaffoldPerson.new(:id => 1, :name => "leon"), ScaffoldPerson.new(:id => 2, :name => "paul")] + assert_equal persons, @controller.instance_eval{ @method_return_value } + end + + def test_scaffold_date_params + get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'DateDiff' + (0..1).each do |param| + (1..3).each do |date_part| + assert_tag :tag => 'select', :attributes => {:name => "method_params[#{param}][#{date_part}]"}, + :children => {:greater_than => 1, :only => {:tag => 'option'}} + end + end + + post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'DateDiff', + :method_params => {'0' => {'1' => '2006', '2' => '2', '3' => '1'}, '1' => {'1' => '2006', '2' => '2', '3' => '2'}} + assert_equal 1, @controller.instance_eval{ @method_return_value } + end + + def test_scaffold_struct_date_params + post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'DateOfBirth', + :method_params => {'0' => {'birth' => {'1' => '2006', '2' => '2', '3' => '1'}, 'id' => '1', 'name' => 'person'}} + assert_equal '2006-02-01', @controller.instance_eval{ @method_return_value } + end + + def test_scaffold_time_params + get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'TimeDiff' + (0..1).each do |param| + (1..6).each do |date_part| + assert_tag :tag => 'select', :attributes => {:name => "method_params[#{param}][#{date_part}]"}, + :children => {:greater_than => 1, :only => {:tag => 'option'}} + end + end + + post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'TimeDiff', + :method_params => {'0' => {'1' => '2006', '2' => '2', '3' => '1', '4' => '1', '5' => '1', '6' => '1'}, + '1' => {'1' => '2006', '2' => '2', '3' => '2', '4' => '1', '5' => '1', '6' => '1'}} + assert_equal 86400, @controller.instance_eval{ @method_return_value } + end + + def test_scaffold_base64 + get :scaffold_invoke_method_params, :service => 'scaffolded', :method => 'Base64Upcase' + assert_tag :tag => 'textarea', :attributes => {:name => 'method_params[0]'} + + post :scaffold_invoke_submit, :service => 'scaffolded', :method => 'Base64Upcase', :method_params => {'0' => 'scaffold'} + assert_equal 'SCAFFOLD', @controller.instance_eval{ @method_return_value } + end +end +require File.dirname(__FILE__) + '/abstract_unit' + +module StructTest + class Struct < ActionWebService::Struct + member :id, Integer + member :name, String + member :items, [String] + member :deleted, :bool + member :emails, [:string] + end +end + +class TC_Struct < Test::Unit::TestCase + include StructTest + + def setup + @struct = Struct.new(:id => 5, + :name => 'hello', + :items => ['one', 'two'], + :deleted => true, + :emails => ['test@test.com']) + end + + def test_members + assert_equal(5, Struct.members.size) + assert_equal(Integer, Struct.members[:id].type_class) + assert_equal(String, Struct.members[:name].type_class) + assert_equal(String, Struct.members[:items].element_type.type_class) + assert_equal(TrueClass, Struct.members[:deleted].type_class) + assert_equal(String, Struct.members[:emails].element_type.type_class) + end + + def test_initializer_and_lookup + assert_equal(5, @struct.id) + assert_equal('hello', @struct.name) + assert_equal(['one', 'two'], @struct.items) + assert_equal(true, @struct.deleted) + assert_equal(['test@test.com'], @struct.emails) + assert_equal(5, @struct['id']) + assert_equal('hello', @struct['name']) + assert_equal(['one', 'two'], @struct['items']) + assert_equal(true, @struct['deleted']) + assert_equal(['test@test.com'], @struct['emails']) + end + + def test_each_pair + @struct.each_pair do |name, value| + assert_equal @struct.__send__(name), value + assert_equal @struct[name], value + end + end +end +require File.dirname(__FILE__) + '/abstract_unit' +require 'action_web_service/test_invoke' + +class TestInvokeAPI < ActionWebService::API::Base + api_method :add, :expects => [:int, :int], :returns => [:int] +end + +class TestInvokeService < ActionWebService::Base + web_service_api TestInvokeAPI + + attr :invoked + + def add(a, b) + @invoked = true + a + b + end +end + +class TestController < ActionController::Base + def rescue_action(e); raise e; end +end + +class TestInvokeDirectController < TestController + web_service_api TestInvokeAPI + + attr :invoked + + def add + @invoked = true + @method_params[0] + @method_params[1] + end +end + +class TestInvokeDelegatedController < TestController + web_service_dispatching_mode :delegated + web_service :service, TestInvokeService.new +end + +class TestInvokeLayeredController < TestController + web_service_dispatching_mode :layered + web_service(:one) { @service_one ||= TestInvokeService.new } + web_service(:two) { @service_two ||= TestInvokeService.new } +end + +class TestInvokeTest < Test::Unit::TestCase + def setup + @request = ActionController::TestRequest.new + @response = ActionController::TestResponse.new + end + + def test_direct_add + @controller = TestInvokeDirectController.new + assert_equal nil, @controller.invoked + result = invoke :add, 25, 25 + assert_equal 50, result + assert_equal true, @controller.invoked + end + + def test_delegated_add + @controller = TestInvokeDelegatedController.new + assert_equal nil, @controller.web_service_object(:service).invoked + result = invoke_delegated :service, :add, 100, 50 + assert_equal 150, result + assert_equal true, @controller.web_service_object(:service).invoked + end + + def test_layered_add + [:soap, :xmlrpc].each do |protocol| + @protocol = protocol + [:one, :two].each do |service| + @controller = TestInvokeLayeredController.new + assert_equal nil, @controller.web_service_object(service).invoked + result = invoke_layered service, :add, 200, -50 + assert_equal 150, result + assert_equal true, @controller.web_service_object(service).invoked + end + end + end + + def test_layered_fail_with_wrong_number_of_arguments + [:soap, :xmlrpc].each do |protocol| + @protocol = protocol + [:one, :two].each do |service| + @controller = TestInvokeLayeredController.new + assert_raise(ArgumentError) { invoke_layered service, :add, 1 } + end + end + end + + def test_delegated_fail_with_wrong_number_of_arguments + @controller = TestInvokeDelegatedController.new + assert_raise(ArgumentError) { invoke_delegated :service, :add, 1 } + end + + def test_direct_fail_with_wrong_number_of_arguments + @controller = TestInvokeDirectController.new + assert_raise(ArgumentError) { invoke :add, 1 } + end + +end +require File.dirname(__FILE__) + '/shared_setup' + +logger = Logger.new(STDOUT) + +# Database setup --------------- + +logger.info "\nCreate tables" + +[ "DROP TABLE companies", "DROP TABLE people", "DROP TABLE people_companies", + "CREATE TABLE companies (id int(11) auto_increment, client_of int(11), name varchar(255), type varchar(100), PRIMARY KEY (id))", + "CREATE TABLE people (id int(11) auto_increment, name varchar(100), PRIMARY KEY (id))", + "CREATE TABLE people_companies (person_id int(11), company_id int(11), PRIMARY KEY (person_id, company_id))", +].each { |statement| + # Tables doesn't necessarily already exist + begin; ActiveRecord::Base.connection.execute(statement); rescue ActiveRecord::StatementInvalid; end +} + + +# Class setup --------------- + +class Company < ActiveRecord::Base + has_and_belongs_to_many :people, :class_name => "Person", :join_table => "people_companies", :table_name => "people" +end + +class Firm < Company + has_many :clients, :foreign_key => "client_of" + + def people_with_all_clients + clients.inject([]) { |people, client| people + client.people } + end +end + +class Client < Company + belongs_to :firm, :foreign_key => "client_of" +end + +class Person < ActiveRecord::Base + has_and_belongs_to_many :companies, :join_table => "people_companies" + def self.table_name() "people" end +end + + +# Usage --------------- + +logger.info "\nCreate fixtures" + +Firm.new("name" => "Next Angle").save +Client.new("name" => "37signals", "client_of" => 1).save +Person.new("name" => "David").save + + +logger.info "\nUsing Finders" + +next_angle = Company.find(1) +next_angle = Firm.find(1) +next_angle = Company.find_first "name = 'Next Angle'" +next_angle = Firm.find_by_sql("SELECT * FROM companies WHERE id = 1").first + +Firm === next_angle + + +logger.info "\nUsing has_many association" + +next_angle.has_clients? +next_angle.clients_count +all_clients = next_angle.clients + +thirty_seven_signals = next_angle.find_in_clients(2) + + +logger.info "\nUsing belongs_to association" + +thirty_seven_signals.has_firm? +thirty_seven_signals.firm?(next_angle) + + +logger.info "\nUsing has_and_belongs_to_many association" + +david = Person.find(1) +david.add_companies(thirty_seven_signals, next_angle) +david.companies.include?(next_angle) +david.companies_count == 2 + +david.remove_companies(next_angle) +david.companies_count == 1 + +thirty_seven_signals.people.include?(david)# Be sure to change the mysql_connection details and create a database for the example + +$: << File.dirname(__FILE__) + '/../lib' + +require 'active_record' +require 'logger'; class Logger; def format_message(severity, timestamp, msg, progname) "#{msg}\n" end; end + +ActiveRecord::Base.logger = Logger.new(STDOUT) +ActiveRecord::Base.establish_connection( + :adapter => "mysql", + :host => "localhost", + :username => "root", + :password => "", + :database => "activerecord_examples" +) +require File.dirname(__FILE__) + '/shared_setup' + +logger = Logger.new(STDOUT) + +# Database setup --------------- + +logger.info "\nCreate tables" + +[ "DROP TABLE people", + "CREATE TABLE people (id int(11) auto_increment, name varchar(100), pass varchar(100), email varchar(100), PRIMARY KEY (id))" +].each { |statement| + begin; ActiveRecord::Base.connection.execute(statement); rescue ActiveRecord::StatementInvalid; end # Tables doesn't necessarily already exist +} + + +# Class setup --------------- + +class Person < ActiveRecord::Base + # Using + def self.authenticate(name, pass) + # find_first "name = '#{name}' AND pass = '#{pass}'" would be open to sql-injection (in a web-app scenario) + find_first [ "name = '%s' AND pass = '%s'", name, pass ] + end + + def self.name_exists?(name, id = nil) + if id.nil? + condition = [ "name = '%s'", name ] + else + # Check if anyone else than the person identified by person_id has that user_name + condition = [ "name = '%s' AND id <> %d", name, id ] + end + + !find_first(condition).nil? + end + + def email_address_with_name + "\"#{name}\" <#{email}>" + end + + protected + def validate + errors.add_on_empty(%w(name pass email)) + errors.add("email", "must be valid") unless email_address_valid? + end + + def validate_on_create + if attribute_present?("name") && Person.name_exists?(name) + errors.add("name", "is already taken by another person") + end + end + + def validate_on_update + if attribute_present?("name") && Person.name_exists?(name, id) + errors.add("name", "is already taken by another person") + end + end + + private + def email_address_valid?() email =~ /\w[-.\w]*\@[-\w]+[-.\w]*\.\w+/ end +end + +# Usage --------------- + +logger.info "\nCreate fixtures" +david = Person.new("name" => "David Heinemeier Hansson", "pass" => "", "email" => "") +unless david.save + puts "There was #{david.errors.count} error(s)" + david.errors.each_full { |error| puts error } +end + +david.pass = "something" +david.email = "invalid_address" +unless david.save + puts "There was #{david.errors.count} error(s)" + puts "It was email with: " + david.errors.on("email") +end + +david.email = "david@loudthinking.com" +if david.save then puts "David finally made it!" end + + +another_david = Person.new("name" => "David Heinemeier Hansson", "pass" => "xc", "email" => "david@loudthinking") +unless another_david.save + puts "Error on name: " + another_david.errors.on("name") +endrequire 'rbconfig' +require 'find' +require 'ftools' + +include Config + +# this was adapted from rdoc's install.rb by ways of Log4r + +$sitedir = CONFIG["sitelibdir"] +unless $sitedir + version = CONFIG["MAJOR"] + "." + CONFIG["MINOR"] + $libdir = File.join(CONFIG["libdir"], "ruby", version) + $sitedir = $:.find {|x| x =~ /site_ruby/ } + if !$sitedir + $sitedir = File.join($libdir, "site_ruby") + elsif $sitedir !~ Regexp.quote(version) + $sitedir = File.join($sitedir, version) + end +end + +# the acual gruntwork +Dir.chdir("lib") + +Find.find("active_record", "active_record.rb") { |f| + if f[-3..-1] == ".rb" + File::install(f, File.join($sitedir, *f.split(/\//)), 0644, true) + else + File::makedirs(File.join($sitedir, *f.split(/\//))) + end +} +module ActiveRecord + module Acts #:nodoc: + module List #:nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # This act provides the capabilities for sorting and reordering a number of objects in a list. + # The class that has this specified needs to have a "position" column defined as an integer on + # the mapped database table. + # + # Todo list example: + # + # class TodoList < ActiveRecord::Base + # has_many :todo_items, :order => "position" + # end + # + # class TodoItem < ActiveRecord::Base + # belongs_to :todo_list + # acts_as_list :scope => :todo_list + # end + # + # todo_list.first.move_to_bottom + # todo_list.last.move_higher + module ClassMethods + # Configuration options are: + # + # * +column+ - specifies the column name to use for keeping the position integer (default: position) + # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id" + # (if that hasn't been already) and use that as the foreign key restriction. It's also possible + # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key. + # Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt> + def acts_as_list(options = {}) + configuration = { :column => "position", :scope => "1 = 1" } + configuration.update(options) if options.is_a?(Hash) + + configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/ + + if configuration[:scope].is_a?(Symbol) + scope_condition_method = %( + def scope_condition + if #{configuration[:scope].to_s}.nil? + "#{configuration[:scope].to_s} IS NULL" + else + "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}" + end + end + ) + else + scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end" + end + + class_eval <<-EOV + include ActiveRecord::Acts::List::InstanceMethods + + def acts_as_list_class + ::#{self.name} + end + + def position_column + '#{configuration[:column]}' + end + + #{scope_condition_method} + + after_destroy :remove_from_list + before_create :add_to_list_bottom + EOV + end + end + + # All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works + # by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter + # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return true if that chapter is + # the first in the list of all chapters. + module InstanceMethods + def insert_at(position = 1) + insert_at_position(position) + end + + def move_lower + return unless lower_item + + acts_as_list_class.transaction do + lower_item.decrement_position + increment_position + end + end + + def move_higher + return unless higher_item + + acts_as_list_class.transaction do + higher_item.increment_position + decrement_position + end + end + + def move_to_bottom + return unless in_list? + acts_as_list_class.transaction do + decrement_positions_on_lower_items + assume_bottom_position + end + end + + def move_to_top + return unless in_list? + acts_as_list_class.transaction do + increment_positions_on_higher_items + assume_top_position + end + end + + def remove_from_list + decrement_positions_on_lower_items if in_list? + end + + def increment_position + return unless in_list? + update_attribute position_column, self.send(position_column).to_i + 1 + end + + def decrement_position + return unless in_list? + update_attribute position_column, self.send(position_column).to_i - 1 + end + + def first? + return false unless in_list? + self.send(position_column) == 1 + end + + def last? + return false unless in_list? + self.send(position_column) == bottom_position_in_list + end + + def higher_item + return nil unless in_list? + acts_as_list_class.find(:first, :conditions => + "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}" + ) + end + + def lower_item + return nil unless in_list? + acts_as_list_class.find(:first, :conditions => + "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}" + ) + end + + def in_list? + !send(position_column).nil? + end + + private + def add_to_list_top + increment_positions_on_all_items + end + + def add_to_list_bottom + self[position_column] = bottom_position_in_list.to_i + 1 + end + + # Overwrite this method to define the scope of the list changes + def scope_condition() "1" end + + def bottom_position_in_list(except = nil) + item = bottom_item(except) + item ? item.send(position_column) : 0 + end + + def bottom_item(except = nil) + conditions = scope_condition + conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except + acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC") + end + + def assume_bottom_position + update_attribute(position_column, bottom_position_in_list(self).to_i + 1) + end + + def assume_top_position + update_attribute(position_column, 1) + end + + # This has the effect of moving all the higher items up one. + def decrement_positions_on_higher_items(position) + acts_as_list_class.update_all( + "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}" + ) + end + + # This has the effect of moving all the lower items up one. + def decrement_positions_on_lower_items + return unless in_list? + acts_as_list_class.update_all( + "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}" + ) + end + + # This has the effect of moving all the higher items down one. + def increment_positions_on_higher_items + return unless in_list? + acts_as_list_class.update_all( + "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}" + ) + end + + # This has the effect of moving all the lower items down one. + def increment_positions_on_lower_items(position) + acts_as_list_class.update_all( + "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}" + ) + end + + def increment_positions_on_all_items + acts_as_list_class.update_all( + "#{position_column} = (#{position_column} + 1)", "#{scope_condition}" + ) + end + + def insert_at_position(position) + remove_from_list + increment_positions_on_lower_items(position) + self.update_attribute(position_column, position) + end + end + end + end +end +module ActiveRecord + module Acts #:nodoc: + module NestedSet #:nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # This acts provides Nested Set functionality. Nested Set is similiar to Tree, but with + # the added feature that you can select the children and all of their descendents with + # a single query. A good use case for this is a threaded post system, where you want + # to display every reply to a comment without multiple selects. + # + # A google search for "Nested Set" should point you in the direction to explain the + # database theory. I figured out a bunch of this from + # http://threebit.net/tutorials/nestedset/tutorial1.html + # + # Instead of picturing a leaf node structure with children pointing back to their parent, + # the best way to imagine how this works is to think of the parent entity surrounding all + # of its children, and its parent surrounding it, etc. Assuming that they are lined up + # horizontally, we store the left and right boundries in the database. + # + # Imagine: + # root + # |_ Child 1 + # |_ Child 1.1 + # |_ Child 1.2 + # |_ Child 2 + # |_ Child 2.1 + # |_ Child 2.2 + # + # If my cirlces in circles description didn't make sense, check out this sweet + # ASCII art: + # + # ___________________________________________________________________ + # | Root | + # | ____________________________ ____________________________ | + # | | Child 1 | | Child 2 | | + # | | __________ _________ | | __________ _________ | | + # | | | C 1.1 | | C 1.2 | | | | C 2.1 | | C 2.2 | | | + # 1 2 3_________4 5________6 7 8 9_________10 11_______12 13 14 + # | |___________________________| |___________________________| | + # |___________________________________________________________________| + # + # The numbers represent the left and right boundries. The table then might + # look like this: + # ID | PARENT | LEFT | RIGHT | DATA + # 1 | 0 | 1 | 14 | root + # 2 | 1 | 2 | 7 | Child 1 + # 3 | 2 | 3 | 4 | Child 1.1 + # 4 | 2 | 5 | 6 | Child 1.2 + # 5 | 1 | 8 | 13 | Child 2 + # 6 | 5 | 9 | 10 | Child 2.1 + # 7 | 5 | 11 | 12 | Child 2.2 + # + # So, to get all children of an entry, you + # SELECT * WHERE CHILD.LEFT IS BETWEEN PARENT.LEFT AND PARENT.RIGHT + # + # To get the count, it's (LEFT - RIGHT + 1)/2, etc. + # + # To get the direct parent, it falls back to using the PARENT_ID field. + # + # There are instance methods for all of these. + # + # The structure is good if you need to group things together; the downside is that + # keeping data integrity is a pain, and both adding and removing an entry + # require a full table write. + # + # This sets up a before_destroy trigger to prune the tree correctly if one of its + # elements gets deleted. + # + module ClassMethods + # Configuration options are: + # + # * +parent_column+ - specifies the column name to use for keeping the position integer (default: parent_id) + # * +left_column+ - column name for left boundry data, default "lft" + # * +right_column+ - column name for right boundry data, default "rgt" + # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach "_id" + # (if that hasn't been already) and use that as the foreign key restriction. It's also possible + # to give it an entire string that is interpolated if you need a tighter scope than just a foreign key. + # Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt> + def acts_as_nested_set(options = {}) + configuration = { :parent_column => "parent_id", :left_column => "lft", :right_column => "rgt", :scope => "1 = 1" } + + configuration.update(options) if options.is_a?(Hash) + + configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/ + + if configuration[:scope].is_a?(Symbol) + scope_condition_method = %( + def scope_condition + if #{configuration[:scope].to_s}.nil? + "#{configuration[:scope].to_s} IS NULL" + else + "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}" + end + end + ) + else + scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end" + end + + class_eval <<-EOV + include ActiveRecord::Acts::NestedSet::InstanceMethods + + #{scope_condition_method} + + def left_col_name() "#{configuration[:left_column]}" end + + def right_col_name() "#{configuration[:right_column]}" end + + def parent_column() "#{configuration[:parent_column]}" end + + EOV + end + end + + module InstanceMethods + # Returns true is this is a root node. + def root? + parent_id = self[parent_column] + (parent_id == 0 || parent_id.nil?) && (self[left_col_name] == 1) && (self[right_col_name] > self[left_col_name]) + end + + # Returns true is this is a child node + def child? + parent_id = self[parent_column] + !(parent_id == 0 || parent_id.nil?) && (self[left_col_name] > 1) && (self[right_col_name] > self[left_col_name]) + end + + # Returns true if we have no idea what this is + def unknown? + !root? && !child? + end + + + # Adds a child to this object in the tree. If this object hasn't been initialized, + # it gets set up as a root node. Otherwise, this method will update all of the + # other elements in the tree and shift them to the right, keeping everything + # balanced. + def add_child( child ) + self.reload + child.reload + + if child.root? + raise "Adding sub-tree isn\'t currently supported" + else + if ( (self[left_col_name] == nil) || (self[right_col_name] == nil) ) + # Looks like we're now the root node! Woo + self[left_col_name] = 1 + self[right_col_name] = 4 + + # What do to do about validation? + return nil unless self.save + + child[parent_column] = self.id + child[left_col_name] = 2 + child[right_col_name]= 3 + return child.save + else + # OK, we need to add and shift everything else to the right + child[parent_column] = self.id + right_bound = self[right_col_name] + child[left_col_name] = right_bound + child[right_col_name] = right_bound + 1 + self[right_col_name] += 2 + self.class.transaction { + self.class.update_all( "#{left_col_name} = (#{left_col_name} + 2)", "#{scope_condition} AND #{left_col_name} >= #{right_bound}" ) + self.class.update_all( "#{right_col_name} = (#{right_col_name} + 2)", "#{scope_condition} AND #{right_col_name} >= #{right_bound}" ) + self.save + child.save + } + end + end + end + + # Returns the number of nested children of this object. + def children_count + return (self[right_col_name] - self[left_col_name] - 1)/2 + end + + # Returns a set of itself and all of its nested children + def full_set + self.class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} BETWEEN #{self[left_col_name]} and #{self[right_col_name]})" ) + end + + # Returns a set of all of its children and nested children + def all_children + self.class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} > #{self[left_col_name]}) and (#{right_col_name} < #{self[right_col_name]})" ) + end + + # Returns a set of only this entry's immediate children + def direct_children + self.class.find(:all, :conditions => "#{scope_condition} and #{parent_column} = #{self.id}") + end + + # Prunes a branch off of the tree, shifting all of the elements on the right + # back to the left so the counts still work. + def before_destroy + return if self[right_col_name].nil? || self[left_col_name].nil? + dif = self[right_col_name] - self[left_col_name] + 1 + + self.class.transaction { + self.class.delete_all( "#{scope_condition} and #{left_col_name} > #{self[left_col_name]} and #{right_col_name} < #{self[right_col_name]}" ) + self.class.update_all( "#{left_col_name} = (#{left_col_name} - #{dif})", "#{scope_condition} AND #{left_col_name} >= #{self[right_col_name]}" ) + self.class.update_all( "#{right_col_name} = (#{right_col_name} - #{dif} )", "#{scope_condition} AND #{right_col_name} >= #{self[right_col_name]}" ) + } + end + end + end + end +end +module ActiveRecord + module Acts #:nodoc: + module Tree #:nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # Specify this act if you want to model a tree structure by providing a parent association and a children + # association. This act requires that you have a foreign key column, which by default is called parent_id. + # + # class Category < ActiveRecord::Base + # acts_as_tree :order => "name" + # end + # + # Example : + # root + # \_ child1 + # \_ subchild1 + # \_ subchild2 + # + # root = Category.create("name" => "root") + # child1 = root.children.create("name" => "child1") + # subchild1 = child1.children.create("name" => "subchild1") + # + # root.parent # => nil + # child1.parent # => root + # root.children # => [child1] + # root.children.first.children.first # => subchild1 + # + # In addition to the parent and children associations, the following instance methods are added to the class + # after specifying the act: + # * siblings : Returns all the children of the parent, excluding the current node ([ subchild2 ] when called from subchild1) + # * self_and_siblings : Returns all the children of the parent, including the current node ([ subchild1, subchild2 ] when called from subchild1) + # * ancestors : Returns all the ancestors of the current node ([child1, root] when called from subchild2) + # * root : Returns the root of the current node (root when called from subchild2) + module ClassMethods + # Configuration options are: + # + # * <tt>foreign_key</tt> - specifies the column name to use for tracking of the tree (default: parent_id) + # * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet. + # * <tt>counter_cache</tt> - keeps a count in a children_count column if set to true (default: false). + def acts_as_tree(options = {}) + configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil } + configuration.update(options) if options.is_a?(Hash) + + belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache] + has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => :destroy + + class_eval <<-EOV + include ActiveRecord::Acts::Tree::InstanceMethods + + def self.roots + find(:all, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}) + end + + def self.root + find(:first, :conditions => "#{configuration[:foreign_key]} IS NULL", :order => #{configuration[:order].nil? ? "nil" : %Q{"#{configuration[:order]}"}}) + end + EOV + end + end + + module InstanceMethods + # Returns list of ancestors, starting from parent until root. + # + # subchild1.ancestors # => [child1, root] + def ancestors + node, nodes = self, [] + nodes << node = node.parent until not node.has_parent? + nodes + end + + def root + node = self + node = node.parent until not node.has_parent? + node + end + + def siblings + self_and_siblings - [self] + end + + def self_and_siblings + has_parent? ? parent.children : self.class.roots + end + end + end + end +end +module ActiveRecord + module Aggregations # :nodoc: + def self.included(base) + base.extend(ClassMethods) + end + + def clear_aggregation_cache #:nodoc: + self.class.reflect_on_all_aggregations.to_a.each do |assoc| + instance_variable_set "@#{assoc.name}", nil + end unless self.new_record? + end + + # Active Record implements aggregation through a macro-like class method called +composed_of+ for representing attributes + # as value objects. It expresses relationships like "Account [is] composed of Money [among other things]" or "Person [is] + # composed of [an] address". Each call to the macro adds a description of how the value objects are created from the + # attributes of the entity object (when the entity is initialized either as a new object or from finding an existing object) + # and how it can be turned back into attributes (when the entity is saved to the database). Example: + # + # class Customer < ActiveRecord::Base + # composed_of :balance, :class_name => "Money", :mapping => %w(balance amount) + # composed_of :address, :mapping => [ %w(address_street street), %w(address_city city) ] + # end + # + # The customer class now has the following methods to manipulate the value objects: + # * <tt>Customer#balance, Customer#balance=(money)</tt> + # * <tt>Customer#address, Customer#address=(address)</tt> + # + # These methods will operate with value objects like the ones described below: + # + # class Money + # include Comparable + # attr_reader :amount, :currency + # EXCHANGE_RATES = { "USD_TO_DKK" => 6 } + # + # def initialize(amount, currency = "USD") + # @amount, @currency = amount, currency + # end + # + # def exchange_to(other_currency) + # exchanged_amount = (amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]).floor + # Money.new(exchanged_amount, other_currency) + # end + # + # def ==(other_money) + # amount == other_money.amount && currency == other_money.currency + # end + # + # def <=>(other_money) + # if currency == other_money.currency + # amount <=> amount + # else + # amount <=> other_money.exchange_to(currency).amount + # end + # end + # end + # + # class Address + # attr_reader :street, :city + # def initialize(street, city) + # @street, @city = street, city + # end + # + # def close_to?(other_address) + # city == other_address.city + # end + # + # def ==(other_address) + # city == other_address.city && street == other_address.street + # end + # end + # + # Now it's possible to access attributes from the database through the value objects instead. If you choose to name the + # composition the same as the attributes name, it will be the only way to access that attribute. That's the case with our + # +balance+ attribute. You interact with the value objects just like you would any other attribute, though: + # + # customer.balance = Money.new(20) # sets the Money value object and the attribute + # customer.balance # => Money value object + # customer.balance.exchanged_to("DKK") # => Money.new(120, "DKK") + # customer.balance > Money.new(10) # => true + # customer.balance == Money.new(20) # => true + # customer.balance < Money.new(5) # => false + # + # Value objects can also be composed of multiple attributes, such as the case of Address. The order of the mappings will + # determine the order of the parameters. Example: + # + # customer.address_street = "Hyancintvej" + # customer.address_city = "Copenhagen" + # customer.address # => Address.new("Hyancintvej", "Copenhagen") + # customer.address = Address.new("May Street", "Chicago") + # customer.address_street # => "May Street" + # customer.address_city # => "Chicago" + # + # == Writing value objects + # + # Value objects are immutable and interchangeable objects that represent a given value, such as a Money object representing + # $5. Two Money objects both representing $5 should be equal (through methods such as == and <=> from Comparable if ranking + # makes sense). This is unlike entity objects where equality is determined by identity. An entity class such as Customer can + # easily have two different objects that both have an address on Hyancintvej. Entity identity is determined by object or + # relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects. + # + # It's also important to treat the value objects as immutable. Don't allow the Money object to have its amount changed after + # creation. Create a new money object with the new value instead. This is exemplified by the Money#exchanged_to method that + # returns a new value object instead of changing its own values. Active Record won't persist value objects that have been + # changed through other means than the writer method. + # + # The immutable requirement is enforced by Active Record by freezing any object assigned as a value object. Attempting to + # change it afterwards will result in a TypeError. + # + # Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not keeping value objects + # immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable + module ClassMethods + # Adds the a reader and writer method for manipulating a value object, so + # <tt>composed_of :address</tt> would add <tt>address</tt> and <tt>address=(new_address)</tt>. + # + # Options are: + # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred + # from the part id. So <tt>composed_of :address</tt> will by default be linked to the +Address+ class, but + # if the real class name is +CompanyAddress+, you'll have to specify it with this option. + # * <tt>:mapping</tt> - specifies a number of mapping arrays (attribute, parameter) that bind an attribute name + # to a constructor parameter on the value class. + # + # Option examples: + # composed_of :temperature, :mapping => %w(reading celsius) + # composed_of :balance, :class_name => "Money", :mapping => %w(balance amount) + # composed_of :address, :mapping => [ %w(address_street street), %w(address_city city) ] + # composed_of :gps_location + def composed_of(part_id, options = {}) + options.assert_valid_keys(:class_name, :mapping) + + name = part_id.id2name + class_name = options[:class_name] || name_to_class_name(name) + mapping = options[:mapping] || [ name, name ] + + reader_method(name, class_name, mapping) + writer_method(name, class_name, mapping) + + create_reflection(:composed_of, part_id, options, self) + end + + private + def name_to_class_name(name) + name.capitalize.gsub(/_(.)/) { |s| $1.capitalize } + end + + def reader_method(name, class_name, mapping) + module_eval <<-end_eval + def #{name}(force_reload = false) + if @#{name}.nil? || force_reload + @#{name} = #{class_name}.new(#{(Array === mapping.first ? mapping : [ mapping ]).collect{ |pair| "read_attribute(\"#{pair.first}\")"}.join(", ")}) + end + + return @#{name} + end + end_eval + end + + def writer_method(name, class_name, mapping) + module_eval <<-end_eval + def #{name}=(part) + @#{name} = part.freeze + #{(Array === mapping.first ? mapping : [ mapping ]).collect{ |pair| "@attributes[\"#{pair.first}\"] = part.#{pair.last}" }.join("\n")} + end + end_eval + end + end + end +end +require 'set' + +module ActiveRecord + module Associations + class AssociationCollection < AssociationProxy #:nodoc: + def to_ary + load_target + @target.to_ary + end + + def reset + @target = [] + @loaded = false + end + + # Add +records+ to this association. Returns +self+ so method calls may be chained. + # Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically. + def <<(*records) + result = true + load_target + + @owner.transaction do + flatten_deeper(records).each do |record| + raise_on_type_mismatch(record) + callback(:before_add, record) + result &&= insert_record(record) unless @owner.new_record? + @target << record + callback(:after_add, record) + end + end + + result && self + end + + alias_method :push, :<< + alias_method :concat, :<< + + # Remove all records from this association + def delete_all + load_target + delete(@target) + @target = [] + end + + # Remove +records+ from this association. Does not destroy +records+. + def delete(*records) + records = flatten_deeper(records) + records.each { |record| raise_on_type_mismatch(record) } + records.reject! { |record| @target.delete(record) if record.new_record? } + return if records.empty? + + @owner.transaction do + records.each { |record| callback(:before_remove, record) } + delete_records(records) + records.each do |record| + @target.delete(record) + callback(:after_remove, record) + end + end + end + + # Removes all records from this association. Returns +self+ so method calls may be chained. + def clear + return self if length.zero? # forces load_target if hasn't happened already + + if @reflection.options[:dependent] && @reflection.options[:dependent] == :delete_all + destroy_all + else + delete_all + end + + self + end + + def destroy_all + @owner.transaction do + each { |record| record.destroy } + end + + @target = [] + end + + def create(attributes = {}) + # Can't use Base.create since the foreign key may be a protected attribute. + if attributes.is_a?(Array) + attributes.collect { |attr| create(attr) } + else + record = build(attributes) + record.save unless @owner.new_record? + record + end + end + + # Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been loaded and + # calling collection.size if it has. If it's more likely than not that the collection does have a size larger than zero + # and you need to fetch that collection afterwards, it'll take one less SELECT query if you use length. + def size + if loaded? then @target.size else count_records end + end + + # Returns the size of the collection by loading it and calling size on the array. If you want to use this method to check + # whether the collection is empty, use collection.length.zero? instead of collection.empty? + def length + load_target.size + end + + def empty? + size.zero? + end + + def uniq(collection = self) + collection.inject([]) { |uniq_records, record| uniq_records << record unless uniq_records.include?(record); uniq_records } + end + + # Replace this collection with +other_array+ + # This will perform a diff and delete/add only records that have changed. + def replace(other_array) + other_array.each { |val| raise_on_type_mismatch(val) } + + load_target + other = other_array.size < 100 ? other_array : other_array.to_set + current = @target.size < 100 ? @target : @target.to_set + + @owner.transaction do + delete(@target.select { |v| !other.include?(v) }) + concat(other_array.select { |v| !current.include?(v) }) + end + end + + private + # Array#flatten has problems with recursive arrays. Going one level deeper solves the majority of the problems. + def flatten_deeper(array) + array.collect { |element| element.respond_to?(:flatten) ? element.flatten : element }.flatten + end + + def callback(method, record) + callbacks_for(method).each do |callback| + case callback + when Symbol + @owner.send(callback, record) + when Proc, Method + callback.call(@owner, record) + else + if callback.respond_to?(method) + callback.send(method, @owner, record) + else + raise ActiveRecordError, "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method." + end + end + end + end + + def callbacks_for(callback_name) + full_callback_name = "#{callback_name}_for_#{@reflection.name}" + @owner.class.read_inheritable_attribute(full_callback_name.to_sym) || [] + end + + end + end +end +module ActiveRecord + module Associations + class AssociationProxy #:nodoc: + attr_reader :reflection + alias_method :proxy_respond_to?, :respond_to? + alias_method :proxy_extend, :extend + instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ } + + def initialize(owner, reflection) + @owner, @reflection = owner, reflection + proxy_extend(reflection.options[:extend]) if reflection.options[:extend] + reset + end + + def respond_to?(symbol, include_priv = false) + proxy_respond_to?(symbol, include_priv) || (load_target && @target.respond_to?(symbol, include_priv)) + end + + # Explicitly proxy === because the instance method removal above + # doesn't catch it. + def ===(other) + load_target + other === @target + end + + def aliased_table_name + @reflection.klass.table_name + end + + def conditions + @conditions ||= eval("%(#{@reflection.active_record.send :sanitize_sql, @reflection.options[:conditions]})") if @reflection.options[:conditions] + end + alias :sql_conditions :conditions + + def reset + @target = nil + @loaded = false + end + + def reload + reset + load_target + end + + def loaded? + @loaded + end + + def loaded + @loaded = true + end + + def target + @target + end + + def target=(target) + @target = target + loaded + end + + protected + def dependent? + @reflection.options[:dependent] || false + end + + def quoted_record_ids(records) + records.map { |record| record.quoted_id }.join(',') + end + + def interpolate_sql_options!(options, *keys) + keys.each { |key| options[key] &&= interpolate_sql(options[key]) } + end + + def interpolate_sql(sql, record = nil) + @owner.send(:interpolate_sql, sql, record) + end + + def sanitize_sql(sql) + @reflection.klass.send(:sanitize_sql, sql) + end + + def extract_options_from_args!(args) + @owner.send(:extract_options_from_args!, args) + end + + def set_belongs_to_association_for(record) + if @reflection.options[:as] + record["#{@reflection.options[:as]}_id"] = @owner.id unless @owner.new_record? + record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s + else + record[@reflection.primary_key_name] = @owner.id unless @owner.new_record? + end + end + + def merge_options_from_reflection!(options) + options.reverse_merge!( + :group => @reflection.options[:group], + :limit => @reflection.options[:limit], + :offset => @reflection.options[:offset], + :joins => @reflection.options[:joins], + :include => @reflection.options[:include], + :select => @reflection.options[:select] + ) + end + + private + def method_missing(method, *args, &block) + load_target + @target.send(method, *args, &block) + end + + def load_target + if !@owner.new_record? || foreign_key_present + begin + @target = find_target if !loaded? + rescue ActiveRecord::RecordNotFound + reset + end + end + + loaded if target + target + end + + # Can be overwritten by associations that might have the foreign key available for an association without + # having the object itself (and still being a new record). Currently, only belongs_to present this scenario. + def foreign_key_present + false + end + + def raise_on_type_mismatch(record) + unless record.is_a?(@reflection.klass) + raise ActiveRecord::AssociationTypeMismatch, "#{@reflection.class_name} expected, got #{record.class}" + end + end + end + end +end +module ActiveRecord + module Associations + class BelongsToAssociation < AssociationProxy #:nodoc: + def create(attributes = {}) + replace(@reflection.klass.create(attributes)) + end + + def build(attributes = {}) + replace(@reflection.klass.new(attributes)) + end + + def replace(record) + counter_cache_name = @reflection.counter_cache_column + + if record.nil? + if counter_cache_name && @owner[counter_cache_name] && !@owner.new_record? + @reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name] + end + + @target = @owner[@reflection.primary_key_name] = nil + else + raise_on_type_mismatch(record) + + if counter_cache_name && !@owner.new_record? + @reflection.klass.increment_counter(counter_cache_name, record.id) + @reflection.klass.decrement_counter(counter_cache_name, @owner[@reflection.primary_key_name]) if @owner[@reflection.primary_key_name] + end + + @target = (AssociationProxy === record ? record.target : record) + @owner[@reflection.primary_key_name] = record.id unless record.new_record? + @updated = true + end + + loaded + record + end + + def updated? + @updated + end + + private + def find_target + @reflection.klass.find( + @owner[@reflection.primary_key_name], + :conditions => conditions, + :include => @reflection.options[:include] + ) + end + + def foreign_key_present + !@owner[@reflection.primary_key_name].nil? + end + end + end +end +module ActiveRecord + module Associations + class BelongsToPolymorphicAssociation < AssociationProxy #:nodoc: + def replace(record) + if record.nil? + @target = @owner[@reflection.primary_key_name] = @owner[@reflection.options[:foreign_type]] = nil + else + @target = (AssociationProxy === record ? record.target : record) + + unless record.new_record? + @owner[@reflection.primary_key_name] = record.id + @owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s + end + + @updated = true + end + + loaded + record + end + + def updated? + @updated + end + + private + def find_target + return nil if association_class.nil? + + if @reflection.options[:conditions] + association_class.find( + @owner[@reflection.primary_key_name], + :conditions => conditions, + :include => @reflection.options[:include] + ) + else + association_class.find(@owner[@reflection.primary_key_name], :include => @reflection.options[:include]) + end + end + + def foreign_key_present + !@owner[@reflection.primary_key_name].nil? + end + + def association_class + @owner[@reflection.options[:foreign_type]] ? @owner[@reflection.options[:foreign_type]].constantize : nil + end + end + end +end +module ActiveRecord + module Associations + class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc: + def initialize(owner, reflection) + super + construct_sql + end + + def build(attributes = {}) + load_target + record = @reflection.klass.new(attributes) + @target << record + record + end + + def find_first + load_target.first + end + + def find(*args) + options = Base.send(:extract_options_from_args!, args) + + # If using a custom finder_sql, scan the entire collection. + if @reflection.options[:finder_sql] + expects_array = args.first.kind_of?(Array) + ids = args.flatten.compact.uniq + + if ids.size == 1 + id = ids.first.to_i + record = load_target.detect { |record| id == record.id } + expects_array ? [record] : record + else + load_target.select { |record| ids.include?(record.id) } + end + else + conditions = "#{@finder_sql}" + + if sanitized_conditions = sanitize_sql(options[:conditions]) + conditions << " AND (#{sanitized_conditions})" + end + + options[:conditions] = conditions + options[:joins] = @join_sql + options[:readonly] = finding_with_ambigious_select?(options[:select]) + + if options[:order] && @reflection.options[:order] + options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" + elsif @reflection.options[:order] + options[:order] = @reflection.options[:order] + end + + merge_options_from_reflection!(options) + + # Pass through args exactly as we received them. + args << options + @reflection.klass.find(*args) + end + end + + def push_with_attributes(record, join_attributes = {}) + raise_on_type_mismatch(record) + join_attributes.each { |key, value| record[key.to_s] = value } + + callback(:before_add, record) + insert_record(record) unless @owner.new_record? + @target << record + callback(:after_add, record) + + self + end + + alias :concat_with_attributes :push_with_attributes + + def size + @reflection.options[:uniq] ? count_records : super + end + + protected + def method_missing(method, *args, &block) + if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) + super + else + @reflection.klass.with_scope(:find => { :conditions => @finder_sql, :joins => @join_sql, :readonly => false }) do + @reflection.klass.send(method, *args, &block) + end + end + end + + def find_target + if @reflection.options[:finder_sql] + records = @reflection.klass.find_by_sql(@finder_sql) + else + records = find(:all) + end + + @reflection.options[:uniq] ? uniq(records) : records + end + + def count_records + load_target.size + end + + def insert_record(record) + if record.new_record? + return false unless record.save + end + + if @reflection.options[:insert_sql] + @owner.connection.execute(interpolate_sql(@reflection.options[:insert_sql], record)) + else + columns = @owner.connection.columns(@reflection.options[:join_table], "#{@reflection.options[:join_table]} Columns") + + attributes = columns.inject({}) do |attributes, column| + case column.name + when @reflection.primary_key_name + attributes[column.name] = @owner.quoted_id + when @reflection.association_foreign_key + attributes[column.name] = record.quoted_id + else + if record.attributes.has_key?(column.name) + value = @owner.send(:quote, record[column.name], column) + attributes[column.name] = value unless value.nil? + end + end + attributes + end + + sql = + "INSERT INTO #{@reflection.options[:join_table]} (#{@owner.send(:quoted_column_names, attributes).join(', ')}) " + + "VALUES (#{attributes.values.join(', ')})" + + @owner.connection.execute(sql) + end + + return true + end + + def delete_records(records) + if sql = @reflection.options[:delete_sql] + records.each { |record| @owner.connection.execute(interpolate_sql(sql, record)) } + else + ids = quoted_record_ids(records) + sql = "DELETE FROM #{@reflection.options[:join_table]} WHERE #{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.association_foreign_key} IN (#{ids})" + @owner.connection.execute(sql) + end + end + + def construct_sql + interpolate_sql_options!(@reflection.options, :finder_sql) + + if @reflection.options[:finder_sql] + @finder_sql = @reflection.options[:finder_sql] + else + @finder_sql = "#{@reflection.options[:join_table]}.#{@reflection.primary_key_name} = #{@owner.quoted_id} " + @finder_sql << " AND (#{conditions})" if conditions + end + + @join_sql = "INNER JOIN #{@reflection.options[:join_table]} ON #{@reflection.klass.table_name}.#{@reflection.klass.primary_key} = #{@reflection.options[:join_table]}.#{@reflection.association_foreign_key}" + end + + # Join tables with additional columns on top of the two foreign keys must be considered ambigious unless a select + # clause has been explicitly defined. Otherwise you can get broken records back, if, say, the join column also has + # and id column, which will then overwrite the id column of the records coming back. + def finding_with_ambigious_select?(select_clause) + !select_clause && @owner.connection.columns(@reflection.options[:join_table], "Join Table Columns").size != 2 + end + end + end +end +module ActiveRecord + module Associations + class HasManyAssociation < AssociationCollection #:nodoc: + def initialize(owner, reflection) + super + construct_sql + end + + def build(attributes = {}) + if attributes.is_a?(Array) + attributes.collect { |attr| build(attr) } + else + load_target + record = @reflection.klass.new(attributes) + set_belongs_to_association_for(record) + @target << record + record + end + end + + # DEPRECATED. + def find_all(runtime_conditions = nil, orderings = nil, limit = nil, joins = nil) + if @reflection.options[:finder_sql] + @reflection.klass.find_by_sql(@finder_sql) + else + conditions = @finder_sql + conditions += " AND (#{sanitize_sql(runtime_conditions)})" if runtime_conditions + orderings ||= @reflection.options[:order] + @reflection.klass.find_all(conditions, orderings, limit, joins) + end + end + + # DEPRECATED. Find the first associated record. All arguments are optional. + def find_first(conditions = nil, orderings = nil) + find_all(conditions, orderings, 1).first + end + + # Count the number of associated records. All arguments are optional. + def count(runtime_conditions = nil) + if @reflection.options[:counter_sql] + @reflection.klass.count_by_sql(@counter_sql) + elsif @reflection.options[:finder_sql] + @reflection.klass.count_by_sql(@finder_sql) + else + sql = @finder_sql + sql += " AND (#{sanitize_sql(runtime_conditions)})" if runtime_conditions + @reflection.klass.count(sql) + end + end + + def find(*args) + options = Base.send(:extract_options_from_args!, args) + + # If using a custom finder_sql, scan the entire collection. + if @reflection.options[:finder_sql] + expects_array = args.first.kind_of?(Array) + ids = args.flatten.compact.uniq + + if ids.size == 1 + id = ids.first + record = load_target.detect { |record| id == record.id } + expects_array ? [ record ] : record + else + load_target.select { |record| ids.include?(record.id) } + end + else + conditions = "#{@finder_sql}" + if sanitized_conditions = sanitize_sql(options[:conditions]) + conditions << " AND (#{sanitized_conditions})" + end + options[:conditions] = conditions + + if options[:order] && @reflection.options[:order] + options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" + elsif @reflection.options[:order] + options[:order] = @reflection.options[:order] + end + + merge_options_from_reflection!(options) + + # Pass through args exactly as we received them. + args << options + @reflection.klass.find(*args) + end + end + + protected + def method_missing(method, *args, &block) + if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) + super + else + @reflection.klass.with_scope( + :find => { + :conditions => @finder_sql, + :joins => @join_sql, + :readonly => false + }, + :create => { + @reflection.primary_key_name => @owner.id + } + ) do + @reflection.klass.send(method, *args, &block) + end + end + end + + def find_target + if @reflection.options[:finder_sql] + @reflection.klass.find_by_sql(@finder_sql) + else + find(:all) + end + end + + def count_records + count = if has_cached_counter? + @owner.send(:read_attribute, cached_counter_attribute_name) + elsif @reflection.options[:counter_sql] + @reflection.klass.count_by_sql(@counter_sql) + else + @reflection.klass.count(@counter_sql) + end + + @target = [] and loaded if count == 0 + + if @reflection.options[:limit] + count = [ @reflection.options[:limit], count ].min + end + + return count + end + + def has_cached_counter? + @owner.attribute_present?(cached_counter_attribute_name) + end + + def cached_counter_attribute_name + "#{@reflection.name}_count" + end + + def insert_record(record) + set_belongs_to_association_for(record) + record.save + end + + def delete_records(records) + if @reflection.options[:dependent] + records.each { |r| r.destroy } + else + ids = quoted_record_ids(records) + @reflection.klass.update_all( + "#{@reflection.primary_key_name} = NULL", + "#{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.klass.primary_key} IN (#{ids})" + ) + end + end + + def target_obsolete? + false + end + + def construct_sql + case + when @reflection.options[:finder_sql] + @finder_sql = interpolate_sql(@reflection.options[:finder_sql]) + + when @reflection.options[:as] + @finder_sql = + "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " + + "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote @owner.class.base_class.name.to_s}" + @finder_sql << " AND (#{conditions})" if conditions + + else + @finder_sql = "#{@reflection.klass.table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" + @finder_sql << " AND (#{conditions})" if conditions + end + + if @reflection.options[:counter_sql] + @counter_sql = interpolate_sql(@reflection.options[:counter_sql]) + elsif @reflection.options[:finder_sql] + # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */ + @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" } + @counter_sql = interpolate_sql(@reflection.options[:counter_sql]) + else + @counter_sql = @finder_sql + end + end + end + end +end +module ActiveRecord + module Associations + class HasManyThroughAssociation < AssociationProxy #:nodoc: + def initialize(owner, reflection) + super + reflection.check_validity! + @finder_sql = construct_conditions + construct_sql + end + + + def find(*args) + options = Base.send(:extract_options_from_args!, args) + + conditions = "#{@finder_sql}" + if sanitized_conditions = sanitize_sql(options[:conditions]) + conditions << " AND (#{sanitized_conditions})" + end + options[:conditions] = conditions + + if options[:order] && @reflection.options[:order] + options[:order] = "#{options[:order]}, #{@reflection.options[:order]}" + elsif @reflection.options[:order] + options[:order] = @reflection.options[:order] + end + + options[:select] = construct_select(options[:select]) + options[:from] ||= construct_from + options[:joins] = construct_joins(options[:joins]) + options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil? + + merge_options_from_reflection!(options) + + # Pass through args exactly as we received them. + args << options + @reflection.klass.find(*args) + end + + def reset + @target = [] + @loaded = false + end + + protected + def method_missing(method, *args, &block) + if @target.respond_to?(method) || (!@reflection.klass.respond_to?(method) && Class.respond_to?(method)) + super + else + @reflection.klass.with_scope(construct_scope) { @reflection.klass.send(method, *args, &block) } + end + end + + def find_target + @reflection.klass.find(:all, + :select => construct_select, + :conditions => construct_conditions, + :from => construct_from, + :joins => construct_joins, + :order => @reflection.options[:order], + :limit => @reflection.options[:limit], + :group => @reflection.options[:group], + :include => @reflection.options[:include] || @reflection.source_reflection.options[:include] + ) + end + + def construct_conditions + conditions = if @reflection.through_reflection.options[:as] + "#{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.options[:as]}_id = #{@owner.quoted_id} " + + "AND #{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.options[:as]}_type = #{@owner.class.quote @owner.class.base_class.name.to_s}" + else + "#{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.primary_key_name} = #{@owner.quoted_id}" + end + conditions << " AND (#{sql_conditions})" if sql_conditions + + return conditions + end + + def construct_from + @reflection.table_name + end + + def construct_select(custom_select = nil) + selected = custom_select || @reflection.options[:select] || "#{@reflection.table_name}.*" + end + + def construct_joins(custom_joins = nil) + polymorphic_join = nil + if @reflection.through_reflection.options[:as] || @reflection.source_reflection.macro == :belongs_to + reflection_primary_key = @reflection.klass.primary_key + source_primary_key = @reflection.source_reflection.primary_key_name + else + reflection_primary_key = @reflection.source_reflection.primary_key_name + source_primary_key = @reflection.klass.primary_key + if @reflection.source_reflection.options[:as] + polymorphic_join = "AND %s.%s = %s" % [ + @reflection.table_name, "#{@reflection.source_reflection.options[:as]}_type", + @owner.class.quote(@reflection.through_reflection.klass.name) + ] + end + end + + "INNER JOIN %s ON %s.%s = %s.%s %s #{@reflection.options[:joins]} #{custom_joins}" % [ + @reflection.through_reflection.table_name, + @reflection.table_name, reflection_primary_key, + @reflection.through_reflection.table_name, source_primary_key, + polymorphic_join + ] + end + + def construct_scope + { + :find => { :from => construct_from, :conditions => construct_conditions, :joins => construct_joins, :select => construct_select }, + :create => { @reflection.primary_key_name => @owner.id } + } + end + + def construct_sql + case + when @reflection.options[:finder_sql] + @finder_sql = interpolate_sql(@reflection.options[:finder_sql]) + + @finder_sql = "#{@reflection.klass.table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" + @finder_sql << " AND (#{conditions})" if conditions + end + + if @reflection.options[:counter_sql] + @counter_sql = interpolate_sql(@reflection.options[:counter_sql]) + elsif @reflection.options[:finder_sql] + # replace the SELECT clause with COUNT(*), preserving any hints within /* ... */ + @reflection.options[:counter_sql] = @reflection.options[:finder_sql].sub(/SELECT (\/\*.*?\*\/ )?(.*)\bFROM\b/im) { "SELECT #{$1}COUNT(*) FROM" } + @counter_sql = interpolate_sql(@reflection.options[:counter_sql]) + else + @counter_sql = @finder_sql + end + end + + def conditions + @conditions ||= [ + (interpolate_sql(@reflection.active_record.send(:sanitize_sql, @reflection.options[:conditions])) if @reflection.options[:conditions]), + (interpolate_sql(@reflection.active_record.send(:sanitize_sql, @reflection.through_reflection.options[:conditions])) if @reflection.through_reflection.options[:conditions]) + ].compact.collect { |condition| "(#{condition})" }.join(' AND ') unless (!@reflection.options[:conditions] && !@reflection.through_reflection.options[:conditions]) + end + + alias_method :sql_conditions, :conditions + end + end +end +module ActiveRecord + module Associations + class HasOneAssociation < BelongsToAssociation #:nodoc: + def initialize(owner, reflection) + super + construct_sql + end + + def create(attributes = {}, replace_existing = true) + record = build(attributes, replace_existing) + record.save + record + end + + def build(attributes = {}, replace_existing = true) + record = @reflection.klass.new(attributes) + + if replace_existing + replace(record, true) + else + record[@reflection.primary_key_name] = @owner.id unless @owner.new_record? + self.target = record + end + + record + end + + def replace(obj, dont_save = false) + load_target + + unless @target.nil? + if dependent? && !dont_save && @target != obj + @target.destroy unless @target.new_record? + @owner.clear_association_cache + else + @target[@reflection.primary_key_name] = nil + @target.save unless @owner.new_record? || @target.new_record? + end + end + + if obj.nil? + @target = nil + else + raise_on_type_mismatch(obj) + set_belongs_to_association_for(obj) + @target = (AssociationProxy === obj ? obj.target : obj) + end + + @loaded = true + + unless @owner.new_record? or obj.nil? or dont_save + return (obj.save ? self : false) + else + return (obj.nil? ? nil : self) + end + end + + private + def find_target + @reflection.klass.find(:first, + :conditions => @finder_sql, + :order => @reflection.options[:order], + :include => @reflection.options[:include] + ) + end + + def construct_sql + case + when @reflection.options[:as] + @finder_sql = + "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_id = #{@owner.quoted_id} AND " + + "#{@reflection.klass.table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote @owner.class.base_class.name.to_s}" + else + @finder_sql = "#{@reflection.table_name}.#{@reflection.primary_key_name} = #{@owner.quoted_id}" + end + @finder_sql << " AND (#{conditions})" if conditions + end + end + end +end +require 'active_record/associations/association_proxy' +require 'active_record/associations/association_collection' +require 'active_record/associations/belongs_to_association' +require 'active_record/associations/belongs_to_polymorphic_association' +require 'active_record/associations/has_one_association' +require 'active_record/associations/has_many_association' +require 'active_record/associations/has_many_through_association' +require 'active_record/associations/has_and_belongs_to_many_association' +require 'active_record/deprecated_associations' + +module ActiveRecord + class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc: + def initialize(reflection) + @reflection = reflection + end + + def message + "Could not find the association #{@reflection.options[:through].inspect} in model #{@reflection.klass}" + end + end + + class HasManyThroughAssociationPolymorphicError < ActiveRecordError #:nodoc: + def initialize(owner_class_name, reflection, source_reflection) + @owner_class_name = owner_class_name + @reflection = reflection + @source_reflection = source_reflection + end + + def message + "Cannot have a has_many :through association '#{@owner_class_name}##{@reflection.name}' on the polymorphic object '#{@source_reflection.class_name}##{@source_reflection.name}'." + end + end + + class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc: + def initialize(reflection) + @reflection = reflection + @through_reflection = reflection.through_reflection + @source_reflection_names = reflection.source_reflection_names + @source_associations = reflection.through_reflection.klass.reflect_on_all_associations.collect { |a| a.name.inspect } + end + + def message + "Could not find the source association(s) #{@source_reflection_names.collect(&:inspect).to_sentence :connector => 'or'} in model #{@through_reflection.klass}. Try 'has_many #{@reflection.name.inspect}, :through => #{@through_reflection.name.inspect}, :source => <name>'. Is it one of #{@source_associations.to_sentence :connector => 'or'}?" + end + end + + class HasManyThroughSourceAssociationMacroError < ActiveRecordError #:nodoc + def initialize(reflection) + @reflection = reflection + @through_reflection = reflection.through_reflection + @source_reflection = reflection.source_reflection + end + + def message + "Invalid source reflection macro :#{@source_reflection.macro}#{" :through" if @source_reflection.options[:through]} for has_many #{@reflection.name.inspect}, :through => #{@through_reflection.name.inspect}. Use :source to specify the source reflection." + end + end + + class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: + def initialize(reflection) + @reflection = reflection + end + + def message + "Can not eagerly load the polymorphic association #{@reflection.name.inspect}" + end + end + + module Associations # :nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + # Clears out the association cache + def clear_association_cache #:nodoc: + self.class.reflect_on_all_associations.to_a.each do |assoc| + instance_variable_set "@#{assoc.name}", nil + end unless self.new_record? + end + + # Associations are a set of macro-like class methods for tying objects together through foreign keys. They express relationships like + # "Project has one Project Manager" or "Project belongs to a Portfolio". Each macro adds a number of methods to the class which are + # specialized according to the collection or association symbol and the options hash. It works much the same way as Ruby's own attr* + # methods. Example: + # + # class Project < ActiveRecord::Base + # belongs_to :portfolio + # has_one :project_manager + # has_many :milestones + # has_and_belongs_to_many :categories + # end + # + # The project class now has the following methods (and more) to ease the traversal and manipulation of its relationships: + # * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt> + # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt> + # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt> + # <tt>Project#milestones.delete(milestone), Project#milestones.find(milestone_id), Project#milestones.find_all(conditions),</tt> + # <tt>Project#milestones.build, Project#milestones.create</tt> + # * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt> + # <tt>Project#categories.delete(category1)</tt> + # + # == Example + # + # link:files/examples/associations.png + # + # == Is it belongs_to or has_one? + # + # Both express a 1-1 relationship, the difference is mostly where to place the foreign key, which goes on the table for the class + # saying belongs_to. Example: + # + # class Post < ActiveRecord::Base + # has_one :author + # end + # + # class Author < ActiveRecord::Base + # belongs_to :post + # end + # + # The tables for these classes could look something like: + # + # CREATE TABLE posts ( + # id int(11) NOT NULL auto_increment, + # title varchar default NULL, + # PRIMARY KEY (id) + # ) + # + # CREATE TABLE authors ( + # id int(11) NOT NULL auto_increment, + # post_id int(11) default NULL, + # name varchar default NULL, + # PRIMARY KEY (id) + # ) + # + # == Unsaved objects and associations + # + # You can manipulate objects and associations before they are saved to the database, but there is some special behaviour you should be + # aware of, mostly involving the saving of associated objects. + # + # === One-to-one associations + # + # * Assigning an object to a has_one association automatically saves that object and the object being replaced (if there is one), in + # order to update their primary keys - except if the parent object is unsaved (new_record? == true). + # * If either of these saves fail (due to one of the objects being invalid) the assignment statement returns false and the assignment + # is cancelled. + # * If you wish to assign an object to a has_one association without saving it, use the #association.build method (documented below). + # * Assigning an object to a belongs_to association does not save the object, since the foreign key field belongs on the parent. It does + # not save the parent either. + # + # === Collections + # + # * Adding an object to a collection (has_many or has_and_belongs_to_many) automatically saves that object, except if the parent object + # (the owner of the collection) is not yet stored in the database. + # * If saving any of the objects being added to a collection (via #push or similar) fails, then #push returns false. + # * You can add an object to a collection without automatically saving it by using the #collection.build method (documented below). + # * All unsaved (new_record? == true) members of the collection are automatically saved when the parent is saved. + # + # === Association callbacks + # + # Similiar to the normal callbacks that hook into the lifecycle of an Active Record object, you can also define callbacks that get + # trigged when you add an object to or removing an object from a association collection. Example: + # + # class Project + # has_and_belongs_to_many :developers, :after_add => :evaluate_velocity + # + # def evaluate_velocity(developer) + # ... + # end + # end + # + # It's possible to stack callbacks by passing them as an array. Example: + # + # class Project + # has_and_belongs_to_many :developers, :after_add => [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}] + # end + # + # Possible callbacks are: before_add, after_add, before_remove and after_remove. + # + # Should any of the before_add callbacks throw an exception, the object does not get added to the collection. Same with + # the before_remove callbacks, if an exception is thrown the object doesn't get removed. + # + # === Association extensions + # + # The proxy objects that controls the access to associations can be extended through anonymous modules. This is especially + # beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association. + # Example: + # + # class Account < ActiveRecord::Base + # has_many :people do + # def find_or_create_by_name(name) + # first_name, last_name = name.split(" ", 2) + # find_or_create_by_first_name_and_last_name(first_name, last_name) + # end + # end + # end + # + # person = Account.find(:first).people.find_or_create_by_name("David Heinemeier Hansson") + # person.first_name # => "David" + # person.last_name # => "Heinemeier Hansson" + # + # If you need to share the same extensions between many associations, you can use a named extension module. Example: + # + # module FindOrCreateByNameExtension + # def find_or_create_by_name(name) + # first_name, last_name = name.split(" ", 2) + # find_or_create_by_first_name_and_last_name(first_name, last_name) + # end + # end + # + # class Account < ActiveRecord::Base + # has_many :people, :extend => FindOrCreateByNameExtension + # end + # + # class Company < ActiveRecord::Base + # has_many :people, :extend => FindOrCreateByNameExtension + # end + # + # === Association Join Models + # + # Has Many associations can be configured with the :through option to use an explicit join model to retrieve the data. This + # operates similarly to a <tt>has_and_belongs_to_many</tt> association. The advantage is that you're able to add validations, + # callbacks, and extra attributes on the join model. Consider the following schema: + # + # class Author < ActiveRecord::Base + # has_many :authorships + # has_many :books, :through => :authorships + # end + # + # class Authorship < ActiveRecord::Base + # belongs_to :author + # belongs_to :book + # end + # + # @author = Author.find :first + # @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to. + # @author.books # selects all books by using the Authorship join model + # + # You can also go through a has_many association on the join model: + # + # class Firm < ActiveRecord::Base + # has_many :clients + # has_many :invoices, :through => :clients + # end + # + # class Client < ActiveRecord::Base + # belongs_to :firm + # has_many :invoices + # end + # + # class Invoice < ActiveRecord::Base + # belongs_to :client + # end + # + # @firm = Firm.find :first + # @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm + # @firm.invoices # selects all invoices by going through the Client join model. + # + # === Polymorphic Associations + # + # Polymorphic associations on models are not restricted on what types of models they can be associated with. Rather, they + # specify an interface that a has_many association must adhere to. + # + # class Asset < ActiveRecord::Base + # belongs_to :attachable, :polymorphic => true + # end + # + # class Post < ActiveRecord::Base + # has_many :assets, :as => :attachable # The <tt>:as</tt> option specifies the polymorphic interface to use. + # end + # + # @asset.attachable = @post + # + # This works by using a type column in addition to a foreign key to specify the associated record. In the Asset example, you'd need + # an attachable_id integer column and an attachable_type string column. + # + # == Caching + # + # All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically + # instructed not to. The cache is even shared across methods to make it even cheaper to use the macro-added methods without + # worrying too much about performance at the first go. Example: + # + # project.milestones # fetches milestones from the database + # project.milestones.size # uses the milestone cache + # project.milestones.empty? # uses the milestone cache + # project.milestones(true).size # fetches milestones from the database + # project.milestones # uses the milestone cache + # + # == Eager loading of associations + # + # Eager loading is a way to find objects of a certain class and a number of named associations along with it in a single SQL call. This is + # one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100 posts that each needs to display their author + # triggers 101 database queries. Through the use of eager loading, the 101 queries can be reduced to 1. Example: + # + # class Post < ActiveRecord::Base + # belongs_to :author + # has_many :comments + # end + # + # Consider the following loop using the class above: + # + # for post in Post.find(:all) + # puts "Post: " + post.title + # puts "Written by: " + post.author.name + # puts "Last comment on: " + post.comments.first.created_on + # end + # + # To iterate over these one hundred posts, we'll generate 201 database queries. Let's first just optimize it for retrieving the author: + # + # for post in Post.find(:all, :include => :author) + # + # This references the name of the belongs_to association that also used the :author symbol, so the find will now weave in a join something + # like this: LEFT OUTER JOIN authors ON authors.id = posts.author_id. Doing so will cut down the number of queries from 201 to 101. + # + # We can improve upon the situation further by referencing both associations in the finder with: + # + # for post in Post.find(:all, :include => [ :author, :comments ]) + # + # That'll add another join along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id. And we'll be down to 1 query. + # But that shouldn't fool you to think that you can pull out huge amounts of data with no performance penalty just because you've reduced + # the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no + # catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above. + # + # Please note that limited eager loading with has_many and has_and_belongs_to_many associations is not compatible with describing conditions + # on these eager tables. This will work: + # + # Post.find(:all, :include => :comments, :conditions => "posts.title = 'magic forest'", :limit => 2) + # + # ...but this will not (and an ArgumentError will be raised): + # + # Post.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%'", :limit => 2) + # + # Also have in mind that since the eager loading is pulling from multiple tables, you'll have to disambiguate any column references + # in both conditions and orders. So :order => "posts.id DESC" will work while :order => "id DESC" will not. This may require that + # you alter the :order and :conditions on the association definitions themselves. + # + # It's currently not possible to use eager loading on multiple associations from the same table. Eager loading will not pull + # additional attributes on join tables, so "rich associations" with has_and_belongs_to_many is not a good fit for eager loading. + # + # == Table Aliasing + # + # ActiveRecord uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once, + # the standard table name is used. The second time, the table is aliased as #{reflection_name}_#{parent_table_name}. Indexes are appended + # for any more successive uses of the table name. + # + # Post.find :all, :include => :comments + # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... + # Post.find :all, :include => :special_comments # STI + # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... AND comments.type = 'SpecialComment' + # Post.find :all, :include => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name + # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... LEFT OUTER JOIN comments special_comments_posts + # + # Acts as tree example: + # + # TreeMixin.find :all, :include => :children + # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... + # TreeMixin.find :all, :include => {:children => :parent} # using cascading eager includes + # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... + # LEFT OUTER JOIN parents_mixins ... + # TreeMixin.find :all, :include => {:children => {:parent => :children}} + # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... + # LEFT OUTER JOIN parents_mixins ... + # LEFT OUTER JOIN mixins childrens_mixins_2 + # + # Has and Belongs to Many join tables use the same idea, but add a _join suffix: + # + # Post.find :all, :include => :categories + # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... + # Post.find :all, :include => {:categories => :posts} + # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... + # LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories + # Post.find :all, :include => {:categories => {:posts => :categories}} + # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... + # LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories + # LEFT OUTER JOIN categories_posts categories_posts_join LEFT OUTER JOIN categories categories_posts + # + # If you wish to specify your own custom joins using a :joins option, those table names will take precedence over the eager associations.. + # + # Post.find :all, :include => :comments, :joins => "inner join comments ..." + # # => SELECT ... FROM posts LEFT OUTER JOIN comments_posts ON ... INNER JOIN comments ... + # Post.find :all, :include => [:comments, :special_comments], :joins => "inner join comments ..." + # # => SELECT ... FROM posts LEFT OUTER JOIN comments comments_posts ON ... + # LEFT OUTER JOIN comments special_comments_posts ... + # INNER JOIN comments ... + # + # Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database. + # + # == Modules + # + # By default, associations will look for objects within the current module scope. Consider: + # + # module MyApplication + # module Business + # class Firm < ActiveRecord::Base + # has_many :clients + # end + # + # class Company < ActiveRecord::Base; end + # end + # end + # + # When Firm#clients is called, it'll in turn call <tt>MyApplication::Business::Company.find(firm.id)</tt>. If you want to associate + # with a class in another module scope this can be done by specifying the complete class name, such as: + # + # module MyApplication + # module Business + # class Firm < ActiveRecord::Base; end + # end + # + # module Billing + # class Account < ActiveRecord::Base + # belongs_to :firm, :class_name => "MyApplication::Business::Firm" + # end + # end + # end + # + # == Type safety with ActiveRecord::AssociationTypeMismatch + # + # If you attempt to assign an object to an association that doesn't match the inferred or specified <tt>:class_name</tt>, you'll + # get a ActiveRecord::AssociationTypeMismatch. + # + # == Options + # + # All of the association macros can be specialized through options which makes more complex cases than the simple and guessable ones + # possible. + module ClassMethods + # Adds the following methods for retrieval and query of collections of associated objects. + # +collection+ is replaced with the symbol passed as the first argument, so + # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>. + # * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. + # An empty array is returned if none are found. + # * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by setting their foreign keys to the collection's primary key. + # * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by setting their foreign keys to NULL. + # This will also destroy the objects if they're declared as belongs_to and dependent on this model. + # * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate. + # * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+ + # * <tt>collection.clear</tt> - removes every object from the collection. This destroys the associated objects if they + # are <tt>:dependent</tt>, deletes them directly from the database if they are <tt>:dependent => :delete_all</tt>, + # and sets their foreign keys to NULL otherwise. + # * <tt>collection.empty?</tt> - returns true if there are no associated objects. + # * <tt>collection.size</tt> - returns the number of associated objects. + # * <tt>collection.find</tt> - finds an associated object according to the same rules as Base.find. + # * <tt>collection.build(attributes = {})</tt> - returns a new object of the collection type that has been instantiated + # with +attributes+ and linked to this object through a foreign key but has not yet been saved. *Note:* This only works if an + # associated object already exists, not if it's nil! + # * <tt>collection.create(attributes = {})</tt> - returns a new object of the collection type that has been instantiated + # with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation). + # *Note:* This only works if an associated object already exists, not if it's nil! + # + # Example: A Firm class declares <tt>has_many :clients</tt>, which will add: + # * <tt>Firm#clients</tt> (similar to <tt>Clients.find :all, :conditions => "firm_id = #{id}"</tt>) + # * <tt>Firm#clients<<</tt> + # * <tt>Firm#clients.delete</tt> + # * <tt>Firm#clients=</tt> + # * <tt>Firm#client_ids=</tt> + # * <tt>Firm#clients.clear</tt> + # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>) + # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>) + # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, :conditions => "firm_id = #{id}")</tt>) + # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>) + # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>) + # The declaration can also include an options hash to specialize the behavior of the association. + # + # Options are: + # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred + # from the association name. So <tt>has_many :products</tt> will by default be linked to the +Product+ class, but + # if the real class name is +SpecialProduct+, you'll have to specify it with this option. + # * <tt>:conditions</tt> - specify the conditions that the associated objects must meet in order to be included as a "WHERE" + # sql fragment, such as "price > 5 AND name LIKE 'B%'". + # * <tt>:order</tt> - specify the order in which the associated objects are returned as a "ORDER BY" sql fragment, + # such as "last_name, first_name DESC" + # * <tt>:group</tt> - specify the attribute by which the associated objects are returned as a "GROUP BY" sql fragment, + # such as "category" + # * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name + # of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_many association will use "person_id" + # as the default foreign_key. + # * <tt>:dependent</tt> - if set to :destroy all the associated objects are destroyed + # alongside this object by calling their destroy method. If set to :delete_all all associated + # objects are deleted *without* calling their destroy method. If set to :nullify all associated + # objects' foreign keys are set to NULL *without* calling their save callbacks. + # NOTE: :dependent => true is deprecated and has been replaced with :dependent => :destroy. + # May not be set if :exclusively_dependent is also set. + # * <tt>:exclusively_dependent</tt> - Deprecated; equivalent to :dependent => :delete_all. If set to true all + # the associated object are deleted in one SQL statement without having their + # before_destroy callback run. This should only be used on associations that depend solely on this class and don't need to do any + # clean-up in before_destroy. The upside is that it's much faster, especially if there's a counter_cache involved. + # May not be set if :dependent is also set. + # * <tt>:finder_sql</tt> - specify a complete SQL statement to fetch the association. This is a good way to go for complex + # associations that depend on multiple tables. Note: When this option is used, +find_in_collection+ is _not_ added. + # * <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If +:finder_sql+ is + # specified but +:counter_sql+, +:counter_sql+ will be generated by replacing SELECT ... FROM with SELECT COUNT(*) FROM. + # * <tt>:extend</tt> - specify a named module for extending the proxy, see "Association extensions". + # * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. + # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. + # * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. + # * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. + # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not + # include the joined columns. + # * <tt>:as</tt>: Specifies a polymorphic interface (See #belongs_to). + # * <tt>:through</tt>: Specifies a Join Model to perform the query through. Options for <tt>:class_name</tt> and <tt>:foreign_key</tt> + # are ignored, as the association uses the source reflection. You can only use a <tt>:through</tt> query through a <tt>belongs_to</tt> + # or <tt>has_many</tt> association. + # * <tt>:source</tt>: Specifies the source association name used by <tt>has_many :through</tt> queries. Only use it if the name cannot be + # inferred from the association. <tt>has_many :subscribers, :through => :subscriptions</tt> will look for either +:subscribers+ or + # +:subscriber+ on +Subscription+, unless a +:source+ is given. + # + # Option examples: + # has_many :comments, :order => "posted_on" + # has_many :comments, :include => :author + # has_many :people, :class_name => "Person", :conditions => "deleted = 0", :order => "name" + # has_many :tracks, :order => "position", :dependent => :destroy + # has_many :comments, :dependent => :nullify + # has_many :tags, :as => :taggable + # has_many :subscribers, :through => :subscriptions, :source => :user + # has_many :subscribers, :class_name => "Person", :finder_sql => + # 'SELECT DISTINCT people.* ' + + # 'FROM people p, post_subscriptions ps ' + + # 'WHERE ps.post_id = #{id} AND ps.person_id = p.id ' + + # 'ORDER BY p.first_name' + def has_many(association_id, options = {}, &extension) + reflection = create_has_many_reflection(association_id, options, &extension) + + configure_dependency_for_has_many(reflection) + + if options[:through] + collection_reader_method(reflection, HasManyThroughAssociation) + else + add_multiple_associated_save_callbacks(reflection.name) + add_association_callbacks(reflection.name, reflection.options) + collection_accessor_methods(reflection, HasManyAssociation) + end + + add_deprecated_api_for_has_many(reflection.name) + end + + # Adds the following methods for retrieval and query of a single associated object. + # +association+ is replaced with the symbol passed as the first argument, so + # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>. + # * <tt>association(force_reload = false)</tt> - returns the associated object. Nil is returned if none is found. + # * <tt>association=(associate)</tt> - assigns the associate object, extracts the primary key, sets it as the foreign key, + # and saves the associate object. + # * <tt>association.nil?</tt> - returns true if there is no associated object. + # * <tt>build_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated + # with +attributes+ and linked to this object through a foreign key but has not yet been saved. Note: This ONLY works if + # an association already exists. It will NOT work if the association is nil. + # * <tt>create_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated + # with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation). + # + # Example: An Account class declares <tt>has_one :beneficiary</tt>, which will add: + # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.find(:first, :conditions => "account_id = #{id}")</tt>) + # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>) + # * <tt>Account#beneficiary.nil?</tt> + # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>) + # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>) + # + # The declaration can also include an options hash to specialize the behavior of the association. + # + # Options are: + # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred + # from the association name. So <tt>has_one :manager</tt> will by default be linked to the +Manager+ class, but + # if the real class name is +Person+, you'll have to specify it with this option. + # * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE" + # sql fragment, such as "rank = 5". + # * <tt>:order</tt> - specify the order from which the associated object will be picked at the top. Specified as + # an "ORDER BY" sql fragment, such as "last_name, first_name DESC" + # * <tt>:dependent</tt> - if set to :destroy (or true) all the associated objects are destroyed when this object is. Also, + # association is assigned. + # * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name + # of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_one association will use "person_id" + # as the default foreign_key. + # * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. + # + # Option examples: + # has_one :credit_card, :dependent => :destroy # destroys the associated credit card + # has_one :credit_card, :dependent => :nullify # updates the associated records foriegn key value to null rather than destroying it + # has_one :last_comment, :class_name => "Comment", :order => "posted_on" + # has_one :project_manager, :class_name => "Person", :conditions => "role = 'project_manager'" + def has_one(association_id, options = {}) + reflection = create_has_one_reflection(association_id, options) + + module_eval do + after_save <<-EOF + association = instance_variable_get("@#{reflection.name}") + unless association.nil? + association["#{reflection.primary_key_name}"] = id + association.save(true) + end + EOF + end + + association_accessor_methods(reflection, HasOneAssociation) + association_constructor_method(:build, reflection, HasOneAssociation) + association_constructor_method(:create, reflection, HasOneAssociation) + + configure_dependency_for_has_one(reflection) + + # deprecated api + deprecated_has_association_method(reflection.name) + deprecated_association_comparison_method(reflection.name, reflection.class_name) + end + + # Adds the following methods for retrieval and query for a single associated object that this object holds an id to. + # +association+ is replaced with the symbol passed as the first argument, so + # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>. + # * <tt>association(force_reload = false)</tt> - returns the associated object. Nil is returned if none is found. + # * <tt>association=(associate)</tt> - assigns the associate object, extracts the primary key, and sets it as the foreign key. + # * <tt>association.nil?</tt> - returns true if there is no associated object. + # * <tt>build_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated + # with +attributes+ and linked to this object through a foreign key but has not yet been saved. + # * <tt>create_association(attributes = {})</tt> - returns a new object of the associated type that has been instantiated + # with +attributes+ and linked to this object through a foreign key and that has already been saved (if it passed the validation). + # + # Example: A Post class declares <tt>belongs_to :author</tt>, which will add: + # * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>) + # * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>) + # * <tt>Post#author?</tt> (similar to <tt>post.author == some_author</tt>) + # * <tt>Post#author.nil?</tt> + # * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>) + # * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>) + # The declaration can also include an options hash to specialize the behavior of the association. + # + # Options are: + # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred + # from the association name. So <tt>has_one :author</tt> will by default be linked to the +Author+ class, but + # if the real class name is +Person+, you'll have to specify it with this option. + # * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE" + # sql fragment, such as "authorized = 1". + # * <tt>:order</tt> - specify the order from which the associated object will be picked at the top. Specified as + # an "ORDER BY" sql fragment, such as "last_name, first_name DESC" + # * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name + # of the associated class in lower-case and "_id" suffixed. So a +Person+ class that makes a belongs_to association to a + # +Boss+ class will use "boss_id" as the default foreign_key. + # * <tt>:counter_cache</tt> - caches the number of belonging objects on the associate class through use of increment_counter + # and decrement_counter. The counter cache is incremented when an object of this class is created and decremented when it's + # destroyed. This requires that a column named "#{table_name}_count" (such as comments_count for a belonging Comment class) + # is used on the associate class (such as a Post class). You can also specify a custom counter cache column by given that + # name instead of a true/false value to this option (e.g., <tt>:counter_cache => :my_custom_counter</tt>.) + # * <tt>:include</tt> - specify second-order associations that should be eager loaded when this object is loaded. + # * <tt>:polymorphic</tt> - specify this association is a polymorphic association by passing true. + # + # Option examples: + # belongs_to :firm, :foreign_key => "client_of" + # belongs_to :author, :class_name => "Person", :foreign_key => "author_id" + # belongs_to :valid_coupon, :class_name => "Coupon", :foreign_key => "coupon_id", + # :conditions => 'discounts > #{payments_count}' + # belongs_to :attachable, :polymorphic => true + def belongs_to(association_id, options = {}) + reflection = create_belongs_to_reflection(association_id, options) + + if reflection.options[:polymorphic] + association_accessor_methods(reflection, BelongsToPolymorphicAssociation) + + module_eval do + before_save <<-EOF + association = instance_variable_get("@#{reflection.name}") + if !association.nil? + if association.new_record? + association.save(true) + end + + if association.updated? + self["#{reflection.primary_key_name}"] = association.id + self["#{reflection.options[:foreign_type]}"] = association.class.base_class.name.to_s + end + end + EOF + end + else + association_accessor_methods(reflection, BelongsToAssociation) + association_constructor_method(:build, reflection, BelongsToAssociation) + association_constructor_method(:create, reflection, BelongsToAssociation) + + module_eval do + before_save <<-EOF + association = instance_variable_get("@#{reflection.name}") + if !association.nil? + if association.new_record? + association.save(true) + end + + if association.updated? + self["#{reflection.primary_key_name}"] = association.id + end + end + EOF + end + + # deprecated api + deprecated_has_association_method(reflection.name) + deprecated_association_comparison_method(reflection.name, reflection.class_name) + end + + if options[:counter_cache] + cache_column = options[:counter_cache] == true ? + "#{self.to_s.underscore.pluralize}_count" : + options[:counter_cache] + + module_eval( + "after_create '#{reflection.name}.class.increment_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + + " unless #{reflection.name}.nil?'" + ) + + module_eval( + "before_destroy '#{reflection.name}.class.decrement_counter(\"#{cache_column}\", #{reflection.primary_key_name})" + + " unless #{reflection.name}.nil?'" + ) + end + end + + # Associates two classes via an intermediate join table. Unless the join table is explicitly specified as + # an option, it is guessed using the lexical order of the class names. So a join between Developer and Project + # will give the default join table name of "developers_projects" because "D" outranks "P". + # + # Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through + # has_and_belongs_to_many associations. Records returned from join tables with additional attributes will be marked as + # ReadOnly (because we can't save changes to the additional attrbutes). It's strongly recommended that you upgrade any + # associations with attributes to a real join model (see introduction). + # + # Adds the following methods for retrieval and query. + # +collection+ is replaced with the symbol passed as the first argument, so + # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>. + # * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects. + # An empty array is returned if none is found. + # * <tt>collection<<(object, ...)</tt> - adds one or more objects to the collection by creating associations in the join table + # (collection.push and collection.concat are aliases to this method). + # * <tt>collection.push_with_attributes(object, join_attributes)</tt> - adds one to the collection by creating an association in the join table that + # also holds the attributes from <tt>join_attributes</tt> (should be a hash with the column names as keys). This can be used to have additional + # attributes on the join, which will be injected into the associated objects when they are retrieved through the collection. + # (collection.concat_with_attributes is an alias to this method). This method is now deprecated. + # * <tt>collection.delete(object, ...)</tt> - removes one or more objects from the collection by removing their associations from the join table. + # This does not destroy the objects. + # * <tt>collection=objects</tt> - replaces the collections content by deleting and adding objects as appropriate. + # * <tt>collection_singular_ids=ids</tt> - replace the collection by the objects identified by the primary keys in +ids+ + # * <tt>collection.clear</tt> - removes every object from the collection. This does not destroy the objects. + # * <tt>collection.empty?</tt> - returns true if there are no associated objects. + # * <tt>collection.size</tt> - returns the number of associated objects. + # * <tt>collection.find(id)</tt> - finds an associated object responding to the +id+ and that + # meets the condition that it has to be associated with this object. + # + # Example: An Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add: + # * <tt>Developer#projects</tt> + # * <tt>Developer#projects<<</tt> + # * <tt>Developer#projects.push_with_attributes</tt> + # * <tt>Developer#projects.delete</tt> + # * <tt>Developer#projects=</tt> + # * <tt>Developer#project_ids=</tt> + # * <tt>Developer#projects.clear</tt> + # * <tt>Developer#projects.empty?</tt> + # * <tt>Developer#projects.size</tt> + # * <tt>Developer#projects.find(id)</tt> + # The declaration may include an options hash to specialize the behavior of the association. + # + # Options are: + # * <tt>:class_name</tt> - specify the class name of the association. Use it only if that name can't be inferred + # from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the + # +Project+ class, but if the real class name is +SuperProject+, you'll have to specify it with this option. + # * <tt>:join_table</tt> - specify the name of the join table if the default based on lexical order isn't what you want. + # WARNING: If you're overwriting the table name of either class, the table_name method MUST be declared underneath any + # has_and_belongs_to_many declaration in order to work. + # * <tt>:foreign_key</tt> - specify the foreign key used for the association. By default this is guessed to be the name + # of this class in lower-case and "_id" suffixed. So a +Person+ class that makes a has_and_belongs_to_many association + # will use "person_id" as the default foreign_key. + # * <tt>:association_foreign_key</tt> - specify the association foreign key used for the association. By default this is + # guessed to be the name of the associated class in lower-case and "_id" suffixed. So if the associated class is +Project+, + # the has_and_belongs_to_many association will use "project_id" as the default association foreign_key. + # * <tt>:conditions</tt> - specify the conditions that the associated object must meet in order to be included as a "WHERE" + # sql fragment, such as "authorized = 1". + # * <tt>:order</tt> - specify the order in which the associated objects are returned as a "ORDER BY" sql fragment, such as "last_name, first_name DESC" + # * <tt>:uniq</tt> - if set to true, duplicate associated objects will be ignored by accessors and query methods + # * <tt>:finder_sql</tt> - overwrite the default generated SQL used to fetch the association with a manual one + # * <tt>:delete_sql</tt> - overwrite the default generated SQL used to remove links between the associated + # classes with a manual one + # * <tt>:insert_sql</tt> - overwrite the default generated SQL used to add links between the associated classes + # with a manual one + # * <tt>:extend</tt> - anonymous module for extending the proxy, see "Association extensions". + # * <tt>:include</tt> - specify second-order associations that should be eager loaded when the collection is loaded. + # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. + # * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. + # * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. + # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not + # include the joined columns. + # + # Option examples: + # has_and_belongs_to_many :projects + # has_and_belongs_to_many :projects, :include => [ :milestones, :manager ] + # has_and_belongs_to_many :nations, :class_name => "Country" + # has_and_belongs_to_many :categories, :join_table => "prods_cats" + # has_and_belongs_to_many :active_projects, :join_table => 'developers_projects', :delete_sql => + # 'DELETE FROM developers_projects WHERE active=1 AND developer_id = #{id} AND project_id = #{record.id}' + def has_and_belongs_to_many(association_id, options = {}, &extension) + reflection = create_has_and_belongs_to_many_reflection(association_id, options, &extension) + + add_multiple_associated_save_callbacks(reflection.name) + collection_accessor_methods(reflection, HasAndBelongsToManyAssociation) + + # Don't use a before_destroy callback since users' before_destroy + # callbacks will be executed after the association is wiped out. + old_method = "destroy_without_habtm_shim_for_#{reflection.name}" + class_eval <<-end_eval + alias_method :#{old_method}, :destroy_without_callbacks + def destroy_without_callbacks + #{reflection.name}.clear + #{old_method} + end + end_eval + + add_association_callbacks(reflection.name, options) + + # deprecated api + deprecated_collection_count_method(reflection.name) + deprecated_add_association_relation(reflection.name) + deprecated_remove_association_relation(reflection.name) + deprecated_has_collection_method(reflection.name) + end + + private + def join_table_name(first_table_name, second_table_name) + if first_table_name < second_table_name + join_table = "#{first_table_name}_#{second_table_name}" + else + join_table = "#{second_table_name}_#{first_table_name}" + end + + table_name_prefix + join_table + table_name_suffix + end + + def association_accessor_methods(reflection, association_proxy_class) + define_method(reflection.name) do |*params| + force_reload = params.first unless params.empty? + association = instance_variable_get("@#{reflection.name}") + + if association.nil? || force_reload + association = association_proxy_class.new(self, reflection) + retval = association.reload + unless retval.nil? + instance_variable_set("@#{reflection.name}", association) + else + instance_variable_set("@#{reflection.name}", nil) + return nil + end + end + association + end + + define_method("#{reflection.name}=") do |new_value| + association = instance_variable_get("@#{reflection.name}") + if association.nil? + association = association_proxy_class.new(self, reflection) + end + + association.replace(new_value) + + unless new_value.nil? + instance_variable_set("@#{reflection.name}", association) + else + instance_variable_set("@#{reflection.name}", nil) + return nil + end + + association + end + + define_method("set_#{reflection.name}_target") do |target| + return if target.nil? + association = association_proxy_class.new(self, reflection) + association.target = target + instance_variable_set("@#{reflection.name}", association) + end + end + + def collection_reader_method(reflection, association_proxy_class) + define_method(reflection.name) do |*params| + force_reload = params.first unless params.empty? + association = instance_variable_get("@#{reflection.name}") + + unless association.respond_to?(:loaded?) + association = association_proxy_class.new(self, reflection) + instance_variable_set("@#{reflection.name}", association) + end + + association.reload if force_reload + + association + end + end + + def collection_accessor_methods(reflection, association_proxy_class) + collection_reader_method(reflection, association_proxy_class) + + define_method("#{reflection.name}=") do |new_value| + association = instance_variable_get("@#{reflection.name}") + unless association.respond_to?(:loaded?) + association = association_proxy_class.new(self, reflection) + instance_variable_set("@#{reflection.name}", association) + end + association.replace(new_value) + association + end + + define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value| + send("#{reflection.name}=", reflection.class_name.constantize.find(new_value)) + end + end + + def require_association_class(class_name) + require_association(Inflector.underscore(class_name)) if class_name + end + + def add_multiple_associated_save_callbacks(association_name) + method_name = "validate_associated_records_for_#{association_name}".to_sym + define_method(method_name) do + association = instance_variable_get("@#{association_name}") + if association.respond_to?(:loaded?) + if new_record? + association + else + association.select { |record| record.new_record? } + end.each do |record| + errors.add "#{association_name}" unless record.valid? + end + end + end + + validate method_name + before_save("@new_record_before_save = new_record?; true") + + after_callback = <<-end_eval + association = instance_variable_get("@#{association_name}") + + if association.respond_to?(:loaded?) + if @new_record_before_save + records_to_save = association + else + records_to_save = association.select { |record| record.new_record? } + end + records_to_save.each { |record| association.send(:insert_record, record) } + association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id + end + end_eval + + # Doesn't use after_save as that would save associations added in after_create/after_update twice + after_create(after_callback) + after_update(after_callback) + end + + def association_constructor_method(constructor, reflection, association_proxy_class) + define_method("#{constructor}_#{reflection.name}") do |*params| + attributees = params.first unless params.empty? + replace_existing = params[1].nil? ? true : params[1] + association = instance_variable_get("@#{reflection.name}") + + if association.nil? + association = association_proxy_class.new(self, reflection) + instance_variable_set("@#{reflection.name}", association) + end + + if association_proxy_class == HasOneAssociation + association.send(constructor, attributees, replace_existing) + else + association.send(constructor, attributees) + end + end + end + + def count_with_associations(options = {}) + catch :invalid_query do + join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins]) + return count_by_sql(construct_counter_sql_with_included_associations(options, join_dependency)) + end + 0 + end + + def find_with_associations(options = {}) + catch :invalid_query do + join_dependency = JoinDependency.new(self, merge_includes(scope(:find, :include), options[:include]), options[:joins]) + rows = select_all_rows(options, join_dependency) + return join_dependency.instantiate(rows) + end + [] + end + + def configure_dependency_for_has_many(reflection) + if reflection.options[:dependent] && reflection.options[:exclusively_dependent] + raise ArgumentError, ':dependent and :exclusively_dependent are mutually exclusive options. You may specify one or the other.' + end + + if reflection.options[:exclusively_dependent] + reflection.options[:dependent] = :delete_all + #warn "The :exclusively_dependent option is deprecated. Please use :dependent => :delete_all instead.") + end + + # See HasManyAssociation#delete_records. Dependent associations + # delete children, otherwise foreign key is set to NULL. + + # Add polymorphic type if the :as option is present + dependent_conditions = %(#{reflection.primary_key_name} = \#{record.quoted_id}) + if reflection.options[:as] + dependent_conditions += " AND #{reflection.options[:as]}_type = '#{base_class.name}'" + end + + case reflection.options[:dependent] + when :destroy, true + module_eval "before_destroy '#{reflection.name}.each { |o| o.destroy }'" + when :delete_all + module_eval "before_destroy { |record| #{reflection.class_name}.delete_all(%(#{dependent_conditions})) }" + when :nullify + module_eval "before_destroy { |record| #{reflection.class_name}.update_all(%(#{reflection.primary_key_name} = NULL), %(#{dependent_conditions})) }" + when nil, false + # pass + else + raise ArgumentError, 'The :dependent option expects either :destroy, :delete_all, or :nullify' + end + end + + def configure_dependency_for_has_one(reflection) + case reflection.options[:dependent] + when :destroy, true + module_eval "before_destroy '#{reflection.name}.destroy unless #{reflection.name}.nil?'" + when :nullify + module_eval "before_destroy '#{reflection.name}.update_attribute(\"#{reflection.primary_key_name}\", nil)'" + when nil, false + # pass + else + raise ArgumentError, "The :dependent option expects either :destroy or :nullify." + end + end + + + def add_deprecated_api_for_has_many(association_name) + deprecated_collection_count_method(association_name) + deprecated_add_association_relation(association_name) + deprecated_remove_association_relation(association_name) + deprecated_has_collection_method(association_name) + deprecated_find_in_collection_method(association_name) + deprecated_find_all_in_collection_method(association_name) + deprecated_collection_create_method(association_name) + deprecated_collection_build_method(association_name) + end + + def create_has_many_reflection(association_id, options, &extension) + options.assert_valid_keys( + :class_name, :table_name, :foreign_key, + :exclusively_dependent, :dependent, + :select, :conditions, :include, :order, :group, :limit, :offset, + :as, :through, :source, + :finder_sql, :counter_sql, + :before_add, :after_add, :before_remove, :after_remove, + :extend + ) + + options[:extend] = create_extension_module(association_id, extension) if block_given? + + create_reflection(:has_many, association_id, options, self) + end + + def create_has_one_reflection(association_id, options) + options.assert_valid_keys( + :class_name, :foreign_key, :remote, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as + ) + + create_reflection(:has_one, association_id, options, self) + end + + def create_belongs_to_reflection(association_id, options) + options.assert_valid_keys( + :class_name, :foreign_key, :foreign_type, :remote, :conditions, :order, :include, :dependent, + :counter_cache, :extend, :polymorphic + ) + + reflection = create_reflection(:belongs_to, association_id, options, self) + + if options[:polymorphic] + reflection.options[:foreign_type] ||= reflection.class_name.underscore + "_type" + end + + reflection + end + + def create_has_and_belongs_to_many_reflection(association_id, options, &extension) + options.assert_valid_keys( + :class_name, :table_name, :join_table, :foreign_key, :association_foreign_key, + :select, :conditions, :include, :order, :group, :limit, :offset, + :finder_sql, :delete_sql, :insert_sql, :uniq, + :before_add, :after_add, :before_remove, :after_remove, + :extend + ) + + options[:extend] = create_extension_module(association_id, extension) if block_given? + + reflection = create_reflection(:has_and_belongs_to_many, association_id, options, self) + + reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name)) + + reflection + end + + def reflect_on_included_associations(associations) + [ associations ].flatten.collect { |association| reflect_on_association(association.to_s.intern) } + end + + def guard_against_unlimitable_reflections(reflections, options) + if (options[:offset] || options[:limit]) && !using_limitable_reflections?(reflections) + raise( + ConfigurationError, + "You can not use offset and limit together with has_many or has_and_belongs_to_many associations" + ) + end + end + + def select_all_rows(options, join_dependency) + connection.select_all( + construct_finder_sql_with_included_associations(options, join_dependency), + "#{name} Load Including Associations" + ) + end + + def construct_counter_sql_with_included_associations(options, join_dependency) + scope = scope(:find) + sql = "SELECT COUNT(DISTINCT #{table_name}.#{primary_key})" + + # A (slower) workaround if we're using a backend, like sqlite, that doesn't support COUNT DISTINCT. + if !Base.connection.supports_count_distinct? + sql = "SELECT COUNT(*) FROM (SELECT DISTINCT #{table_name}.#{primary_key}" + end + + sql << " FROM #{table_name} " + sql << join_dependency.join_associations.collect{|join| join.association_join }.join + + add_joins!(sql, options, scope) + add_conditions!(sql, options[:conditions], scope) + add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && ((scope && scope[:limit]) || options[:limit]) + + add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections) + + if !Base.connection.supports_count_distinct? + sql << ")" + end + + return sanitize_sql(sql) + end + + def construct_finder_sql_with_included_associations(options, join_dependency) + scope = scope(:find) + sql = "SELECT #{column_aliases(join_dependency)} FROM #{(scope && scope[:from]) || options[:from] || table_name} " + sql << join_dependency.join_associations.collect{|join| join.association_join }.join + + add_joins!(sql, options, scope) + add_conditions!(sql, options[:conditions], scope) + add_limited_ids_condition!(sql, options, join_dependency) if !using_limitable_reflections?(join_dependency.reflections) && options[:limit] + + sql << "ORDER BY #{options[:order]} " if options[:order] + + add_limit!(sql, options, scope) if using_limitable_reflections?(join_dependency.reflections) + + return sanitize_sql(sql) + end + + def add_limited_ids_condition!(sql, options, join_dependency) + unless (id_list = select_limited_ids_list(options, join_dependency)).empty? + sql << "#{condition_word(sql)} #{table_name}.#{primary_key} IN (#{id_list}) " + else + throw :invalid_query + end + end + + def select_limited_ids_list(options, join_dependency) + connection.select_all( + construct_finder_sql_for_association_limiting(options, join_dependency), + "#{name} Load IDs For Limited Eager Loading" + ).collect { |row| connection.quote(row[primary_key]) }.join(", ") + end + + def construct_finder_sql_for_association_limiting(options, join_dependency) + scope = scope(:find) + sql = "SELECT " + sql << "DISTINCT #{table_name}." if include_eager_conditions?(options) || include_eager_order?(options) + sql << primary_key + sql << ", #{options[:order].split(',').collect { |s| s.split.first } * ', '}" if options[:order] && (include_eager_conditions?(options) || include_eager_order?(options)) + sql << " FROM #{table_name} " + + if include_eager_conditions?(options) || include_eager_order?(options) + sql << join_dependency.join_associations.collect{|join| join.association_join }.join + add_joins!(sql, options, scope) + end + + add_conditions!(sql, options[:conditions], scope) + sql << "ORDER BY #{options[:order]} " if options[:order] + add_limit!(sql, options, scope) + return sanitize_sql(sql) + end + + # Checks if the conditions reference a table other than the current model table + def include_eager_conditions?(options) + # look in both sets of conditions + conditions = [scope(:find, :conditions), options[:conditions]].inject([]) do |all, cond| + case cond + when nil then all + when Array then all << cond.first + else all << cond + end + end + return false unless conditions.any? + conditions.join(' ').scan(/(\w+)\.\w+/).flatten.any? do |condition_table_name| + condition_table_name != table_name + end + end + + # Checks if the query order references a table other than the current model's table. + def include_eager_order?(options) + order = options[:order] + return false unless order + order.scan(/(\w+)\.\w+/).flatten.any? do |order_table_name| + order_table_name != table_name + end + end + + def using_limitable_reflections?(reflections) + reflections.reject { |r| [ :belongs_to, :has_one ].include?(r.macro) }.length.zero? + end + + def column_aliases(join_dependency) + join_dependency.joins.collect{|join| join.column_names_with_alias.collect{|column_name, aliased_name| + "#{join.aliased_table_name}.#{connection.quote_column_name column_name} AS #{aliased_name}"}}.flatten.join(", ") + end + + def add_association_callbacks(association_name, options) + callbacks = %w(before_add after_add before_remove after_remove) + callbacks.each do |callback_name| + full_callback_name = "#{callback_name.to_s}_for_#{association_name.to_s}" + defined_callbacks = options[callback_name.to_sym] + if options.has_key?(callback_name.to_sym) + class_inheritable_reader full_callback_name.to_sym + write_inheritable_array(full_callback_name.to_sym, [defined_callbacks].flatten) + end + end + end + + def condition_word(sql) + sql =~ /where/i ? " AND " : "WHERE " + end + + def create_extension_module(association_id, extension) + extension_module_name = "#{self.to_s}#{association_id.to_s.camelize}AssociationExtension" + + silence_warnings do + Object.const_set(extension_module_name, Module.new(&extension)) + end + + extension_module_name.constantize + end + + class JoinDependency + attr_reader :joins, :reflections, :table_aliases + + def initialize(base, associations, joins) + @joins = [JoinBase.new(base, joins)] + @associations = associations + @reflections = [] + @base_records_hash = {} + @base_records_in_order = [] + @table_aliases = Hash.new { |aliases, table| aliases[table] = 0 } + @table_aliases[base.table_name] = 1 + build(associations) + end + + def join_associations + @joins[1..-1].to_a + end + + def join_base + @joins[0] + end + + def instantiate(rows) + rows.each_with_index do |row, i| + primary_id = join_base.record_id(row) + unless @base_records_hash[primary_id] + @base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(row)) + end + construct(@base_records_hash[primary_id], @associations, join_associations.dup, row) + end + return @base_records_in_order + end + + def aliased_table_names_for(table_name) + joins.select{|join| join.table_name == table_name }.collect{|join| join.aliased_table_name} + end + + protected + def build(associations, parent = nil) + parent ||= @joins.last + case associations + when Symbol, String + reflection = parent.reflections[associations.to_s.intern] or + raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?" + @reflections << reflection + @joins << JoinAssociation.new(reflection, self, parent) + when Array + associations.each do |association| + build(association, parent) + end + when Hash + associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| + build(name, parent) + build(associations[name]) + end + else + raise ConfigurationError, associations.inspect + end + end + + def construct(parent, associations, joins, row) + case associations + when Symbol, String + while (join = joins.shift).reflection.name.to_s != associations.to_s + raise ConfigurationError, "Not Enough Associations" if joins.empty? + end + construct_association(parent, join, row) + when Array + associations.each do |association| + construct(parent, association, joins, row) + end + when Hash + associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name| + association = construct_association(parent, joins.shift, row) + construct(association, associations[name], joins, row) if association + end + else + raise ConfigurationError, associations.inspect + end + end + + def construct_association(record, join, row) + case join.reflection.macro + when :has_many, :has_and_belongs_to_many + collection = record.send(join.reflection.name) + collection.loaded + + return nil if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil? + association = join.instantiate(row) + collection.target.push(association) unless collection.target.include?(association) + when :has_one, :belongs_to + return if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil? + association = join.instantiate(row) + record.send("set_#{join.reflection.name}_target", association) + else + raise ConfigurationError, "unknown macro: #{join.reflection.macro}" + end + return association + end + + class JoinBase + attr_reader :active_record, :table_joins + delegate :table_name, :column_names, :primary_key, :reflections, :sanitize_sql, :to => :active_record + + def initialize(active_record, joins = nil) + @active_record = active_record + @cached_record = {} + @table_joins = joins + end + + def aliased_prefix + "t0" + end + + def aliased_primary_key + "#{ aliased_prefix }_r0" + end + + def aliased_table_name + active_record.table_name + end + + def column_names_with_alias + unless @column_names_with_alias + @column_names_with_alias = [] + ([primary_key] + (column_names - [primary_key])).each_with_index do |column_name, i| + @column_names_with_alias << [column_name, "#{ aliased_prefix }_r#{ i }"] + end + end + return @column_names_with_alias + end + + def extract_record(row) + column_names_with_alias.inject({}){|record, (cn, an)| record[cn] = row[an]; record} + end + + def record_id(row) + row[aliased_primary_key] + end + + def instantiate(row) + @cached_record[record_id(row)] ||= active_record.instantiate(extract_record(row)) + end + end + + class JoinAssociation < JoinBase + attr_reader :reflection, :parent, :aliased_table_name, :aliased_prefix, :aliased_join_table_name, :parent_table_name + delegate :options, :klass, :through_reflection, :source_reflection, :to => :reflection + + def initialize(reflection, join_dependency, parent = nil) + reflection.check_validity! + if reflection.options[:polymorphic] + raise EagerLoadPolymorphicError.new(reflection) + end + + super(reflection.klass) + @parent = parent + @reflection = reflection + @aliased_prefix = "t#{ join_dependency.joins.size }" + @aliased_table_name = table_name # start with the table name + @parent_table_name = parent.active_record.table_name + + if !parent.table_joins.blank? && parent.table_joins.to_s.downcase =~ %r{join(\s+\w+)?\s+#{aliased_table_name.downcase}\son} + join_dependency.table_aliases[aliased_table_name] += 1 + end + + unless join_dependency.table_aliases[aliased_table_name].zero? + # if the table name has been used, then use an alias + @aliased_table_name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}" + table_index = join_dependency.table_aliases[aliased_table_name] + @aliased_table_name = @aliased_table_name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 + end + join_dependency.table_aliases[aliased_table_name] += 1 + + if reflection.macro == :has_and_belongs_to_many || (reflection.macro == :has_many && reflection.options[:through]) + @aliased_join_table_name = reflection.macro == :has_and_belongs_to_many ? reflection.options[:join_table] : reflection.through_reflection.klass.table_name + unless join_dependency.table_aliases[aliased_join_table_name].zero? + @aliased_join_table_name = active_record.connection.table_alias_for "#{pluralize(reflection.name)}_#{parent_table_name}_join" + table_index = join_dependency.table_aliases[aliased_join_table_name] + @aliased_join_table_name = @aliased_join_table_name[0..active_record.connection.table_alias_length-3] + "_#{table_index+1}" if table_index > 0 + end + join_dependency.table_aliases[aliased_join_table_name] += 1 + end + end + + def association_join + join = case reflection.macro + when :has_and_belongs_to_many + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_alias_for(options[:join_table], aliased_join_table_name), + aliased_join_table_name, + options[:foreign_key] || reflection.active_record.to_s.classify.foreign_key, + reflection.active_record.table_name, reflection.active_record.primary_key] + + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_name_and_alias, aliased_table_name, klass.primary_key, + aliased_join_table_name, options[:association_foreign_key] || klass.table_name.classify.foreign_key + ] + when :has_many, :has_one + case + when reflection.macro == :has_many && reflection.options[:through] + through_conditions = through_reflection.options[:conditions] ? "AND #{interpolate_sql(sanitize_sql(through_reflection.options[:conditions]))}" : '' + if through_reflection.options[:as] # has_many :through against a polymorphic join + polymorphic_foreign_key = through_reflection.options[:as].to_s + '_id' + polymorphic_foreign_type = through_reflection.options[:as].to_s + '_type' + + " LEFT OUTER JOIN %s ON (%s.%s = %s.%s AND %s.%s = %s) " % [ + table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), + aliased_join_table_name, polymorphic_foreign_key, + parent.aliased_table_name, parent.primary_key, + aliased_join_table_name, polymorphic_foreign_type, klass.quote(parent.active_record.base_class.name)] + + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [table_name_and_alias, + aliased_table_name, primary_key, aliased_join_table_name, options[:foreign_key] || reflection.klass.to_s.classify.foreign_key + ] + else + if source_reflection.macro == :has_many && source_reflection.options[:as] + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name, + through_reflection.primary_key_name, + parent.aliased_table_name, parent.primary_key] + + " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s " % [ + table_name_and_alias, + aliased_table_name, "#{source_reflection.options[:as]}_id", + aliased_join_table_name, options[:foreign_key] || primary_key, + aliased_table_name, "#{source_reflection.options[:as]}_type", + klass.quote(source_reflection.active_record.base_class.name) + ] + else + case source_reflection.macro + when :belongs_to + first_key = primary_key + second_key = options[:foreign_key] || klass.to_s.classify.foreign_key + when :has_many + first_key = through_reflection.klass.to_s.classify.foreign_key + second_key = options[:foreign_key] || primary_key + end + + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_alias_for(through_reflection.klass.table_name, aliased_join_table_name), aliased_join_table_name, + through_reflection.primary_key_name, + parent.aliased_table_name, parent.primary_key] + + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_name_and_alias, + aliased_table_name, first_key, + aliased_join_table_name, second_key + ] + end + end + + when reflection.macro == :has_many && reflection.options[:as] + " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s" % [ + table_name_and_alias, + aliased_table_name, "#{reflection.options[:as]}_id", + parent.aliased_table_name, parent.primary_key, + aliased_table_name, "#{reflection.options[:as]}_type", + klass.quote(parent.active_record.base_class.name) + ] + when reflection.macro == :has_one && reflection.options[:as] + " LEFT OUTER JOIN %s ON %s.%s = %s.%s AND %s.%s = %s " % [ + table_name_and_alias, + aliased_table_name, "#{reflection.options[:as]}_id", + parent.aliased_table_name, parent.primary_key, + aliased_table_name, "#{reflection.options[:as]}_type", + klass.quote(reflection.active_record.base_class.name) + ] + else + foreign_key = options[:foreign_key] || reflection.active_record.name.foreign_key + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_name_and_alias, + aliased_table_name, foreign_key, + parent.aliased_table_name, parent.primary_key + ] + end + when :belongs_to + " LEFT OUTER JOIN %s ON %s.%s = %s.%s " % [ + table_name_and_alias, aliased_table_name, reflection.klass.primary_key, + parent.aliased_table_name, options[:foreign_key] || klass.to_s.foreign_key + ] + else + "" + end || '' + join << %(AND %s.%s = %s ) % [ + aliased_table_name, + reflection.active_record.connection.quote_column_name(reflection.active_record.inheritance_column), + klass.quote(klass.name)] unless klass.descends_from_active_record? + join << "AND #{interpolate_sql(sanitize_sql(reflection.options[:conditions]))} " if reflection.options[:conditions] + join + end + + protected + def pluralize(table_name) + ActiveRecord::Base.pluralize_table_names ? table_name.to_s.pluralize : table_name + end + + def table_alias_for(table_name, table_alias) + "#{table_name} #{table_alias if table_name != table_alias}".strip + end + + def table_name_and_alias + table_alias_for table_name, @aliased_table_name + end + + def interpolate_sql(sql) + instance_eval("%@#{sql.gsub('@', '\@')}@") + end + end + end + end + end +end +require 'yaml' +require 'set' +require 'active_record/deprecated_finders' + +module ActiveRecord #:nodoc: + class ActiveRecordError < StandardError #:nodoc: + end + class SubclassNotFound < ActiveRecordError #:nodoc: + end + class AssociationTypeMismatch < ActiveRecordError #:nodoc: + end + class SerializationTypeMismatch < ActiveRecordError #:nodoc: + end + class AdapterNotSpecified < ActiveRecordError # :nodoc: + end + class AdapterNotFound < ActiveRecordError # :nodoc: + end + class ConnectionNotEstablished < ActiveRecordError #:nodoc: + end + class ConnectionFailed < ActiveRecordError #:nodoc: + end + class RecordNotFound < ActiveRecordError #:nodoc: + end + class RecordNotSaved < ActiveRecordError #:nodoc: + end + class StatementInvalid < ActiveRecordError #:nodoc: + end + class PreparedStatementInvalid < ActiveRecordError #:nodoc: + end + class StaleObjectError < ActiveRecordError #:nodoc: + end + class ConfigurationError < StandardError #:nodoc: + end + class ReadOnlyRecord < StandardError #:nodoc: + end + + class AttributeAssignmentError < ActiveRecordError #:nodoc: + attr_reader :exception, :attribute + def initialize(message, exception, attribute) + @exception = exception + @attribute = attribute + @message = message + end + end + + class MultiparameterAssignmentErrors < ActiveRecordError #:nodoc: + attr_reader :errors + def initialize(errors) + @errors = errors + end + end + + # Active Record objects don't specify their attributes directly, but rather infer them from the table definition with + # which they're linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change + # is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain + # database table will happen automatically in most common cases, but can be overwritten for the uncommon ones. + # + # See the mapping rules in table_name and the full example in link:files/README.html for more insight. + # + # == Creation + # + # Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when + # you're receiving the data from somewhere else, like a HTTP request. It works like this: + # + # user = User.new(:name => "David", :occupation => "Code Artist") + # user.name # => "David" + # + # You can also use block initialization: + # + # user = User.new do |u| + # u.name = "David" + # u.occupation = "Code Artist" + # end + # + # And of course you can just create a bare object and specify the attributes after the fact: + # + # user = User.new + # user.name = "David" + # user.occupation = "Code Artist" + # + # == Conditions + # + # Conditions can either be specified as a string or an array representing the WHERE-part of an SQL statement. + # The array form is to be used when the condition input is tainted and requires sanitization. The string form can + # be used for statements that don't involve tainted data. Examples: + # + # User < ActiveRecord::Base + # def self.authenticate_unsafely(user_name, password) + # find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'") + # end + # + # def self.authenticate_safely(user_name, password) + # find(:first, :conditions => [ "user_name = ? AND password = ?", user_name, password ]) + # end + # end + # + # The <tt>authenticate_unsafely</tt> method inserts the parameters directly into the query and is thus susceptible to SQL-injection + # attacks if the <tt>user_name</tt> and +password+ parameters come directly from a HTTP request. The <tt>authenticate_safely</tt> method, + # on the other hand, will sanitize the <tt>user_name</tt> and +password+ before inserting them in the query, which will ensure that + # an attacker can't escape the query and fake the login (or worse). + # + # When using multiple parameters in the conditions, it can easily become hard to read exactly what the fourth or fifth + # question mark is supposed to represent. In those cases, you can resort to named bind variables instead. That's done by replacing + # the question marks with symbols and supplying a hash with values for the matching symbol keys: + # + # Company.find(:first, [ + # "id = :id AND name = :name AND division = :division AND created_at > :accounting_date", + # { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' } + # ]) + # + # == Overwriting default accessors + # + # All column values are automatically available through basic accessors on the Active Record object, but some times you + # want to specialize this behavior. This can be done by either by overwriting the default accessors (using the same + # name as the attribute) calling read_attribute(attr_name) and write_attribute(attr_name, value) to actually change things. + # Example: + # + # class Song < ActiveRecord::Base + # # Uses an integer of seconds to hold the length of the song + # + # def length=(minutes) + # write_attribute(:length, minutes * 60) + # end + # + # def length + # read_attribute(:length) / 60 + # end + # end + # + # You can alternatively use self[:attribute]=(value) and self[:attribute] instead of write_attribute(:attribute, vaule) and + # read_attribute(:attribute) as a shorter form. + # + # == Accessing attributes before they have been typecasted + # + # Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first. + # That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model + # has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast. + # + # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display + # the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you + # want. + # + # == Dynamic attribute-based finders + # + # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by + # appending the name of an attribute to <tt>find_by_</tt> or <tt>find_all_by_</tt>, so you get finders like Person.find_by_user_name, + # Person.find_all_by_last_name, Payment.find_by_transaction_id. So instead of writing + # <tt>Person.find(:first, ["user_name = ?", user_name])</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>. + # And instead of writing <tt>Person.find(:all, ["last_name = ?", last_name])</tt>, you just do <tt>Person.find_all_by_last_name(last_name)</tt>. + # + # It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like + # <tt>Person.find_by_user_name_and_password</tt> or even <tt>Payment.find_by_purchaser_and_state_and_country</tt>. So instead of writing + # <tt>Person.find(:first, ["user_name = ? AND password = ?", user_name, password])</tt>, you just do + # <tt>Person.find_by_user_name_and_password(user_name, password)</tt>. + # + # It's even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount + # is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is + # actually Person.find_by_user_name(user_name, options). So you could call <tt>Payment.find_all_by_amount(50, :order => "created_on")</tt>. + # + # The same dynamic finder style can be used to create the object if it doesn't already exist. This dynamic finder is called with + # <tt>find_or_create_by_</tt> and will return the object if it already exists and otherwise creates it, then returns it. Example: + # + # # No 'Summer' tag exists + # Tag.find_or_create_by_name("Summer") # equal to Tag.create(:name => "Summer") + # + # # Now the 'Summer' tag does exist + # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer") + # + # == Saving arrays, hashes, and other non-mappable objects in text columns + # + # Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method +serialize+. + # This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work. Example: + # + # class User < ActiveRecord::Base + # serialize :preferences + # end + # + # user = User.create(:preferences => { "background" => "black", "display" => large }) + # User.find(user.id).preferences # => { "background" => "black", "display" => large } + # + # You can also specify a class option as the second parameter that'll raise an exception if a serialized object is retrieved as a + # descendent of a class not in the hierarchy. Example: + # + # class User < ActiveRecord::Base + # serialize :preferences, Hash + # end + # + # user = User.create(:preferences => %w( one two three )) + # User.find(user.id).preferences # raises SerializationTypeMismatch + # + # == Single table inheritance + # + # Active Record allows inheritance by storing the name of the class in a column that by default is called "type" (can be changed + # by overwriting <tt>Base.inheritance_column</tt>). This means that an inheritance looking like this: + # + # class Company < ActiveRecord::Base; end + # class Firm < Company; end + # class Client < Company; end + # class PriorityClient < Client; end + # + # When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = "Firm". You can then + # fetch this row again using Company.find(:first, "name = '37signals'") and it will return a Firm object. + # + # If you don't have a type column defined in your table, single-table inheritance won't be triggered. In that case, it'll work just + # like normal subclasses with no special magic for differentiating between them or reloading the right type with find. + # + # Note, all the attributes for all the cases are kept in the same table. Read more: + # http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html + # + # == Connection to multiple databases in different models + # + # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection. + # All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection. + # For example, if Course is a ActiveRecord::Base, but resides in a different database you can just say Course.establish_connection + # and Course *and all its subclasses* will use this connection instead. + # + # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is + # requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool. + # + # == Exceptions + # + # * +ActiveRecordError+ -- generic error class and superclass of all other errors raised by Active Record + # * +AdapterNotSpecified+ -- the configuration hash used in <tt>establish_connection</tt> didn't include a + # <tt>:adapter</tt> key. + # * +AdapterNotFound+ -- the <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified an non-existent adapter + # (or a bad spelling of an existing one). + # * +AssociationTypeMismatch+ -- the object assigned to the association wasn't of the type specified in the association definition. + # * +SerializationTypeMismatch+ -- the object serialized wasn't of the class specified as the second parameter. + # * +ConnectionNotEstablished+ -- no connection has been established. Use <tt>establish_connection</tt> before querying. + # * +RecordNotFound+ -- no record responded to the find* method. + # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions. + # * +StatementInvalid+ -- the database server rejected the SQL statement. The precise error is added in the message. + # Either the record with the given ID doesn't exist or the record didn't meet the additional restrictions. + # * +MultiparameterAssignmentErrors+ -- collection of errors that occurred during a mass assignment using the + # +attributes=+ method. The +errors+ property of this exception contains an array of +AttributeAssignmentError+ + # objects that should be inspected to determine which attributes triggered the errors. + # * +AttributeAssignmentError+ -- an error occurred while doing a mass assignment through the +attributes=+ method. + # You can inspect the +attribute+ property of the exception object to determine which attribute triggered the error. + # + # *Note*: The attributes listed are class-level attributes (accessible from both the class and instance level). + # So it's possible to assign a logger to the class through Base.logger= which will then be used by all + # instances in the current object space. + class Base + # Accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then passed + # on to any new database connections made and which can be retrieved on both a class and instance level by calling +logger+. + cattr_accessor :logger + + include Reloadable::Subclasses + + def self.inherited(child) #:nodoc: + @@subclasses[self] ||= [] + @@subclasses[self] << child + super + end + + def self.reset_subclasses #:nodoc: + nonreloadables = [] + subclasses.each do |klass| + unless klass.reloadable? + nonreloadables << klass + next + end + klass.instance_variables.each { |var| klass.send(:remove_instance_variable, var) } + klass.instance_methods(false).each { |m| klass.send :undef_method, m } + end + @@subclasses = {} + nonreloadables.each { |klass| (@@subclasses[klass.superclass] ||= []) << klass } + end + + @@subclasses = {} + + cattr_accessor :configurations + @@configurations = {} + + # Accessor for the prefix type that will be prepended to every primary key column name. The options are :table_name and + # :table_name_with_underscore. If the first is specified, the Product class will look for "productid" instead of "id" as + # the primary column. If the latter is specified, the Product class will look for "product_id" instead of "id". Remember + # that this is a global setting for all Active Records. + cattr_accessor :primary_key_prefix_type + @@primary_key_prefix_type = nil + + # Accessor for the name of the prefix string to prepend to every table name. So if set to "basecamp_", all + # table names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient way of creating a namespace + # for tables in a shared database. By default, the prefix is the empty string. + cattr_accessor :table_name_prefix + @@table_name_prefix = "" + + # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp", + # "people_basecamp"). By default, the suffix is the empty string. + cattr_accessor :table_name_suffix + @@table_name_suffix = "" + + # Indicates whether or not table names should be the pluralized versions of the corresponding class names. + # If true, the default table name for a +Product+ class will be +products+. If false, it would just be +product+. + # See table_name for the full rules on table/class naming. This is true, by default. + cattr_accessor :pluralize_table_names + @@pluralize_table_names = true + + # Determines whether or not to use ANSI codes to colorize the logging statements committed by the connection adapter. These colors + # make it much easier to overview things during debugging (when used through a reader like +tail+ and on a black background), but + # may complicate matters if you use software like syslog. This is true, by default. + cattr_accessor :colorize_logging + @@colorize_logging = true + + # Determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates and times from the database. + # This is set to :local by default. + cattr_accessor :default_timezone + @@default_timezone = :local + + # Determines whether or not to use a connection for each thread, or a single shared connection for all threads. + # Defaults to false. Set to true if you're writing a threaded application. + cattr_accessor :allow_concurrency + @@allow_concurrency = false + + # Determines whether to speed up access by generating optimized reader + # methods to avoid expensive calls to method_missing when accessing + # attributes by name. You might want to set this to false in development + # mode, because the methods would be regenerated on each request. + cattr_accessor :generate_read_methods + @@generate_read_methods = true + + # Specifies the format to use when dumping the database schema with Rails' + # Rakefile. If :sql, the schema is dumped as (potentially database- + # specific) SQL statements. If :ruby, the schema is dumped as an + # ActiveRecord::Schema file which can be loaded into any database that + # supports migrations. Use :ruby if you want to have different database + # adapters for, e.g., your development and test environments. + cattr_accessor :schema_format + @@schema_format = :ruby + + class << self # Class methods + # Find operates with three different retrieval approaches: + # + # * Find by id: This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). + # If no record can be found for all of the listed ids, then RecordNotFound will be raised. + # * Find first: This will return the first record matched by the options used. These options can either be specific + # conditions or merely an order. If no record can matched, nil is returned. + # * Find all: This will return all the records matched by the options used. If no records are found, an empty array is returned. + # + # All approaches accept an option hash as their last parameter. The options are: + # + # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro. + # * <tt>:order</tt>: An SQL fragment like "created_at DESC, name". + # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. + # * <tt>:limit</tt>: An integer determining the limit on the number of rows that should be returned. + # * <tt>:offset</tt>: An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. + # * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed). + # The records will be returned read-only since they will have attributes that do not correspond to the table's columns. + # Pass :readonly => false to override. + # * <tt>:include</tt>: Names associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer + # to already defined associations. See eager loading under Associations. + # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not + # include the joined columns. + # * <tt>:readonly</tt>: Mark the returned records read-only so they cannot be saved or updated. + # + # Examples for find by id: + # Person.find(1) # returns the object for ID = 1 + # Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6) + # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17) + # Person.find([1]) # returns an array for objects the object with ID = 1 + # Person.find(1, :conditions => "administrator = 1", :order => "created_on DESC") + # + # Examples for find first: + # Person.find(:first) # returns the first object fetched by SELECT * FROM people + # Person.find(:first, :conditions => [ "user_name = ?", user_name]) + # Person.find(:first, :order => "created_on DESC", :offset => 5) + # + # Examples for find all: + # Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people + # Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50) + # Person.find(:all, :offset => 10, :limit => 10) + # Person.find(:all, :include => [ :account, :friends ]) + # Person.find(:all, :group => "category") + def find(*args) + options = extract_options_from_args!(args) + validate_find_options(options) + set_readonly_option!(options) + + case args.first + when :first then find_initial(options) + when :all then find_every(options) + else find_from_ids(args, options) + end + end + + # Works like find(:all), but requires a complete SQL string. Examples: + # Post.find_by_sql "SELECT p.*, c.author FROM posts p, comments c WHERE p.id = c.post_id" + # Post.find_by_sql ["SELECT * FROM posts WHERE author = ? AND created > ?", author_id, start_date] + def find_by_sql(sql) + connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) } + end + + # Returns true if the given +id+ represents the primary key of a record in the database, false otherwise. + # Example: + # Person.exists?(5) + def exists?(id) + !find(:first, :conditions => ["#{primary_key} = ?", id]).nil? rescue false + end + + # Creates an object, instantly saves it as a record (if the validation permits it), and returns it. If the save + # fails under validations, the unsaved object is still returned. + def create(attributes = nil) + if attributes.is_a?(Array) + attributes.collect { |attr| create(attr) } + else + object = new(attributes) + scope(:create).each { |att,value| object.send("#{att}=", value) } if scoped?(:create) + object.save + object + end + end + + # Finds the record from the passed +id+, instantly saves it with the passed +attributes+ (if the validation permits it), + # and returns it. If the save fails under validations, the unsaved object is still returned. + # + # The arguments may also be given as arrays in which case the update method is called for each pair of +id+ and + # +attributes+ and an array of objects is returned. + # + # Example of updating one record: + # Person.update(15, {:user_name => 'Samuel', :group => 'expert'}) + # + # Example of updating multiple records: + # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy"} } + # Person.update(people.keys, people.values) + def update(id, attributes) + if id.is_a?(Array) + idx = -1 + id.collect { |id| idx += 1; update(id, attributes[idx]) } + else + object = find(id) + object.update_attributes(attributes) + object + end + end + + # Deletes the record with the given +id+ without instantiating an object first. If an array of ids is provided, all of them + # are deleted. + def delete(id) + delete_all([ "#{primary_key} IN (?)", id ]) + end + + # Destroys the record with the given +id+ by instantiating the object and calling #destroy (all the callbacks are the triggered). + # If an array of ids is provided, all of them are destroyed. + def destroy(id) + id.is_a?(Array) ? id.each { |id| destroy(id) } : find(id).destroy + end + + # Updates all records with the SET-part of an SQL update statement in +updates+ and returns an integer with the number of rows updated. + # A subset of the records can be selected by specifying +conditions+. Example: + # Billing.update_all "category = 'authorized', approved = 1", "author = 'David'" + def update_all(updates, conditions = nil) + sql = "UPDATE #{table_name} SET #{sanitize_sql(updates)} " + add_conditions!(sql, conditions, scope(:find)) + connection.update(sql, "#{name} Update") + end + + # Destroys the objects for all the records that match the +condition+ by instantiating each object and calling + # the destroy method. Example: + # Person.destroy_all "last_login < '2004-04-04'" + def destroy_all(conditions = nil) + find(:all, :conditions => conditions).each { |object| object.destroy } + end + + # Deletes all the records that match the +condition+ without instantiating the objects first (and hence not + # calling the destroy method). Example: + # Post.delete_all "person_id = 5 AND (category = 'Something' OR category = 'Else')" + def delete_all(conditions = nil) + sql = "DELETE FROM #{table_name} " + add_conditions!(sql, conditions, scope(:find)) + connection.delete(sql, "#{name} Delete all") + end + + # Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part. + # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id" + def count_by_sql(sql) + sql = sanitize_conditions(sql) + connection.select_value(sql, "#{name} Count").to_i + end + + # Increments the specified counter by one. So <tt>DiscussionBoard.increment_counter("post_count", + # discussion_board_id)</tt> would increment the "post_count" counter on the board responding to discussion_board_id. + # This is used for caching aggregate values, so that they don't need to be computed every time. Especially important + # for looping over a collection where each element require a number of aggregate values. Like the DiscussionBoard + # that needs to list both the number of posts and comments. + def increment_counter(counter_name, id) + update_all "#{counter_name} = #{counter_name} + 1", "#{primary_key} = #{quote(id)}" + end + + # Works like increment_counter, but decrements instead. + def decrement_counter(counter_name, id) + update_all "#{counter_name} = #{counter_name} - 1", "#{primary_key} = #{quote(id)}" + end + + + # Attributes named in this macro are protected from mass-assignment, such as <tt>new(attributes)</tt> and + # <tt>attributes=(attributes)</tt>. Their assignment will simply be ignored. Instead, you can use the direct writer + # methods to do assignment. This is meant to protect sensitive attributes from being overwritten by URL/form hackers. Example: + # + # class Customer < ActiveRecord::Base + # attr_protected :credit_rating + # end + # + # customer = Customer.new("name" => David, "credit_rating" => "Excellent") + # customer.credit_rating # => nil + # customer.attributes = { "description" => "Jolly fellow", "credit_rating" => "Superb" } + # customer.credit_rating # => nil + # + # customer.credit_rating = "Average" + # customer.credit_rating # => "Average" + def attr_protected(*attributes) + write_inheritable_array("attr_protected", attributes - (protected_attributes || [])) + end + + # Returns an array of all the attributes that have been protected from mass-assignment. + def protected_attributes # :nodoc: + read_inheritable_attribute("attr_protected") + end + + # If this macro is used, only those attributes named in it will be accessible for mass-assignment, such as + # <tt>new(attributes)</tt> and <tt>attributes=(attributes)</tt>. This is the more conservative choice for mass-assignment + # protection. If you'd rather start from an all-open default and restrict attributes as needed, have a look at + # attr_protected. + def attr_accessible(*attributes) + write_inheritable_array("attr_accessible", attributes - (accessible_attributes || [])) + end + + # Returns an array of all the attributes that have been made accessible to mass-assignment. + def accessible_attributes # :nodoc: + read_inheritable_attribute("attr_accessible") + end + + + # Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized + # after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized + # object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised. + def serialize(attr_name, class_name = Object) + serialized_attributes[attr_name.to_s] = class_name + end + + # Returns a hash of all the attributes that have been specified for serialization as keys and their class restriction as values. + def serialized_attributes + read_inheritable_attribute("attr_serialized") or write_inheritable_attribute("attr_serialized", {}) + end + + + # Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending + # directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used + # to guess the table name from even when called on Reply. The rules used to do the guess are handled by the Inflector class + # in Active Support, which knows almost all common English inflections (report a bug if your inflection isn't covered). + # + # Additionally, the class-level table_name_prefix is prepended to the table_name and the table_name_suffix is appended. + # So if you have "myapp_" as a prefix, the table name guess for an Account class becomes "myapp_accounts". + # + # You can also overwrite this class method to allow for unguessable links, such as a Mouse class with a link to a + # "mice" table. Example: + # + # class Mouse < ActiveRecord::Base + # set_table_name "mice" + # end + def table_name + reset_table_name + end + + def reset_table_name #:nodoc: + name = "#{table_name_prefix}#{undecorated_table_name(base_class.name)}#{table_name_suffix}" + set_table_name(name) + name + end + + # Defines the primary key field -- can be overridden in subclasses. Overwriting will negate any effect of the + # primary_key_prefix_type setting, though. + def primary_key + reset_primary_key + end + + def reset_primary_key #:nodoc: + key = 'id' + case primary_key_prefix_type + when :table_name + key = Inflector.foreign_key(base_class.name, false) + when :table_name_with_underscore + key = Inflector.foreign_key(base_class.name) + end + set_primary_key(key) + key + end + + # Defines the column name for use with single table inheritance -- can be overridden in subclasses. + def inheritance_column + "type" + end + + # Lazy-set the sequence name to the connection's default. This method + # is only ever called once since set_sequence_name overrides it. + def sequence_name #:nodoc: + reset_sequence_name + end + + def reset_sequence_name #:nodoc: + default = connection.default_sequence_name(table_name, primary_key) + set_sequence_name(default) + default + end + + # Sets the table name to use to the given value, or (if the value + # is nil or false) to the value returned by the given block. + # + # Example: + # + # class Project < ActiveRecord::Base + # set_table_name "project" + # end + def set_table_name(value = nil, &block) + define_attr_method :table_name, value, &block + end + alias :table_name= :set_table_name + + # Sets the name of the primary key column to use to the given value, + # or (if the value is nil or false) to the value returned by the given + # block. + # + # Example: + # + # class Project < ActiveRecord::Base + # set_primary_key "sysid" + # end + def set_primary_key(value = nil, &block) + define_attr_method :primary_key, value, &block + end + alias :primary_key= :set_primary_key + + # Sets the name of the inheritance column to use to the given value, + # or (if the value # is nil or false) to the value returned by the + # given block. + # + # Example: + # + # class Project < ActiveRecord::Base + # set_inheritance_column do + # original_inheritance_column + "_id" + # end + # end + def set_inheritance_column(value = nil, &block) + define_attr_method :inheritance_column, value, &block + end + alias :inheritance_column= :set_inheritance_column + + # Sets the name of the sequence to use when generating ids to the given + # value, or (if the value is nil or false) to the value returned by the + # given block. This is required for Oracle and is useful for any + # database which relies on sequences for primary key generation. + # + # If a sequence name is not explicitly set when using Oracle or Firebird, + # it will default to the commonly used pattern of: #{table_name}_seq + # + # If a sequence name is not explicitly set when using PostgreSQL, it + # will discover the sequence corresponding to your primary key for you. + # + # Example: + # + # class Project < ActiveRecord::Base + # set_sequence_name "projectseq" # default would have been "project_seq" + # end + def set_sequence_name(value = nil, &block) + define_attr_method :sequence_name, value, &block + end + alias :sequence_name= :set_sequence_name + + # Turns the +table_name+ back into a class name following the reverse rules of +table_name+. + def class_name(table_name = table_name) # :nodoc: + # remove any prefix and/or suffix from the table name + class_name = table_name[table_name_prefix.length..-(table_name_suffix.length + 1)].camelize + class_name = class_name.singularize if pluralize_table_names + class_name + end + + # Indicates whether the table associated with this class exists + def table_exists? + if connection.respond_to?(:tables) + connection.tables.include? table_name + else + # if the connection adapter hasn't implemented tables, there are two crude tests that can be + # used - see if getting column info raises an error, or if the number of columns returned is zero + begin + reset_column_information + columns.size > 0 + rescue ActiveRecord::StatementInvalid + false + end + end + end + + # Returns an array of column objects for the table associated with this class. + def columns + unless @columns + @columns = connection.columns(table_name, "#{name} Columns") + @columns.each {|column| column.primary = column.name == primary_key} + end + @columns + end + + # Returns an array of column objects for the table associated with this class. + def columns_hash + @columns_hash ||= columns.inject({}) { |hash, column| hash[column.name] = column; hash } + end + + # Returns an array of column names as strings. + def column_names + @column_names ||= columns.map { |column| column.name } + end + + # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count", + # and columns used for single table inheritance have been removed. + def content_columns + @content_columns ||= columns.reject { |c| c.primary || c.name =~ /(_id|_count)$/ || c.name == inheritance_column } + end + + # Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key + # and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute + # is available. + def column_methods_hash #:nodoc: + @dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr| + attr_name = attr.to_s + methods[attr.to_sym] = attr_name + methods["#{attr}=".to_sym] = attr_name + methods["#{attr}?".to_sym] = attr_name + methods["#{attr}_before_type_cast".to_sym] = attr_name + methods + end + end + + # Contains the names of the generated reader methods. + def read_methods #:nodoc: + @read_methods ||= Set.new + end + + # Resets all the cached information about columns, which will cause them to be reloaded on the next request. + def reset_column_information + read_methods.each { |name| undef_method(name) } + @column_names = @columns = @columns_hash = @content_columns = @dynamic_methods_hash = @read_methods = nil + end + + def reset_column_information_and_inheritable_attributes_for_all_subclasses#:nodoc: + subclasses.each { |klass| klass.reset_inheritable_attributes; klass.reset_column_information } + end + + # Transforms attribute key names into a more humane format, such as "First name" instead of "first_name". Example: + # Person.human_attribute_name("first_name") # => "First name" + # Deprecated in favor of just calling "first_name".humanize + def human_attribute_name(attribute_key_name) #:nodoc: + attribute_key_name.humanize + end + + def descends_from_active_record? # :nodoc: + superclass == Base || !columns_hash.include?(inheritance_column) + end + + def quote(object) #:nodoc: + connection.quote(object) + end + + # Used to sanitize objects before they're used in an SELECT SQL-statement. Delegates to <tt>connection.quote</tt>. + def sanitize(object) #:nodoc: + connection.quote(object) + end + + # Log and benchmark multiple statements in a single block. Example: + # + # Project.benchmark("Creating project") do + # project = Project.create("name" => "stuff") + # project.create_manager("name" => "David") + # project.milestones << Milestone.find(:all) + # end + # + # The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it + # easy to include benchmarking statements in production software that will remain inexpensive because the benchmark + # will only be conducted if the log level is low enough. + # + # The logging of the multiple statements is turned off unless <tt>use_silence</tt> is set to false. + def benchmark(title, log_level = Logger::DEBUG, use_silence = true) + if logger && logger.level == log_level + result = nil + seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield } + logger.add(log_level, "#{title} (#{'%.5f' % seconds})") + result + else + yield + end + end + + # Silences the logger for the duration of the block. + def silence + old_logger_level, logger.level = logger.level, Logger::ERROR if logger + yield + ensure + logger.level = old_logger_level if logger + end + + # Scope parameters to method calls within the block. Takes a hash of method_name => parameters hash. + # method_name may be :find or :create. :find parameters may include the <tt>:conditions</tt>, <tt>:joins</tt>, + # <tt>:include</tt>, <tt>:offset</tt>, <tt>:limit</tt>, and <tt>:readonly</tt> options. :create parameters are an attributes hash. + # + # Article.with_scope(:find => { :conditions => "blog_id = 1" }, :create => { :blog_id => 1 }) do + # Article.find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1 + # a = Article.create(1) + # a.blog_id # => 1 + # end + # + # In nested scopings, all previous parameters are overwritten by inner rule + # except :conditions in :find, that are merged as hash. + # + # Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do + # Article.with_scope(:find => { :limit => 10}) + # Article.find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10 + # end + # Article.with_scope(:find => { :conditions => "author_id = 3" }) + # Article.find(:all) # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1 + # end + # end + # + # You can ignore any previous scopings by using <tt>with_exclusive_scope</tt> method. + # + # Article.with_scope(:find => { :conditions => "blog_id = 1", :limit => 1 }) do + # Article.with_exclusive_scope(:find => { :limit => 10 }) + # Article.find(:all) # => SELECT * from articles LIMIT 10 + # end + # end + def with_scope(method_scoping = {}, action = :merge, &block) + method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping) + + # Dup first and second level of hash (method and params). + method_scoping = method_scoping.inject({}) do |hash, (method, params)| + hash[method] = (params == true) ? params : params.dup + hash + end + + method_scoping.assert_valid_keys([ :find, :create ]) + + if f = method_scoping[:find] + f.assert_valid_keys([ :conditions, :joins, :select, :include, :from, :offset, :limit, :readonly ]) + f[:readonly] = true if !f[:joins].blank? && !f.has_key?(:readonly) + end + + # Merge scopings + if action == :merge && current_scoped_methods + method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)| + case hash[method] + when Hash + if method == :find + (hash[method].keys + params.keys).uniq.each do |key| + merge = hash[method][key] && params[key] # merge if both scopes have the same key + if key == :conditions && merge + hash[method][key] = [params[key], hash[method][key]].collect{ |sql| "( %s )" % sanitize_sql(sql) }.join(" AND ") + elsif key == :include && merge + hash[method][key] = merge_includes(hash[method][key], params[key]).uniq + else + hash[method][key] = hash[method][key] || params[key] + end + end + else + hash[method] = params.merge(hash[method]) + end + else + hash[method] = params + end + hash + end + end + + self.scoped_methods << method_scoping + + begin + yield + ensure + self.scoped_methods.pop + end + end + + # Works like with_scope, but discards any nested properties. + def with_exclusive_scope(method_scoping = {}, &block) + with_scope(method_scoping, :overwrite, &block) + end + + # Overwrite the default class equality method to provide support for association proxies. + def ===(object) + object.is_a?(self) + end + + # Deprecated + def threaded_connections #:nodoc: + allow_concurrency + end + + # Deprecated + def threaded_connections=(value) #:nodoc: + self.allow_concurrency = value + end + + # Returns the base AR subclass that this class descends from. If A + # extends AR::Base, A.base_class will return A. If B descends from A + # through some arbitrarily deep hierarchy, B.base_class will return A. + def base_class + class_of_active_record_descendant(self) + end + + # Set this to true if this is an abstract class (see #abstract_class?). + attr_accessor :abstract_class + + # Returns whether this class is a base AR class. If A is a base class and + # B descends from A, then B.base_class will return B. + def abstract_class? + abstract_class == true + end + + private + def find_initial(options) + options.update(:limit => 1) unless options[:include] + find_every(options).first + end + + def find_every(options) + records = scoped?(:find, :include) || options[:include] ? + find_with_associations(options) : + find_by_sql(construct_finder_sql(options)) + + records.each { |record| record.readonly! } if options[:readonly] + + records + end + + def find_from_ids(ids, options) + expects_array = ids.first.kind_of?(Array) + return ids.first if expects_array && ids.first.empty? + + ids = ids.flatten.compact.uniq + + case ids.size + when 0 + raise RecordNotFound, "Couldn't find #{name} without an ID" + when 1 + result = find_one(ids.first, options) + expects_array ? [ result ] : result + else + find_some(ids, options) + end + end + + def find_one(id, options) + conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions] + options.update :conditions => "#{table_name}.#{primary_key} = #{sanitize(id)}#{conditions}" + + if result = find_initial(options) + result + else + raise RecordNotFound, "Couldn't find #{name} with ID=#{id}#{conditions}" + end + end + + def find_some(ids, options) + conditions = " AND (#{sanitize_sql(options[:conditions])})" if options[:conditions] + ids_list = ids.map { |id| sanitize(id) }.join(',') + options.update :conditions => "#{table_name}.#{primary_key} IN (#{ids_list})#{conditions}" + + result = find_every(options) + + if result.size == ids.size + result + else + raise RecordNotFound, "Couldn't find all #{name.pluralize} with IDs (#{ids_list})#{conditions}" + end + end + + # Finder methods must instantiate through this method to work with the single-table inheritance model + # that makes it possible to create objects of different types from the same table. + def instantiate(record) + object = + if subclass_name = record[inheritance_column] + if subclass_name.empty? + allocate + else + require_association_class(subclass_name) + begin + compute_type(subclass_name).allocate + rescue NameError + raise SubclassNotFound, + "The single-table inheritance mechanism failed to locate the subclass: '#{record[inheritance_column]}'. " + + "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " + + "Please rename this column if you didn't intend it to be used for storing the inheritance class " + + "or overwrite #{self.to_s}.inheritance_column to use another column for that information." + end + end + else + allocate + end + + object.instance_variable_set("@attributes", record) + object + end + + # Nest the type name in the same module as this class. + # Bar is "MyApp::Business::Bar" relative to MyApp::Business::Foo + def type_name_with_module(type_name) + (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}" + end + + def construct_finder_sql(options) + scope = scope(:find) + sql = "SELECT #{(scope && scope[:select]) || options[:select] || '*'} " + sql << "FROM #{(scope && scope[:from]) || options[:from] || table_name} " + + add_joins!(sql, options, scope) + add_conditions!(sql, options[:conditions], scope) + + sql << " GROUP BY #{options[:group]} " if options[:group] + sql << " ORDER BY #{options[:order]} " if options[:order] + + add_limit!(sql, options, scope) + + sql + end + + # Merges includes so that the result is a valid +include+ + def merge_includes(first, second) + safe_to_array(first) + safe_to_array(second) + end + + # Object#to_a is deprecated, though it does have the desired behaviour + def safe_to_array(o) + case o + when NilClass + [] + when Array + o + else + [o] + end + end + + # The optional scope argument is for the current :find scope. + def add_limit!(sql, options, scope = :auto) + scope = scope(:find) if :auto == scope + if scope + options[:limit] ||= scope[:limit] + options[:offset] ||= scope[:offset] + end + connection.add_limit_offset!(sql, options) + end + + # The optional scope argument is for the current :find scope. + def add_joins!(sql, options, scope = :auto) + scope = scope(:find) if :auto == scope + join = (scope && scope[:joins]) || options[:joins] + sql << " #{join} " if join + end + + # Adds a sanitized version of +conditions+ to the +sql+ string. Note that the passed-in +sql+ string is changed. + # The optional scope argument is for the current :find scope. + def add_conditions!(sql, conditions, scope = :auto) + scope = scope(:find) if :auto == scope + segments = [] + segments << sanitize_sql(scope[:conditions]) if scope && scope[:conditions] + segments << sanitize_sql(conditions) unless conditions.nil? + segments << type_condition unless descends_from_active_record? + segments.compact! + sql << "WHERE (#{segments.join(") AND (")}) " unless segments.empty? + end + + def type_condition + quoted_inheritance_column = connection.quote_column_name(inheritance_column) + type_condition = subclasses.inject("#{table_name}.#{quoted_inheritance_column} = '#{name.demodulize}' ") do |condition, subclass| + condition << "OR #{table_name}.#{quoted_inheritance_column} = '#{subclass.name.demodulize}' " + end + + " (#{type_condition}) " + end + + # Guesses the table name, but does not decorate it with prefix and suffix information. + def undecorated_table_name(class_name = base_class.name) + table_name = Inflector.underscore(Inflector.demodulize(class_name)) + table_name = Inflector.pluralize(table_name) if pluralize_table_names + table_name + end + + # Enables dynamic finders like find_by_user_name(user_name) and find_by_user_name_and_password(user_name, password) that are turned into + # find(:first, :conditions => ["user_name = ?", user_name]) and find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password]) + # respectively. Also works for find(:all), but using find_all_by_amount(50) that are turned into find(:all, :conditions => ["amount = ?", 50]). + # + # It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount + # is actually find_all_by_amount(amount, options). + def method_missing(method_id, *arguments) + if match = /find_(all_by|by)_([_a-zA-Z]\w*)/.match(method_id.to_s) + finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match) + + attribute_names = extract_attribute_names_from_match(match) + super unless all_attributes_exists?(attribute_names) + + conditions = construct_conditions_from_arguments(attribute_names, arguments) + + case extra_options = arguments[attribute_names.size] + when nil + options = { :conditions => conditions } + set_readonly_option!(options) + send(finder, options) + + when Hash + finder_options = extra_options.merge(:conditions => conditions) + validate_find_options(finder_options) + set_readonly_option!(finder_options) + + if extra_options[:conditions] + with_scope(:find => { :conditions => extra_options[:conditions] }) do + send(finder, finder_options) + end + else + send(finder, finder_options) + end + + else + send(deprecated_finder, conditions, *arguments[attribute_names.length..-1]) # deprecated API + end + elsif match = /find_or_create_by_([_a-zA-Z]\w*)/.match(method_id.to_s) + attribute_names = extract_attribute_names_from_match(match) + super unless all_attributes_exists?(attribute_names) + + options = { :conditions => construct_conditions_from_arguments(attribute_names, arguments) } + set_readonly_option!(options) + find_initial(options) || create(construct_attributes_from_arguments(attribute_names, arguments)) + else + super + end + end + + def determine_finder(match) + match.captures.first == 'all_by' ? :find_every : :find_initial + end + + def determine_deprecated_finder(match) + match.captures.first == 'all_by' ? :find_all : :find_first + end + + def extract_attribute_names_from_match(match) + match.captures.last.split('_and_') + end + + def construct_conditions_from_arguments(attribute_names, arguments) + conditions = [] + attribute_names.each_with_index { |name, idx| conditions << "#{table_name}.#{connection.quote_column_name(name)} #{attribute_condition(arguments[idx])} " } + [ conditions.join(" AND "), *arguments[0...attribute_names.length] ] + end + + def construct_attributes_from_arguments(attribute_names, arguments) + attributes = {} + attribute_names.each_with_index { |name, idx| attributes[name] = arguments[idx] } + attributes + end + + def all_attributes_exists?(attribute_names) + attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) } + end + + def attribute_condition(argument) + case argument + when nil then "IS ?" + when Array then "IN (?)" + else "= ?" + end + end + + # Defines an "attribute" method (like #inheritance_column or + # #table_name). A new (class) method will be created with the + # given name. If a value is specified, the new method will + # return that value (as a string). Otherwise, the given block + # will be used to compute the value of the method. + # + # The original method will be aliased, with the new name being + # prefixed with "original_". This allows the new method to + # access the original value. + # + # Example: + # + # class A < ActiveRecord::Base + # define_attr_method :primary_key, "sysid" + # define_attr_method( :inheritance_column ) do + # original_inheritance_column + "_id" + # end + # end + def define_attr_method(name, value=nil, &block) + sing = class << self; self; end + sing.send :alias_method, "original_#{name}", name + if block_given? + sing.send :define_method, name, &block + else + # use eval instead of a block to work around a memory leak in dev + # mode in fcgi + sing.class_eval "def #{name}; #{value.to_s.inspect}; end" + end + end + + protected + def subclasses #:nodoc: + @@subclasses[self] ||= [] + @@subclasses[self] + extra = @@subclasses[self].inject([]) {|list, subclass| list + subclass.subclasses } + end + + # Test whether the given method and optional key are scoped. + def scoped?(method, key = nil) #:nodoc: + if current_scoped_methods && (scope = current_scoped_methods[method]) + !key || scope.has_key?(key) + end + end + + # Retrieve the scope for the given method and optional key. + def scope(method, key = nil) #:nodoc: + if current_scoped_methods && (scope = current_scoped_methods[method]) + key ? scope[key] : scope + end + end + + def thread_safe_scoped_methods #:nodoc: + scoped_methods = (Thread.current[:scoped_methods] ||= {}) + scoped_methods[self] ||= [] + end + + def single_threaded_scoped_methods #:nodoc: + @scoped_methods ||= [] + end + + # pick up the correct scoped_methods version from @@allow_concurrency + if @@allow_concurrency + alias_method :scoped_methods, :thread_safe_scoped_methods + else + alias_method :scoped_methods, :single_threaded_scoped_methods + end + + def current_scoped_methods #:nodoc: + scoped_methods.last + end + + # Returns the class type of the record using the current module as a prefix. So descendents of + # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass. + def compute_type(type_name) + modularized_name = type_name_with_module(type_name) + begin + instance_eval(modularized_name) + rescue NameError => e + instance_eval(type_name) + end + end + + # Returns the class descending directly from ActiveRecord in the inheritance hierarchy. + def class_of_active_record_descendant(klass) + if klass.superclass == Base || klass.superclass.abstract_class? + klass + elsif klass.superclass.nil? + raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord" + else + class_of_active_record_descendant(klass.superclass) + end + end + + # Returns the name of the class descending directly from ActiveRecord in the inheritance hierarchy. + def class_name_of_active_record_descendant(klass) #:nodoc: + klass.base_class.name + end + + # Accepts an array or string. The string is returned untouched, but the array has each value + # sanitized and interpolated into the sql statement. + # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'" + def sanitize_sql(ary) + return ary unless ary.is_a?(Array) + + statement, *values = ary + if values.first.is_a?(Hash) and statement =~ /:\w+/ + replace_named_bind_variables(statement, values.first) + elsif statement.include?('?') + replace_bind_variables(statement, values) + else + statement % values.collect { |value| connection.quote_string(value.to_s) } + end + end + + alias_method :sanitize_conditions, :sanitize_sql + + def replace_bind_variables(statement, values) #:nodoc: + raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size) + bound = values.dup + statement.gsub('?') { quote_bound_value(bound.shift) } + end + + def replace_named_bind_variables(statement, bind_vars) #:nodoc: + statement.gsub(/:(\w+)/) do + match = $1.to_sym + if bind_vars.include?(match) + quote_bound_value(bind_vars[match]) + else + raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}" + end + end + end + + def quote_bound_value(value) #:nodoc: + if (value.respond_to?(:map) && !value.is_a?(String)) + value.map { |v| connection.quote(v) }.join(',') + else + connection.quote(value) + end + end + + def raise_if_bind_arity_mismatch(statement, expected, provided) #:nodoc: + unless expected == provided + raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}" + end + end + + def extract_options_from_args!(args) #:nodoc: + args.last.is_a?(Hash) ? args.pop : {} + end + + VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, + :order, :select, :readonly, :group, :from ] + + def validate_find_options(options) #:nodoc: + options.assert_valid_keys(VALID_FIND_OPTIONS) + end + + def set_readonly_option!(options) #:nodoc: + # Inherit :readonly from finder scope if set. Otherwise, + # if :joins is not blank then :readonly defaults to true. + unless options.has_key?(:readonly) + if scoped?(:find, :readonly) + options[:readonly] = scope(:find, :readonly) + elsif !options[:joins].blank? && !options[:select] + options[:readonly] = true + end + end + end + + def encode_quoted_value(value) #:nodoc: + quoted_value = connection.quote(value) + quoted_value = "'#{quoted_value[1..-2].gsub(/\'/, "\\\\'")}'" if quoted_value.include?("\\\'") # (for ruby mode) " + quoted_value + end + end + + public + # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with + # attributes but not yet saved (pass a hash with key names matching the associated table column names). + # In both instances, valid attribute keys are determined by the column names of the associated table -- + # hence you can't have attributes that aren't part of the table columns. + def initialize(attributes = nil) + @attributes = attributes_from_column_definition + @new_record = true + ensure_proper_type + self.attributes = attributes unless attributes.nil? + yield self if block_given? + end + + # A model instance's primary key is always available as model.id + # whether you name it the default 'id' or set it to something else. + def id + attr_name = self.class.primary_key + column = column_for_attribute(attr_name) + define_read_method(:id, attr_name, column) if self.class.generate_read_methods + read_attribute(attr_name) + end + + # Enables Active Record objects to be used as URL parameters in Action Pack automatically. + alias_method :to_param, :id + + def id_before_type_cast #:nodoc: + read_attribute_before_type_cast(self.class.primary_key) + end + + def quoted_id #:nodoc: + quote(id, column_for_attribute(self.class.primary_key)) + end + + # Sets the primary ID. + def id=(value) + write_attribute(self.class.primary_key, value) + end + + # Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet. + def new_record? + @new_record + end + + # * No record exists: Creates a new record with values matching those of the object attributes. + # * A record does exist: Updates the record with values matching those of the object attributes. + def save + raise ReadOnlyRecord if readonly? + create_or_update + end + + # Attempts to save the record, but instead of just returning false if it couldn't happen, it raises a + # RecordNotSaved exception + def save! + save || raise(RecordNotSaved) + end + + # Deletes the record in the database and freezes this instance to reflect that no changes should + # be made (since they can't be persisted). + def destroy + unless new_record? + connection.delete <<-end_sql, "#{self.class.name} Destroy" + DELETE FROM #{self.class.table_name} + WHERE #{self.class.primary_key} = #{quoted_id} + end_sql + end + + freeze + end + + # Returns a clone of the record that hasn't been assigned an id yet and + # is treated as a new record. Note that this is a "shallow" clone: + # it copies the object's attributes only, not its associations. + # The extent of a "deep" clone is application-specific and is therefore + # left to the application to implement according to its need. + def clone + attrs = self.attributes_before_type_cast + attrs.delete(self.class.primary_key) + self.class.new do |record| + record.send :instance_variable_set, '@attributes', attrs + end + end + + # Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. + # Note: This method is overwritten by the Validation module that'll make sure that updates made with this method + # doesn't get subjected to validation checks. Hence, attributes can be updated even if the full object isn't valid. + def update_attribute(name, value) + send(name.to_s + '=', value) + save + end + + # Updates all the attributes from the passed-in Hash and saves the record. If the object is invalid, the saving will + # fail and false will be returned. + def update_attributes(attributes) + self.attributes = attributes + save + end + + # Initializes the +attribute+ to zero if nil and adds one. Only makes sense for number-based attributes. Returns self. + def increment(attribute) + self[attribute] ||= 0 + self[attribute] += 1 + self + end + + # Increments the +attribute+ and saves the record. + def increment!(attribute) + increment(attribute).update_attribute(attribute, self[attribute]) + end + + # Initializes the +attribute+ to zero if nil and subtracts one. Only makes sense for number-based attributes. Returns self. + def decrement(attribute) + self[attribute] ||= 0 + self[attribute] -= 1 + self + end + + # Decrements the +attribute+ and saves the record. + def decrement!(attribute) + decrement(attribute).update_attribute(attribute, self[attribute]) + end + + # Turns an +attribute+ that's currently true into false and vice versa. Returns self. + def toggle(attribute) + self[attribute] = !send("#{attribute}?") + self + end + + # Toggles the +attribute+ and saves the record. + def toggle!(attribute) + toggle(attribute).update_attribute(attribute, self[attribute]) + end + + # Reloads the attributes of this object from the database. + def reload + clear_aggregation_cache + clear_association_cache + @attributes.update(self.class.find(self.id).instance_variable_get('@attributes')) + self + end + + # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, + # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). + # (Alias for the protected read_attribute method). + def [](attr_name) + read_attribute(attr_name) + end + + # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. + # (Alias for the protected write_attribute method). + def []=(attr_name, value) + write_attribute(attr_name, value) + end + + # Allows you to set all the attributes at once by passing in a hash with keys + # matching the attribute names (which again matches the column names). Sensitive attributes can be protected + # from this form of mass-assignment by using the +attr_protected+ macro. Or you can alternatively + # specify which attributes *can* be accessed in with the +attr_accessible+ macro. Then all the + # attributes not included in that won't be allowed to be mass-assigned. + def attributes=(new_attributes) + return if new_attributes.nil? + attributes = new_attributes.dup + attributes.stringify_keys! + + multi_parameter_attributes = [] + remove_attributes_protected_from_mass_assignment(attributes).each do |k, v| + k.include?("(") ? multi_parameter_attributes << [ k, v ] : send(k + "=", v) + end + + assign_multiparameter_attributes(multi_parameter_attributes) + end + + + # Returns a hash of all the attributes with their names as keys and clones of their objects as values. + def attributes(options = nil) + attributes = clone_attributes :read_attribute + + if options.nil? + attributes + else + if except = options[:except] + except = Array(except).collect { |attribute| attribute.to_s } + except.each { |attribute_name| attributes.delete(attribute_name) } + attributes + elsif only = options[:only] + only = Array(only).collect { |attribute| attribute.to_s } + attributes.delete_if { |key, value| !only.include?(key) } + attributes + else + raise ArgumentError, "Options does not specify :except or :only (#{options.keys.inspect})" + end + end + end + + # Returns a hash of cloned attributes before typecasting and deserialization. + def attributes_before_type_cast + clone_attributes :read_attribute_before_type_cast + end + + # Returns true if the specified +attribute+ has been set by the user or by a database load and is neither + # nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings). + def attribute_present?(attribute) + value = read_attribute(attribute) + !value.blank? or value == 0 + end + + # Returns true if the given attribute is in the attributes hash + def has_attribute?(attr_name) + @attributes.has_key?(attr_name.to_s) + end + + # Returns an array of names for the attributes available on this object sorted alphabetically. + def attribute_names + @attributes.keys.sort + end + + # Returns the column object for the named attribute. + def column_for_attribute(name) + self.class.columns_hash[name.to_s] + end + + # Returns true if the +comparison_object+ is the same object, or is of the same type and has the same id. + def ==(comparison_object) + comparison_object.equal?(self) || + (comparison_object.instance_of?(self.class) && + comparison_object.id == id && + !comparison_object.new_record?) + end + + # Delegates to == + def eql?(comparison_object) + self == (comparison_object) + end + + # Delegates to id in order to allow two records of the same type and id to work with something like: + # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ] + def hash + id.hash + end + + # For checking respond_to? without searching the attributes (which is faster). + alias_method :respond_to_without_attributes?, :respond_to? + + # A Person object with a name attribute can ask person.respond_to?("name"), person.respond_to?("name="), and + # person.respond_to?("name?") which will all return true. + def respond_to?(method, include_priv = false) + if @attributes.nil? + return super + elsif attr_name = self.class.column_methods_hash[method.to_sym] + return true if @attributes.include?(attr_name) || attr_name == self.class.primary_key + return false if self.class.read_methods.include?(attr_name) + elsif @attributes.include?(method_name = method.to_s) + return true + elsif md = /(=|\?|_before_type_cast)$/.match(method_name) + return true if @attributes.include?(md.pre_match) + end + # super must be called at the end of the method, because the inherited respond_to? + # would return true for generated readers, even if the attribute wasn't present + super + end + + # Just freeze the attributes hash, such that associations are still accessible even on destroyed records. + def freeze + @attributes.freeze; self + end + + def frozen? + @attributes.frozen? + end + + # Records loaded through joins with piggy-back attributes will be marked as read only as they cannot be saved and return true to this query. + def readonly? + @readonly == true + end + + def readonly! #:nodoc: + @readonly = true + end + + # Builds an XML document to represent the model. Some configuration is + # availble through +options+, however more complicated cases should use + # Builder. + # + # By default the generated XML document will include the processing + # instruction and all object's attributes. For example: + # + # <?xml version="1.0" encoding="UTF-8"?> + # <topic> + # <title>The First Topic</title> + # <author-name>David</author-name> + # <id type="integer">1</id> + # <approved type="boolean">false</approved> + # <replies-count type="integer">0</replies-count> + # <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time> + # <written-on type="datetime">2003-07-16T09:28:00+1200</written-on> + # <content>Have a nice day</content> + # <author-email-address>david@loudthinking.com</author-email-address> + # <parent-id></parent-id> + # <last-read type="date">2004-04-15</last-read> + # </topic> + # + # This behaviour can be controlled with :only, :except, and :skip_instruct + # for instance: + # + # topic.to_xml(:skip_instruct => true, :except => [ :id, bonus_time, :written_on, replies_count ]) + # + # <topic> + # <title>The First Topic</title> + # <author-name>David</author-name> + # <approved type="boolean">false</approved> + # <content>Have a nice day</content> + # <author-email-address>david@loudthinking.com</author-email-address> + # <parent-id></parent-id> + # <last-read type="date">2004-04-15</last-read> + # </topic> + # + # To include first level associations use :include + # + # firm.to_xml :include => [ :account, :clients ] + # + # <?xml version="1.0" encoding="UTF-8"?> + # <firm> + # <id type="integer">1</id> + # <rating type="integer">1</rating> + # <name>37signals</name> + # <clients> + # <client> + # <rating type="integer">1</rating> + # <name>Summit</name> + # </client> + # <client> + # <rating type="integer">1</rating> + # <name>Microsoft</name> + # </client> + # </clients> + # <account> + # <id type="integer">1</id> + # <credit-limit type="integer">50</credit-limit> + # </account> + # </firm> + def to_xml(options = {}) + options[:root] ||= self.class.to_s.underscore + options[:except] = Array(options[:except]) << self.class.inheritance_column unless options[:only] # skip type column + root_only_or_except = { :only => options[:only], :except => options[:except] } + + attributes_for_xml = attributes(root_only_or_except) + + if include_associations = options.delete(:include) + include_has_options = include_associations.is_a?(Hash) + + for association in include_has_options ? include_associations.keys : Array(include_associations) + association_options = include_has_options ? include_associations[association] : root_only_or_except + + case self.class.reflect_on_association(association).macro + when :has_many, :has_and_belongs_to_many + records = send(association).to_a + unless records.empty? + attributes_for_xml[association] = records.collect do |record| + record.attributes(association_options) + end + end + when :has_one, :belongs_to + if record = send(association) + attributes_for_xml[association] = record.attributes(association_options) + end + end + end + end + + attributes_for_xml.to_xml(options) + end + + private + def create_or_update + if new_record? then create else update end + end + + # Updates the associated record with values matching those of the instance attributes. + def update + connection.update( + "UPDATE #{self.class.table_name} " + + "SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false))} " + + "WHERE #{self.class.primary_key} = #{quote(id)}", + "#{self.class.name} Update" + ) + + return true + end + + # Creates a new record with values matching those of the instance attributes. + def create + if self.id.nil? && connection.prefetch_primary_key?(self.class.table_name) + self.id = connection.next_sequence_value(self.class.sequence_name) + end + + self.id = connection.insert( + "INSERT INTO #{self.class.table_name} " + + "(#{quoted_column_names.join(', ')}) " + + "VALUES(#{attributes_with_quotes.values.join(', ')})", + "#{self.class.name} Create", + self.class.primary_key, self.id, self.class.sequence_name + ) + + @new_record = false + + return true + end + + # Sets the attribute used for single table inheritance to this class name if this is not the ActiveRecord descendent. + # Considering the hierarchy Reply < Message < ActiveRecord, this makes it possible to do Reply.new without having to + # set Reply[Reply.inheritance_column] = "Reply" yourself. No such attribute would be set for objects of the + # Message class in that example. + def ensure_proper_type + unless self.class.descends_from_active_record? + write_attribute(self.class.inheritance_column, Inflector.demodulize(self.class.name)) + end + end + + # Allows access to the object attributes, which are held in the @attributes hash, as were + # they first-class methods. So a Person class with a name attribute can use Person#name and + # Person#name= and never directly use the attributes hash -- except for multiple assigns with + # ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that + # the completed attribute is not nil or 0. + # + # It's also possible to instantiate related objects, so a Client class belonging to the clients + # table with a master_id foreign key can instantiate master through Client#master. + def method_missing(method_id, *args, &block) + method_name = method_id.to_s + if @attributes.include?(method_name) or + (md = /\?$/.match(method_name) and + @attributes.include?(method_name = md.pre_match)) + define_read_methods if self.class.read_methods.empty? && self.class.generate_read_methods + md ? query_attribute(method_name) : read_attribute(method_name) + elsif self.class.primary_key.to_s == method_name + id + elsif md = /(=|_before_type_cast)$/.match(method_name) + attribute_name, method_type = md.pre_match, md.to_s + if @attributes.include?(attribute_name) + case method_type + when '=' + write_attribute(attribute_name, args.first) + when '_before_type_cast' + read_attribute_before_type_cast(attribute_name) + end + else + super + end + else + super + end + end + + # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, + # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). + def read_attribute(attr_name) + attr_name = attr_name.to_s + if !(value = @attributes[attr_name]).nil? + if column = column_for_attribute(attr_name) + if unserializable_attribute?(attr_name, column) + unserialize_attribute(attr_name) + else + column.type_cast(value) + end + else + value + end + else + nil + end + end + + def read_attribute_before_type_cast(attr_name) + @attributes[attr_name] + end + + # Called on first read access to any given column and generates reader + # methods for all columns in the columns_hash if + # ActiveRecord::Base.generate_read_methods is set to true. + def define_read_methods + self.class.columns_hash.each do |name, column| + unless self.class.serialized_attributes[name] + define_read_method(name.to_sym, name, column) unless respond_to_without_attributes?(name) + define_question_method(name) unless respond_to_without_attributes?("#{name}?") + end + end + end + + # Define an attribute reader method. Cope with nil column. + def define_read_method(symbol, attr_name, column) + cast_code = column.type_cast_code('v') if column + access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']" + + unless attr_name.to_s == self.class.primary_key.to_s + access_code = access_code.insert(0, "raise NoMethodError, 'missing attribute: #{attr_name}', caller unless @attributes.has_key?('#{attr_name}'); ") + self.class.read_methods << attr_name + end + + evaluate_read_method attr_name, "def #{symbol}; #{access_code}; end" + end + + # Define an attribute ? method. + def define_question_method(attr_name) + unless attr_name.to_s == self.class.primary_key.to_s + self.class.read_methods << "#{attr_name}?" + end + + evaluate_read_method attr_name, "def #{attr_name}?; query_attribute('#{attr_name}'); end" + end + + # Evaluate the definition for an attribute reader or ? method + def evaluate_read_method(attr_name, method_definition) + begin + self.class.class_eval(method_definition) + rescue SyntaxError => err + self.class.read_methods.delete(attr_name) + if logger + logger.warn "Exception occured during reader method compilation." + logger.warn "Maybe #{attr_name} is not a valid Ruby identifier?" + logger.warn "#{err.message}" + end + end + end + + # Returns true if the attribute is of a text column and marked for serialization. + def unserializable_attribute?(attr_name, column) + column.text? && self.class.serialized_attributes[attr_name] + end + + # Returns the unserialized object of the attribute. + def unserialize_attribute(attr_name) + unserialized_object = object_from_yaml(@attributes[attr_name]) + + if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) + @attributes[attr_name] = unserialized_object + else + raise SerializationTypeMismatch, + "#{attr_name} was supposed to be a #{self.class.serialized_attributes[attr_name]}, but was a #{unserialized_object.class.to_s}" + end + end + + # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float + # columns are turned into nil. + def write_attribute(attr_name, value) + attr_name = attr_name.to_s + if (column = column_for_attribute(attr_name)) && column.number? + @attributes[attr_name] = convert_number_column_value(value) + else + @attributes[attr_name] = value + end + end + + def convert_number_column_value(value) + case value + when FalseClass: 0 + when TrueClass: 1 + when '': nil + else value + end + end + + def query_attribute(attr_name) + attribute = @attributes[attr_name] + if attribute.kind_of?(Fixnum) && attribute == 0 + false + elsif attribute.kind_of?(String) && attribute == "0" + false + elsif attribute.kind_of?(String) && attribute.empty? + false + elsif attribute.nil? + false + elsif attribute == false + false + elsif attribute == "f" + false + elsif attribute == "false" + false + else + true + end + end + + def remove_attributes_protected_from_mass_assignment(attributes) + if self.class.accessible_attributes.nil? && self.class.protected_attributes.nil? + attributes.reject { |key, value| attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) } + elsif self.class.protected_attributes.nil? + attributes.reject { |key, value| !self.class.accessible_attributes.include?(key.gsub(/\(.+/, "").intern) || attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) } + elsif self.class.accessible_attributes.nil? + attributes.reject { |key, value| self.class.protected_attributes.include?(key.gsub(/\(.+/,"").intern) || attributes_protected_by_default.include?(key.gsub(/\(.+/, "")) } + end + end + + # The primary key and inheritance column can never be set by mass-assignment for security reasons. + def attributes_protected_by_default + default = [ self.class.primary_key, self.class.inheritance_column ] + default << 'id' unless self.class.primary_key.eql? 'id' + default + end + + # Returns copy of the attributes hash where all the values have been safely quoted for use in + # an SQL statement. + def attributes_with_quotes(include_primary_key = true) + attributes.inject({}) do |quoted, (name, value)| + if column = column_for_attribute(name) + quoted[name] = quote(value, column) unless !include_primary_key && column.primary + end + quoted + end + end + + # Quote strings appropriately for SQL statements. + def quote(value, column = nil) + self.class.connection.quote(value, column) + end + + # Interpolate custom sql string in instance context. + # Optional record argument is meant for custom insert_sql. + def interpolate_sql(sql, record = nil) + instance_eval("%@#{sql.gsub('@', '\@')}@") + end + + # Initializes the attributes array with keys matching the columns from the linked table and + # the values matching the corresponding default value of that column, so + # that a new instance, or one populated from a passed-in Hash, still has all the attributes + # that instances loaded from the database would. + def attributes_from_column_definition + self.class.columns.inject({}) do |attributes, column| + attributes[column.name] = column.default unless column.name == self.class.primary_key + attributes + end + end + + # Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done + # by calling new on the column type or aggregation type (through composed_of) object with these parameters. + # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate + # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the + # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum, f for Float, + # s for String, and a for Array. If all the values for a given attribute is empty, the attribute will be set to nil. + def assign_multiparameter_attributes(pairs) + execute_callstack_for_multiparameter_attributes( + extract_callstack_for_multiparameter_attributes(pairs) + ) + end + + # Includes an ugly hack for Time.local instead of Time.new because the latter is reserved by Time itself. + def execute_callstack_for_multiparameter_attributes(callstack) + errors = [] + callstack.each do |name, values| + klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass + if values.empty? + send(name + "=", nil) + else + begin + send(name + "=", Time == klass ? klass.local(*values) : klass.new(*values)) + rescue => ex + errors << AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name) + end + end + end + unless errors.empty? + raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes" + end + end + + def extract_callstack_for_multiparameter_attributes(pairs) + attributes = { } + + for pair in pairs + multiparameter_name, value = pair + attribute_name = multiparameter_name.split("(").first + attributes[attribute_name] = [] unless attributes.include?(attribute_name) + + unless value.empty? + attributes[attribute_name] << + [ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ] + end + end + + attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } } + end + + def type_cast_attribute_value(multiparameter_name, value) + multiparameter_name =~ /\([0-9]*([a-z])\)/ ? value.send("to_" + $1) : value + end + + def find_parameter_position(multiparameter_name) + multiparameter_name.scan(/\(([0-9]*).*\)/).first.first + end + + # Returns a comma-separated pair list, like "key1 = val1, key2 = val2". + def comma_pair_list(hash) + hash.inject([]) { |list, pair| list << "#{pair.first} = #{pair.last}" }.join(", ") + end + + def quoted_column_names(attributes = attributes_with_quotes) + attributes.keys.collect do |column_name| + self.class.connection.quote_column_name(column_name) + end + end + + def quote_columns(quoter, hash) + hash.inject({}) do |quoted, (name, value)| + quoted[quoter.quote_column_name(name)] = value + quoted + end + end + + def quoted_comma_pair_list(quoter, hash) + comma_pair_list(quote_columns(quoter, hash)) + end + + def object_from_yaml(string) + return string unless string.is_a?(String) + YAML::load(string) rescue string + end + + def clone_attributes(reader_method = :read_attribute, attributes = {}) + self.attribute_names.inject(attributes) do |attributes, name| + attributes[name] = clone_attribute_value(reader_method, name) + attributes + end + end + + def clone_attribute_value(reader_method, attribute_name) + value = send(reader_method, attribute_name) + value.clone + rescue TypeError, NoMethodError + value + end + end +end +module ActiveRecord + module Calculations #:nodoc: + CALCULATIONS_OPTIONS = [:conditions, :joins, :order, :select, :group, :having, :distinct, :limit, :offset] + def self.included(base) + base.extend(ClassMethods) + end + + module ClassMethods + # Count operates using three different approaches. + # + # * Count all: By not passing any parameters to count, it will return a count of all the rows for the model. + # * Count by conditions or joins: For backwards compatibility, you can pass in +conditions+ and +joins+ as individual parameters. + # * Count using options will find the row count matched by the options used. + # + # The last approach, count using options, accepts an option hash as the only parameter. The options are: + # + # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro. + # * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed). + # The records will be returned read-only since they will have attributes that do not correspond to the table's columns. + # * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer + # to already defined associations. When using named associations count returns the number DISTINCT items for the model you're counting. + # See eager loading under Associations. + # * <tt>:order</tt>: An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations). + # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. + # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not + # include the joined columns. + # * <tt>:distinct</tt>: Set this to true to make this a distinct calculation, such as SELECT COUNT(DISTINCT posts.id) ... + # + # Examples for counting all: + # Person.count # returns the total count of all people + # + # Examples for count by +conditions+ and +joins+ (for backwards compatibility): + # Person.count("age > 26") # returns the number of people older than 26 + # Person.find("age > 26 AND job.salary > 60000", "LEFT JOIN jobs on jobs.person_id = person.id") # returns the total number of rows matching the conditions and joins fetched by SELECT COUNT(*). + # + # Examples for count with options: + # Person.count(:conditions => "age > 26") + # Person.count(:conditions => "age > 26 AND job.salary > 60000", :include => :job) # because of the named association, it finds the DISTINCT count using LEFT OUTER JOIN. + # Person.count(:conditions => "age > 26 AND job.salary > 60000", :joins => "LEFT JOIN jobs on jobs.person_id = person.id") # finds the number of rows matching the conditions and joins. + # Person.count('id', :conditions => "age > 26") # Performs a COUNT(id) + # Person.count(:all, :conditions => "age > 26") # Performs a COUNT(*) (:all is an alias for '*') + # + # Note: Person.count(:all) will not work because it will use :all as the condition. Use Person.count instead. + def count(*args) + options = {} + column_name = :all + # For backwards compatibility, we need to handle both count(conditions=nil, joins=nil) or count(options={}) or count(column_name=:all, options={}). + if args.size >= 0 && args.size <= 2 + if args.first.is_a?(Hash) + options = args.first + elsif args[1].is_a?(Hash) + options = args[1] + column_name = args.first + else + # Handle legacy paramter options: def count(conditions=nil, joins=nil) + options.merge!(:conditions => args[0]) if args.length > 0 + options.merge!(:joins => args[1]) if args.length > 1 + end + else + raise(ArgumentError, "Unexpected parameters passed to count(*args): expected either count(conditions=nil, joins=nil) or count(options={})") + end + + if options[:include] || scope(:find, :include) + count_with_associations(options) + else + calculate(:count, column_name, options) + end + end + + # Calculates average value on a given column. The value is returned as a float. See #calculate for examples with options. + # + # Person.average('age') + def average(column_name, options = {}) + calculate(:avg, column_name, options) + end + + # Calculates the minimum value on a given column. The value is returned with the same data type of the column.. See #calculate for examples with options. + # + # Person.minimum('age') + def minimum(column_name, options = {}) + calculate(:min, column_name, options) + end + + # Calculates the maximum value on a given column. The value is returned with the same data type of the column.. See #calculate for examples with options. + # + # Person.maximum('age') + def maximum(column_name, options = {}) + calculate(:max, column_name, options) + end + + # Calculates the sum value on a given column. The value is returned with the same data type of the column.. See #calculate for examples with options. + # + # Person.sum('age') + def sum(column_name, options = {}) + calculate(:sum, column_name, options) + end + + # This calculates aggregate values in the given column: Methods for count, sum, average, minimum, and maximum have been added as shortcuts. + # Options such as :conditions, :order, :group, :having, and :joins can be passed to customize the query. + # + # There are two basic forms of output: + # * Single aggregate value: The single value is type cast to Fixnum for COUNT, Float for AVG, and the given column's type for everything else. + # * Grouped values: This returns an ordered hash of the values and groups them by the :group option. It takes either a column name, or the name + # of a belongs_to association. + # + # values = Person.maximum(:age, :group => 'last_name') + # puts values["Drake"] + # => 43 + # + # drake = Family.find_by_last_name('Drake') + # values = Person.maximum(:age, :group => :family) # Person belongs_to :family + # puts values[drake] + # => 43 + # + # values.each do |family, max_age| + # ... + # end + # + # Options: + # * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro. + # * <tt>:joins</tt>: An SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id". (Rarely needed). + # The records will be returned read-only since they will have attributes that do not correspond to the table's columns. + # * <tt>:order</tt>: An SQL fragment like "created_at DESC, name" (really only used with GROUP BY calculations). + # * <tt>:group</tt>: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. + # * <tt>:select</tt>: By default, this is * as in SELECT * FROM, but can be changed if you for example want to do a join, but not + # include the joined columns. + # * <tt>:distinct</tt>: Set this to true to make this a distinct calculation, such as SELECT COUNT(DISTINCT posts.id) ... + # + # Examples: + # Person.calculate(:count, :all) # The same as Person.count + # Person.average(:age) # SELECT AVG(age) FROM people... + # Person.minimum(:age, :conditions => ['last_name != ?', 'Drake']) # Selects the minimum age for everyone with a last name other than 'Drake' + # Person.minimum(:age, :having => 'min(age) > 17', :group => :last_name) # Selects the minimum age for any family without any minors + def calculate(operation, column_name, options = {}) + validate_calculation_options(operation, options) + column_name = options[:select] if options[:select] + column_name = '*' if column_name == :all + column = column_for column_name + aggregate = select_aggregate(operation, column_name, options) + aggregate_alias = column_alias_for(operation, column_name) + if options[:group] + execute_grouped_calculation(operation, column_name, column, aggregate, aggregate_alias, options) + else + execute_simple_calculation(operation, column_name, column, aggregate, aggregate_alias, options) + end + end + + protected + def construct_calculation_sql(aggregate, aggregate_alias, options) #:nodoc: + scope = scope(:find) + sql = "SELECT #{aggregate} AS #{aggregate_alias}" + sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group] + sql << " FROM #{table_name} " + add_joins!(sql, options, scope) + add_conditions!(sql, options[:conditions], scope) + sql << " GROUP BY #{options[:group_field]}" if options[:group] + sql << " HAVING #{options[:having]}" if options[:group] && options[:having] + sql << " ORDER BY #{options[:order]}" if options[:order] + add_limit!(sql, options) + sql + end + + def execute_simple_calculation(operation, column_name, column, aggregate, aggregate_alias, options) #:nodoc: + value = connection.select_value(construct_calculation_sql(aggregate, aggregate_alias, options)) + type_cast_calculated_value(value, column, operation) + end + + def execute_grouped_calculation(operation, column_name, column, aggregate, aggregate_alias, options) #:nodoc: + group_attr = options[:group].to_s + association = reflect_on_association(group_attr.to_sym) + associated = association && association.macro == :belongs_to # only count belongs_to associations + group_field = (associated ? "#{options[:group]}_id" : options[:group]).to_s + group_alias = column_alias_for(group_field) + group_column = column_for group_field + sql = construct_calculation_sql(aggregate, aggregate_alias, options.merge(:group_field => group_field, :group_alias => group_alias)) + calculated_data = connection.select_all(sql) + + if association + key_ids = calculated_data.collect { |row| row[group_alias] } + key_records = association.klass.base_class.find(key_ids) + key_records = key_records.inject({}) { |hsh, r| hsh.merge(r.id => r) } + end + + calculated_data.inject(OrderedHash.new) do |all, row| + key = associated ? key_records[row[group_alias].to_i] : type_cast_calculated_value(row[group_alias], group_column) + value = row[aggregate_alias] + all << [key, type_cast_calculated_value(value, column, operation)] + end + end + + private + def validate_calculation_options(operation, options = {}) + if operation.to_s == 'count' + options.assert_valid_keys(CALCULATIONS_OPTIONS + [:include]) + else + options.assert_valid_keys(CALCULATIONS_OPTIONS) + end + end + + def select_aggregate(operation, column_name, options) + "#{operation}(#{'DISTINCT ' if options[:distinct]}#{column_name})" + end + + # converts a given key to the value that the database adapter returns as + # + # users.id #=> users_id + # sum(id) #=> sum_id + # count(distinct users.id) #=> count_distinct_users_id + # count(*) #=> count_all + def column_alias_for(*keys) + keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_') + end + + def column_for(field) + field_name = field.to_s.split('.').last + columns.detect { |c| c.name.to_s == field_name } + end + + def type_cast_calculated_value(value, column, operation = nil) + operation = operation.to_s.downcase + case operation + when 'count' then value.to_i + when 'avg' then value.to_f + else column ? column.type_cast(value) : value + end + end + end + end +end +require 'observer' + +module ActiveRecord + # Callbacks are hooks into the lifecycle of an Active Record object that allows you to trigger logic + # before or after an alteration of the object state. This can be used to make sure that associated and + # dependent objects are deleted when destroy is called (by overwriting before_destroy) or to massage attributes + # before they're validated (by overwriting before_validation). As an example of the callbacks initiated, consider + # the Base#save call: + # + # * (-) save + # * (-) valid? + # * (1) before_validation + # * (2) before_validation_on_create + # * (-) validate + # * (-) validate_on_create + # * (3) after_validation + # * (4) after_validation_on_create + # * (5) before_save + # * (6) before_create + # * (-) create + # * (7) after_create + # * (8) after_save + # + # That's a total of eight callbacks, which gives you immense power to react and prepare for each state in the + # Active Record lifecycle. + # + # Examples: + # class CreditCard < ActiveRecord::Base + # # Strip everything but digits, so the user can specify "555 234 34" or + # # "5552-3434" or both will mean "55523434" + # def before_validation_on_create + # self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number") + # end + # end + # + # class Subscription < ActiveRecord::Base + # before_create :record_signup + # + # private + # def record_signup + # self.signed_up_on = Date.today + # end + # end + # + # class Firm < ActiveRecord::Base + # # Destroys the associated clients and people when the firm is destroyed + # before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" } + # before_destroy { |record| Client.destroy_all "client_of = #{record.id}" } + # end + # + # == Inheritable callback queues + # + # Besides the overwriteable callback methods, it's also possible to register callbacks through the use of the callback macros. + # Their main advantage is that the macros add behavior into a callback queue that is kept intact down through an inheritance + # hierarchy. Example: + # + # class Topic < ActiveRecord::Base + # before_destroy :destroy_author + # end + # + # class Reply < Topic + # before_destroy :destroy_readers + # end + # + # Now, when Topic#destroy is run only +destroy_author+ is called. When Reply#destroy is run both +destroy_author+ and + # +destroy_readers+ is called. Contrast this to the situation where we've implemented the save behavior through overwriteable + # methods: + # + # class Topic < ActiveRecord::Base + # def before_destroy() destroy_author end + # end + # + # class Reply < Topic + # def before_destroy() destroy_readers end + # end + # + # In that case, Reply#destroy would only run +destroy_readers+ and _not_ +destroy_author+. So use the callback macros when + # you want to ensure that a certain callback is called for the entire hierarchy and the regular overwriteable methods when you + # want to leave it up to each descendent to decide whether they want to call +super+ and trigger the inherited callbacks. + # + # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the callbacks before specifying the + # associations. Otherwise, you might trigger the loading of a child before the parent has registered the callbacks and they won't + # be inherited. + # + # == Types of callbacks + # + # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects, + # inline methods (using a proc), and inline eval methods (using a string). Method references and callback objects are the + # recommended approaches, inline methods using a proc are sometimes appropriate (such as for creating mix-ins), and inline + # eval methods are deprecated. + # + # The method reference callbacks work by specifying a protected or private method available in the object, like this: + # + # class Topic < ActiveRecord::Base + # before_destroy :delete_parents + # + # private + # def delete_parents + # self.class.delete_all "parent_id = #{id}" + # end + # end + # + # The callback objects have methods named after the callback called with the record as the only parameter, such as: + # + # class BankAccount < ActiveRecord::Base + # before_save EncryptionWrapper.new("credit_card_number") + # after_save EncryptionWrapper.new("credit_card_number") + # after_initialize EncryptionWrapper.new("credit_card_number") + # end + # + # class EncryptionWrapper + # def initialize(attribute) + # @attribute = attribute + # end + # + # def before_save(record) + # record.credit_card_number = encrypt(record.credit_card_number) + # end + # + # def after_save(record) + # record.credit_card_number = decrypt(record.credit_card_number) + # end + # + # alias_method :after_find, :after_save + # + # private + # def encrypt(value) + # # Secrecy is committed + # end + # + # def decrypt(value) + # # Secrecy is unveiled + # end + # end + # + # So you specify the object you want messaged on a given callback. When that callback is triggered, the object has + # a method by the name of the callback messaged. + # + # The callback macros usually accept a symbol for the method they're supposed to run, but you can also pass a "method string", + # which will then be evaluated within the binding of the callback. Example: + # + # class Topic < ActiveRecord::Base + # before_destroy 'self.class.delete_all "parent_id = #{id}"' + # end + # + # Notice that single plings (') are used so the #{id} part isn't evaluated until the callback is triggered. Also note that these + # inline callbacks can be stacked just like the regular ones: + # + # class Topic < ActiveRecord::Base + # before_destroy 'self.class.delete_all "parent_id = #{id}"', + # 'puts "Evaluated after parents are destroyed"' + # end + # + # == The after_find and after_initialize exceptions + # + # Because after_find and after_initialize are called for each object found and instantiated by a finder, such as Base.find(:all), we've had + # to implement a simple performance constraint (50% more speed on a simple test case). Unlike all the other callbacks, after_find and + # after_initialize will only be run if an explicit implementation is defined (<tt>def after_find</tt>). In that case, all of the + # callback types will be called. + # + # == Cancelling callbacks + # + # If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns + # false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks + # defined as methods on the model, which are called last. + module Callbacks + CALLBACKS = %w( + after_find after_initialize before_save after_save before_create after_create before_update after_update before_validation + after_validation before_validation_on_create after_validation_on_create before_validation_on_update + after_validation_on_update before_destroy after_destroy + ) + + def self.append_features(base) #:nodoc: + super + + base.extend(ClassMethods) + base.class_eval do + class << self + include Observable + alias_method :instantiate_without_callbacks, :instantiate + alias_method :instantiate, :instantiate_with_callbacks + end + + alias_method :initialize_without_callbacks, :initialize + alias_method :initialize, :initialize_with_callbacks + + alias_method :create_or_update_without_callbacks, :create_or_update + alias_method :create_or_update, :create_or_update_with_callbacks + + alias_method :valid_without_callbacks, :valid? + alias_method :valid?, :valid_with_callbacks + + alias_method :create_without_callbacks, :create + alias_method :create, :create_with_callbacks + + alias_method :update_without_callbacks, :update + alias_method :update, :update_with_callbacks + + alias_method :destroy_without_callbacks, :destroy + alias_method :destroy, :destroy_with_callbacks + end + + CALLBACKS.each do |method| + base.class_eval <<-"end_eval" + def self.#{method}(*callbacks, &block) + callbacks << block if block_given? + write_inheritable_array(#{method.to_sym.inspect}, callbacks) + end + end_eval + end + end + + module ClassMethods #:nodoc: + def instantiate_with_callbacks(record) + object = instantiate_without_callbacks(record) + + if object.respond_to_without_attributes?(:after_find) + object.send(:callback, :after_find) + end + + if object.respond_to_without_attributes?(:after_initialize) + object.send(:callback, :after_initialize) + end + + object + end + end + + # Is called when the object was instantiated by one of the finders, like Base.find. + #def after_find() end + + # Is called after the object has been instantiated by a call to Base.new. + #def after_initialize() end + + def initialize_with_callbacks(attributes = nil) #:nodoc: + initialize_without_callbacks(attributes) + result = yield self if block_given? + callback(:after_initialize) if respond_to_without_attributes?(:after_initialize) + result + end + + # Is called _before_ Base.save (regardless of whether it's a create or update save). + def before_save() end + + # Is called _after_ Base.save (regardless of whether it's a create or update save). + # + # class Contact < ActiveRecord::Base + # after_save { logger.info( 'New contact saved!' ) } + # end + def after_save() end + def create_or_update_with_callbacks #:nodoc: + return false if callback(:before_save) == false + result = create_or_update_without_callbacks + callback(:after_save) + result + end + + # Is called _before_ Base.save on new objects that haven't been saved yet (no record exists). + def before_create() end + + # Is called _after_ Base.save on new objects that haven't been saved yet (no record exists). + def after_create() end + def create_with_callbacks #:nodoc: + return false if callback(:before_create) == false + result = create_without_callbacks + callback(:after_create) + result + end + + # Is called _before_ Base.save on existing objects that have a record. + def before_update() end + + # Is called _after_ Base.save on existing objects that have a record. + def after_update() end + + def update_with_callbacks #:nodoc: + return false if callback(:before_update) == false + result = update_without_callbacks + callback(:after_update) + result + end + + # Is called _before_ Validations.validate (which is part of the Base.save call). + def before_validation() end + + # Is called _after_ Validations.validate (which is part of the Base.save call). + def after_validation() end + + # Is called _before_ Validations.validate (which is part of the Base.save call) on new objects + # that haven't been saved yet (no record exists). + def before_validation_on_create() end + + # Is called _after_ Validations.validate (which is part of the Base.save call) on new objects + # that haven't been saved yet (no record exists). + def after_validation_on_create() end + + # Is called _before_ Validations.validate (which is part of the Base.save call) on + # existing objects that have a record. + def before_validation_on_update() end + + # Is called _after_ Validations.validate (which is part of the Base.save call) on + # existing objects that have a record. + def after_validation_on_update() end + + def valid_with_callbacks #:nodoc: + return false if callback(:before_validation) == false + if new_record? then result = callback(:before_validation_on_create) else result = callback(:before_validation_on_update) end + return false if result == false + + result = valid_without_callbacks + + callback(:after_validation) + if new_record? then callback(:after_validation_on_create) else callback(:after_validation_on_update) end + + return result + end + + # Is called _before_ Base.destroy. + # + # Note: If you need to _destroy_ or _nullify_ associated records first, + # use the _:dependent_ option on your associations. + def before_destroy() end + + # Is called _after_ Base.destroy (and all the attributes have been frozen). + # + # class Contact < ActiveRecord::Base + # after_destroy { |record| logger.info( "Contact #{record.id} was destroyed." ) } + # end + def after_destroy() end + def destroy_with_callbacks #:nodoc: + return false if callback(:before_destroy) == false + result = destroy_without_callbacks + callback(:after_destroy) + result + end + + private + def callback(method) + notify(method) + + callbacks_for(method).each do |callback| + result = case callback + when Symbol + self.send(callback) + when String + eval(callback, binding) + when Proc, Method + callback.call(self) + else + if callback.respond_to?(method) + callback.send(method, self) + else + raise ActiveRecordError, "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method." + end + end + return false if result == false + end + + result = send(method) if respond_to_without_attributes?(method) + + return result + end + + def callbacks_for(method) + self.class.read_inheritable_attribute(method.to_sym) or [] + end + + def invoke_and_notify(method) + notify(method) + send(method) if respond_to_without_attributes?(method) + end + + def notify(method) #:nodoc: + self.class.changed + self.class.notify_observers(method, self) + end + end +end +require 'set' + +module ActiveRecord + class Base + class ConnectionSpecification #:nodoc: + attr_reader :config, :adapter_method + def initialize (config, adapter_method) + @config, @adapter_method = config, adapter_method + end + end + + # Check for activity after at least +verification_timeout+ seconds. + # Defaults to 0 (always check.) + cattr_accessor :verification_timeout + @@verification_timeout = 0 + + # The class -> [adapter_method, config] map + @@defined_connections = {} + + # The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency) + @@active_connections = {} + + class << self + # Retrieve the connection cache. + def thread_safe_active_connections #:nodoc: + @@active_connections[Thread.current.object_id] ||= {} + end + + def single_threaded_active_connections #:nodoc: + @@active_connections + end + + # pick up the right active_connection method from @@allow_concurrency + if @@allow_concurrency + alias_method :active_connections, :thread_safe_active_connections + else + alias_method :active_connections, :single_threaded_active_connections + end + + # set concurrency support flag (not thread safe, like most of the methods in this file) + def allow_concurrency=(threaded) #:nodoc: + logger.debug "allow_concurrency=#{threaded}" if logger + return if @@allow_concurrency == threaded + clear_all_cached_connections! + @@allow_concurrency = threaded + method_prefix = threaded ? "thread_safe" : "single_threaded" + sing = (class << self; self; end) + [:active_connections, :scoped_methods].each do |method| + sing.send(:alias_method, method, "#{method_prefix}_#{method}") + end + log_connections if logger + end + + def active_connection_name #:nodoc: + @active_connection_name ||= + if active_connections[name] || @@defined_connections[name] + name + elsif self == ActiveRecord::Base + nil + else + superclass.active_connection_name + end + end + + def clear_active_connection_name #:nodoc: + @active_connection_name = nil + subclasses.each { |klass| klass.clear_active_connection_name } + end + + # Returns the connection currently associated with the class. This can + # also be used to "borrow" the connection to do database work unrelated + # to any of the specific Active Records. + def connection + if @active_connection_name && (conn = active_connections[@active_connection_name]) + conn + else + # retrieve_connection sets the cache key. + conn = retrieve_connection + active_connections[@active_connection_name] = conn + end + end + + # Clears the cache which maps classes to connections. + def clear_active_connections! + clear_cache!(@@active_connections) do |name, conn| + conn.disconnect! + end + end + + # Verify active connections. + def verify_active_connections! #:nodoc: + if @@allow_concurrency + remove_stale_cached_threads!(@@active_connections) do |name, conn| + conn.disconnect! + end + end + + active_connections.each_value do |connection| + connection.verify!(@@verification_timeout) + end + end + + private + def clear_cache!(cache, thread_id = nil, &block) + if cache + if @@allow_concurrency + thread_id ||= Thread.current.object_id + thread_cache, cache = cache, cache[thread_id] + return unless cache + end + + cache.each(&block) if block_given? + cache.clear + end + ensure + if thread_cache && @@allow_concurrency + thread_cache.delete(thread_id) + end + end + + # Remove stale threads from the cache. + def remove_stale_cached_threads!(cache, &block) + stale = Set.new(cache.keys) + + Thread.list.each do |thread| + stale.delete(thread.object_id) if thread.alive? + end + + stale.each do |thread_id| + clear_cache!(cache, thread_id, &block) + end + end + + def clear_all_cached_connections! + if @@allow_concurrency + @@active_connections.each_value do |connection_hash_for_thread| + connection_hash_for_thread.each_value {|conn| conn.disconnect! } + connection_hash_for_thread.clear + end + else + @@active_connections.each_value {|conn| conn.disconnect! } + end + @@active_connections.clear + end + end + + # Returns the connection currently associated with the class. This can + # also be used to "borrow" the connection to do database work that isn't + # easily done without going straight to SQL. + def connection + self.class.connection + end + + # Establishes the connection to the database. Accepts a hash as input where + # the :adapter key must be specified with the name of a database adapter (in lower-case) + # example for regular databases (MySQL, Postgresql, etc): + # + # ActiveRecord::Base.establish_connection( + # :adapter => "mysql", + # :host => "localhost", + # :username => "myuser", + # :password => "mypass", + # :database => "somedatabase" + # ) + # + # Example for SQLite database: + # + # ActiveRecord::Base.establish_connection( + # :adapter => "sqlite", + # :database => "path/to/dbfile" + # ) + # + # Also accepts keys as strings (for parsing from yaml for example): + # ActiveRecord::Base.establish_connection( + # "adapter" => "sqlite", + # "database" => "path/to/dbfile" + # ) + # + # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError + # may be returned on an error. + def self.establish_connection(spec = nil) + case spec + when nil + raise AdapterNotSpecified unless defined? RAILS_ENV + establish_connection(RAILS_ENV) + when ConnectionSpecification + clear_active_connection_name + @active_connection_name = name + @@defined_connections[name] = spec + when Symbol, String + if configuration = configurations[spec.to_s] + establish_connection(configuration) + else + raise AdapterNotSpecified, "#{spec} database is not configured" + end + else + spec = spec.symbolize_keys + unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end + adapter_method = "#{spec[:adapter]}_connection" + unless respond_to?(adapter_method) then raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter" end + remove_connection + establish_connection(ConnectionSpecification.new(spec, adapter_method)) + end + end + + # Locate the connection of the nearest super class. This can be an + # active or defined connections: if it is the latter, it will be + # opened and set as the active connection for the class it was defined + # for (not necessarily the current class). + def self.retrieve_connection #:nodoc: + # Name is nil if establish_connection hasn't been called for + # some class along the inheritance chain up to AR::Base yet. + if name = active_connection_name + if conn = active_connections[name] + # Verify the connection. + conn.verify!(@@verification_timeout) + elsif spec = @@defined_connections[name] + # Activate this connection specification. + klass = name.constantize + klass.connection = spec + conn = active_connections[name] + end + end + + conn or raise ConnectionNotEstablished + end + + # Returns true if a connection that's accessible to this class have already been opened. + def self.connected? + active_connections[active_connection_name] ? true : false + end + + # Remove the connection for this class. This will close the active + # connection and the defined connection (if they exist). The result + # can be used as argument for establish_connection, for easy + # re-establishing of the connection. + def self.remove_connection(klass=self) + spec = @@defined_connections[klass.name] + konn = active_connections[klass.name] + @@defined_connections.delete_if { |key, value| value == spec } + active_connections.delete_if { |key, value| value == konn } + konn.disconnect! if konn + spec.config if spec + end + + # Set the connection for the class. + def self.connection=(spec) #:nodoc: + if spec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter) + active_connections[name] = spec + elsif spec.kind_of?(ConnectionSpecification) + self.connection = self.send(spec.adapter_method, spec.config) + elsif spec.nil? + raise ConnectionNotEstablished + else + establish_connection spec + end + end + + # connection state logging + def self.log_connections #:nodoc: + if logger + logger.info "Defined connections: #{@@defined_connections.inspect}" + logger.info "Active connections: #{active_connections.inspect}" + logger.info "Active connection name: #{@active_connection_name}" + end + end + end +end +module ActiveRecord + module ConnectionAdapters # :nodoc: + module DatabaseStatements + # Returns an array of record hashes with the column names as keys and + # column values as values. + def select_all(sql, name = nil) + end + + # Returns a record hash with the column names as keys and column values + # as values. + def select_one(sql, name = nil) + end + + # Returns a single value from a record + def select_value(sql, name = nil) + result = select_one(sql, name) + result.nil? ? nil : result.values.first + end + + # Returns an array of the values of the first column in a select: + # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3] + def select_values(sql, name = nil) + result = select_all(sql, name) + result.map{ |v| v.values.first } + end + + # Executes the SQL statement in the context of this connection. + # This abstract method raises a NotImplementedError. + def execute(sql, name = nil) + raise NotImplementedError, "execute is an abstract method" + end + + # Returns the last auto-generated ID from the affected table. + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) end + + # Executes the update statement and returns the number of rows affected. + def update(sql, name = nil) end + + # Executes the delete statement and returns the number of rows affected. + def delete(sql, name = nil) end + + # Wrap a block in a transaction. Returns result of block. + def transaction(start_db_transaction = true) + transaction_open = false + begin + if block_given? + if start_db_transaction + begin_db_transaction + transaction_open = true + end + yield + end + rescue Exception => database_transaction_rollback + if transaction_open + transaction_open = false + rollback_db_transaction + end + raise + end + ensure + commit_db_transaction if transaction_open + end + + # Begins the transaction (and turns off auto-committing). + def begin_db_transaction() end + + # Commits the transaction (and turns on auto-committing). + def commit_db_transaction() end + + # Rolls back the transaction (and turns on auto-committing). Must be + # done if the transaction block raises an exception or returns false. + def rollback_db_transaction() end + + # Alias for #add_limit_offset!. + def add_limit!(sql, options) + add_limit_offset!(sql, options) if options + end + + # Appends +LIMIT+ and +OFFSET+ options to a SQL statement. + # This method *modifies* the +sql+ parameter. + # ===== Examples + # add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50}) + # generates + # SELECT * FROM suppliers LIMIT 10 OFFSET 50 + def add_limit_offset!(sql, options) + if limit = options[:limit] + sql << " LIMIT #{limit}" + if offset = options[:offset] + sql << " OFFSET #{offset}" + end + end + end + + def default_sequence_name(table, column) + nil + end + + # Set the sequence to the max value of the table's column. + def reset_sequence!(table, column, sequence = nil) + # Do nothing by default. Implement for PostgreSQL, Oracle, ... + end + end + end +end +module ActiveRecord + module ConnectionAdapters # :nodoc: + module Quoting + # Quotes the column value to help prevent + # {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection]. + def quote(value, column = nil) + case value + when String + if column && column.type == :binary && column.class.respond_to?(:string_to_binary) + "'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode) + elsif column && [:integer, :float].include?(column.type) + value.to_s + else + "'#{quote_string(value)}'" # ' (for ruby-mode) + end + when NilClass then "NULL" + when TrueClass then (column && column.type == :integer ? '1' : quoted_true) + when FalseClass then (column && column.type == :integer ? '0' : quoted_false) + when Float, Fixnum, Bignum then value.to_s + when Date then "'#{value.to_s}'" + when Time, DateTime then "'#{quoted_date(value)}'" + else "'#{quote_string(value.to_yaml)}'" + end + end + + # Quotes a string, escaping any ' (single quote) and \ (backslash) + # characters. + def quote_string(s) + s.gsub(/\\/, '\&\&').gsub(/'/, "''") # ' (for ruby-mode) + end + + # Returns a quoted form of the column name. This is highly adapter + # specific. + def quote_column_name(name) + name + end + + def quoted_true + "'t'" + end + + def quoted_false + "'f'" + end + + def quoted_date(value) + value.strftime("%Y-%m-%d %H:%M:%S") + end + end + end +end +require 'parsedate' + +module ActiveRecord + module ConnectionAdapters #:nodoc: + # An abstract definition of a column in a table. + class Column + attr_reader :name, :default, :type, :limit, :null, :sql_type + attr_accessor :primary + + # Instantiates a new column in the table. + # + # +name+ is the column's name, as in <tt><b>supplier_id</b> int(11)</tt>. + # +default+ is the type-casted default value, such as <tt>sales_stage varchar(20) default <b>'new'</b></tt>. + # +sql_type+ is only used to extract the column's length, if necessary. For example, <tt>company_name varchar(<b>60</b>)</tt>. + # +null+ determines if this column allows +NULL+ values. + def initialize(name, default, sql_type = nil, null = true) + @name, @type, @null = name, simplified_type(sql_type), null + @sql_type = sql_type + # have to do this one separately because type_cast depends on #type + @default = type_cast(default) + @limit = extract_limit(sql_type) unless sql_type.nil? + @primary = nil + @text = [:string, :text].include? @type + @number = [:float, :integer].include? @type + end + + def text? + @text + end + + def number? + @number + end + + # Returns the Ruby class that corresponds to the abstract data type. + def klass + case type + when :integer then Fixnum + when :float then Float + when :datetime then Time + when :date then Date + when :timestamp then Time + when :time then Time + when :text, :string then String + when :binary then String + when :boolean then Object + end + end + + # Casts value (which is a String) to an appropriate instance. + def type_cast(value) + return nil if value.nil? + case type + when :string then value + when :text then value + when :integer then value.to_i rescue value ? 1 : 0 + when :float then value.to_f + when :datetime then self.class.string_to_time(value) + when :timestamp then self.class.string_to_time(value) + when :time then self.class.string_to_dummy_time(value) + when :date then self.class.string_to_date(value) + when :binary then self.class.binary_to_string(value) + when :boolean then self.class.value_to_boolean(value) + else value + end + end + + def type_cast_code(var_name) + case type + when :string then nil + when :text then nil + when :integer then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)" + when :float then "#{var_name}.to_f" + when :datetime then "#{self.class.name}.string_to_time(#{var_name})" + when :timestamp then "#{self.class.name}.string_to_time(#{var_name})" + when :time then "#{self.class.name}.string_to_dummy_time(#{var_name})" + when :date then "#{self.class.name}.string_to_date(#{var_name})" + when :binary then "#{self.class.name}.binary_to_string(#{var_name})" + when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})" + else nil + end + end + + # Returns the human name of the column name. + # + # ===== Examples + # Column.new('sales_stage', ...).human_name #=> 'Sales stage' + def human_name + Base.human_attribute_name(@name) + end + + # Used to convert from Strings to BLOBs + def self.string_to_binary(value) + value + end + + # Used to convert from BLOBs to Strings + def self.binary_to_string(value) + value + end + + def self.string_to_date(string) + return string unless string.is_a?(String) + date_array = ParseDate.parsedate(string) + # treat 0000-00-00 as nil + Date.new(date_array[0], date_array[1], date_array[2]) rescue nil + end + + def self.string_to_time(string) + return string unless string.is_a?(String) + time_array = ParseDate.parsedate(string)[0..5] + # treat 0000-00-00 00:00:00 as nil + Time.send(Base.default_timezone, *time_array) rescue nil + end + + def self.string_to_dummy_time(string) + return string unless string.is_a?(String) + time_array = ParseDate.parsedate(string) + # pad the resulting array with dummy date information + time_array[0] = 2000; time_array[1] = 1; time_array[2] = 1; + Time.send(Base.default_timezone, *time_array) rescue nil + end + + # convert something to a boolean + def self.value_to_boolean(value) + return value if value==true || value==false + case value.to_s.downcase + when "true", "t", "1" then true + else false + end + end + + private + def extract_limit(sql_type) + $1.to_i if sql_type =~ /\((.*)\)/ + end + + def simplified_type(field_type) + case field_type + when /int/i + :integer + when /float|double|decimal|numeric/i + :float + when /datetime/i + :datetime + when /timestamp/i + :timestamp + when /time/i + :time + when /date/i + :date + when /clob/i, /text/i + :text + when /blob/i, /binary/i + :binary + when /char/i, /string/i + :string + when /boolean/i + :boolean + end + end + end + + class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc: + end + + class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :default, :null) #:nodoc: + def to_sql + column_sql = "#{base.quote_column_name(name)} #{type_to_sql(type.to_sym, limit)}" + add_column_options!(column_sql, :null => null, :default => default) + column_sql + end + alias to_s :to_sql + + private + def type_to_sql(name, limit) + base.type_to_sql(name, limit) rescue name + end + + def add_column_options!(sql, options) + base.add_column_options!(sql, options.merge(:column => self)) + end + end + + # Represents a SQL table in an abstract way. + # Columns are stored as ColumnDefinition in the #columns attribute. + class TableDefinition + attr_accessor :columns + + def initialize(base) + @columns = [] + @base = base + end + + # Appends a primary key definition to the table definition. + # Can be called multiple times, but this is probably not a good idea. + def primary_key(name) + column(name, native[:primary_key]) + end + + # Returns a ColumnDefinition for the column with name +name+. + def [](name) + @columns.find {|column| column.name.to_s == name.to_s} + end + + # Instantiates a new column for the table. + # The +type+ parameter must be one of the following values: + # <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>, + # <tt>:integer</tt>, <tt>:float</tt>, <tt>:datetime</tt>, + # <tt>:timestamp</tt>, <tt>:time</tt>, <tt>:date</tt>, + # <tt>:binary</tt>, <tt>:boolean</tt>. + # + # Available options are (none of these exists by default): + # * <tt>:limit</tt>: + # Requests a maximum column length (<tt>:string</tt>, <tt>:text</tt>, + # <tt>:binary</tt> or <tt>:integer</tt> columns only) + # * <tt>:default</tt>: + # The column's default value. You cannot explicitely set the default + # value to +NULL+. Simply leave off this option if you want a +NULL+ + # default value. + # * <tt>:null</tt>: + # Allows or disallows +NULL+ values in the column. This option could + # have been named <tt>:null_allowed</tt>. + # + # This method returns <tt>self</tt>. + # + # ===== Examples + # # Assuming def is an instance of TableDefinition + # def.column(:granted, :boolean) + # #=> granted BOOLEAN + # + # def.column(:picture, :binary, :limit => 2.megabytes) + # #=> picture BLOB(2097152) + # + # def.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false) + # #=> sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL + def column(name, type, options = {}) + column = self[name] || ColumnDefinition.new(@base, name, type) + column.limit = options[:limit] || native[type.to_sym][:limit] if options[:limit] or native[type.to_sym] + column.default = options[:default] + column.null = options[:null] + @columns << column unless @columns.include? column + self + end + + # Returns a String whose contents are the column definitions + # concatenated together. This string can then be pre and appended to + # to generate the final SQL to create the table. + def to_sql + @columns * ', ' + end + + private + def native + @base.native_database_types + end + end + end +end +module ActiveRecord + module ConnectionAdapters # :nodoc: + module SchemaStatements + # Returns a Hash of mappings from the abstract data types to the native + # database types. See TableDefinition#column for details on the recognized + # abstract data types. + def native_database_types + {} + end + + # This is the maximum length a table alias can be + def table_alias_length + 255 + end + + # Truncates a table alias according to the limits of the current adapter. + def table_alias_for(table_name) + table_name[0..table_alias_length-1].gsub(/\./, '_') + end + + # def tables(name = nil) end + + # Returns an array of indexes for the given table. + # def indexes(table_name, name = nil) end + + # Returns an array of Column objects for the table specified by +table_name+. + # See the concrete implementation for details on the expected parameter values. + def columns(table_name, name = nil) end + + # Creates a new table + # There are two ways to work with #create_table. You can use the block + # form or the regular form, like this: + # + # === Block form + # # create_table() yields a TableDefinition instance + # create_table(:suppliers) do |t| + # t.column :name, :string, :limit => 60 + # # Other fields here + # end + # + # === Regular form + # create_table(:suppliers) + # add_column(:suppliers, :name, :string, {:limit => 60}) + # + # The +options+ hash can include the following keys: + # [<tt>:id</tt>] + # Set to true or false to add/not add a primary key column + # automatically. Defaults to true. + # [<tt>:primary_key</tt>] + # The name of the primary key, if one is to be added automatically. + # Defaults to +id+. + # [<tt>:options</tt>] + # Any extra options you want appended to the table definition. + # [<tt>:temporary</tt>] + # Make a temporary table. + # [<tt>:force</tt>] + # Set to true or false to drop the table before creating it. + # Defaults to false. + # + # ===== Examples + # ====== Add a backend specific option to the generated SQL (MySQL) + # create_table(:suppliers, :options => 'ENGINE=InnoDB DEFAULT CHARSET=utf8') + # generates: + # CREATE TABLE suppliers ( + # id int(11) DEFAULT NULL auto_increment PRIMARY KEY + # ) ENGINE=InnoDB DEFAULT CHARSET=utf8 + # + # ====== Rename the primary key column + # create_table(:objects, :primary_key => 'guid') do |t| + # t.column :name, :string, :limit => 80 + # end + # generates: + # CREATE TABLE objects ( + # guid int(11) DEFAULT NULL auto_increment PRIMARY KEY, + # name varchar(80) + # ) + # + # ====== Do not add a primary key column + # create_table(:categories_suppliers, :id => false) do |t| + # t.column :category_id, :integer + # t.column :supplier_id, :integer + # end + # generates: + # CREATE TABLE categories_suppliers_join ( + # category_id int, + # supplier_id int + # ) + # + # See also TableDefinition#column for details on how to create columns. + def create_table(name, options = {}) + table_definition = TableDefinition.new(self) + table_definition.primary_key(options[:primary_key] || "id") unless options[:id] == false + + yield table_definition + + if options[:force] + drop_table(name) rescue nil + end + + create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE " + create_sql << "#{name} (" + create_sql << table_definition.to_sql + create_sql << ") #{options[:options]}" + execute create_sql + end + + # Renames a table. + # ===== Example + # rename_table('octopuses', 'octopi') + def rename_table(name, new_name) + raise NotImplementedError, "rename_table is not implemented" + end + + # Drops a table from the database. + def drop_table(name) + execute "DROP TABLE #{name}" + end + + # Adds a new column to the named table. + # See TableDefinition#column for details of the options you can use. + def add_column(table_name, column_name, type, options = {}) + add_column_sql = "ALTER TABLE #{table_name} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit])}" + add_column_options!(add_column_sql, options) + execute(add_column_sql) + end + + # Removes the column from the table definition. + # ===== Examples + # remove_column(:suppliers, :qualification) + def remove_column(table_name, column_name) + execute "ALTER TABLE #{table_name} DROP #{quote_column_name(column_name)}" + end + + # Changes the column's definition according to the new options. + # See TableDefinition#column for details of the options you can use. + # ===== Examples + # change_column(:suppliers, :name, :string, :limit => 80) + # change_column(:accounts, :description, :text) + def change_column(table_name, column_name, type, options = {}) + raise NotImplementedError, "change_column is not implemented" + end + + # Sets a new default value for a column. If you want to set the default + # value to +NULL+, you are out of luck. You need to + # DatabaseStatements#execute the apppropriate SQL statement yourself. + # ===== Examples + # change_column_default(:suppliers, :qualification, 'new') + # change_column_default(:accounts, :authorized, 1) + def change_column_default(table_name, column_name, default) + raise NotImplementedError, "change_column_default is not implemented" + end + + # Renames a column. + # ===== Example + # rename_column(:suppliers, :description, :name) + def rename_column(table_name, column_name, new_column_name) + raise NotImplementedError, "rename_column is not implemented" + end + + # Adds a new index to the table. +column_name+ can be a single Symbol, or + # an Array of Symbols. + # + # The index will be named after the table and the first column names, + # unless you pass +:name+ as an option. + # + # When creating an index on multiple columns, the first column is used as a name + # for the index. For example, when you specify an index on two columns + # [+:first+, +:last+], the DBMS creates an index for both columns as well as an + # index for the first colum +:first+. Using just the first name for this index + # makes sense, because you will never have to create a singular index with this + # name. + # + # ===== Examples + # ====== Creating a simple index + # add_index(:suppliers, :name) + # generates + # CREATE INDEX suppliers_name_index ON suppliers(name) + # ====== Creating a unique index + # add_index(:accounts, [:branch_id, :party_id], :unique => true) + # generates + # CREATE UNIQUE INDEX accounts_branch_id_index ON accounts(branch_id, party_id) + # ====== Creating a named index + # add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party') + # generates + # CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id) + def add_index(table_name, column_name, options = {}) + column_names = Array(column_name) + index_name = index_name(table_name, :column => column_names.first) + + if Hash === options # legacy support, since this param was a string + index_type = options[:unique] ? "UNIQUE" : "" + index_name = options[:name] || index_name + else + index_type = options + end + quoted_column_names = column_names.map { |e| quote_column_name(e) }.join(", ") + execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{table_name} (#{quoted_column_names})" + end + + # Remove the given index from the table. + # + # Remove the suppliers_name_index in the suppliers table (legacy support, use the second or third forms). + # remove_index :suppliers, :name + # Remove the index named accounts_branch_id in the accounts table. + # remove_index :accounts, :column => :branch_id + # Remove the index named by_branch_party in the accounts table. + # remove_index :accounts, :name => :by_branch_party + # + # You can remove an index on multiple columns by specifying the first column. + # add_index :accounts, [:username, :password] + # remove_index :accounts, :username + def remove_index(table_name, options = {}) + execute "DROP INDEX #{quote_column_name(index_name(table_name, options))} ON #{table_name}" + end + + def index_name(table_name, options) #:nodoc: + if Hash === options # legacy support + if options[:column] + "#{table_name}_#{options[:column]}_index" + elsif options[:name] + options[:name] + else + raise ArgumentError, "You must specify the index name" + end + else + "#{table_name}_#{options}_index" + end + end + + # Returns a string of <tt>CREATE TABLE</tt> SQL statement(s) for recreating the + # entire structure of the database. + def structure_dump + end + + # Should not be called normally, but this operation is non-destructive. + # The migrations module handles this automatically. + def initialize_schema_information + begin + execute "CREATE TABLE #{ActiveRecord::Migrator.schema_info_table_name} (version #{type_to_sql(:integer)})" + execute "INSERT INTO #{ActiveRecord::Migrator.schema_info_table_name} (version) VALUES(0)" + rescue ActiveRecord::StatementInvalid + # Schema has been intialized + end + end + + def dump_schema_information #:nodoc: + begin + if (current_schema = ActiveRecord::Migrator.current_version) > 0 + return "INSERT INTO #{ActiveRecord::Migrator.schema_info_table_name} (version) VALUES (#{current_schema})" + end + rescue ActiveRecord::StatementInvalid + # No Schema Info + end + end + + + def type_to_sql(type, limit = nil) #:nodoc: + native = native_database_types[type] + limit ||= native[:limit] + column_type_sql = native[:name] + column_type_sql << "(#{limit})" if limit + column_type_sql + end + + def add_column_options!(sql, options) #:nodoc: + sql << " DEFAULT #{quote(options[:default], options[:column])}" unless options[:default].nil? + sql << " NOT NULL" if options[:null] == false + end + end + end +end +require 'benchmark' +require 'date' + +require 'active_record/connection_adapters/abstract/schema_definitions' +require 'active_record/connection_adapters/abstract/schema_statements' +require 'active_record/connection_adapters/abstract/database_statements' +require 'active_record/connection_adapters/abstract/quoting' +require 'active_record/connection_adapters/abstract/connection_specification' + +module ActiveRecord + module ConnectionAdapters # :nodoc: + # All the concrete database adapters follow the interface laid down in this class. + # You can use this interface directly by borrowing the database connection from the Base with + # Base.connection. + # + # Most of the methods in the adapter are useful during migrations. Most + # notably, SchemaStatements#create_table, SchemaStatements#drop_table, + # SchemaStatements#add_index, SchemaStatements#remove_index, + # SchemaStatements#add_column, SchemaStatements#change_column and + # SchemaStatements#remove_column are very useful. + class AbstractAdapter + include Quoting, DatabaseStatements, SchemaStatements + @@row_even = true + + def initialize(connection, logger = nil) #:nodoc: + @connection, @logger = connection, logger + @runtime = 0 + @last_verification = 0 + end + + # Returns the human-readable name of the adapter. Use mixed case - one + # can always use downcase if needed. + def adapter_name + 'Abstract' + end + + # Does this adapter support migrations? Backend specific, as the + # abstract adapter always returns +false+. + def supports_migrations? + false + end + + # Does this adapter support using DISTINCT within COUNT? This is +true+ + # for all adapters except sqlite. + def supports_count_distinct? + true + end + + # Should primary key values be selected from their corresponding + # sequence before the insert statement? If true, next_sequence_value + # is called before each insert to set the record's primary key. + # This is false for all adapters but Firebird. + def prefetch_primary_key?(table_name = nil) + false + end + + def reset_runtime #:nodoc: + rt, @runtime = @runtime, 0 + rt + end + + + # CONNECTION MANAGEMENT ==================================== + + # Is this connection active and ready to perform queries? + def active? + @active != false + end + + # Close this connection and open a new one in its place. + def reconnect! + @active = true + end + + # Close this connection + def disconnect! + @active = false + end + + # Lazily verify this connection, calling +active?+ only if it hasn't + # been called for +timeout+ seconds. + def verify!(timeout) + now = Time.now.to_i + if (now - @last_verification) > timeout + reconnect! unless active? + @last_verification = now + end + end + + # Provides access to the underlying database connection. Useful for + # when you need to call a proprietary method such as postgresql's lo_* + # methods + def raw_connection + @connection + end + + protected + def log(sql, name) + if block_given? + if @logger and @logger.level <= Logger::INFO + result = nil + seconds = Benchmark.realtime { result = yield } + @runtime += seconds + log_info(sql, name, seconds) + result + else + yield + end + else + log_info(sql, name, 0) + nil + end + rescue Exception => e + # Log message and raise exception. + # Set last_verfication to 0, so that connection gets verified + # upon reentering the request loop + @last_verification = 0 + message = "#{e.class.name}: #{e.message}: #{sql}" + log_info(message, name, 0) + raise ActiveRecord::StatementInvalid, message + end + + def log_info(sql, name, runtime) + return unless @logger + + @logger.debug( + format_log_entry( + "#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})", + sql.gsub(/ +/, " ") + ) + ) + end + + def format_log_entry(message, dump = nil) + if ActiveRecord::Base.colorize_logging + if @@row_even + @@row_even = false + message_color, dump_color = "4;36;1", "0;1" + else + @@row_even = true + message_color, dump_color = "4;35;1", "0" + end + + log_entry = " \e[#{message_color}m#{message}\e[0m " + log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump + log_entry + else + "%s %s" % [message, dump] + end + end + end + end +end +# Author/Maintainer: Maik Schmidt <contact@maik-schmidt.de> + +require 'active_record/connection_adapters/abstract_adapter' + +begin + require 'db2/db2cli' unless self.class.const_defined?(:DB2CLI) + require 'active_record/vendor/db2' + + module ActiveRecord + class Base + # Establishes a connection to the database that's used by + # all Active Record objects + def self.db2_connection(config) # :nodoc: + config = config.symbolize_keys + usr = config[:username] + pwd = config[:password] + schema = config[:schema] + + if config.has_key?(:database) + database = config[:database] + else + raise ArgumentError, 'No database specified. Missing argument: database.' + end + + connection = DB2::Connection.new(DB2::Environment.new) + connection.connect(database, usr, pwd) + ConnectionAdapters::DB2Adapter.new(connection, logger, :schema => schema) + end + end + + module ConnectionAdapters + # The DB2 adapter works with the C-based CLI driver (http://rubyforge.org/projects/ruby-dbi/) + # + # Options: + # + # * <tt>:username</tt> -- Defaults to nothing + # * <tt>:password</tt> -- Defaults to nothing + # * <tt>:database</tt> -- The name of the database. No default, must be provided. + # * <tt>:schema</tt> -- Database schema to be set initially. + class DB2Adapter < AbstractAdapter + def initialize(connection, logger, connection_options) + super(connection, logger) + @connection_options = connection_options + if schema = @connection_options[:schema] + with_statement do |stmt| + stmt.exec_direct("SET SCHEMA=#{schema}") + end + end + end + + def select_all(sql, name = nil) + select(sql, name) + end + + def select_one(sql, name = nil) + select(sql, name).first + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) + execute(sql, name = nil) + id_value || last_insert_id + end + + def execute(sql, name = nil) + rows_affected = 0 + with_statement do |stmt| + log(sql, name) do + stmt.exec_direct(sql) + rows_affected = stmt.row_count + end + end + rows_affected + end + + alias_method :update, :execute + alias_method :delete, :execute + + def begin_db_transaction + @connection.set_auto_commit_off + end + + def commit_db_transaction + @connection.commit + @connection.set_auto_commit_on + end + + def rollback_db_transaction + @connection.rollback + @connection.set_auto_commit_on + end + + def quote_column_name(column_name) + column_name + end + + def adapter_name() + 'DB2' + end + + def quote_string(string) + string.gsub(/'/, "''") # ' (for ruby-mode) + end + + def add_limit_offset!(sql, options) + if limit = options[:limit] + offset = options[:offset] || 0 + # The following trick was added by andrea+rails@webcom.it. + sql.gsub!(/SELECT/i, 'SELECT B.* FROM (SELECT A.*, row_number() over () AS internal$rownum FROM (SELECT') + sql << ") A ) B WHERE B.internal$rownum > #{offset} AND B.internal$rownum <= #{limit + offset}" + end + end + + def tables(name = nil) + result = [] + schema = @connection_options[:schema] || '%' + with_statement do |stmt| + stmt.tables(schema).each { |t| result << t[2].downcase } + end + result + end + + def indexes(table_name, name = nil) + tmp = {} + schema = @connection_options[:schema] || '' + with_statement do |stmt| + stmt.indexes(table_name, schema).each do |t| + next unless t[5] + next if t[4] == 'SYSIBM' # Skip system indexes. + idx_name = t[5].downcase + col_name = t[8].downcase + if tmp.has_key?(idx_name) + tmp[idx_name].columns << col_name + else + is_unique = t[3] == 0 + tmp[idx_name] = IndexDefinition.new(table_name, idx_name, is_unique, [col_name]) + end + end + end + tmp.values + end + + def columns(table_name, name = nil) + result = [] + schema = @connection_options[:schema] || '%' + with_statement do |stmt| + stmt.columns(table_name, schema).each do |c| + c_name = c[3].downcase + c_default = c[12] == 'NULL' ? nil : c[12] + c_default.gsub!(/^'(.*)'$/, '\1') if !c_default.nil? + c_type = c[5].downcase + c_type += "(#{c[6]})" if !c[6].nil? && c[6] != '' + result << Column.new(c_name, c_default, c_type, c[17] == 'YES') + end + end + result + end + + def native_database_types + { + :primary_key => 'int generated by default as identity (start with 42) primary key', + :string => { :name => 'varchar', :limit => 255 }, + :text => { :name => 'clob', :limit => 32768 }, + :integer => { :name => 'int' }, + :float => { :name => 'float' }, + :datetime => { :name => 'timestamp' }, + :timestamp => { :name => 'timestamp' }, + :time => { :name => 'time' }, + :date => { :name => 'date' }, + :binary => { :name => 'blob', :limit => 32768 }, + :boolean => { :name => 'decimal', :limit => 1 } + } + end + + def quoted_true + '1' + end + + def quoted_false + '0' + end + + def active? + @connection.select_one 'select 1 from ibm.sysdummy1' + true + rescue Exception + false + end + + def reconnect! + end + + def table_alias_length + 128 + end + + private + + def with_statement + stmt = DB2::Statement.new(@connection) + yield stmt + stmt.free + end + + def last_insert_id + row = select_one(<<-GETID.strip) + with temp(id) as (values (identity_val_local())) select * from temp + GETID + row['id'].to_i + end + + def select(sql, name = nil) + rows = [] + with_statement do |stmt| + log(sql, name) do + stmt.exec_direct("#{sql.gsub(/=\s*null/i, 'IS NULL')} with ur") + end + + while row = stmt.fetch_as_hash + row.delete('internal$rownum') + rows << row + end + end + rows + end + end + end + end +rescue LoadError + # DB2 driver is unavailable. + module ActiveRecord # :nodoc: + class Base + def self.db2_connection(config) # :nodoc: + # Set up a reasonable error message + raise LoadError, "DB2 Libraries could not be loaded." + end + end + end +end +# Author: Ken Kunz <kennethkunz@gmail.com> + +require 'active_record/connection_adapters/abstract_adapter' + +module FireRuby # :nodoc: all + class Database + def self.new_from_params(database, host, port, service) + db_string = "" + if host + db_string << host + db_string << "/#{service || port}" if service || port + db_string << ":" + end + db_string << database + new(db_string) + end + end +end + +module ActiveRecord + class << Base + def firebird_connection(config) # :nodoc: + require_library_or_gem 'fireruby' + unless defined? FireRuby::SQLType + raise AdapterNotFound, + 'The Firebird adapter requires FireRuby version 0.4.0 or greater; you appear ' << + 'to be running an older version -- please update FireRuby (gem install fireruby).' + end + config = config.symbolize_keys + unless config.has_key?(:database) + raise ArgumentError, "No database specified. Missing argument: database." + end + options = config[:charset] ? { CHARACTER_SET => config[:charset] } : {} + connection_params = [config[:username], config[:password], options] + db = FireRuby::Database.new_from_params(*config.values_at(:database, :host, :port, :service)) + connection = db.connect(*connection_params) + ConnectionAdapters::FirebirdAdapter.new(connection, logger, connection_params) + end + end + + module ConnectionAdapters + class FirebirdColumn < Column # :nodoc: + VARCHAR_MAX_LENGTH = 32_765 + BLOB_MAX_LENGTH = 32_767 + + def initialize(name, domain, type, sub_type, length, precision, scale, default_source, null_flag) + @firebird_type = FireRuby::SQLType.to_base_type(type, sub_type).to_s + super(name.downcase, nil, @firebird_type, !null_flag) + @default = parse_default(default_source) if default_source + @limit = type == 'BLOB' ? BLOB_MAX_LENGTH : length + @domain, @sub_type, @precision, @scale = domain, sub_type, precision, scale + end + + def type + if @domain =~ /BOOLEAN/ + :boolean + elsif @type == :binary and @sub_type == 1 + :text + else + @type + end + end + + # Submits a _CAST_ query to the database, casting the default value to the specified SQL type. + # This enables Firebird to provide an actual value when context variables are used as column + # defaults (such as CURRENT_TIMESTAMP). + def default + if @default + sql = "SELECT CAST(#{@default} AS #{column_def}) FROM RDB$DATABASE" + connection = ActiveRecord::Base.active_connections.values.detect { |conn| conn && conn.adapter_name == 'Firebird' } + if connection + type_cast connection.execute(sql).to_a.first['CAST'] + else + raise ConnectionNotEstablished, "No Firebird connections established." + end + end + end + + def type_cast(value) + if type == :boolean + value == true or value == ActiveRecord::ConnectionAdapters::FirebirdAdapter.boolean_domain[:true] + else + super + end + end + + private + def parse_default(default_source) + default_source =~ /^\s*DEFAULT\s+(.*)\s*$/i + return $1 unless $1.upcase == "NULL" + end + + def column_def + case @firebird_type + when 'BLOB' then "VARCHAR(#{VARCHAR_MAX_LENGTH})" + when 'CHAR', 'VARCHAR' then "#{@firebird_type}(#{@limit})" + when 'NUMERIC', 'DECIMAL' then "#{@firebird_type}(#{@precision},#{@scale.abs})" + when 'DOUBLE' then "DOUBLE PRECISION" + else @firebird_type + end + end + + def simplified_type(field_type) + if field_type == 'TIMESTAMP' + :datetime + else + super + end + end + end + + # The Firebird adapter relies on the FireRuby[http://rubyforge.org/projects/fireruby/] + # extension, version 0.4.0 or later (available as a gem or from + # RubyForge[http://rubyforge.org/projects/fireruby/]). FireRuby works with + # Firebird 1.5.x on Linux, OS X and Win32 platforms. + # + # == Usage Notes + # + # === Sequence (Generator) Names + # The Firebird adapter supports the same approach adopted for the Oracle + # adapter. See ActiveRecord::Base#set_sequence_name for more details. + # + # Note that in general there is no need to create a <tt>BEFORE INSERT</tt> + # trigger corresponding to a Firebird sequence generator when using + # ActiveRecord. In other words, you don't have to try to make Firebird + # simulate an <tt>AUTO_INCREMENT</tt> or +IDENTITY+ column. When saving a + # new record, ActiveRecord pre-fetches the next sequence value for the table + # and explicitly includes it in the +INSERT+ statement. (Pre-fetching the + # next primary key value is the only reliable method for the Firebird + # adapter to report back the +id+ after a successful insert.) + # + # === BOOLEAN Domain + # Firebird 1.5 does not provide a native +BOOLEAN+ type. But you can easily + # define a +BOOLEAN+ _domain_ for this purpose, e.g.: + # + # CREATE DOMAIN D_BOOLEAN AS SMALLINT CHECK (VALUE IN (0, 1)); + # + # When the Firebird adapter encounters a column that is based on a domain + # that includes "BOOLEAN" in the domain name, it will attempt to treat + # the column as a +BOOLEAN+. + # + # By default, the Firebird adapter will assume that the BOOLEAN domain is + # defined as above. This can be modified if needed. For example, if you + # have a legacy schema with the following +BOOLEAN+ domain defined: + # + # CREATE DOMAIN BOOLEAN AS CHAR(1) CHECK (VALUE IN ('T', 'F')); + # + # ...you can add the following line to your <tt>environment.rb</tt> file: + # + # ActiveRecord::ConnectionAdapters::FirebirdAdapter.boolean_domain = { :true => 'T', :false => 'F' } + # + # === BLOB Elements + # The Firebird adapter currently provides only limited support for +BLOB+ + # columns. You cannot currently retrieve or insert a +BLOB+ as an IO stream. + # When selecting a +BLOB+, the entire element is converted into a String. + # When inserting or updating a +BLOB+, the entire value is included in-line + # in the SQL statement, limiting you to values <= 32KB in size. + # + # === Column Name Case Semantics + # Firebird and ActiveRecord have somewhat conflicting case semantics for + # column names. + # + # [*Firebird*] + # The standard practice is to use unquoted column names, which can be + # thought of as case-insensitive. (In fact, Firebird converts them to + # uppercase.) Quoted column names (not typically used) are case-sensitive. + # [*ActiveRecord*] + # Attribute accessors corresponding to column names are case-sensitive. + # The defaults for primary key and inheritance columns are lowercase, and + # in general, people use lowercase attribute names. + # + # In order to map between the differing semantics in a way that conforms + # to common usage for both Firebird and ActiveRecord, uppercase column names + # in Firebird are converted to lowercase attribute names in ActiveRecord, + # and vice-versa. Mixed-case column names retain their case in both + # directions. Lowercase (quoted) Firebird column names are not supported. + # This is similar to the solutions adopted by other adapters. + # + # In general, the best approach is to use unqouted (case-insensitive) column + # names in your Firebird DDL (or if you must quote, use uppercase column + # names). These will correspond to lowercase attributes in ActiveRecord. + # + # For example, a Firebird table based on the following DDL: + # + # CREATE TABLE products ( + # id BIGINT NOT NULL PRIMARY KEY, + # "TYPE" VARCHAR(50), + # name VARCHAR(255) ); + # + # ...will correspond to an ActiveRecord model class called +Product+ with + # the following attributes: +id+, +type+, +name+. + # + # ==== Quoting <tt>"TYPE"</tt> and other Firebird reserved words: + # In ActiveRecord, the default inheritance column name is +type+. The word + # _type_ is a Firebird reserved word, so it must be quoted in any Firebird + # SQL statements. Because of the case mapping described above, you should + # always reference this column using quoted-uppercase syntax + # (<tt>"TYPE"</tt>) within Firebird DDL or other SQL statements (as in the + # example above). This holds true for any other Firebird reserved words used + # as column names as well. + # + # === Migrations + # The Firebird adapter does not currently support Migrations. I hope to + # add this feature in the near future. + # + # == Connection Options + # The following options are supported by the Firebird adapter. None of the + # options have default values. + # + # <tt>:database</tt>:: + # <i>Required option.</i> Specifies one of: (i) a Firebird database alias; + # (ii) the full path of a database file; _or_ (iii) a full Firebird + # connection string. <i>Do not specify <tt>:host</tt>, <tt>:service</tt> + # or <tt>:port</tt> as separate options when using a full connection + # string.</i> + # <tt>:host</tt>:: + # Set to <tt>"remote.host.name"</tt> for remote database connections. + # May be omitted for local connections if a full database path is + # specified for <tt>:database</tt>. Some platforms require a value of + # <tt>"localhost"</tt> for local connections when using a Firebird + # database _alias_. + # <tt>:service</tt>:: + # Specifies a service name for the connection. Only used if <tt>:host</tt> + # is provided. Required when connecting to a non-standard service. + # <tt>:port</tt>:: + # Specifies the connection port. Only used if <tt>:host</tt> is provided + # and <tt>:service</tt> is not. Required when connecting to a non-standard + # port and <tt>:service</tt> is not defined. + # <tt>:username</tt>:: + # Specifies the database user. May be omitted or set to +nil+ (together + # with <tt>:password</tt>) to use the underlying operating system user + # credentials on supported platforms. + # <tt>:password</tt>:: + # Specifies the database password. Must be provided if <tt>:username</tt> + # is explicitly specified; should be omitted if OS user credentials are + # are being used. + # <tt>:charset</tt>:: + # Specifies the character set to be used by the connection. Refer to + # Firebird documentation for valid options. + class FirebirdAdapter < AbstractAdapter + @@boolean_domain = { :true => 1, :false => 0 } + cattr_accessor :boolean_domain + + def initialize(connection, logger, connection_params=nil) + super(connection, logger) + @connection_params = connection_params + end + + def adapter_name # :nodoc: + 'Firebird' + end + + # Returns true for Firebird adapter (since Firebird requires primary key + # values to be pre-fetched before insert). See also #next_sequence_value. + def prefetch_primary_key?(table_name = nil) + true + end + + def default_sequence_name(table_name, primary_key) # :nodoc: + "#{table_name}_seq" + end + + + # QUOTING ================================================== + + def quote(value, column = nil) # :nodoc: + if [Time, DateTime].include?(value.class) + "CAST('#{value.strftime("%Y-%m-%d %H:%M:%S")}' AS TIMESTAMP)" + else + super + end + end + + def quote_string(string) # :nodoc: + string.gsub(/'/, "''") + end + + def quote_column_name(column_name) # :nodoc: + %Q("#{ar_to_fb_case(column_name)}") + end + + def quoted_true # :nodoc: + quote(boolean_domain[:true]) + end + + def quoted_false # :nodoc: + quote(boolean_domain[:false]) + end + + + # CONNECTION MANAGEMENT ==================================== + + def active? + not @connection.closed? + end + + def reconnect! + @connection.close + @connection = @connection.database.connect(*@connection_params) + end + + + # DATABASE STATEMENTS ====================================== + + def select_all(sql, name = nil) # :nodoc: + select(sql, name) + end + + def select_one(sql, name = nil) # :nodoc: + result = select(sql, name) + result.nil? ? nil : result.first + end + + def execute(sql, name = nil, &block) # :nodoc: + log(sql, name) do + if @transaction + @connection.execute(sql, @transaction, &block) + else + @connection.execute_immediate(sql, &block) + end + end + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) # :nodoc: + execute(sql, name) + id_value + end + + alias_method :update, :execute + alias_method :delete, :execute + + def begin_db_transaction() # :nodoc: + @transaction = @connection.start_transaction + end + + def commit_db_transaction() # :nodoc: + @transaction.commit + ensure + @transaction = nil + end + + def rollback_db_transaction() # :nodoc: + @transaction.rollback + ensure + @transaction = nil + end + + def add_limit_offset!(sql, options) # :nodoc: + if options[:limit] + limit_string = "FIRST #{options[:limit]}" + limit_string << " SKIP #{options[:offset]}" if options[:offset] + sql.sub!(/\A(\s*SELECT\s)/i, '\&' + limit_string + ' ') + end + end + + # Returns the next sequence value from a sequence generator. Not generally + # called directly; used by ActiveRecord to get the next primary key value + # when inserting a new database record (see #prefetch_primary_key?). + def next_sequence_value(sequence_name) + FireRuby::Generator.new(sequence_name, @connection).next(1) + end + + + # SCHEMA STATEMENTS ======================================== + + def columns(table_name, name = nil) # :nodoc: + sql = <<-END_SQL + SELECT r.rdb$field_name, r.rdb$field_source, f.rdb$field_type, f.rdb$field_sub_type, + f.rdb$field_length, f.rdb$field_precision, f.rdb$field_scale, + COALESCE(r.rdb$default_source, f.rdb$default_source) rdb$default_source, + COALESCE(r.rdb$null_flag, f.rdb$null_flag) rdb$null_flag + FROM rdb$relation_fields r + JOIN rdb$fields f ON r.rdb$field_source = f.rdb$field_name + WHERE r.rdb$relation_name = '#{table_name.to_s.upcase}' + ORDER BY r.rdb$field_position + END_SQL + execute(sql, name).collect do |field| + field_values = field.values.collect do |value| + case value + when String then value.rstrip + when FireRuby::Blob then value.to_s + else value + end + end + FirebirdColumn.new(*field_values) + end + end + + private + def select(sql, name = nil) + execute(sql, name).collect do |row| + hashed_row = {} + row.each do |column, value| + value = value.to_s if FireRuby::Blob === value + hashed_row[fb_to_ar_case(column)] = value + end + hashed_row + end + end + + # Maps uppercase Firebird column names to lowercase for ActiveRecord; + # mixed-case columns retain their original case. + def fb_to_ar_case(column_name) + column_name =~ /[[:lower:]]/ ? column_name : column_name.downcase + end + + # Maps lowercase ActiveRecord column names to uppercase for Fierbird; + # mixed-case columns retain their original case. + def ar_to_fb_case(column_name) + column_name =~ /[[:upper:]]/ ? column_name : column_name.upcase + end + end + end +end +require 'active_record/connection_adapters/abstract_adapter' + +module ActiveRecord + class Base + # Establishes a connection to the database that's used by all Active Record objects. + def self.mysql_connection(config) # :nodoc: + # Only include the MySQL driver if one hasn't already been loaded + unless defined? Mysql + begin + require_library_or_gem 'mysql' + rescue LoadError => cannot_require_mysql + # Only use the supplied backup Ruby/MySQL driver if no driver is already in place + begin + require 'active_record/vendor/mysql' + rescue LoadError + raise cannot_require_mysql + end + end + end + + config = config.symbolize_keys + host = config[:host] + port = config[:port] + socket = config[:socket] + username = config[:username] ? config[:username].to_s : 'root' + password = config[:password].to_s + + if config.has_key?(:database) + database = config[:database] + else + raise ArgumentError, "No database specified. Missing argument: database." + end + + mysql = Mysql.init + mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslkey] + ConnectionAdapters::MysqlAdapter.new(mysql, logger, [host, username, password, database, port, socket], config) + end + end + + module ConnectionAdapters + class MysqlColumn < Column #:nodoc: + private + def simplified_type(field_type) + return :boolean if MysqlAdapter.emulate_booleans && field_type.downcase.index("tinyint(1)") + return :string if field_type =~ /enum/i + super + end + end + + # The MySQL adapter will work with both Ruby/MySQL, which is a Ruby-based MySQL adapter that comes bundled with Active Record, and with + # the faster C-based MySQL/Ruby adapter (available both as a gem and from http://www.tmtm.org/en/mysql/ruby/). + # + # Options: + # + # * <tt>:host</tt> -- Defaults to localhost + # * <tt>:port</tt> -- Defaults to 3306 + # * <tt>:socket</tt> -- Defaults to /tmp/mysql.sock + # * <tt>:username</tt> -- Defaults to root + # * <tt>:password</tt> -- Defaults to nothing + # * <tt>:database</tt> -- The name of the database. No default, must be provided. + # * <tt>:sslkey</tt> -- Necessary to use MySQL with an SSL connection + # * <tt>:sslcert</tt> -- Necessary to use MySQL with an SSL connection + # * <tt>:sslcapath</tt> -- Necessary to use MySQL with an SSL connection + # * <tt>:sslcipher</tt> -- Necessary to use MySQL with an SSL connection + # + # By default, the MysqlAdapter will consider all columns of type tinyint(1) + # as boolean. If you wish to disable this emulation (which was the default + # behavior in versions 0.13.1 and earlier) you can add the following line + # to your environment.rb file: + # + # ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false + class MysqlAdapter < AbstractAdapter + @@emulate_booleans = true + cattr_accessor :emulate_booleans + + LOST_CONNECTION_ERROR_MESSAGES = [ + "Server shutdown in progress", + "Broken pipe", + "Lost connection to MySQL server during query", + "MySQL server has gone away" + ] + + def initialize(connection, logger, connection_options, config) + super(connection, logger) + @connection_options, @config = connection_options, config + @null_values_in_each_hash = Mysql.const_defined?(:VERSION) + connect + end + + def adapter_name #:nodoc: + 'MySQL' + end + + def supports_migrations? #:nodoc: + true + end + + def native_database_types #:nodoc + { + :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY", + :string => { :name => "varchar", :limit => 255 }, + :text => { :name => "text" }, + :integer => { :name => "int", :limit => 11 }, + :float => { :name => "float" }, + :datetime => { :name => "datetime" }, + :timestamp => { :name => "datetime" }, + :time => { :name => "time" }, + :date => { :name => "date" }, + :binary => { :name => "blob" }, + :boolean => { :name => "tinyint", :limit => 1 } + } + end + + + # QUOTING ================================================== + + def quote(value, column = nil) + if value.kind_of?(String) && column && column.type == :binary && column.class.respond_to?(:string_to_binary) + s = column.class.string_to_binary(value).unpack("H*")[0] + "x'#{s}'" + else + super + end + end + + def quote_column_name(name) #:nodoc: + "`#{name}`" + end + + def quote_string(string) #:nodoc: + @connection.quote(string) + end + + def quoted_true + "1" + end + + def quoted_false + "0" + end + + + # CONNECTION MANAGEMENT ==================================== + + def active? + if @connection.respond_to?(:stat) + @connection.stat + else + @connection.query 'select 1' + end + + # mysql-ruby doesn't raise an exception when stat fails. + if @connection.respond_to?(:errno) + @connection.errno.zero? + else + true + end + rescue Mysql::Error + false + end + + def reconnect! + disconnect! + connect + end + + def disconnect! + @connection.close rescue nil + end + + + # DATABASE STATEMENTS ====================================== + + def select_all(sql, name = nil) #:nodoc: + select(sql, name) + end + + def select_one(sql, name = nil) #:nodoc: + result = select(sql, name) + result.nil? ? nil : result.first + end + + def execute(sql, name = nil, retries = 2) #:nodoc: + log(sql, name) { @connection.query(sql) } + rescue ActiveRecord::StatementInvalid => exception + if exception.message.split(":").first =~ /Packets out of order/ + raise ActiveRecord::StatementInvalid, "'Packets out of order' error was received from the database. Please update your mysql bindings (gem install mysql) and read http://dev.mysql.com/doc/mysql/en/password-hashing.html for more information. If you're on Windows, use the Instant Rails installer to get the updated mysql bindings." + else + raise + end + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: + execute(sql, name = nil) + id_value || @connection.insert_id + end + + def update(sql, name = nil) #:nodoc: + execute(sql, name) + @connection.affected_rows + end + + alias_method :delete, :update #:nodoc: + + + def begin_db_transaction #:nodoc: + execute "BEGIN" + rescue Exception + # Transactions aren't supported + end + + def commit_db_transaction #:nodoc: + execute "COMMIT" + rescue Exception + # Transactions aren't supported + end + + def rollback_db_transaction #:nodoc: + execute "ROLLBACK" + rescue Exception + # Transactions aren't supported + end + + + def add_limit_offset!(sql, options) #:nodoc + if limit = options[:limit] + unless offset = options[:offset] + sql << " LIMIT #{limit}" + else + sql << " LIMIT #{offset}, #{limit}" + end + end + end + + + # SCHEMA STATEMENTS ======================================== + + def structure_dump #:nodoc: + if supports_views? + sql = "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'" + else + sql = "SHOW TABLES" + end + + select_all(sql).inject("") do |structure, table| + table.delete('Table_type') + structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n" + end + end + + def recreate_database(name) #:nodoc: + drop_database(name) + create_database(name) + end + + def create_database(name) #:nodoc: + execute "CREATE DATABASE `#{name}`" + end + + def drop_database(name) #:nodoc: + execute "DROP DATABASE IF EXISTS `#{name}`" + end + + def current_database + select_one("SELECT DATABASE() as db")["db"] + end + + def tables(name = nil) #:nodoc: + tables = [] + execute("SHOW TABLES", name).each { |field| tables << field[0] } + tables + end + + def indexes(table_name, name = nil)#:nodoc: + indexes = [] + current_index = nil + execute("SHOW KEYS FROM #{table_name}", name).each do |row| + if current_index != row[2] + next if row[2] == "PRIMARY" # skip the primary key + current_index = row[2] + indexes << IndexDefinition.new(row[0], row[2], row[1] == "0", []) + end + + indexes.last.columns << row[4] + end + indexes + end + + def columns(table_name, name = nil)#:nodoc: + sql = "SHOW FIELDS FROM #{table_name}" + columns = [] + execute(sql, name).each { |field| columns << MysqlColumn.new(field[0], field[4], field[1], field[2] == "YES") } + columns + end + + def create_table(name, options = {}) #:nodoc: + super(name, {:options => "ENGINE=InnoDB"}.merge(options)) + end + + def rename_table(name, new_name) + execute "RENAME TABLE #{name} TO #{new_name}" + end + + def change_column_default(table_name, column_name, default) #:nodoc: + current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"] + + change_column(table_name, column_name, current_type, { :default => default }) + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + options[:default] ||= select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Default"] + + change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit])}" + add_column_options!(change_column_sql, options) + execute(change_column_sql) + end + + def rename_column(table_name, column_name, new_column_name) #:nodoc: + current_type = select_one("SHOW COLUMNS FROM #{table_name} LIKE '#{column_name}'")["Type"] + execute "ALTER TABLE #{table_name} CHANGE #{column_name} #{new_column_name} #{current_type}" + end + + + private + def connect + encoding = @config[:encoding] + if encoding + @connection.options(Mysql::SET_CHARSET_NAME, encoding) rescue nil + end + @connection.real_connect(*@connection_options) + execute("SET NAMES '#{encoding}'") if encoding + end + + def select(sql, name = nil) + @connection.query_with_result = true + result = execute(sql, name) + rows = [] + if @null_values_in_each_hash + result.each_hash { |row| rows << row } + else + all_fields = result.fetch_fields.inject({}) { |fields, f| fields[f.name] = nil; fields } + result.each_hash { |row| rows << all_fields.dup.update(row) } + end + result.free + rows + end + + def supports_views? + version[0] >= 5 + end + + def version + @version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i } + end + end + end +end +require 'active_record/connection_adapters/abstract_adapter' + +module ActiveRecord + class Base + # Establishes a connection to the database that's used by all Active Record objects + def self.openbase_connection(config) # :nodoc: + require_library_or_gem 'openbase' unless self.class.const_defined?(:OpenBase) + + config = config.symbolize_keys + host = config[:host] + username = config[:username].to_s + password = config[:password].to_s + + + if config.has_key?(:database) + database = config[:database] + else + raise ArgumentError, "No database specified. Missing argument: database." + end + + oba = ConnectionAdapters::OpenBaseAdapter.new( + OpenBase.new(database, host, username, password), logger + ) + + oba + end + + end + + module ConnectionAdapters + class OpenBaseColumn < Column #:nodoc: + private + def simplified_type(field_type) + return :integer if field_type.downcase =~ /long/ + return :float if field_type.downcase == "money" + return :binary if field_type.downcase == "object" + super + end + end + # The OpenBase adapter works with the Ruby/Openbase driver by Tetsuya Suzuki. + # http://www.spice-of-life.net/ruby-openbase/ (needs version 0.7.3+) + # + # Options: + # + # * <tt>:host</tt> -- Defaults to localhost + # * <tt>:username</tt> -- Defaults to nothing + # * <tt>:password</tt> -- Defaults to nothing + # * <tt>:database</tt> -- The name of the database. No default, must be provided. + # + # The OpenBase adapter will make use of OpenBase's ability to generate unique ids + # for any column with an unique index applied. Thus, if the value of a primary + # key is not specified at the time an INSERT is performed, the adapter will prefetch + # a unique id for the primary key. This prefetching is also necessary in order + # to return the id after an insert. + # + # Caveat: Operations involving LIMIT and OFFSET do not yet work! + # + # Maintainer: derrickspell@cdmplus.com + class OpenBaseAdapter < AbstractAdapter + def adapter_name + 'OpenBase' + end + + def native_database_types + { + :primary_key => "integer UNIQUE INDEX DEFAULT _rowid", + :string => { :name => "char", :limit => 4096 }, + :text => { :name => "text" }, + :integer => { :name => "integer" }, + :float => { :name => "float" }, + :datetime => { :name => "datetime" }, + :timestamp => { :name => "timestamp" }, + :time => { :name => "time" }, + :date => { :name => "date" }, + :binary => { :name => "object" }, + :boolean => { :name => "boolean" } + } + end + + def supports_migrations? + false + end + + def prefetch_primary_key?(table_name = nil) + true + end + + def default_sequence_name(table_name, primary_key) # :nodoc: + "#{table_name} #{primary_key}" + end + + def next_sequence_value(sequence_name) + ary = sequence_name.split(' ') + if (!ary[1]) then + ary[0] =~ /(\w+)_nonstd_seq/ + ary[0] = $1 + end + @connection.unique_row_id(ary[0], ary[1]) + end + + + # QUOTING ================================================== + + def quote(value, column = nil) + if value.kind_of?(String) && column && column.type == :binary + "'#{@connection.insert_binary(value)}'" + else + super + end + end + + def quoted_true + "1" + end + + def quoted_false + "0" + end + + + + # DATABASE STATEMENTS ====================================== + + def add_limit_offset!(sql, options) #:nodoc + if limit = options[:limit] + unless offset = options[:offset] + sql << " RETURN RESULTS #{limit}" + else + limit = limit + offset + sql << " RETURN RESULTS #{offset} TO #{limit}" + end + end + end + + def select_all(sql, name = nil) #:nodoc: + select(sql, name) + end + + def select_one(sql, name = nil) #:nodoc: + add_limit_offset!(sql,{:limit => 1}) + results = select(sql, name) + results.first if results + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: + execute(sql, name) + update_nulls_after_insert(sql, name, pk, id_value, sequence_name) + id_value + end + + def execute(sql, name = nil) #:nodoc: + log(sql, name) { @connection.execute(sql) } + end + + def update(sql, name = nil) #:nodoc: + execute(sql, name).rows_affected + end + + alias_method :delete, :update #:nodoc: +#=begin + def begin_db_transaction #:nodoc: + execute "START TRANSACTION" + rescue Exception + # Transactions aren't supported + end + + def commit_db_transaction #:nodoc: + execute "COMMIT" + rescue Exception + # Transactions aren't supported + end + + def rollback_db_transaction #:nodoc: + execute "ROLLBACK" + rescue Exception + # Transactions aren't supported + end +#=end + + # SCHEMA STATEMENTS ======================================== + + # Return the list of all tables in the schema search path. + def tables(name = nil) #:nodoc: + tables = @connection.tables + tables.reject! { |t| /\A_SYS_/ === t } + tables + end + + def columns(table_name, name = nil) #:nodoc: + sql = "SELECT * FROM _sys_tables " + sql << "WHERE tablename='#{table_name}' AND INDEXOF(fieldname,'_')<>0 " + sql << "ORDER BY columnNumber" + columns = [] + select_all(sql, name).each do |row| + columns << OpenBaseColumn.new(row["fieldname"], + default_value(row["defaultvalue"]), + sql_type_name(row["typename"],row["length"]), + row["notnull"] + ) + # breakpoint() if row["fieldname"] == "content" + end + columns + end + + def indexes(table_name, name = nil)#:nodoc: + sql = "SELECT fieldname, notnull, searchindex, uniqueindex, clusteredindex FROM _sys_tables " + sql << "WHERE tablename='#{table_name}' AND INDEXOF(fieldname,'_')<>0 " + sql << "AND primarykey=0 " + sql << "AND (searchindex=1 OR uniqueindex=1 OR clusteredindex=1) " + sql << "ORDER BY columnNumber" + indexes = [] + execute(sql, name).each do |row| + indexes << IndexDefinition.new(table_name,index_name(row),row[3]==1,[row[0]]) + end + indexes + end + + + private + def select(sql, name = nil) + sql = translate_sql(sql) + results = execute(sql, name) + + date_cols = [] + col_names = [] + results.column_infos.each do |info| + col_names << info.name + date_cols << info.name if info.type == "date" + end + + rows = [] + if ( results.rows_affected ) + results.each do |row| # loop through result rows + hashed_row = {} + row.each_index do |index| + hashed_row["#{col_names[index]}"] = row[index] unless col_names[index] == "_rowid" + end + date_cols.each do |name| + unless hashed_row["#{name}"].nil? or hashed_row["#{name}"].empty? + hashed_row["#{name}"] = Date.parse(hashed_row["#{name}"],false).to_s + end + end + rows << hashed_row + end + end + rows + end + + def default_value(value) + # Boolean type values + return true if value =~ /true/ + return false if value =~ /false/ + + # Date / Time magic values + return Time.now.to_s if value =~ /^now\(\)/i + + # Empty strings should be set to null + return nil if value.empty? + + # Otherwise return what we got from OpenBase + # and hope for the best... + return value + end + + def sql_type_name(type_name, length) + return "#{type_name}(#{length})" if ( type_name =~ /char/ ) + type_name + end + + def index_name(row = []) + name = "" + name << "UNIQUE " if row[3] + name << "CLUSTERED " if row[4] + name << "INDEX" + name + end + + def translate_sql(sql) + + # Change table.* to list of columns in table + while (sql =~ /SELECT.*\s(\w+)\.\*/) + table = $1 + cols = columns(table) + if ( cols.size == 0 ) then + # Maybe this is a table alias + sql =~ /FROM(.+?)(?:LEFT|OUTER|JOIN|WHERE|GROUP|HAVING|ORDER|RETURN|$)/ + $1 =~ /[\s|,](\w+)\s+#{table}[\s|,]/ # get the tablename for this alias + cols = columns($1) + end + select_columns = [] + cols.each do |col| + select_columns << table + '.' + col.name + end + sql.gsub!(table + '.*',select_columns.join(", ")) if select_columns + end + + # Change JOIN clause to table list and WHERE condition + while (sql =~ /JOIN/) + sql =~ /((LEFT )?(OUTER )?JOIN (\w+) ON )(.+?)(?:LEFT|OUTER|JOIN|WHERE|GROUP|HAVING|ORDER|RETURN|$)/ + join_clause = $1 + $5 + is_outer_join = $3 + join_table = $4 + join_condition = $5 + join_condition.gsub!(/=/,"*") if is_outer_join + if (sql =~ /WHERE/) + sql.gsub!(/WHERE/,"WHERE (#{join_condition}) AND") + else + sql.gsub!(join_clause,"#{join_clause} WHERE #{join_condition}") + end + sql =~ /(FROM .+?)(?:LEFT|OUTER|JOIN|WHERE|$)/ + from_clause = $1 + sql.gsub!(from_clause,"#{from_clause}, #{join_table} ") + sql.gsub!(join_clause,"") + end + + # ORDER BY _rowid if no explicit ORDER BY + # This will ensure that find(:first) returns the first inserted row + if (sql !~ /(ORDER BY)|(GROUP BY)/) + if (sql =~ /RETURN RESULTS/) + sql.sub!(/RETURN RESULTS/,"ORDER BY _rowid RETURN RESULTS") + else + sql << " ORDER BY _rowid" + end + end + + sql + end + + def update_nulls_after_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) + sql =~ /INSERT INTO (\w+) \((.*)\) VALUES\s*\((.*)\)/m + table = $1 + cols = $2 + values = $3 + cols = cols.split(',') + values.gsub!(/'[^']*'/,"''") + values.gsub!(/"[^"]*"/,"\"\"") + values = values.split(',') + update_cols = [] + values.each_index { |index| update_cols << cols[index] if values[index] =~ /\s*NULL\s*/ } + update_sql = "UPDATE #{table} SET" + update_cols.each { |col| update_sql << " #{col}=NULL," unless col.empty? } + update_sql.chop!() + update_sql << " WHERE #{pk}=#{quote(id_value)}" + execute(update_sql, name + " NULL Correction") if update_cols.size > 0 + end + + end + end +end +# oracle_adapter.rb -- ActiveRecord adapter for Oracle 8i, 9i, 10g +# +# Original author: Graham Jenkins +# +# Current maintainer: Michael Schoen <schoenm@earthlink.net> +# +######################################################################### +# +# Implementation notes: +# 1. Redefines (safely) a method in ActiveRecord to make it possible to +# implement an autonumbering solution for Oracle. +# 2. The OCI8 driver is patched to properly handle values for LONG and +# TIMESTAMP columns. The driver-author has indicated that a future +# release of the driver will obviate this patch. +# 3. LOB support is implemented through an after_save callback. +# 4. Oracle does not offer native LIMIT and OFFSET options; this +# functionality is mimiced through the use of nested selects. +# See http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:127412348064 +# +# Do what you want with this code, at your own peril, but if any +# significant portion of my code remains then please acknowledge my +# contribution. +# portions Copyright 2005 Graham Jenkins + +require 'active_record/connection_adapters/abstract_adapter' +require 'delegate' + +begin + require_library_or_gem 'oci8' unless self.class.const_defined? :OCI8 + + module ActiveRecord + class Base + def self.oracle_connection(config) #:nodoc: + # Use OCI8AutoRecover instead of normal OCI8 driver. + ConnectionAdapters::OracleAdapter.new OCI8AutoRecover.new(config), logger + end + + # for backwards-compatibility + def self.oci_connection(config) #:nodoc: + config[:database] = config[:host] + self.oracle_connection(config) + end + + # Enable the id column to be bound into the sql later, by the adapter's insert method. + # This is preferable to inserting the hard-coded value here, because the insert method + # needs to know the id value explicitly. + alias :attributes_with_quotes_pre_oracle :attributes_with_quotes + def attributes_with_quotes(include_primary_key = true) #:nodoc: + aq = attributes_with_quotes_pre_oracle(include_primary_key) + if connection.class == ConnectionAdapters::OracleAdapter + aq[self.class.primary_key] = ":id" if include_primary_key && aq[self.class.primary_key].nil? + end + aq + end + + # After setting large objects to empty, select the OCI8::LOB + # and write back the data. + after_save :write_lobs + def write_lobs() #:nodoc: + if connection.is_a?(ConnectionAdapters::OracleAdapter) + self.class.columns.select { |c| c.type == :binary }.each { |c| + value = self[c.name] + next if value.nil? || (value == '') + lob = connection.select_one( + "SELECT #{ c.name} FROM #{ self.class.table_name } WHERE #{ self.class.primary_key} = #{quote(id)}", + 'Writable Large Object')[c.name] + lob.write value + } + end + end + + private :write_lobs + end + + + module ConnectionAdapters #:nodoc: + class OracleColumn < Column #:nodoc: + attr_reader :sql_type + + # overridden to add the concept of scale, required to differentiate + # between integer and float fields + def initialize(name, default, sql_type, limit, scale, null) + @name, @limit, @sql_type, @scale, @null = name, limit, sql_type, scale, null + + @type = simplified_type(sql_type) + @default = type_cast(default) + + @primary = nil + @text = [:string, :text].include? @type + @number = [:float, :integer].include? @type + end + + def type_cast(value) + return nil if value.nil? || value =~ /^\s*null\s*$/i + case type + when :string then value + when :integer then defined?(value.to_i) ? value.to_i : (value ? 1 : 0) + when :float then value.to_f + when :datetime then cast_to_date_or_time(value) + when :time then cast_to_time(value) + else value + end + end + + private + def simplified_type(field_type) + case field_type + when /char/i : :string + when /num|float|double|dec|real|int/i : @scale == 0 ? :integer : :float + when /date|time/i : @name =~ /_at$/ ? :time : :datetime + when /clob/i : :text + when /blob/i : :binary + end + end + + def cast_to_date_or_time(value) + return value if value.is_a? Date + return nil if value.blank? + guess_date_or_time (value.is_a? Time) ? value : cast_to_time(value) + end + + def cast_to_time(value) + return value if value.is_a? Time + time_array = ParseDate.parsedate value + time_array[0] ||= 2000; time_array[1] ||= 1; time_array[2] ||= 1; + Time.send(Base.default_timezone, *time_array) rescue nil + end + + def guess_date_or_time(value) + (value.hour == 0 and value.min == 0 and value.sec == 0) ? + Date.new(value.year, value.month, value.day) : value + end + end + + + # This is an Oracle/OCI adapter for the ActiveRecord persistence + # framework. It relies upon the OCI8 driver, which works with Oracle 8i + # and above. Most recent development has been on Debian Linux against + # a 10g database, ActiveRecord 1.12.1 and OCI8 0.1.13. + # See: http://rubyforge.org/projects/ruby-oci8/ + # + # Usage notes: + # * Key generation assumes a "${table_name}_seq" sequence is available + # for all tables; the sequence name can be changed using + # ActiveRecord::Base.set_sequence_name. When using Migrations, these + # sequences are created automatically. + # * Oracle uses DATE or TIMESTAMP datatypes for both dates and times. + # Consequently some hacks are employed to map data back to Date or Time + # in Ruby. If the column_name ends in _time it's created as a Ruby Time. + # Else if the hours/minutes/seconds are 0, I make it a Ruby Date. Else + # it's a Ruby Time. This is a bit nasty - but if you use Duck Typing + # you'll probably not care very much. In 9i and up it's tempting to + # map DATE to Date and TIMESTAMP to Time, but too many databases use + # DATE for both. Timezones and sub-second precision on timestamps are + # not supported. + # * Default values that are functions (such as "SYSDATE") are not + # supported. This is a restriction of the way ActiveRecord supports + # default values. + # * Support for Oracle8 is limited by Rails' use of ANSI join syntax, which + # is supported in Oracle9i and later. You will need to use #finder_sql for + # has_and_belongs_to_many associations to run against Oracle8. + # + # Required parameters: + # + # * <tt>:username</tt> + # * <tt>:password</tt> + # * <tt>:database</tt> + class OracleAdapter < AbstractAdapter + + def adapter_name #:nodoc: + 'Oracle' + end + + def supports_migrations? #:nodoc: + true + end + + def native_database_types #:nodoc + { + :primary_key => "NUMBER(38) NOT NULL PRIMARY KEY", + :string => { :name => "VARCHAR2", :limit => 255 }, + :text => { :name => "CLOB" }, + :integer => { :name => "NUMBER", :limit => 38 }, + :float => { :name => "NUMBER" }, + :datetime => { :name => "DATE" }, + :timestamp => { :name => "DATE" }, + :time => { :name => "DATE" }, + :date => { :name => "DATE" }, + :binary => { :name => "BLOB" }, + :boolean => { :name => "NUMBER", :limit => 1 } + } + end + + def table_alias_length + 30 + end + + # QUOTING ================================================== + # + # see: abstract/quoting.rb + + # camelCase column names need to be quoted; not that anyone using Oracle + # would really do this, but handling this case means we pass the test... + def quote_column_name(name) #:nodoc: + name =~ /[A-Z]/ ? "\"#{name}\"" : name + end + + def quote_string(string) #:nodoc: + string.gsub(/'/, "''") + end + + def quote(value, column = nil) #:nodoc: + if column && column.type == :binary + %Q{empty_#{ column.sql_type rescue 'blob' }()} + else + case value + when String : %Q{'#{quote_string(value)}'} + when NilClass : 'null' + when TrueClass : '1' + when FalseClass : '0' + when Numeric : value.to_s + when Date, Time : %Q{'#{value.strftime("%Y-%m-%d %H:%M:%S")}'} + else %Q{'#{quote_string(value.to_yaml)}'} + end + end + end + + + # CONNECTION MANAGEMENT ==================================== + # + + # Returns true if the connection is active. + def active? + # Pings the connection to check if it's still good. Note that an + # #active? method is also available, but that simply returns the + # last known state, which isn't good enough if the connection has + # gone stale since the last use. + @connection.ping + rescue OCIException + false + end + + # Reconnects to the database. + def reconnect! + @connection.reset! + rescue OCIException => e + @logger.warn "#{adapter_name} automatic reconnection failed: #{e.message}" + end + + # Disconnects from the database. + def disconnect! + @connection.logoff rescue nil + @connection.active = false + end + + + # DATABASE STATEMENTS ====================================== + # + # see: abstract/database_statements.rb + + def select_all(sql, name = nil) #:nodoc: + select(sql, name) + end + + def select_one(sql, name = nil) #:nodoc: + result = select_all(sql, name) + result.size > 0 ? result.first : nil + end + + def execute(sql, name = nil) #:nodoc: + log(sql, name) { @connection.exec sql } + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: + if pk.nil? # Who called us? What does the sql look like? No idea! + execute sql, name + elsif id_value # Pre-assigned id + log(sql, name) { @connection.exec sql } + else # Assume the sql contains a bind-variable for the id + id_value = select_one("select #{sequence_name}.nextval id from dual")['id'] + log(sql, name) { @connection.exec sql, id_value } + end + + id_value + end + + alias :update :execute #:nodoc: + alias :delete :execute #:nodoc: + + def begin_db_transaction #:nodoc: + @connection.autocommit = false + end + + def commit_db_transaction #:nodoc: + @connection.commit + ensure + @connection.autocommit = true + end + + def rollback_db_transaction #:nodoc: + @connection.rollback + ensure + @connection.autocommit = true + end + + def add_limit_offset!(sql, options) #:nodoc: + offset = options[:offset] || 0 + + if limit = options[:limit] + sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_ where rownum <= #{offset+limit}) where raw_rnum_ > #{offset}" + elsif offset > 0 + sql.replace "select * from (select raw_sql_.*, rownum raw_rnum_ from (#{sql}) raw_sql_) where raw_rnum_ > #{offset}" + end + end + + def default_sequence_name(table, column) #:nodoc: + "#{table}_seq" + end + + + # SCHEMA STATEMENTS ======================================== + # + # see: abstract/schema_statements.rb + + def current_database #:nodoc: + select_one("select sys_context('userenv','db_name') db from dual")["db"] + end + + def tables(name = nil) #:nodoc: + select_all("select lower(table_name) from user_tables").inject([]) do | tabs, t | + tabs << t.to_a.first.last + end + end + + def indexes(table_name, name = nil) #:nodoc: + result = select_all(<<-SQL, name) + SELECT lower(i.index_name) as index_name, i.uniqueness, lower(c.column_name) as column_name + FROM user_indexes i, user_ind_columns c + WHERE i.table_name = '#{table_name.to_s.upcase}' + AND c.index_name = i.index_name + AND i.index_name NOT IN (SELECT index_name FROM user_constraints WHERE constraint_type = 'P') + ORDER BY i.index_name, c.column_position + SQL + + current_index = nil + indexes = [] + + result.each do |row| + if current_index != row['index_name'] + indexes << IndexDefinition.new(table_name, row['index_name'], row['uniqueness'] == "UNIQUE", []) + current_index = row['index_name'] + end + + indexes.last.columns << row['column_name'] + end + + indexes + end + + def columns(table_name, name = nil) #:nodoc: + (owner, table_name) = @connection.describe(table_name) + + table_cols = %Q{ + select column_name, data_type, data_default, nullable, + decode(data_type, 'NUMBER', data_precision, + 'VARCHAR2', data_length, + null) as length, + decode(data_type, 'NUMBER', data_scale, null) as scale + from all_tab_columns + where owner = '#{owner}' + and table_name = '#{table_name}' + order by column_id + } + + select_all(table_cols, name).map do |row| + if row['data_default'] + row['data_default'].sub!(/^(.*?)\s*$/, '\1') + row['data_default'].sub!(/^'(.*)'$/, '\1') + end + OracleColumn.new( + oracle_downcase(row['column_name']), + row['data_default'], + row['data_type'], + (l = row['length']).nil? ? nil : l.to_i, + (s = row['scale']).nil? ? nil : s.to_i, + row['nullable'] == 'Y' + ) + end + end + + def create_table(name, options = {}) #:nodoc: + super(name, options) + execute "CREATE SEQUENCE #{name}_seq START WITH 10000" unless options[:id] == false + end + + def rename_table(name, new_name) #:nodoc: + execute "RENAME #{name} TO #{new_name}" + execute "RENAME #{name}_seq TO #{new_name}_seq" rescue nil + end + + def drop_table(name) #:nodoc: + super(name) + execute "DROP SEQUENCE #{name}_seq" rescue nil + end + + def remove_index(table_name, options = {}) #:nodoc: + execute "DROP INDEX #{index_name(table_name, options)}" + end + + def change_column_default(table_name, column_name, default) #:nodoc: + execute "ALTER TABLE #{table_name} MODIFY #{column_name} DEFAULT #{quote(default)}" + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit])}" + add_column_options!(change_column_sql, options) + execute(change_column_sql) + end + + def rename_column(table_name, column_name, new_column_name) #:nodoc: + execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} to #{new_column_name}" + end + + def remove_column(table_name, column_name) #:nodoc: + execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}" + end + + def structure_dump #:nodoc: + s = select_all("select sequence_name from user_sequences").inject("") do |structure, seq| + structure << "create sequence #{seq.to_a.first.last};\n\n" + end + + select_all("select table_name from user_tables").inject(s) do |structure, table| + ddl = "create table #{table.to_a.first.last} (\n " + cols = select_all(%Q{ + select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable + from user_tab_columns + where table_name = '#{table.to_a.first.last}' + order by column_id + }).map do |row| + col = "#{row['column_name'].downcase} #{row['data_type'].downcase}" + if row['data_type'] =='NUMBER' and !row['data_precision'].nil? + col << "(#{row['data_precision'].to_i}" + col << ",#{row['data_scale'].to_i}" if !row['data_scale'].nil? + col << ')' + elsif row['data_type'].include?('CHAR') + col << "(#{row['data_length'].to_i})" + end + col << " default #{row['data_default']}" if !row['data_default'].nil? + col << ' not null' if row['nullable'] == 'N' + col + end + ddl << cols.join(",\n ") + ddl << ");\n\n" + structure << ddl + end + end + + def structure_drop #:nodoc: + s = select_all("select sequence_name from user_sequences").inject("") do |drop, seq| + drop << "drop sequence #{seq.to_a.first.last};\n\n" + end + + select_all("select table_name from user_tables").inject(s) do |drop, table| + drop << "drop table #{table.to_a.first.last} cascade constraints;\n\n" + end + end + + + private + + def select(sql, name = nil) + cursor = execute(sql, name) + cols = cursor.get_col_names.map { |x| oracle_downcase(x) } + rows = [] + + while row = cursor.fetch + hash = Hash.new + + cols.each_with_index do |col, i| + hash[col] = + case row[i] + when OCI8::LOB + name == 'Writable Large Object' ? row[i]: row[i].read + when OraDate + (row[i].hour == 0 and row[i].minute == 0 and row[i].second == 0) ? + row[i].to_date : row[i].to_time + else row[i] + end unless col == 'raw_rnum_' + end + + rows << hash + end + + rows + ensure + cursor.close if cursor + end + + # Oracle column names by default are case-insensitive, but treated as upcase; + # for neatness, we'll downcase within Rails. EXCEPT that folks CAN quote + # their column names when creating Oracle tables, which makes then case-sensitive. + # I don't know anybody who does this, but we'll handle the theoretical case of a + # camelCase column name. I imagine other dbs handle this different, since there's a + # unit test that's currently failing test_oci. + def oracle_downcase(column_name) + column_name =~ /[a-z]/ ? column_name : column_name.downcase + end + + end + end + end + + + class OCI8 #:nodoc: + + # This OCI8 patch may not longer be required with the upcoming + # release of version 0.2. + class Cursor #:nodoc: + alias :define_a_column_pre_ar :define_a_column + def define_a_column(i) + case do_ocicall(@ctx) { @parms[i - 1].attrGet(OCI_ATTR_DATA_TYPE) } + when 8 : @stmt.defineByPos(i, String, 65535) # Read LONG values + when 187 : @stmt.defineByPos(i, OraDate) # Read TIMESTAMP values + when 108 + if @parms[i - 1].attrGet(OCI_ATTR_TYPE_NAME) == 'XMLTYPE' + @stmt.defineByPos(i, String, 65535) + else + raise 'unsupported datatype' + end + else define_a_column_pre_ar i + end + end + end + + # missing constant from oci8 < 0.1.14 + OCI_PTYPE_UNK = 0 unless defined?(OCI_PTYPE_UNK) + + # Uses the describeAny OCI call to find the target owner and table_name + # indicated by +name+, parsing through synonynms as necessary. Returns + # an array of [owner, table_name]. + def describe(name) + @desc ||= @@env.alloc(OCIDescribe) + @desc.attrSet(OCI_ATTR_DESC_PUBLIC, -1) if VERSION >= '0.1.14' + @desc.describeAny(@svc, name.to_s, OCI_PTYPE_UNK) + info = @desc.attrGet(OCI_ATTR_PARAM) + + case info.attrGet(OCI_ATTR_PTYPE) + when OCI_PTYPE_TABLE, OCI_PTYPE_VIEW + owner = info.attrGet(OCI_ATTR_OBJ_SCHEMA) + table_name = info.attrGet(OCI_ATTR_OBJ_NAME) + [owner, table_name] + when OCI_PTYPE_SYN + schema = info.attrGet(OCI_ATTR_SCHEMA_NAME) + name = info.attrGet(OCI_ATTR_NAME) + describe(schema + '.' + name) + end + end + + end + + + # The OracleConnectionFactory factors out the code necessary to connect and + # configure an Oracle/OCI connection. + class OracleConnectionFactory #:nodoc: + def new_connection(username, password, database) + conn = OCI8.new username, password, database + conn.exec %q{alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'} + conn.exec %q{alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS'} rescue nil + conn.autocommit = true + conn + end + end + + + # The OCI8AutoRecover class enhances the OCI8 driver with auto-recover and + # reset functionality. If a call to #exec fails, and autocommit is turned on + # (ie., we're not in the middle of a longer transaction), it will + # automatically reconnect and try again. If autocommit is turned off, + # this would be dangerous (as the earlier part of the implied transaction + # may have failed silently if the connection died) -- so instead the + # connection is marked as dead, to be reconnected on it's next use. + class OCI8AutoRecover < DelegateClass(OCI8) #:nodoc: + attr_accessor :active + alias :active? :active + + cattr_accessor :auto_retry + class << self + alias :auto_retry? :auto_retry + end + @@auto_retry = false + + def initialize(config, factory = OracleConnectionFactory.new) + @active = true + @username, @password, @database = config[:username], config[:password], config[:database] + @factory = factory + @connection = @factory.new_connection @username, @password, @database + super @connection + end + + # Checks connection, returns true if active. Note that ping actively + # checks the connection, while #active? simply returns the last + # known state. + def ping + @connection.exec("select 1 from dual") { |r| nil } + @active = true + rescue + @active = false + raise + end + + # Resets connection, by logging off and creating a new connection. + def reset! + logoff rescue nil + begin + @connection = @factory.new_connection @username, @password, @database + __setobj__ @connection + @active = true + rescue + @active = false + raise + end + end + + # ORA-00028: your session has been killed + # ORA-01012: not logged on + # ORA-03113: end-of-file on communication channel + # ORA-03114: not connected to ORACLE + LOST_CONNECTION_ERROR_CODES = [ 28, 1012, 3113, 3114 ] + + # Adds auto-recovery functionality. + # + # See: http://www.jiubao.org/ruby-oci8/api.en.html#label-11 + def exec(sql, *bindvars) + should_retry = self.class.auto_retry? && autocommit? + + begin + @connection.exec(sql, *bindvars) + rescue OCIException => e + raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code) + @active = false + raise unless should_retry + should_retry = false + reset! rescue nil + retry + end + end + + end + +rescue LoadError + # OCI8 driver is unavailable. + module ActiveRecord # :nodoc: + class Base + def self.oracle_connection(config) # :nodoc: + # Set up a reasonable error message + raise LoadError, "Oracle/OCI libraries could not be loaded." + end + def self.oci_connection(config) # :nodoc: + # Set up a reasonable error message + raise LoadError, "Oracle/OCI libraries could not be loaded." + end + end + end +end +require 'active_record/connection_adapters/abstract_adapter' + +module ActiveRecord + class Base + # Establishes a connection to the database that's used by all Active Record objects + def self.postgresql_connection(config) # :nodoc: + require_library_or_gem 'postgres' unless self.class.const_defined?(:PGconn) + + config = config.symbolize_keys + host = config[:host] + port = config[:port] || 5432 unless host.nil? + username = config[:username].to_s + password = config[:password].to_s + + min_messages = config[:min_messages] + + if config.has_key?(:database) + database = config[:database] + else + raise ArgumentError, "No database specified. Missing argument: database." + end + + pga = ConnectionAdapters::PostgreSQLAdapter.new( + PGconn.connect(host, port, "", "", database, username, password), logger, config + ) + + PGconn.translate_results = false if PGconn.respond_to? :translate_results= + + pga.schema_search_path = config[:schema_search_path] || config[:schema_order] + + pga + end + end + + module ConnectionAdapters + # The PostgreSQL adapter works both with the C-based (http://www.postgresql.jp/interfaces/ruby/) and the Ruby-base + # (available both as gem and from http://rubyforge.org/frs/?group_id=234&release_id=1145) drivers. + # + # Options: + # + # * <tt>:host</tt> -- Defaults to localhost + # * <tt>:port</tt> -- Defaults to 5432 + # * <tt>:username</tt> -- Defaults to nothing + # * <tt>:password</tt> -- Defaults to nothing + # * <tt>:database</tt> -- The name of the database. No default, must be provided. + # * <tt>:schema_search_path</tt> -- An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the :schema_order option. + # * <tt>:encoding</tt> -- An optional client encoding that is using in a SET client_encoding TO <encoding> call on connection. + # * <tt>:min_messages</tt> -- An optional client min messages that is using in a SET client_min_messages TO <min_messages> call on connection. + class PostgreSQLAdapter < AbstractAdapter + def adapter_name + 'PostgreSQL' + end + + def initialize(connection, logger, config = {}) + super(connection, logger) + @config = config + configure_connection + end + + # Is this connection alive and ready for queries? + def active? + if @connection.respond_to?(:status) + @connection.status == PGconn::CONNECTION_OK + else + @connection.query 'SELECT 1' + true + end + # postgres-pr raises a NoMethodError when querying if no conn is available + rescue PGError, NoMethodError + false + end + + # Close then reopen the connection. + def reconnect! + # TODO: postgres-pr doesn't have PGconn#reset. + if @connection.respond_to?(:reset) + @connection.reset + configure_connection + end + end + + def disconnect! + # Both postgres and postgres-pr respond to :close + @connection.close rescue nil + end + + def native_database_types + { + :primary_key => "serial primary key", + :string => { :name => "character varying", :limit => 255 }, + :text => { :name => "text" }, + :integer => { :name => "integer" }, + :float => { :name => "float" }, + :datetime => { :name => "timestamp" }, + :timestamp => { :name => "timestamp" }, + :time => { :name => "time" }, + :date => { :name => "date" }, + :binary => { :name => "bytea" }, + :boolean => { :name => "boolean" } + } + end + + def supports_migrations? + true + end + + def table_alias_length + 63 + end + + # QUOTING ================================================== + + def quote(value, column = nil) + if value.kind_of?(String) && column && column.type == :binary + "'#{escape_bytea(value)}'" + else + super + end + end + + def quote_column_name(name) + %("#{name}") + end + + + # DATABASE STATEMENTS ====================================== + + def select_all(sql, name = nil) #:nodoc: + select(sql, name) + end + + def select_one(sql, name = nil) #:nodoc: + result = select(sql, name) + result.first if result + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: + execute(sql, name) + table = sql.split(" ", 4)[2] + id_value || last_insert_id(table, sequence_name || default_sequence_name(table, pk)) + end + + def query(sql, name = nil) #:nodoc: + log(sql, name) { @connection.query(sql) } + end + + def execute(sql, name = nil) #:nodoc: + log(sql, name) { @connection.exec(sql) } + end + + def update(sql, name = nil) #:nodoc: + execute(sql, name).cmdtuples + end + + alias_method :delete, :update #:nodoc: + + + def begin_db_transaction #:nodoc: + execute "BEGIN" + end + + def commit_db_transaction #:nodoc: + execute "COMMIT" + end + + def rollback_db_transaction #:nodoc: + execute "ROLLBACK" + end + + + # SCHEMA STATEMENTS ======================================== + + # Return the list of all tables in the schema search path. + def tables(name = nil) #:nodoc: + schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',') + query(<<-SQL, name).map { |row| row[0] } + SELECT tablename + FROM pg_tables + WHERE schemaname IN (#{schemas}) + SQL + end + + def indexes(table_name, name = nil) #:nodoc: + result = query(<<-SQL, name) + SELECT i.relname, d.indisunique, a.attname + FROM pg_class t, pg_class i, pg_index d, pg_attribute a + WHERE i.relkind = 'i' + AND d.indexrelid = i.oid + AND d.indisprimary = 'f' + AND t.oid = d.indrelid + AND t.relname = '#{table_name}' + AND a.attrelid = t.oid + AND ( d.indkey[0]=a.attnum OR d.indkey[1]=a.attnum + OR d.indkey[2]=a.attnum OR d.indkey[3]=a.attnum + OR d.indkey[4]=a.attnum OR d.indkey[5]=a.attnum + OR d.indkey[6]=a.attnum OR d.indkey[7]=a.attnum + OR d.indkey[8]=a.attnum OR d.indkey[9]=a.attnum ) + ORDER BY i.relname + SQL + + current_index = nil + indexes = [] + + result.each do |row| + if current_index != row[0] + indexes << IndexDefinition.new(table_name, row[0], row[1] == "t", []) + current_index = row[0] + end + + indexes.last.columns << row[2] + end + + indexes + end + + def columns(table_name, name = nil) #:nodoc: + column_definitions(table_name).collect do |name, type, default, notnull| + Column.new(name, default_value(default), translate_field_type(type), + notnull == "f") + end + end + + # Set the schema search path to a string of comma-separated schema names. + # Names beginning with $ are quoted (e.g. $user => '$user') + # See http://www.postgresql.org/docs/8.0/interactive/ddl-schemas.html + def schema_search_path=(schema_csv) #:nodoc: + if schema_csv + execute "SET search_path TO #{schema_csv}" + @schema_search_path = nil + end + end + + def schema_search_path #:nodoc: + @schema_search_path ||= query('SHOW search_path')[0][0] + end + + def default_sequence_name(table_name, pk = nil) + default_pk, default_seq = pk_and_sequence_for(table_name) + default_seq || "#{table_name}_#{pk || default_pk || 'id'}_seq" + end + + # Resets sequence to the max value of the table's pk if present. + def reset_pk_sequence!(table, pk = nil, sequence = nil) + unless pk and sequence + default_pk, default_sequence = pk_and_sequence_for(table) + pk ||= default_pk + sequence ||= default_sequence + end + if pk + if sequence + select_value <<-end_sql, 'Reset sequence' + SELECT setval('#{sequence}', (SELECT COALESCE(MAX(#{pk})+(SELECT increment_by FROM #{sequence}), (SELECT min_value FROM #{sequence})) FROM #{table}), false) + end_sql + else + @logger.warn "#{table} has primary key #{pk} with no default sequence" if @logger + end + end + end + + # Find a table's primary key and sequence. + def pk_and_sequence_for(table) + # First try looking for a sequence with a dependency on the + # given table's primary key. + result = execute(<<-end_sql, 'PK and serial sequence')[0] + SELECT attr.attname, name.nspname, seq.relname + FROM pg_class seq, + pg_attribute attr, + pg_depend dep, + pg_namespace name, + pg_constraint cons + WHERE seq.oid = dep.objid + AND seq.relnamespace = name.oid + AND seq.relkind = 'S' + AND attr.attrelid = dep.refobjid + AND attr.attnum = dep.refobjsubid + AND attr.attrelid = cons.conrelid + AND attr.attnum = cons.conkey[1] + AND cons.contype = 'p' + AND dep.refobjid = '#{table}'::regclass + end_sql + + if result.nil? or result.empty? + # If that fails, try parsing the primary key's default value. + # Support the 7.x and 8.0 nextval('foo'::text) as well as + # the 8.1+ nextval('foo'::regclass). + # TODO: assumes sequence is in same schema as table. + result = execute(<<-end_sql, 'PK and custom sequence')[0] + SELECT attr.attname, name.nspname, split_part(def.adsrc, '\\\'', 2) + FROM pg_class t + JOIN pg_namespace name ON (t.relnamespace = name.oid) + JOIN pg_attribute attr ON (t.oid = attrelid) + JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum) + JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1]) + WHERE t.oid = '#{table}'::regclass + AND cons.contype = 'p' + AND def.adsrc ~* 'nextval' + end_sql + end + # check for existence of . in sequence name as in public.foo_sequence. if it does not exist, join the current namespace + result.last['.'] ? [result.first, result.last] : [result.first, "#{result[1]}.#{result[2]}"] + rescue + nil + end + + def rename_table(name, new_name) + execute "ALTER TABLE #{name} RENAME TO #{new_name}" + end + + def add_column(table_name, column_name, type, options = {}) + execute("ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type, options[:limit])}") + execute("ALTER TABLE #{table_name} ALTER #{column_name} SET NOT NULL") if options[:null] == false + change_column_default(table_name, column_name, options[:default]) unless options[:default].nil? + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + begin + execute "ALTER TABLE #{table_name} ALTER #{column_name} TYPE #{type_to_sql(type, options[:limit])}" + rescue ActiveRecord::StatementInvalid + # This is PG7, so we use a more arcane way of doing it. + begin_db_transaction + add_column(table_name, "#{column_name}_ar_tmp", type, options) + execute "UPDATE #{table_name} SET #{column_name}_ar_tmp = CAST(#{column_name} AS #{type_to_sql(type, options[:limit])})" + remove_column(table_name, column_name) + rename_column(table_name, "#{column_name}_ar_tmp", column_name) + commit_db_transaction + end + change_column_default(table_name, column_name, options[:default]) unless options[:default].nil? + end + + def change_column_default(table_name, column_name, default) #:nodoc: + execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT '#{default}'" + end + + def rename_column(table_name, column_name, new_column_name) #:nodoc: + execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} TO #{new_column_name}" + end + + def remove_index(table_name, options) #:nodoc: + execute "DROP INDEX #{index_name(table_name, options)}" + end + + private + BYTEA_COLUMN_TYPE_OID = 17 + TIMESTAMPOID = 1114 + TIMESTAMPTZOID = 1184 + + def configure_connection + if @config[:encoding] + execute("SET client_encoding TO '#{@config[:encoding]}'") + end + if @config[:min_messages] + execute("SET client_min_messages TO '#{@config[:min_messages]}'") + end + end + + def last_insert_id(table, sequence_name) + Integer(select_value("SELECT currval('#{sequence_name}')")) + end + + def select(sql, name = nil) + res = execute(sql, name) + results = res.result + rows = [] + if results.length > 0 + fields = res.fields + results.each do |row| + hashed_row = {} + row.each_index do |cel_index| + column = row[cel_index] + + case res.type(cel_index) + when BYTEA_COLUMN_TYPE_OID + column = unescape_bytea(column) + when TIMESTAMPTZOID, TIMESTAMPOID + column = cast_to_time(column) + end + + hashed_row[fields[cel_index]] = column + end + rows << hashed_row + end + end + return rows + end + + def escape_bytea(s) + if PGconn.respond_to? :escape_bytea + self.class.send(:define_method, :escape_bytea) do |s| + PGconn.escape_bytea(s) if s + end + else + self.class.send(:define_method, :escape_bytea) do |s| + if s + result = '' + s.each_byte { |c| result << sprintf('\\\\%03o', c) } + result + end + end + end + escape_bytea(s) + end + + def unescape_bytea(s) + if PGconn.respond_to? :unescape_bytea + self.class.send(:define_method, :unescape_bytea) do |s| + PGconn.unescape_bytea(s) if s + end + else + self.class.send(:define_method, :unescape_bytea) do |s| + if s + result = '' + i, max = 0, s.size + while i < max + char = s[i] + if char == ?\\ + if s[i+1] == ?\\ + char = ?\\ + i += 1 + else + char = s[i+1..i+3].oct + i += 3 + end + end + result << char + i += 1 + end + result + end + end + end + unescape_bytea(s) + end + + # Query a table's column names, default values, and types. + # + # The underlying query is roughly: + # SELECT column.name, column.type, default.value + # FROM column LEFT JOIN default + # ON column.table_id = default.table_id + # AND column.num = default.column_num + # WHERE column.table_id = get_table_id('table_name') + # AND column.num > 0 + # AND NOT column.is_dropped + # ORDER BY column.num + # + # If the table name is not prefixed with a schema, the database will + # take the first match from the schema search path. + # + # Query implementation notes: + # - format_type includes the column size constraint, e.g. varchar(50) + # - ::regclass is a function that gives the id for a table name + def column_definitions(table_name) + query <<-end_sql + SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull + FROM pg_attribute a LEFT JOIN pg_attrdef d + ON a.attrelid = d.adrelid AND a.attnum = d.adnum + WHERE a.attrelid = '#{table_name}'::regclass + AND a.attnum > 0 AND NOT a.attisdropped + ORDER BY a.attnum + end_sql + end + + # Translate PostgreSQL-specific types into simplified SQL types. + # These are special cases; standard types are handled by + # ConnectionAdapters::Column#simplified_type. + def translate_field_type(field_type) + # Match the beginning of field_type since it may have a size constraint on the end. + case field_type + when /^timestamp/i then 'datetime' + when /^real|^money/i then 'float' + when /^interval/i then 'string' + # geometric types (the line type is currently not implemented in postgresql) + when /^(?:point|lseg|box|"?path"?|polygon|circle)/i then 'string' + when /^bytea/i then 'binary' + else field_type # Pass through standard types. + end + end + + def default_value(value) + # Boolean types + return "t" if value =~ /true/i + return "f" if value =~ /false/i + + # Char/String/Bytea type values + return $1 if value =~ /^'(.*)'::(bpchar|text|character varying|bytea)$/ + + # Numeric values + return value if value =~ /^-?[0-9]+(\.[0-9]*)?/ + + # Fixed dates / times + return $1 if value =~ /^'(.+)'::(date|timestamp)/ + + # Anything else is blank, some user type, or some function + # and we can't know the value of that, so return nil. + return nil + end + + # Only needed for DateTime instances + def cast_to_time(value) + return value unless value.class == DateTime + v = value + time_array = [v.year, v.month, v.day, v.hour, v.min, v.sec] + Time.send(Base.default_timezone, *time_array) rescue nil + end + end + end +end +# Author: Luke Holden <lholden@cablelan.net> +# Updated for SQLite3: Jamis Buck <jamis@37signals.com> + +require 'active_record/connection_adapters/abstract_adapter' + +module ActiveRecord + class Base + class << self + # sqlite3 adapter reuses sqlite_connection. + def sqlite3_connection(config) # :nodoc: + parse_config!(config) + + unless self.class.const_defined?(:SQLite3) + require_library_or_gem(config[:adapter]) + end + + db = SQLite3::Database.new( + config[:database], + :results_as_hash => true, + :type_translation => false + ) + ConnectionAdapters::SQLiteAdapter.new(db, logger) + end + + # Establishes a connection to the database that's used by all Active Record objects + def sqlite_connection(config) # :nodoc: + parse_config!(config) + + unless self.class.const_defined?(:SQLite) + require_library_or_gem(config[:adapter]) + + db = SQLite::Database.new(config[:database], 0) + db.show_datatypes = "ON" if !defined? SQLite::Version + db.results_as_hash = true if defined? SQLite::Version + db.type_translation = false + + # "Downgrade" deprecated sqlite API + if SQLite.const_defined?(:Version) + ConnectionAdapters::SQLite2Adapter.new(db, logger) + else + ConnectionAdapters::DeprecatedSQLiteAdapter.new(db, logger) + end + end + end + + private + def parse_config!(config) + config[:database] ||= config[:dbfile] + # Require database. + unless config[:database] + raise ArgumentError, "No database file specified. Missing argument: database" + end + + # Allow database path relative to RAILS_ROOT, but only if + # the database path is not the special path that tells + # Sqlite build a database only in memory. + if Object.const_defined?(:RAILS_ROOT) && ':memory:' != config[:database] + config[:database] = File.expand_path(config[:database], RAILS_ROOT) + end + end + end + end + + module ConnectionAdapters #:nodoc: + class SQLiteColumn < Column #:nodoc: + class << self + def string_to_binary(value) + value.gsub(/\0|\%/) do |b| + case b + when "\0" then "%00" + when "%" then "%25" + end + end + end + + def binary_to_string(value) + value.gsub(/%00|%25/) do |b| + case b + when "%00" then "\0" + when "%25" then "%" + end + end + end + end + end + + # The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby drivers (available both as gems and + # from http://rubyforge.org/projects/sqlite-ruby/). + # + # Options: + # + # * <tt>:database</tt> -- Path to the database file. + class SQLiteAdapter < AbstractAdapter + def adapter_name #:nodoc: + 'SQLite' + end + + def supports_migrations? #:nodoc: + true + end + + def supports_count_distinct? #:nodoc: + false + end + + def native_database_types #:nodoc: + { + :primary_key => "INTEGER PRIMARY KEY NOT NULL", + :string => { :name => "varchar", :limit => 255 }, + :text => { :name => "text" }, + :integer => { :name => "integer" }, + :float => { :name => "float" }, + :datetime => { :name => "datetime" }, + :timestamp => { :name => "datetime" }, + :time => { :name => "datetime" }, + :date => { :name => "date" }, + :binary => { :name => "blob" }, + :boolean => { :name => "boolean" } + } + end + + + # QUOTING ================================================== + + def quote_string(s) #:nodoc: + @connection.class.quote(s) + end + + def quote_column_name(name) #:nodoc: + %Q("#{name}") + end + + + # DATABASE STATEMENTS ====================================== + + def execute(sql, name = nil) #:nodoc: + catch_schema_changes { log(sql, name) { @connection.execute(sql) } } + end + + def update(sql, name = nil) #:nodoc: + execute(sql, name) + @connection.changes + end + + def delete(sql, name = nil) #:nodoc: + sql += " WHERE 1=1" unless sql =~ /WHERE/i + execute(sql, name) + @connection.changes + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc: + execute(sql, name = nil) + id_value || @connection.last_insert_row_id + end + + def select_all(sql, name = nil) #:nodoc: + execute(sql, name).map do |row| + record = {} + row.each_key do |key| + if key.is_a?(String) + record[key.sub(/^\w+\./, '')] = row[key] + end + end + record + end + end + + def select_one(sql, name = nil) #:nodoc: + result = select_all(sql, name) + result.nil? ? nil : result.first + end + + + def begin_db_transaction #:nodoc: + catch_schema_changes { @connection.transaction } + end + + def commit_db_transaction #:nodoc: + catch_schema_changes { @connection.commit } + end + + def rollback_db_transaction #:nodoc: + catch_schema_changes { @connection.rollback } + end + + + # SCHEMA STATEMENTS ======================================== + + def tables(name = nil) #:nodoc: + execute("SELECT name FROM sqlite_master WHERE type = 'table'", name).map do |row| + row[0] + end + end + + def columns(table_name, name = nil) #:nodoc: + table_structure(table_name).map do |field| + SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'] == "0") + end + end + + def indexes(table_name, name = nil) #:nodoc: + execute("PRAGMA index_list(#{table_name})", name).map do |row| + index = IndexDefinition.new(table_name, row['name']) + index.unique = row['unique'] != '0' + index.columns = execute("PRAGMA index_info('#{index.name}')").map { |col| col['name'] } + index + end + end + + def primary_key(table_name) #:nodoc: + column = table_structure(table_name).find {|field| field['pk'].to_i == 1} + column ? column['name'] : nil + end + + def remove_index(table_name, options={}) #:nodoc: + execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}" + end + + def rename_table(name, new_name) + move_table(name, new_name) + end + + def add_column(table_name, column_name, type, options = {}) #:nodoc: + alter_table(table_name) do |definition| + definition.column(column_name, type, options) + end + end + + def remove_column(table_name, column_name) #:nodoc: + alter_table(table_name) do |definition| + definition.columns.delete(definition[column_name]) + end + end + + def change_column_default(table_name, column_name, default) #:nodoc: + alter_table(table_name) do |definition| + definition[column_name].default = default + end + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + alter_table(table_name) do |definition| + definition[column_name].instance_eval do + self.type = type + self.limit = options[:limit] if options[:limit] + self.default = options[:default] if options[:default] + end + end + end + + def rename_column(table_name, column_name, new_column_name) #:nodoc: + alter_table(table_name, :rename => {column_name => new_column_name}) + end + + + protected + def table_structure(table_name) + returning structure = execute("PRAGMA table_info(#{table_name})") do + raise ActiveRecord::StatementInvalid if structure.empty? + end + end + + def alter_table(table_name, options = {}) #:nodoc: + altered_table_name = "altered_#{table_name}" + caller = lambda {|definition| yield definition if block_given?} + + transaction do + move_table(table_name, altered_table_name, + options.merge(:temporary => true)) + move_table(altered_table_name, table_name, &caller) + end + end + + def move_table(from, to, options = {}, &block) #:nodoc: + copy_table(from, to, options, &block) + drop_table(from) + end + + def copy_table(from, to, options = {}) #:nodoc: + create_table(to, options) do |@definition| + columns(from).each do |column| + column_name = options[:rename] ? + (options[:rename][column.name] || + options[:rename][column.name.to_sym] || + column.name) : column.name + + @definition.column(column_name, column.type, + :limit => column.limit, :default => column.default, + :null => column.null) + end + @definition.primary_key(primary_key(from)) + yield @definition if block_given? + end + + copy_table_indexes(from, to) + copy_table_contents(from, to, + @definition.columns.map {|column| column.name}, + options[:rename] || {}) + end + + def copy_table_indexes(from, to) #:nodoc: + indexes(from).each do |index| + name = index.name + if to == "altered_#{from}" + name = "temp_#{name}" + elsif from == "altered_#{to}" + name = name[5..-1] + end + + opts = { :name => name } + opts[:unique] = true if index.unique + add_index(to, index.columns, opts) + end + end + + def copy_table_contents(from, to, columns, rename = {}) #:nodoc: + column_mappings = Hash[*columns.map {|name| [name, name]}.flatten] + rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map} + + @connection.execute "SELECT * FROM #{from}" do |row| + sql = "INSERT INTO #{to} VALUES (" + sql << columns.map {|col| quote row[column_mappings[col]]} * ', ' + sql << ')' + @connection.execute sql + end + end + + def catch_schema_changes + return yield + rescue ActiveRecord::StatementInvalid => exception + if exception.message =~ /database schema has changed/ + reconnect! + retry + else + raise + end + end + end + + class SQLite2Adapter < SQLiteAdapter # :nodoc: + # SQLite 2 does not support COUNT(DISTINCT) queries: + # + # select COUNT(DISTINCT ArtistID) from CDs; + # + # In order to get the number of artists we execute the following statement + # + # SELECT COUNT(ArtistID) FROM (SELECT DISTINCT ArtistID FROM CDs); + def execute(sql, name = nil) #:nodoc: + super(rewrite_count_distinct_queries(sql), name) + end + + def rewrite_count_distinct_queries(sql) + if sql =~ /count\(distinct ([^\)]+)\)( AS \w+)? (.*)/i + distinct_column = $1 + distinct_query = $3 + column_name = distinct_column.split('.').last + "SELECT COUNT(#{column_name}) FROM (SELECT DISTINCT #{distinct_column} #{distinct_query})" + else + sql + end + end + end + + class DeprecatedSQLiteAdapter < SQLite2Adapter # :nodoc: + def insert(sql, name = nil, pk = nil, id_value = nil) + execute(sql, name = nil) + id_value || @connection.last_insert_rowid + end + end + end +end +require 'active_record/connection_adapters/abstract_adapter' + +# sqlserver_adapter.rb -- ActiveRecord adapter for Microsoft SQL Server +# +# Author: Joey Gibson <joey@joeygibson.com> +# Date: 10/14/2004 +# +# Modifications: DeLynn Berry <delynnb@megastarfinancial.com> +# Date: 3/22/2005 +# +# Modifications (ODBC): Mark Imbriaco <mark.imbriaco@pobox.com> +# Date: 6/26/2005 +# +# Current maintainer: Ryan Tomayko <rtomayko@gmail.com> +# +# Modifications (Migrations): Tom Ward <tom@popdog.net> +# Date: 27/10/2005 +# + +module ActiveRecord + class Base + def self.sqlserver_connection(config) #:nodoc: + require_library_or_gem 'dbi' unless self.class.const_defined?(:DBI) + + config = config.symbolize_keys + + mode = config[:mode] ? config[:mode].to_s.upcase : 'ADO' + username = config[:username] ? config[:username].to_s : 'sa' + password = config[:password] ? config[:password].to_s : '' + autocommit = config.key?(:autocommit) ? config[:autocommit] : true + if mode == "ODBC" + raise ArgumentError, "Missing DSN. Argument ':dsn' must be set in order for this adapter to work." unless config.has_key?(:dsn) + dsn = config[:dsn] + driver_url = "DBI:ODBC:#{dsn}" + else + raise ArgumentError, "Missing Database. Argument ':database' must be set in order for this adapter to work." unless config.has_key?(:database) + database = config[:database] + host = config[:host] ? config[:host].to_s : 'localhost' + driver_url = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User Id=#{username};Password=#{password};" + end + conn = DBI.connect(driver_url, username, password) + conn["AutoCommit"] = autocommit + ConnectionAdapters::SQLServerAdapter.new(conn, logger, [driver_url, username, password]) + end + end # class Base + + module ConnectionAdapters + class ColumnWithIdentity < Column# :nodoc: + attr_reader :identity, :is_special, :scale + + def initialize(name, default, sql_type = nil, is_identity = false, null = true, scale_value = 0) + super(name, default, sql_type, null) + @identity = is_identity + @is_special = sql_type =~ /text|ntext|image/i ? true : false + @scale = scale_value + # SQL Server only supports limits on *char and float types + @limit = nil unless @type == :float or @type == :string + end + + def simplified_type(field_type) + case field_type + when /int|bigint|smallint|tinyint/i then :integer + when /float|double|decimal|money|numeric|real|smallmoney/i then @scale == 0 ? :integer : :float + when /datetime|smalldatetime/i then :datetime + when /timestamp/i then :timestamp + when /time/i then :time + when /text|ntext/i then :text + when /binary|image|varbinary/i then :binary + when /char|nchar|nvarchar|string|varchar/i then :string + when /bit/i then :boolean + when /uniqueidentifier/i then :string + end + end + + def type_cast(value) + return nil if value.nil? || value =~ /^\s*null\s*$/i + case type + when :string then value + when :integer then value == true || value == false ? value == true ? 1 : 0 : value.to_i + when :float then value.to_f + when :datetime then cast_to_datetime(value) + when :timestamp then cast_to_time(value) + when :time then cast_to_time(value) + when :date then cast_to_datetime(value) + when :boolean then value == true or (value =~ /^t(rue)?$/i) == 0 or value.to_s == '1' + else value + end + end + + def cast_to_time(value) + return value if value.is_a?(Time) + time_array = ParseDate.parsedate(value) + time_array[0] ||= 2000 + time_array[1] ||= 1 + time_array[2] ||= 1 + Time.send(Base.default_timezone, *time_array) rescue nil + end + + def cast_to_datetime(value) + if value.is_a?(Time) + if value.year != 0 and value.month != 0 and value.day != 0 + return value + else + return Time.mktime(2000, 1, 1, value.hour, value.min, value.sec) rescue nil + end + end + return cast_to_time(value) if value.is_a?(Date) or value.is_a?(String) rescue nil + value + end + + # These methods will only allow the adapter to insert binary data with a length of 7K or less + # because of a SQL Server statement length policy. + def self.string_to_binary(value) + value.gsub(/(\r|\n|\0|\x1a)/) do + case $1 + when "\r" then "%00" + when "\n" then "%01" + when "\0" then "%02" + when "\x1a" then "%03" + end + end + end + + def self.binary_to_string(value) + value.gsub(/(%00|%01|%02|%03)/) do + case $1 + when "%00" then "\r" + when "%01" then "\n" + when "%02\0" then "\0" + when "%03" then "\x1a" + end + end + end + end + + # In ADO mode, this adapter will ONLY work on Windows systems, + # since it relies on Win32OLE, which, to my knowledge, is only + # available on Windows. + # + # This mode also relies on the ADO support in the DBI module. If you are using the + # one-click installer of Ruby, then you already have DBI installed, but + # the ADO module is *NOT* installed. You will need to get the latest + # source distribution of Ruby-DBI from http://ruby-dbi.sourceforge.net/ + # unzip it, and copy the file + # <tt>src/lib/dbd_ado/ADO.rb</tt> + # to + # <tt>X:/Ruby/lib/ruby/site_ruby/1.8/DBD/ADO/ADO.rb</tt> + # (you will more than likely need to create the ADO directory). + # Once you've installed that file, you are ready to go. + # + # In ODBC mode, the adapter requires the ODBC support in the DBI module which requires + # the Ruby ODBC module. Ruby ODBC 0.996 was used in development and testing, + # and it is available at http://www.ch-werner.de/rubyodbc/ + # + # Options: + # + # * <tt>:mode</tt> -- ADO or ODBC. Defaults to ADO. + # * <tt>:username</tt> -- Defaults to sa. + # * <tt>:password</tt> -- Defaults to empty string. + # + # ADO specific options: + # + # * <tt>:host</tt> -- Defaults to localhost. + # * <tt>:database</tt> -- The name of the database. No default, must be provided. + # + # ODBC specific options: + # + # * <tt>:dsn</tt> -- Defaults to nothing. + # + # ADO code tested on Windows 2000 and higher systems, + # running ruby 1.8.2 (2004-07-29) [i386-mswin32], and SQL Server 2000 SP3. + # + # ODBC code tested on a Fedora Core 4 system, running FreeTDS 0.63, + # unixODBC 2.2.11, Ruby ODBC 0.996, Ruby DBI 0.0.23 and Ruby 1.8.2. + # [Linux strongmad 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 i686 i386 GNU/Linux] + class SQLServerAdapter < AbstractAdapter + + def initialize(connection, logger, connection_options=nil) + super(connection, logger) + @connection_options = connection_options + end + + def native_database_types + { + :primary_key => "int NOT NULL IDENTITY(1, 1) PRIMARY KEY", + :string => { :name => "varchar", :limit => 255 }, + :text => { :name => "text" }, + :integer => { :name => "int" }, + :float => { :name => "float", :limit => 8 }, + :datetime => { :name => "datetime" }, + :timestamp => { :name => "datetime" }, + :time => { :name => "datetime" }, + :date => { :name => "datetime" }, + :binary => { :name => "image"}, + :boolean => { :name => "bit"} + } + end + + def adapter_name + 'SQLServer' + end + + def supports_migrations? #:nodoc: + true + end + + # CONNECTION MANAGEMENT ====================================# + + # Returns true if the connection is active. + def active? + @connection.execute("SELECT 1") { } + true + rescue DBI::DatabaseError, DBI::InterfaceError + false + end + + # Reconnects to the database, returns false if no connection could be made. + def reconnect! + disconnect! + @connection = DBI.connect(*@connection_options) + rescue DBI::DatabaseError => e + @logger.warn "#{adapter_name} reconnection failed: #{e.message}" if @logger + false + end + + # Disconnects from the database + + def disconnect! + @connection.disconnect rescue nil + end + + def select_all(sql, name = nil) + select(sql, name) + end + + def select_one(sql, name = nil) + add_limit!(sql, :limit => 1) + result = select(sql, name) + result.nil? ? nil : result.first + end + + def columns(table_name, name = nil) + return [] if table_name.blank? + table_name = table_name.to_s if table_name.is_a?(Symbol) + table_name = table_name.split('.')[-1] unless table_name.nil? + sql = "SELECT COLUMN_NAME as ColName, COLUMN_DEFAULT as DefaultValue, DATA_TYPE as ColType, IS_NULLABLE As IsNullable, COL_LENGTH('#{table_name}', COLUMN_NAME) as Length, COLUMNPROPERTY(OBJECT_ID('#{table_name}'), COLUMN_NAME, 'IsIdentity') as IsIdentity, NUMERIC_SCALE as Scale FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '#{table_name}'" + # Comment out if you want to have the Columns select statment logged. + # Personally, I think it adds unnecessary bloat to the log. + # If you do comment it out, make sure to un-comment the "result" line that follows + result = log(sql, name) { @connection.select_all(sql) } + #result = @connection.select_all(sql) + columns = [] + result.each do |field| + default = field[:DefaultValue].to_s.gsub!(/[()\']/,"") =~ /null/ ? nil : field[:DefaultValue] + type = "#{field[:ColType]}(#{field[:Length]})" + is_identity = field[:IsIdentity] == 1 + is_nullable = field[:IsNullable] == 'YES' + columns << ColumnWithIdentity.new(field[:ColName], default, type, is_identity, is_nullable, field[:Scale]) + end + columns + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) + begin + table_name = get_table_name(sql) + col = get_identity_column(table_name) + ii_enabled = false + + if col != nil + if query_contains_identity_column(sql, col) + begin + execute enable_identity_insert(table_name, true) + ii_enabled = true + rescue Exception => e + raise ActiveRecordError, "IDENTITY_INSERT could not be turned ON" + end + end + end + log(sql, name) do + @connection.execute(sql) + id_value || select_one("SELECT @@IDENTITY AS Ident")["Ident"] + end + ensure + if ii_enabled + begin + execute enable_identity_insert(table_name, false) + rescue Exception => e + raise ActiveRecordError, "IDENTITY_INSERT could not be turned OFF" + end + end + end + end + + def execute(sql, name = nil) + if sql =~ /^\s*INSERT/i + insert(sql, name) + elsif sql =~ /^\s*UPDATE|^\s*DELETE/i + log(sql, name) do + @connection.execute(sql) + retVal = select_one("SELECT @@ROWCOUNT AS AffectedRows")["AffectedRows"] + end + else + log(sql, name) { @connection.execute(sql) } + end + end + + def update(sql, name = nil) + execute(sql, name) + end + alias_method :delete, :update + + def begin_db_transaction + @connection["AutoCommit"] = false + rescue Exception => e + @connection["AutoCommit"] = true + end + + def commit_db_transaction + @connection.commit + ensure + @connection["AutoCommit"] = true + end + + def rollback_db_transaction + @connection.rollback + ensure + @connection["AutoCommit"] = true + end + + def quote(value, column = nil) + case value + when String + if column && column.type == :binary && column.class.respond_to?(:string_to_binary) + "'#{quote_string(column.class.string_to_binary(value))}'" + else + "'#{quote_string(value)}'" + end + when NilClass then "NULL" + when TrueClass then '1' + when FalseClass then '0' + when Float, Fixnum, Bignum then value.to_s + when Date then "'#{value.to_s}'" + when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'" + else "'#{quote_string(value.to_yaml)}'" + end + end + + def quote_string(string) + string.gsub(/\'/, "''") + end + + def quoted_true + "1" + end + + def quoted_false + "0" + end + + def quote_column_name(name) + "[#{name}]" + end + + def add_limit_offset!(sql, options) + if options[:limit] and options[:offset] + total_rows = @connection.select_all("SELECT count(*) as TotalRows from (#{sql.gsub(/\bSELECT\b/i, "SELECT TOP 1000000000")}) tally")[0][:TotalRows].to_i + if (options[:limit] + options[:offset]) >= total_rows + options[:limit] = (total_rows - options[:offset] >= 0) ? (total_rows - options[:offset]) : 0 + end + sql.sub!(/^\s*SELECT/i, "SELECT * FROM (SELECT TOP #{options[:limit]} * FROM (SELECT TOP #{options[:limit] + options[:offset]} ") + sql << ") AS tmp1" + if options[:order] + options[:order] = options[:order].split(',').map do |field| + parts = field.split(" ") + tc = parts[0] + if sql =~ /\.\[/ and tc =~ /\./ # if column quoting used in query + tc.gsub!(/\./, '\\.\\[') + tc << '\\]' + end + if sql =~ /#{tc} AS (t\d_r\d\d?)/ + parts[0] = $1 + end + parts.join(' ') + end.join(', ') + sql << " ORDER BY #{change_order_direction(options[:order])}) AS tmp2 ORDER BY #{options[:order]}" + else + sql << " ) AS tmp2" + end + elsif sql !~ /^\s*SELECT (@@|COUNT\()/i + sql.sub!(/^\s*SELECT([\s]*distinct)?/i) do + "SELECT#{$1} TOP #{options[:limit]}" + end unless options[:limit].nil? + end + end + + def recreate_database(name) + drop_database(name) + create_database(name) + end + + def drop_database(name) + execute "DROP DATABASE #{name}" + end + + def create_database(name) + execute "CREATE DATABASE #{name}" + end + + def current_database + @connection.select_one("select DB_NAME()")[0] + end + + def tables(name = nil) + execute("SELECT table_name from information_schema.tables WHERE table_type = 'BASE TABLE'", name).inject([]) do |tables, field| + table_name = field[0] + tables << table_name unless table_name == 'dtproperties' + tables + end + end + + def indexes(table_name, name = nil) + indexes = [] + execute("EXEC sp_helpindex #{table_name}", name).each do |index| + unique = index[1] =~ /unique/ + primary = index[1] =~ /primary key/ + if !primary + indexes << IndexDefinition.new(table_name, index[0], unique, index[2].split(", ")) + end + end + indexes + end + + def rename_table(name, new_name) + execute "EXEC sp_rename '#{name}', '#{new_name}'" + end + + def remove_column(table_name, column_name) + execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}" + end + + def rename_column(table, column, new_column_name) + execute "EXEC sp_rename '#{table}.#{column}', '#{new_column_name}'" + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + sql_commands = ["ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"] + if options[:default] + remove_default_constraint(table_name, column_name) + sql_commands << "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{options[:default]} FOR #{column_name}" + end + sql_commands.each {|c| + execute(c) + } + end + + def remove_column(table_name, column_name) + remove_default_constraint(table_name, column_name) + execute "ALTER TABLE #{table_name} DROP COLUMN #{column_name}" + end + + def remove_default_constraint(table_name, column_name) + defaults = select "select def.name from sysobjects def, syscolumns col, sysobjects tab where col.cdefault = def.id and col.name = '#{column_name}' and tab.name = '#{table_name}' and col.id = tab.id" + defaults.each {|constraint| + execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{constraint["name"]}" + } + end + + def remove_index(table_name, options = {}) + execute "DROP INDEX #{table_name}.#{index_name(table_name, options)}" + end + + def type_to_sql(type, limit = nil) #:nodoc: + native = native_database_types[type] + # if there's no :limit in the default type definition, assume that type doesn't support limits + limit = limit || native[:limit] + column_type_sql = native[:name] + column_type_sql << "(#{limit})" if limit + column_type_sql + end + + private + def select(sql, name = nil) + rows = [] + repair_special_columns(sql) + log(sql, name) do + @connection.select_all(sql) do |row| + record = {} + row.column_names.each do |col| + record[col] = row[col] + record[col] = record[col].to_time if record[col].is_a? DBI::Timestamp + end + rows << record + end + end + rows + end + + def enable_identity_insert(table_name, enable = true) + if has_identity_column(table_name) + "SET IDENTITY_INSERT #{table_name} #{enable ? 'ON' : 'OFF'}" + end + end + + def get_table_name(sql) + if sql =~ /^\s*insert\s+into\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i + $1 + elsif sql =~ /from\s+([^\(\s]+)\s*/i + $1 + else + nil + end + end + + def has_identity_column(table_name) + !get_identity_column(table_name).nil? + end + + def get_identity_column(table_name) + @table_columns = {} unless @table_columns + @table_columns[table_name] = columns(table_name) if @table_columns[table_name] == nil + @table_columns[table_name].each do |col| + return col.name if col.identity + end + + return nil + end + + def query_contains_identity_column(sql, col) + sql =~ /\[#{col}\]/ + end + + def change_order_direction(order) + order.split(",").collect {|fragment| + case fragment + when /\bDESC\b/i then fragment.gsub(/\bDESC\b/i, "ASC") + when /\bASC\b/i then fragment.gsub(/\bASC\b/i, "DESC") + else String.new(fragment).split(',').join(' DESC,') + ' DESC' + end + }.join(",") + end + + def get_special_columns(table_name) + special = [] + @table_columns ||= {} + @table_columns[table_name] ||= columns(table_name) + @table_columns[table_name].each do |col| + special << col.name if col.is_special + end + special + end + + def repair_special_columns(sql) + special_cols = get_special_columns(get_table_name(sql)) + for col in special_cols.to_a + sql.gsub!(Regexp.new(" #{col.to_s} = "), " #{col.to_s} LIKE ") + sql.gsub!(/ORDER BY #{col.to_s}/i, '') + end + sql + end + + end #class SQLServerAdapter < AbstractAdapter + end #module ConnectionAdapters +end #module ActiveRecord +# sybase_adaptor.rb +# Author: John Sheets <dev@metacasa.net> +# Date: 01 Mar 2006 +# +# Based on code from Will Sobel (http://dev.rubyonrails.org/ticket/2030) +# +# 17 Mar 2006: Added support for migrations; fixed issues with :boolean columns. +# + +require 'active_record/connection_adapters/abstract_adapter' + +begin +require 'sybsql' + +module ActiveRecord + class Base + # Establishes a connection to the database that's used by all Active Record objects + def self.sybase_connection(config) # :nodoc: + config = config.symbolize_keys + + username = config[:username] ? config[:username].to_s : 'sa' + password = config[:password] ? config[:password].to_s : '' + + if config.has_key?(:host) + host = config[:host] + else + raise ArgumentError, "No database server name specified. Missing argument: host." + end + + if config.has_key?(:database) + database = config[:database] + else + raise ArgumentError, "No database specified. Missing argument: database." + end + + ConnectionAdapters::SybaseAdapter.new( + SybSQL.new({'S' => host, 'U' => username, 'P' => password}, + ConnectionAdapters::SybaseAdapterContext), database, logger) + end + end # class Base + + module ConnectionAdapters + + # ActiveRecord connection adapter for Sybase Open Client bindings + # (see http://raa.ruby-lang.org/project/sybase-ctlib). + # + # Options: + # + # * <tt>:host</tt> -- The name of the database server. No default, must be provided. + # * <tt>:database</tt> -- The name of the database. No default, must be provided. + # * <tt>:username</tt> -- Defaults to sa. + # * <tt>:password</tt> -- Defaults to empty string. + # + # Usage Notes: + # + # * The sybase-ctlib bindings do not support the DATE SQL column type; use DATETIME instead. + # * Table and column names are limited to 30 chars in Sybase 12.5 + # * :binary columns not yet supported + # * :boolean columns use the BIT SQL type, which does not allow nulls or + # indexes. If a DEFAULT is not specified for ALTER TABLE commands, the + # column will be declared with DEFAULT 0 (false). + # + # Migrations: + # + # The Sybase adapter supports migrations, but for ALTER TABLE commands to + # work, the database must have the database option 'select into' set to + # 'true' with sp_dboption (see below). The sp_helpdb command lists the current + # options for all databases. + # + # 1> use mydb + # 2> go + # 1> master..sp_dboption mydb, "select into", true + # 2> go + # 1> checkpoint + # 2> go + class SybaseAdapter < AbstractAdapter # :nodoc: + class ColumnWithIdentity < Column + attr_reader :identity, :primary + + def initialize(name, default, sql_type = nil, nullable = nil, identity = nil, primary = nil) + super(name, default, sql_type, nullable) + @default, @identity, @primary = type_cast(default), identity, primary + end + + def simplified_type(field_type) + case field_type + when /int|bigint|smallint|tinyint/i then :integer + when /float|double|decimal|money|numeric|real|smallmoney/i then :float + when /text|ntext/i then :text + when /binary|image|varbinary/i then :binary + when /char|nchar|nvarchar|string|varchar/i then :string + when /bit/i then :boolean + when /datetime|smalldatetime/i then :datetime + else super + end + end + + def self.string_to_binary(value) + "0x#{value.unpack("H*")[0]}" + end + + def self.binary_to_string(value) + # FIXME: sybase-ctlib uses separate sql method for binary columns. + value + end + end # class ColumnWithIdentity + + # Sybase adapter + def initialize(connection, database, logger = nil) + super(connection, logger) + context = connection.context + context.init(logger) + @limit = @offset = 0 + unless connection.sql_norow("USE #{database}") + raise "Cannot USE #{database}" + end + end + + def native_database_types + { + :primary_key => "numeric(9,0) IDENTITY PRIMARY KEY", + :string => { :name => "varchar", :limit => 255 }, + :text => { :name => "text" }, + :integer => { :name => "int" }, + :float => { :name => "float", :limit => 8 }, + :datetime => { :name => "datetime" }, + :timestamp => { :name => "timestamp" }, + :time => { :name => "time" }, + :date => { :name => "datetime" }, + :binary => { :name => "image"}, + :boolean => { :name => "bit" } + } + end + + def adapter_name + 'Sybase' + end + + def active? + !(@connection.connection.nil? || @connection.connection_dead?) + end + + def disconnect! + @connection.close rescue nil + end + + def reconnect! + raise "Sybase Connection Adapter does not yet support reconnect!" + # disconnect! + # connect! # Not yet implemented + end + + def table_alias_length + 30 + end + + # Check for a limit statement and parse out the limit and + # offset if specified. Remove the limit from the sql statement + # and call select. + def select_all(sql, name = nil) + select(sql, name) + end + + # Remove limit clause from statement. This will almost always + # contain LIMIT 1 from the caller. set the rowcount to 1 before + # calling select. + def select_one(sql, name = nil) + result = select(sql, name) + result.nil? ? nil : result.first + end + + def columns(table_name, name = nil) + table_structure(table_name).inject([]) do |columns, column| + name, default, type, nullable, identity, primary = column + columns << ColumnWithIdentity.new(name, default, type, nullable, identity, primary) + columns + end + end + + def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) + begin + table_name = get_table_name(sql) + col = get_identity_column(table_name) + ii_enabled = false + + if col != nil + if query_contains_identity_column(sql, col) + begin + execute enable_identity_insert(table_name, true) + ii_enabled = true + rescue Exception => e + raise ActiveRecordError, "IDENTITY_INSERT could not be turned ON" + end + end + end + + log(sql, name) do + execute(sql, name) + ident = select_one("SELECT @@IDENTITY AS last_id")["last_id"] + id_value || ident + end + ensure + if ii_enabled + begin + execute enable_identity_insert(table_name, false) + rescue Exception => e + raise ActiveRecordError, "IDENTITY_INSERT could not be turned OFF" + end + end + end + end + + def execute(sql, name = nil) + log(sql, name) do + @connection.context.reset + @connection.set_rowcount(@limit || 0) + @limit = @offset = nil + @connection.sql_norow(sql) + if @connection.cmd_fail? or @connection.context.failed? + raise "SQL Command Failed for #{name}: #{sql}\nMessage: #{@connection.context.message}" + end + end + # Return rows affected + @connection.results[0].row_count + end + + alias_method :update, :execute + alias_method :delete, :execute + + def begin_db_transaction() execute "BEGIN TRAN" end + def commit_db_transaction() execute "COMMIT TRAN" end + def rollback_db_transaction() execute "ROLLBACK TRAN" end + + def tables(name = nil) + tables = [] + select("select name from sysobjects where type='U'", name).each do |row| + tables << row['name'] + end + tables + end + + def indexes(table_name, name = nil) + indexes = [] + select("exec sp_helpindex #{table_name}", name).each do |index| + unique = index["index_description"] =~ /unique/ + primary = index["index_description"] =~ /^clustered/ + if !primary + cols = index["index_keys"].split(", ").each { |col| col.strip! } + indexes << IndexDefinition.new(table_name, index["index_name"], unique, cols) + end + end + indexes + end + + def quoted_true + "1" + end + + def quoted_false + "0" + end + + def quote(value, column = nil) + case value + when String + if column && column.type == :binary && column.class.respond_to?(:string_to_binary) + "#{quote_string(column.class.string_to_binary(value))}" + elsif value =~ /^[+-]?[0-9]+$/o + value + else + "'#{quote_string(value)}'" + end + when NilClass then (column && column.type == :boolean) ? '0' : "NULL" + when TrueClass then '1' + when FalseClass then '0' + when Float, Fixnum, Bignum then value.to_s + when Date then "'#{value.to_s}'" + when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'" + else "'#{quote_string(value.to_yaml)}'" + end + end + + def quote_column(type, value) + case type + when :boolean + case value + when String then value =~ /^[ty]/o ? 1 : 0 + when true then 1 + when false then 0 + else value.to_i + end + when :integer then value.to_i + when :float then value.to_f + when :text, :string, :enum + case value + when String, Symbol, Fixnum, Float, Bignum, TrueClass, FalseClass + "'#{quote_string(value.to_s)}'" + else + "'#{quote_string(value.to_yaml)}'" + end + when :date, :datetime, :time + case value + when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'" + when Date then "'#{value.to_s}'" + else "'#{quote_string(value)}'" + end + else "'#{quote_string(value.to_yaml)}'" + end + end + + def quote_string(s) + s.gsub(/'/, "''") # ' (for ruby-mode) + end + + def quote_column_name(name) + "[#{name}]" + end + + def add_limit_offset!(sql, options) # :nodoc: + @limit = options[:limit] + @offset = options[:offset] + if !normal_select? + # Use temp table to hack offset with Sybase + sql.sub!(/ FROM /i, ' INTO #artemp FROM ') + elsif zero_limit? + # "SET ROWCOUNT 0" turns off limits, so we have + # to use a cheap trick. + if sql =~ /WHERE/i + sql.sub!(/WHERE/i, 'WHERE 1 = 2 AND ') + elsif sql =~ /ORDER\s+BY/i + sql.sub!(/ORDER\s+BY/i, 'WHERE 1 = 2 ORDER BY') + else + sql << 'WHERE 1 = 2' + end + end + end + + def supports_migrations? #:nodoc: + true + end + + def rename_table(name, new_name) + execute "EXEC sp_rename '#{name}', '#{new_name}'" + end + + def rename_column(table, column, new_column_name) + execute "EXEC sp_rename '#{table}.#{column}', '#{new_column_name}'" + end + + def change_column(table_name, column_name, type, options = {}) #:nodoc: + sql_commands = ["ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit])}"] + if options[:default] + remove_default_constraint(table_name, column_name) + sql_commands << "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{options[:default]} FOR #{column_name}" + end + sql_commands.each { |c| execute(c) } + end + + def remove_column(table_name, column_name) + remove_default_constraint(table_name, column_name) + execute "ALTER TABLE #{table_name} DROP #{column_name}" + end + + def remove_default_constraint(table_name, column_name) + defaults = select "select def.name from sysobjects def, syscolumns col, sysobjects tab where col.cdefault = def.id and col.name = '#{column_name}' and tab.name = '#{table_name}' and col.id = tab.id" + defaults.each {|constraint| + execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{constraint["name"]}" + } + end + + def remove_index(table_name, options = {}) + execute "DROP INDEX #{table_name}.#{index_name(table_name, options)}" + end + + def add_column_options!(sql, options) #:nodoc: + sql << " DEFAULT #{quote(options[:default], options[:column])}" unless options[:default].nil? + + if check_null_for_column?(options[:column], sql) + sql << (options[:null] == false ? " NOT NULL" : " NULL") + end + sql + end + + private + def check_null_for_column?(col, sql) + # Sybase columns are NOT NULL by default, so explicitly set NULL + # if :null option is omitted. Disallow NULLs for boolean. + type = col.nil? ? "" : col[:type] + + # Ignore :null if a primary key + return false if type =~ /PRIMARY KEY/i + + # Ignore :null if a :boolean or BIT column + if (sql =~ /\s+bit(\s+DEFAULT)?/i) || type == :boolean + # If no default clause found on a boolean column, add one. + sql << " DEFAULT 0" if $1.nil? + return false + end + true + end + + # Return the last value of the identity global value. + def last_insert_id + @connection.sql("SELECT @@IDENTITY") + unless @connection.cmd_fail? + id = @connection.top_row_result.rows.first.first + if id + id = id.to_i + id = nil if id == 0 + end + else + id = nil + end + id + end + + def affected_rows(name = nil) + @connection.sql("SELECT @@ROWCOUNT") + unless @connection.cmd_fail? + count = @connection.top_row_result.rows.first.first + count = count.to_i if count + else + 0 + end + end + + def normal_select? + # If limit is not set at all, we can ignore offset; + # If limit *is* set but offset is zero, use normal select + # with simple SET ROWCOUNT. Thus, only use the temp table + # if limit is set and offset > 0. + has_limit = !@limit.nil? + has_offset = !@offset.nil? && @offset > 0 + !has_limit || !has_offset + end + + def zero_limit? + !@limit.nil? && @limit == 0 + end + + # Select limit number of rows starting at optional offset. + def select(sql, name = nil) + @connection.context.reset + log(sql, name) do + if normal_select? + # If limit is not explicitly set, return all results. + @logger.debug "Setting row count to (#{@limit || 'off'})" if @logger + + # Run a normal select + @connection.set_rowcount(@limit || 0) + @connection.sql(sql) + else + # Select into a temp table and prune results + @logger.debug "Selecting #{@limit + (@offset || 0)} or fewer rows into #artemp" if @logger + @connection.set_rowcount(@limit + (@offset || 0)) + @connection.sql_norow(sql) # Select into temp table + @logger.debug "Deleting #{@offset || 0} or fewer rows from #artemp" if @logger + @connection.set_rowcount(@offset || 0) + @connection.sql_norow("delete from #artemp") # Delete leading rows + @connection.set_rowcount(0) + @connection.sql("select * from #artemp") # Return the rest + end + end + + rows = [] + if @connection.context.failed? or @connection.cmd_fail? + raise StatementInvalid, "SQL Command Failed for #{name}: #{sql}\nMessage: #{@connection.context.message}" + else + results = @connection.top_row_result + if results && results.rows.length > 0 + fields = fixup_column_names(results.columns) + results.rows.each do |row| + hashed_row = {} + row.zip(fields) { |cell, column| hashed_row[column] = cell } + rows << hashed_row + end + end + end + @connection.sql_norow("drop table #artemp") if !normal_select? + @limit = @offset = nil + return rows + end + + def enable_identity_insert(table_name, enable = true) + if has_identity_column(table_name) + "SET IDENTITY_INSERT #{table_name} #{enable ? 'ON' : 'OFF'}" + end + end + + def get_table_name(sql) + if sql =~ /^\s*insert\s+into\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i + $1 + elsif sql =~ /from\s+([^\(\s]+)\s*/i + $1 + else + nil + end + end + + def has_identity_column(table_name) + !get_identity_column(table_name).nil? + end + + def get_identity_column(table_name) + @table_columns = {} unless @table_columns + @table_columns[table_name] = columns(table_name) if @table_columns[table_name] == nil + @table_columns[table_name].each do |col| + return col.name if col.identity + end + + return nil + end + + def query_contains_identity_column(sql, col) + sql =~ /\[#{col}\]/ + end + + # Remove trailing _ from names. + def fixup_column_names(columns) + columns.map { |column| column.sub(/_$/, '') } + end + + def table_structure(table_name) + sql = <<SQLTEXT +SELECT col.name AS name, type.name AS type, col.prec, col.scale, col.length, + col.status, obj.sysstat2, def.text + FROM sysobjects obj, syscolumns col, systypes type, syscomments def + WHERE obj.id = col.id AND col.usertype = type.usertype AND col.cdefault *= def.id + AND obj.type = 'U' AND obj.name = '#{table_name}' ORDER BY col.colid +SQLTEXT + log(sql, "Get Column Info ") do + @connection.set_rowcount(0) + @connection.sql(sql) + end + if @connection.context.failed? + raise "SQL Command for table_structure for #{table_name} failed\nMessage: #{@connection.context.message}" + elsif !@connection.cmd_fail? + columns = [] + results = @connection.top_row_result + results.rows.each do |row| + name, type, prec, scale, length, status, sysstat2, default = row + type = normalize_type(type, prec, scale, length) + default_value = nil + name.sub!(/_$/o, '') + if default =~ /DEFAULT\s+(.+)/o + default_value = $1.strip + default_value = default_value[1...-1] if default_value =~ /^['"]/o + end + nullable = (status & 8) == 8 + identity = status >= 128 + primary = (sysstat2 & 8) == 8 + + columns << [name, default_value, type, nullable, identity, primary] + end + columns + else + nil + end + end + + def normalize_type(field_type, prec, scale, length) + if field_type =~ /numeric/i and (scale.nil? or scale == 0) + type = 'int' + elsif field_type =~ /money/i + type = 'numeric' + else + type = field_type + end + size = '' + if prec + size = "(#{prec})" + elsif length + size = "(#{length})" + end + return type + size + end + + def default_value(value) + end + end # class SybaseAdapter + + class SybaseAdapterContext < SybSQLContext + DEADLOCK = 1205 + attr_reader :message + + def init(logger = nil) + @deadlocked = false + @failed = false + @logger = logger + @message = nil + end + + def srvmsgCB(con, msg) + # Do not log change of context messages. + if msg['severity'] == 10 or msg['severity'] == 0 + return true + end + + if msg['msgnumber'] == DEADLOCK + @deadlocked = true + else + @logger.info "SQL Command failed!" if @logger + @failed = true + end + + if @logger + @logger.error "** SybSQLContext Server Message: **" + @logger.error " Message number #{msg['msgnumber']} Severity #{msg['severity']} State #{msg['state']} Line #{msg['line']}" + @logger.error " Server #{msg['srvname']}" + @logger.error " Procedure #{msg['proc']}" + @logger.error " Message String: #{msg['text']}" + end + + @message = msg['text'] + + true + end + + def deadlocked? + @deadlocked + end + + def failed? + @failed + end + + def reset + @deadlocked = false + @failed = false + @message = nil + end + + def cltmsgCB(con, msg) + return true unless ( msg.kind_of?(Hash) ) + unless ( msg[ "severity" ] ) then + return true + end + + if @logger + @logger.error "** SybSQLContext Client-Message: **" + @logger.error " Message number: LAYER=#{msg[ 'layer' ]} ORIGIN=#{msg[ 'origin' ]} SEVERITY=#{msg[ 'severity' ]} NUMBER=#{msg[ 'number' ]}" + @logger.error " Message String: #{msg['msgstring']}" + @logger.error " OS Error: #{msg['osstring']}" + + @message = msg['msgstring'] + end + + @failed = true + + # Not retry , CS_CV_RETRY_FAIL( probability TimeOut ) + if( msg[ 'severity' ] == "RETRY_FAIL" ) then + @timeout_p = true + return false + end + + return true + end + end # class SybaseAdapterContext + + end # module ConnectionAdapters +end # module ActiveRecord + + +# Allow identity inserts for fixtures. +require "active_record/fixtures" +class Fixtures + alias :original_insert_fixtures :insert_fixtures + + def insert_fixtures + values.each do |fixture| + allow_identity_inserts table_name, true + @connection.execute "INSERT INTO #{@table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert' + allow_identity_inserts table_name, false + end + end + + def allow_identity_inserts(table_name, enable) + @connection.execute "SET IDENTITY_INSERT #{table_name} #{enable ? 'ON' : 'OFF'}" rescue nil + end +end + +rescue LoadError => cannot_require_sybase + # Couldn't load sybase adapter +endmodule ActiveRecord + module Associations # :nodoc: + module ClassMethods + def deprecated_collection_count_method(collection_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def #{collection_name}_count(force_reload = false) + #{collection_name}.reload if force_reload + #{collection_name}.size + end + end_eval + end + + def deprecated_add_association_relation(association_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def add_#{association_name}(*items) + #{association_name}.concat(items) + end + end_eval + end + + def deprecated_remove_association_relation(association_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def remove_#{association_name}(*items) + #{association_name}.delete(items) + end + end_eval + end + + def deprecated_has_collection_method(collection_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def has_#{collection_name}?(force_reload = false) + !#{collection_name}(force_reload).empty? + end + end_eval + end + + def deprecated_find_in_collection_method(collection_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def find_in_#{collection_name}(association_id) + #{collection_name}.find(association_id) + end + end_eval + end + + def deprecated_find_all_in_collection_method(collection_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def find_all_in_#{collection_name}(runtime_conditions = nil, orderings = nil, limit = nil, joins = nil) + #{collection_name}.find_all(runtime_conditions, orderings, limit, joins) + end + end_eval + end + + def deprecated_collection_create_method(collection_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def create_in_#{collection_name}(attributes = {}) + #{collection_name}.create(attributes) + end + end_eval + end + + def deprecated_collection_build_method(collection_name)# :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def build_to_#{collection_name}(attributes = {}) + #{collection_name}.build(attributes) + end + end_eval + end + + def deprecated_association_comparison_method(association_name, association_class_name) # :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def #{association_name}?(comparison_object, force_reload = false) + if comparison_object.kind_of?(#{association_class_name}) + #{association_name}(force_reload) == comparison_object + else + raise "Comparison object is a #{association_class_name}, should have been \#{comparison_object.class.name}" + end + end + end_eval + end + + def deprecated_has_association_method(association_name) # :nodoc: + module_eval <<-"end_eval", __FILE__, __LINE__ + def has_#{association_name}?(force_reload = false) + !#{association_name}(force_reload).nil? + end + end_eval + end + end + end +end +module ActiveRecord + class Base + class << self + # This method is deprecated in favor of find with the :conditions option. + # + # Works like find, but the record matching +id+ must also meet the +conditions+. + # +RecordNotFound+ is raised if no record can be found matching the +id+ or meeting the condition. + # Example: + # Person.find_on_conditions 5, "first_name LIKE '%dav%' AND last_name = 'heinemeier'" + def find_on_conditions(ids, conditions) # :nodoc: + find(ids, :conditions => conditions) + end + + # This method is deprecated in favor of find(:first, options). + # + # Returns the object for the first record responding to the conditions in +conditions+, + # such as "group = 'master'". If more than one record is returned from the query, it's the first that'll + # be used to create the object. In such cases, it might be beneficial to also specify + # +orderings+, like "income DESC, name", to control exactly which record is to be used. Example: + # Employee.find_first "income > 50000", "income DESC, name" + def find_first(conditions = nil, orderings = nil, joins = nil) # :nodoc: + find(:first, :conditions => conditions, :order => orderings, :joins => joins) + end + + # This method is deprecated in favor of find(:all, options). + # + # Returns an array of all the objects that could be instantiated from the associated + # table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part), + # such as by "color = 'red'", and arrangement of the selection can be done through +orderings+ (ORDER BY-part), + # such as by "last_name, first_name DESC". A maximum of returned objects and their offset can be specified in + # +limit+ with either just a single integer as the limit or as an array with the first element as the limit, + # the second as the offset. Examples: + # Project.find_all "category = 'accounts'", "last_accessed DESC", 15 + # Project.find_all ["category = ?", category_name], "created ASC", [15, 20] + def find_all(conditions = nil, orderings = nil, limit = nil, joins = nil) # :nodoc: + limit, offset = limit.is_a?(Array) ? limit : [ limit, nil ] + find(:all, :conditions => conditions, :order => orderings, :joins => joins, :limit => limit, :offset => offset) + end + end + end +endrequire 'erb' +require 'yaml' +require 'csv' + +module YAML #:nodoc: + class Omap #:nodoc: + def keys; map { |k, v| k } end + def values; map { |k, v| v } end + end +end + +class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc: +end + +# Fixtures are a way of organizing data that you want to test against; in short, sample data. They come in 3 flavours: +# +# 1. YAML fixtures +# 2. CSV fixtures +# 3. Single-file fixtures +# +# = YAML fixtures +# +# This type of fixture is in YAML format and the preferred default. YAML is a file format which describes data structures +# in a non-verbose, humanly-readable format. It ships with Ruby 1.8.1+. +# +# Unlike single-file fixtures, YAML fixtures are stored in a single file per model, which are placed in the directory appointed +# by <tt>Test::Unit::TestCase.fixture_path=(path)</tt> (this is automatically configured for Rails, so you can just +# put your files in <your-rails-app>/test/fixtures/). The fixture file ends with the .yml file extension (Rails example: +# "<your-rails-app>/test/fixtures/web_sites.yml"). The format of a YAML fixture file looks like this: +# +# rubyonrails: +# id: 1 +# name: Ruby on Rails +# url: http://www.rubyonrails.org +# +# google: +# id: 2 +# name: Google +# url: http://www.google.com +# +# This YAML fixture file includes two fixtures. Each YAML fixture (ie. record) is given a name and is followed by an +# indented list of key/value pairs in the "key: value" format. Records are separated by a blank line for your viewing +# pleasure. +# +# Note that YAML fixtures are unordered. If you want ordered fixtures, use the omap YAML type. See http://yaml.org/type/omap.html +# for the specification. You will need ordered fixtures when you have foreign key constraints on keys in the same table. +# This is commonly needed for tree structures. Example: +# +# --- !omap +# - parent: +# id: 1 +# parent_id: NULL +# title: Parent +# - child: +# id: 2 +# parent_id: 1 +# title: Child +# +# = CSV fixtures +# +# Fixtures can also be kept in the Comma Separated Value format. Akin to YAML fixtures, CSV fixtures are stored +# in a single file, but instead end with the .csv file extension (Rails example: "<your-rails-app>/test/fixtures/web_sites.csv") +# +# The format of this type of fixture file is much more compact than the others, but also a little harder to read by us +# humans. The first line of the CSV file is a comma-separated list of field names. The rest of the file is then comprised +# of the actual data (1 per line). Here's an example: +# +# id, name, url +# 1, Ruby On Rails, http://www.rubyonrails.org +# 2, Google, http://www.google.com +# +# Should you have a piece of data with a comma character in it, you can place double quotes around that value. If you +# need to use a double quote character, you must escape it with another double quote. +# +# Another unique attribute of the CSV fixture is that it has *no* fixture name like the other two formats. Instead, the +# fixture names are automatically generated by deriving the class name of the fixture file and adding an incrementing +# number to the end. In our example, the 1st fixture would be called "web_site_1" and the 2nd one would be called +# "web_site_2". +# +# Most databases and spreadsheets support exporting to CSV format, so this is a great format for you to choose if you +# have existing data somewhere already. +# +# = Single-file fixtures +# +# This type of fixtures was the original format for Active Record that has since been deprecated in favor of the YAML and CSV formats. +# Fixtures for this format are created by placing text files in a sub-directory (with the name of the model) to the directory +# appointed by <tt>Test::Unit::TestCase.fixture_path=(path)</tt> (this is automatically configured for Rails, so you can just +# put your files in <your-rails-app>/test/fixtures/<your-model-name>/ -- like <your-rails-app>/test/fixtures/web_sites/ for the WebSite +# model). +# +# Each text file placed in this directory represents a "record". Usually these types of fixtures are named without +# extensions, but if you are on a Windows machine, you might consider adding .txt as the extension. Here's what the +# above example might look like: +# +# web_sites/google +# web_sites/yahoo.txt +# web_sites/ruby-on-rails +# +# The file format of a standard fixture is simple. Each line is a property (or column in db speak) and has the syntax +# of "name => value". Here's an example of the ruby-on-rails fixture above: +# +# id => 1 +# name => Ruby on Rails +# url => http://www.rubyonrails.org +# +# = Using Fixtures +# +# Since fixtures are a testing construct, we use them in our unit and functional tests. There are two ways to use the +# fixtures, but first let's take a look at a sample unit test found: +# +# require 'web_site' +# +# class WebSiteTest < Test::Unit::TestCase +# def test_web_site_count +# assert_equal 2, WebSite.count +# end +# end +# +# As it stands, unless we pre-load the web_site table in our database with two records, this test will fail. Here's the +# easiest way to add fixtures to the database: +# +# ... +# class WebSiteTest < Test::Unit::TestCase +# fixtures :web_sites # add more by separating the symbols with commas +# ... +# +# By adding a "fixtures" method to the test case and passing it a list of symbols (only one is shown here tho), we trigger +# the testing environment to automatically load the appropriate fixtures into the database before each test. +# To ensure consistent data, the environment deletes the fixtures before running the load. +# +# In addition to being available in the database, the fixtures are also loaded into a hash stored in an instance variable +# of the test case. It is named after the symbol... so, in our example, there would be a hash available called +# @web_sites. This is where the "fixture name" comes into play. +# +# On top of that, each record is automatically "found" (using Model.find(id)) and placed in the instance variable of its name. +# So for the YAML fixtures, we'd get @rubyonrails and @google, which could be interrogated using regular Active Record semantics: +# +# # test if the object created from the fixture data has the same attributes as the data itself +# def test_find +# assert_equal @web_sites["rubyonrails"]["name"], @rubyonrails.name +# end +# +# As seen above, the data hash created from the YAML fixtures would have @web_sites["rubyonrails"]["url"] return +# "http://www.rubyonrails.org" and @web_sites["google"]["name"] would return "Google". The same fixtures, but loaded +# from a CSV fixture file, would be accessible via @web_sites["web_site_1"]["name"] == "Ruby on Rails" and have the individual +# fixtures available as instance variables @web_site_1 and @web_site_2. +# +# If you do not wish to use instantiated fixtures (usually for performance reasons) there are two options. +# +# - to completely disable instantiated fixtures: +# self.use_instantiated_fixtures = false +# +# - to keep the fixture instance (@web_sites) available, but do not automatically 'find' each instance: +# self.use_instantiated_fixtures = :no_instances +# +# Even if auto-instantiated fixtures are disabled, you can still access them +# by name via special dynamic methods. Each method has the same name as the +# model, and accepts the name of the fixture to instantiate: +# +# fixtures :web_sites +# +# def test_find +# assert_equal "Ruby on Rails", web_sites(:rubyonrails).name +# end +# +# = Dynamic fixtures with ERb +# +# Some times you don't care about the content of the fixtures as much as you care about the volume. In these cases, you can +# mix ERb in with your YAML or CSV fixtures to create a bunch of fixtures for load testing, like: +# +# <% for i in 1..1000 %> +# fix_<%= i %>: +# id: <%= i %> +# name: guy_<%= 1 %> +# <% end %> +# +# This will create 1000 very simple YAML fixtures. +# +# Using ERb, you can also inject dynamic values into your fixtures with inserts like <%= Date.today.strftime("%Y-%m-%d") %>. +# This is however a feature to be used with some caution. The point of fixtures are that they're stable units of predictable +# sample data. If you feel that you need to inject dynamic values, then perhaps you should reexamine whether your application +# is properly testable. Hence, dynamic values in fixtures are to be considered a code smell. +# +# = Transactional fixtures +# +# TestCases can use begin+rollback to isolate their changes to the database instead of having to delete+insert for every test case. +# They can also turn off auto-instantiation of fixture data since the feature is costly and often unused. +# +# class FooTest < Test::Unit::TestCase +# self.use_transactional_fixtures = true +# self.use_instantiated_fixtures = false +# +# fixtures :foos +# +# def test_godzilla +# assert !Foo.find(:all).empty? +# Foo.destroy_all +# assert Foo.find(:all).empty? +# end +# +# def test_godzilla_aftermath +# assert !Foo.find(:all).empty? +# end +# end +# +# If you preload your test database with all fixture data (probably in the Rakefile task) and use transactional fixtures, +# then you may omit all fixtures declarations in your test cases since all the data's already there and every case rolls back its changes. +# +# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to true. This will provide +# access to fixture data for every table that has been loaded through fixtures (depending on the value of +use_instantiated_fixtures+) +# +# When *not* to use transactional fixtures: +# 1. You're testing whether a transaction works correctly. Nested transactions don't commit until all parent transactions commit, +# particularly, the fixtures transaction which is begun in setup and rolled back in teardown. Thus, you won't be able to verify +# the results of your transaction until Active Record supports nested transactions or savepoints (in progress.) +# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM. +# Use InnoDB, MaxDB, or NDB instead. +class Fixtures < YAML::Omap + DEFAULT_FILTER_RE = /\.ya?ml$/ + + def self.instantiate_fixtures(object, table_name, fixtures, load_instances=true) + object.instance_variable_set "@#{table_name.to_s.gsub('.','_')}", fixtures + if load_instances + ActiveRecord::Base.silence do + fixtures.each do |name, fixture| + begin + object.instance_variable_set "@#{name}", fixture.find + rescue FixtureClassNotFound + nil + end + end + end + end + end + + def self.instantiate_all_loaded_fixtures(object, load_instances=true) + all_loaded_fixtures.each do |table_name, fixtures| + Fixtures.instantiate_fixtures(object, table_name, fixtures, load_instances) + end + end + + cattr_accessor :all_loaded_fixtures + self.all_loaded_fixtures = {} + + def self.create_fixtures(fixtures_directory, table_names, class_names = {}) + table_names = [table_names].flatten.map { |n| n.to_s } + connection = block_given? ? yield : ActiveRecord::Base.connection + ActiveRecord::Base.silence do + fixtures_map = {} + fixtures = table_names.map do |table_name| + fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s)) + end + all_loaded_fixtures.merge! fixtures_map + + connection.transaction do + fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures } + fixtures.each { |fixture| fixture.insert_fixtures } + + # Cap primary key sequences to max(pk). + if connection.respond_to?(:reset_pk_sequence!) + table_names.each do |table_name| + connection.reset_pk_sequence!(table_name) + end + end + end + + return fixtures.size > 1 ? fixtures : fixtures.first + end + end + + + attr_reader :table_name + + def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE) + @connection, @table_name, @fixture_path, @file_filter = connection, table_name, fixture_path, file_filter + @class_name = class_name || + (ActiveRecord::Base.pluralize_table_names ? @table_name.singularize.camelize : @table_name.camelize) + @table_name = ActiveRecord::Base.table_name_prefix + @table_name + ActiveRecord::Base.table_name_suffix + read_fixture_files + end + + def delete_existing_fixtures + @connection.delete "DELETE FROM #{@table_name}", 'Fixture Delete' + end + + def insert_fixtures + values.each do |fixture| + @connection.execute "INSERT INTO #{@table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert' + end + end + + private + + def read_fixture_files + if File.file?(yaml_file_path) + # YAML fixtures + begin + yaml_string = "" + Dir["#{@fixture_path}/**/*.yml"].select {|f| test(?f,f) }.each do |subfixture_path| + yaml_string << IO.read(subfixture_path) + end + yaml_string << IO.read(yaml_file_path) + + if yaml = YAML::load(erb_render(yaml_string)) + yaml = yaml.value if yaml.respond_to?(:type_id) and yaml.respond_to?(:value) + yaml.each do |name, data| + self[name] = Fixture.new(data, @class_name) + end + end + rescue Exception=>boom + raise Fixture::FormatError, "a YAML error occured parsing #{yaml_file_path}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{boom.class}: #{boom}" + end + elsif File.file?(csv_file_path) + # CSV fixtures + reader = CSV::Reader.create(erb_render(IO.read(csv_file_path))) + header = reader.shift + i = 0 + reader.each do |row| + data = {} + row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip } + self["#{Inflector::underscore(@class_name)}_#{i+=1}"]= Fixture.new(data, @class_name) + end + elsif File.file?(deprecated_yaml_file_path) + raise Fixture::FormatError, ".yml extension required: rename #{deprecated_yaml_file_path} to #{yaml_file_path}" + else + # Standard fixtures + Dir.entries(@fixture_path).each do |file| + path = File.join(@fixture_path, file) + if File.file?(path) and file !~ @file_filter + self[file] = Fixture.new(path, @class_name) + end + end + end + end + + def yaml_file_path + "#{@fixture_path}.yml" + end + + def deprecated_yaml_file_path + "#{@fixture_path}.yaml" + end + + def csv_file_path + @fixture_path + ".csv" + end + + def yaml_fixtures_key(path) + File.basename(@fixture_path).split(".").first + end + + def erb_render(fixture_content) + ERB.new(fixture_content).result + end +end + +class Fixture #:nodoc: + include Enumerable + class FixtureError < StandardError#:nodoc: + end + class FormatError < FixtureError#:nodoc: + end + + def initialize(fixture, class_name) + case fixture + when Hash, YAML::Omap + @fixture = fixture + when String + @fixture = read_fixture_file(fixture) + else + raise ArgumentError, "Bad fixture argument #{fixture.inspect}" + end + + @class_name = class_name + end + + def each + @fixture.each { |item| yield item } + end + + def [](key) + @fixture[key] + end + + def to_hash + @fixture + end + + def key_list + columns = @fixture.keys.collect{ |column_name| ActiveRecord::Base.connection.quote_column_name(column_name) } + columns.join(", ") + end + + def value_list + @fixture.values.map { |v| ActiveRecord::Base.connection.quote(v).gsub('\\n', "\n").gsub('\\r', "\r") }.join(", ") + end + + def find + klass = @class_name.is_a?(Class) ? @class_name : Object.const_get(@class_name) rescue nil + if klass + klass.find(self[klass.primary_key]) + else + raise FixtureClassNotFound, "The class #{@class_name.inspect} was not found." + end + end + + private + def read_fixture_file(fixture_file_path) + IO.readlines(fixture_file_path).inject({}) do |fixture, line| + # Mercifully skip empty lines. + next if line =~ /^\s*$/ + + # Use the same regular expression for attributes as Active Record. + unless md = /^\s*([a-zA-Z][-_\w]*)\s*=>\s*(.+)\s*$/.match(line) + raise FormatError, "#{fixture_file_path}: fixture format error at '#{line}'. Expecting 'key => value'." + end + key, value = md.captures + + # Disallow duplicate keys to catch typos. + raise FormatError, "#{fixture_file_path}: duplicate '#{key}' in fixture." if fixture[key] + fixture[key] = value.strip + fixture + end + end +end + +module Test #:nodoc: + module Unit #:nodoc: + class TestCase #:nodoc: + cattr_accessor :fixture_path + class_inheritable_accessor :fixture_table_names + class_inheritable_accessor :fixture_class_names + class_inheritable_accessor :use_transactional_fixtures + class_inheritable_accessor :use_instantiated_fixtures # true, false, or :no_instances + class_inheritable_accessor :pre_loaded_fixtures + + self.fixture_table_names = [] + self.use_transactional_fixtures = false + self.use_instantiated_fixtures = true + self.pre_loaded_fixtures = false + + self.fixture_class_names = {} + + @@already_loaded_fixtures = {} + self.fixture_class_names = {} + + def self.set_fixture_class(class_names = {}) + self.fixture_class_names = self.fixture_class_names.merge(class_names) + end + + def self.fixtures(*table_names) + table_names = table_names.flatten.map { |n| n.to_s } + self.fixture_table_names |= table_names + require_fixture_classes(table_names) + setup_fixture_accessors(table_names) + end + + def self.require_fixture_classes(table_names=nil) + (table_names || fixture_table_names).each do |table_name| + file_name = table_name.to_s + file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names + begin + require file_name + rescue LoadError + # Let's hope the developer has included it himself + end + end + end + + def self.setup_fixture_accessors(table_names=nil) + (table_names || fixture_table_names).each do |table_name| + table_name = table_name.to_s.tr('.','_') + define_method(table_name) do |fixture, *optionals| + force_reload = optionals.shift + @fixture_cache[table_name] ||= Hash.new + @fixture_cache[table_name][fixture] = nil if force_reload + if @loaded_fixtures[table_name][fixture.to_s] + @fixture_cache[table_name][fixture] ||= @loaded_fixtures[table_name][fixture.to_s].find + else + raise StandardError, "No fixture with name '#{fixture}' found for table '#{table_name}'" + end + end + end + end + + def self.uses_transaction(*methods) + @uses_transaction ||= [] + @uses_transaction.concat methods.map { |m| m.to_s } + end + + def self.uses_transaction?(method) + @uses_transaction && @uses_transaction.include?(method.to_s) + end + + def use_transactional_fixtures? + use_transactional_fixtures && + !self.class.uses_transaction?(method_name) + end + + def setup_with_fixtures + if pre_loaded_fixtures && !use_transactional_fixtures + raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures' + end + + @fixture_cache = Hash.new + + # Load fixtures once and begin transaction. + if use_transactional_fixtures? + if @@already_loaded_fixtures[self.class] + @loaded_fixtures = @@already_loaded_fixtures[self.class] + else + load_fixtures + @@already_loaded_fixtures[self.class] = @loaded_fixtures + end + ActiveRecord::Base.lock_mutex + ActiveRecord::Base.connection.begin_db_transaction + + # Load fixtures for every test. + else + @@already_loaded_fixtures[self.class] = nil + load_fixtures + end + + # Instantiate fixtures for every test if requested. + instantiate_fixtures if use_instantiated_fixtures + end + + alias_method :setup, :setup_with_fixtures + + def teardown_with_fixtures + # Rollback changes. + if use_transactional_fixtures? + ActiveRecord::Base.connection.rollback_db_transaction + ActiveRecord::Base.unlock_mutex + end + ActiveRecord::Base.verify_active_connections! + end + + alias_method :teardown, :teardown_with_fixtures + + def self.method_added(method) + case method.to_s + when 'setup' + unless method_defined?(:setup_without_fixtures) + alias_method :setup_without_fixtures, :setup + define_method(:setup) do + setup_with_fixtures + setup_without_fixtures + end + end + when 'teardown' + unless method_defined?(:teardown_without_fixtures) + alias_method :teardown_without_fixtures, :teardown + define_method(:teardown) do + teardown_without_fixtures + teardown_with_fixtures + end + end + end + end + + private + def load_fixtures + @loaded_fixtures = {} + fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names) + unless fixtures.nil? + if fixtures.instance_of?(Fixtures) + @loaded_fixtures[fixtures.table_name] = fixtures + else + fixtures.each { |f| @loaded_fixtures[f.table_name] = f } + end + end + end + + # for pre_loaded_fixtures, only require the classes once. huge speed improvement + @@required_fixture_classes = false + + def instantiate_fixtures + if pre_loaded_fixtures + raise RuntimeError, 'Load fixtures before instantiating them.' if Fixtures.all_loaded_fixtures.empty? + unless @@required_fixture_classes + self.class.require_fixture_classes Fixtures.all_loaded_fixtures.keys + @@required_fixture_classes = true + end + Fixtures.instantiate_all_loaded_fixtures(self, load_instances?) + else + raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil? + @loaded_fixtures.each do |table_name, fixtures| + Fixtures.instantiate_fixtures(self, table_name, fixtures, load_instances?) + end + end + end + + def load_instances? + use_instantiated_fixtures != :no_instances + end + end + + end +end +module ActiveRecord + # Active Records support optimistic locking if the field <tt>lock_version</tt> is present. Each update to the + # record increments the lock_version column and the locking facilities ensure that records instantiated twice + # will let the last one saved raise a StaleObjectError if the first was also updated. Example: + # + # p1 = Person.find(1) + # p2 = Person.find(1) + # + # p1.first_name = "Michael" + # p1.save + # + # p2.first_name = "should fail" + # p2.save # Raises a ActiveRecord::StaleObjectError + # + # You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, + # or otherwise apply the business logic needed to resolve the conflict. + # + # You must ensure that your database schema defaults the lock_version column to 0. + # + # This behavior can be turned off by setting <tt>ActiveRecord::Base.lock_optimistically = false</tt>. + # To override the name of the lock_version column, invoke the <tt>set_locking_column</tt> method. + # This method uses the same syntax as <tt>set_table_name</tt> + module Locking + def self.append_features(base) #:nodoc: + super + base.class_eval do + alias_method :update_without_lock, :update + alias_method :update, :update_with_lock + end + end + + def update_with_lock #:nodoc: + return update_without_lock unless locking_enabled? + + lock_col = self.class.locking_column + previous_value = send(lock_col) + send(lock_col + '=', previous_value + 1) + + affected_rows = connection.update(<<-end_sql, "#{self.class.name} Update with optimistic locking") + UPDATE #{self.class.table_name} + SET #{quoted_comma_pair_list(connection, attributes_with_quotes(false))} + WHERE #{self.class.primary_key} = #{quote(id)} + AND #{lock_col} = #{quote(previous_value)} + end_sql + + unless affected_rows == 1 + raise ActiveRecord::StaleObjectError, "Attempted to update a stale object" + end + + return true + end + end + + class Base + @@lock_optimistically = true + cattr_accessor :lock_optimistically + + def locking_enabled? #:nodoc: + lock_optimistically && respond_to?(self.class.locking_column) + end + + class << self + def set_locking_column(value = nil, &block) + define_attr_method :locking_column, value, &block + end + + def locking_column #:nodoc: + reset_locking_column + end + + def reset_locking_column #:nodoc: + default = 'lock_version' + set_locking_column(default) + default + end + end + + end +end +module ActiveRecord + class IrreversibleMigration < ActiveRecordError#:nodoc: + end + + class DuplicateMigrationVersionError < ActiveRecordError#:nodoc: + def initialize(version) + super("Multiple migrations have the version number #{version}") + end + end + + # Migrations can manage the evolution of a schema used by several physical databases. It's a solution + # to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to + # push that change to other developers and to the production server. With migrations, you can describe the transformations + # in self-contained classes that can be checked into version control systems and executed against another database that + # might be one, two, or five versions behind. + # + # Example of a simple migration: + # + # class AddSsl < ActiveRecord::Migration + # def self.up + # add_column :accounts, :ssl_enabled, :boolean, :default => 1 + # end + # + # def self.down + # remove_column :accounts, :ssl_enabled + # end + # end + # + # This migration will add a boolean flag to the accounts table and remove it again, if you're backing out of the migration. + # It shows how all migrations have two class methods +up+ and +down+ that describes the transformations required to implement + # or remove the migration. These methods can consist of both the migration specific methods, like add_column and remove_column, + # but may also contain regular Ruby code for generating data needed for the transformations. + # + # Example of a more complex migration that also needs to initialize data: + # + # class AddSystemSettings < ActiveRecord::Migration + # def self.up + # create_table :system_settings do |t| + # t.column :name, :string + # t.column :label, :string + # t.column :value, :text + # t.column :type, :string + # t.column :position, :integer + # end + # + # SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1 + # end + # + # def self.down + # drop_table :system_settings + # end + # end + # + # This migration first adds the system_settings table, then creates the very first row in it using the Active Record model + # that relies on the table. It also uses the more advanced create_table syntax where you can specify a complete table schema + # in one block call. + # + # == Available transformations + # + # * <tt>create_table(name, options)</tt> Creates a table called +name+ and makes the table object available to a block + # that can then add columns to it, following the same format as add_column. See example above. The options hash is for + # fragments like "DEFAULT CHARSET=UTF-8" that are appended to the create table definition. + # * <tt>drop_table(name)</tt>: Drops the table called +name+. + # * <tt>rename_table(old_name, new_name)</tt>: Renames the table called +old_name+ to +new_name+. + # * <tt>add_column(table_name, column_name, type, options)</tt>: Adds a new column to the table called +table_name+ + # named +column_name+ specified to be one of the following types: + # :string, :text, :integer, :float, :datetime, :timestamp, :time, :date, :binary, :boolean. A default value can be specified + # by passing an +options+ hash like { :default => 11 }. + # * <tt>rename_column(table_name, column_name, new_column_name)</tt>: Renames a column but keeps the type and content. + # * <tt>change_column(table_name, column_name, type, options)</tt>: Changes the column to a different type using the same + # parameters as add_column. + # * <tt>remove_column(table_name, column_name)</tt>: Removes the column named +column_name+ from the table called +table_name+. + # * <tt>add_index(table_name, column_names, index_type, index_name)</tt>: Add a new index with the name of the column, or +index_name+ (if specified) on the column(s). Specify an optional +index_type+ (e.g. UNIQUE). + # * <tt>remove_index(table_name, index_name)</tt>: Remove the index specified by +index_name+. + # + # == Irreversible transformations + # + # Some transformations are destructive in a manner that cannot be reversed. Migrations of that kind should raise + # an <tt>IrreversibleMigration</tt> exception in their +down+ method. + # + # == Running migrations from within Rails + # + # The Rails package has several tools to help create and apply migrations. + # + # To generate a new migration, use <tt>script/generate migration MyNewMigration</tt> + # where MyNewMigration is the name of your migration. The generator will + # create a file <tt>nnn_my_new_migration.rb</tt> in the <tt>db/migrate/</tt> + # directory, where <tt>nnn</tt> is the next largest migration number. + # You may then edit the <tt>self.up</tt> and <tt>self.down</tt> methods of + # n MyNewMigration. + # + # To run migrations against the currently configured database, use + # <tt>rake migrate</tt>. This will update the database by running all of the + # pending migrations, creating the <tt>schema_info</tt> table if missing. + # + # To roll the database back to a previous migration version, use + # <tt>rake migrate VERSION=X</tt> where <tt>X</tt> is the version to which + # you wish to downgrade. If any of the migrations throw an + # <tt>IrreversibleMigration</tt> exception, that step will fail and you'll + # have some manual work to do. + # + # == Database support + # + # Migrations are currently supported in MySQL, PostgreSQL, SQLite, + # SQL Server, Sybase, and Oracle (all supported databases except DB2). + # + # == More examples + # + # Not all migrations change the schema. Some just fix the data: + # + # class RemoveEmptyTags < ActiveRecord::Migration + # def self.up + # Tag.find(:all).each { |tag| tag.destroy if tag.pages.empty? } + # end + # + # def self.down + # # not much we can do to restore deleted data + # raise IrreversibleMigration + # end + # end + # + # Others remove columns when they migrate up instead of down: + # + # class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration + # def self.up + # remove_column :items, :incomplete_items_count + # remove_column :items, :completed_items_count + # end + # + # def self.down + # add_column :items, :incomplete_items_count + # add_column :items, :completed_items_count + # end + # end + # + # And sometimes you need to do something in SQL not abstracted directly by migrations: + # + # class MakeJoinUnique < ActiveRecord::Migration + # def self.up + # execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)" + # end + # + # def self.down + # execute "ALTER TABLE `pages_linked_pages` DROP INDEX `page_id_linked_page_id`" + # end + # end + # + # == Using a model after changing its table + # + # Sometimes you'll want to add a column in a migration and populate it immediately after. In that case, you'll need + # to make a call to Base#reset_column_information in order to ensure that the model has the latest column data from + # after the new column was added. Example: + # + # class AddPeopleSalary < ActiveRecord::Migration + # def self.up + # add_column :people, :salary, :integer + # Person.reset_column_information + # Person.find(:all).each do |p| + # p.salary = SalaryCalculator.compute(p) + # end + # end + # end + # + # == Controlling verbosity + # + # By default, migrations will describe the actions they are taking, writing + # them to the console as they happen, along with benchmarks describing how + # long each step took. + # + # You can quiet them down by setting ActiveRecord::Migration.verbose = false. + # + # You can also insert your own messages and benchmarks by using the #say_with_time + # method: + # + # def self.up + # ... + # say_with_time "Updating salaries..." do + # Person.find(:all).each do |p| + # p.salary = SalaryCalculator.compute(p) + # end + # end + # ... + # end + # + # The phrase "Updating salaries..." would then be printed, along with the + # benchmark for the block when the block completes. + class Migration + @@verbose = true + cattr_accessor :verbose + + class << self + def up_using_benchmarks #:nodoc: + migrate(:up) + end + + def down_using_benchmarks #:nodoc: + migrate(:down) + end + + # Execute this migration in the named direction + def migrate(direction) + return unless respond_to?(direction) + + case direction + when :up then announce "migrating" + when :down then announce "reverting" + end + + result = nil + time = Benchmark.measure { result = send("real_#{direction}") } + + case direction + when :up then announce "migrated (%.4fs)" % time.real; write + when :down then announce "reverted (%.4fs)" % time.real; write + end + + result + end + + # Because the method added may do an alias_method, it can be invoked + # recursively. We use @ignore_new_methods as a guard to indicate whether + # it is safe for the call to proceed. + def singleton_method_added(sym) #:nodoc: + return if @ignore_new_methods + + begin + @ignore_new_methods = true + + case sym + when :up, :down + klass = (class << self; self; end) + klass.send(:alias_method, "real_#{sym}", sym) + klass.send(:alias_method, sym, "#{sym}_using_benchmarks") + end + ensure + @ignore_new_methods = false + end + end + + def write(text="") + puts(text) if verbose + end + + def announce(message) + text = "#{name}: #{message}" + length = [0, 75 - text.length].max + write "== %s %s" % [text, "=" * length] + end + + def say(message, subitem=false) + write "#{subitem ? " ->" : "--"} #{message}" + end + + def say_with_time(message) + say(message) + result = nil + time = Benchmark.measure { result = yield } + say "%.4fs" % time.real, :subitem + result + end + + def suppress_messages + save = verbose + self.verbose = false + yield + ensure + self.verbose = save + end + + def method_missing(method, *arguments, &block) + say_with_time "#{method}(#{arguments.map { |a| a.inspect }.join(", ")})" do + arguments[0] = Migrator.proper_table_name(arguments.first) unless arguments.empty? || method == :execute + ActiveRecord::Base.connection.send(method, *arguments, &block) + end + end + end + end + + class Migrator#:nodoc: + class << self + def migrate(migrations_path, target_version = nil) + Base.connection.initialize_schema_information + + case + when target_version.nil?, current_version < target_version + up(migrations_path, target_version) + when current_version > target_version + down(migrations_path, target_version) + when current_version == target_version + return # You're on the right version + end + end + + def up(migrations_path, target_version = nil) + self.new(:up, migrations_path, target_version).migrate + end + + def down(migrations_path, target_version = nil) + self.new(:down, migrations_path, target_version).migrate + end + + def schema_info_table_name + Base.table_name_prefix + "schema_info" + Base.table_name_suffix + end + + def current_version + (Base.connection.select_one("SELECT version FROM #{schema_info_table_name}") || {"version" => 0})["version"].to_i + end + + def proper_table_name(name) + # Use the ActiveRecord objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string + name.table_name rescue "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}" + end + + end + + def initialize(direction, migrations_path, target_version = nil) + raise StandardError.new("This database does not yet support migrations") unless Base.connection.supports_migrations? + @direction, @migrations_path, @target_version = direction, migrations_path, target_version + Base.connection.initialize_schema_information + end + + def current_version + self.class.current_version + end + + def migrate + migration_classes.each do |(version, migration_class)| + Base.logger.info("Reached target version: #{@target_version}") and break if reached_target_version?(version) + next if irrelevant_migration?(version) + + Base.logger.info "Migrating to #{migration_class} (#{version})" + migration_class.migrate(@direction) + set_schema_version(version) + end + end + + private + def migration_classes + migrations = migration_files.inject([]) do |migrations, migration_file| + load(migration_file) + version, name = migration_version_and_name(migration_file) + assert_unique_migration_version(migrations, version.to_i) + migrations << [ version.to_i, migration_class(name) ] + end + + down? ? migrations.sort.reverse : migrations.sort + end + + def assert_unique_migration_version(migrations, version) + if !migrations.empty? && migrations.transpose.first.include?(version) + raise DuplicateMigrationVersionError.new(version) + end + end + + def migration_files + files = Dir["#{@migrations_path}/[0-9]*_*.rb"].sort_by do |f| + migration_version_and_name(f).first.to_i + end + down? ? files.reverse : files + end + + def migration_class(migration_name) + migration_name.camelize.constantize + end + + def migration_version_and_name(migration_file) + return *migration_file.scan(/([0-9]+)_([_a-z0-9]*).rb/).first + end + + def set_schema_version(version) + Base.connection.update("UPDATE #{self.class.schema_info_table_name} SET version = #{down? ? version.to_i - 1 : version.to_i}") + end + + def up? + @direction == :up + end + + def down? + @direction == :down + end + + def reached_target_version?(version) + (up? && version.to_i - 1 == @target_version) || (down? && version.to_i == @target_version) + end + + def irrelevant_migration?(version) + (up? && version.to_i <= current_version) || (down? && version.to_i > current_version) + end + end +end +require 'singleton' + +module ActiveRecord + module Observing # :nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + module ClassMethods + # Activates the observers assigned. Examples: + # + # # Calls PersonObserver.instance + # ActiveRecord::Base.observers = :person_observer + # + # # Calls Cacher.instance and GarbageCollector.instance + # ActiveRecord::Base.observers = :cacher, :garbage_collector + # + # # Same as above, just using explicit class references + # ActiveRecord::Base.observers = Cacher, GarbageCollector + def observers=(*observers) + observers = [ observers ].flatten.each do |observer| + observer.is_a?(Symbol) ? + observer.to_s.camelize.constantize.instance : + observer.instance + end + end + end + end + + # Observer classes respond to lifecycle callbacks to implement trigger-like + # behavior outside the original class. This is a great way to reduce the + # clutter that normally comes when the model class is burdened with + # functionality that doesn't pertain to the core responsibility of the + # class. Example: + # + # class CommentObserver < ActiveRecord::Observer + # def after_save(comment) + # Notifications.deliver_comment("admin@do.com", "New comment was posted", comment) + # end + # end + # + # This Observer sends an email when a Comment#save is finished. + # + # class ContactObserver < ActiveRecord::Observer + # def after_create(contact) + # contact.logger.info('New contact added!') + # end + # + # def after_destroy(contact) + # contact.logger.warn("Contact with an id of #{contact.id} was destroyed!") + # end + # end + # + # This Observer uses logger to log when specific callbacks are triggered. + # + # == Observing a class that can't be inferred + # + # Observers will by default be mapped to the class with which they share a name. So CommentObserver will + # be tied to observing Comment, ProductManagerObserver to ProductManager, and so on. If you want to name your observer + # differently than the class you're interested in observing, you can use the Observer.observe class method: + # + # class AuditObserver < ActiveRecord::Observer + # observe Account + # + # def after_update(account) + # AuditTrail.new(account, "UPDATED") + # end + # end + # + # If the audit observer needs to watch more than one kind of object, this can be specified with multiple arguments: + # + # class AuditObserver < ActiveRecord::Observer + # observe Account, Balance + # + # def after_update(record) + # AuditTrail.new(record, "UPDATED") + # end + # end + # + # The AuditObserver will now act on both updates to Account and Balance by treating them both as records. + # + # == Available callback methods + # + # The observer can implement callback methods for each of the methods described in the Callbacks module. + # + # == Storing Observers in Rails + # + # If you're using Active Record within Rails, observer classes are usually stored in app/models with the + # naming convention of app/models/audit_observer.rb. + # + # == Configuration + # + # In order to activate an observer, list it in the <tt>config.active_record.observers</tt> configuration setting in your + # <tt>config/environment.rb</tt> file. + # + # config.active_record.observers = :comment_observer, :signup_observer + # + # Observers will not be invoked unless you define these in your application configuration. + # + class Observer + include Singleton + + # Observer subclasses should be reloaded by the dispatcher in Rails + # when Dependencies.mechanism = :load. + include Reloadable::Subclasses + + # Attaches the observer to the supplied model classes. + def self.observe(*models) + define_method(:observed_class) { models } + end + + def initialize + observed_classes = [ observed_class ].flatten + observed_subclasses_class = observed_classes.collect {|c| c.send(:subclasses) }.flatten! + (observed_classes + observed_subclasses_class).each do |klass| + klass.add_observer(self) + klass.send(:define_method, :after_find) unless klass.respond_to?(:after_find) + end + end + + def update(callback_method, object) #:nodoc: + send(callback_method, object) if respond_to?(callback_method) + end + + private + def observed_class + if self.class.respond_to? "observed_class" + self.class.observed_class + else + Object.const_get(infer_observed_class_name) + end + end + + def infer_observed_class_name + self.class.name.scan(/(.*)Observer/)[0][0] + end + end +end +module ActiveRecord + class QueryCache #:nodoc: + def initialize(connection) + @connection = connection + @query_cache = {} + end + + def clear_query_cache + @query_cache = {} + end + + def select_all(sql, name = nil) + (@query_cache[sql] ||= @connection.select_all(sql, name)).dup + end + + def select_one(sql, name = nil) + @query_cache[sql] ||= @connection.select_one(sql, name) + end + + def columns(table_name, name = nil) + @query_cache["SHOW FIELDS FROM #{table_name}"] ||= @connection.columns(table_name, name) + end + + def insert(sql, name = nil, pk = nil, id_value = nil) + clear_query_cache + @connection.insert(sql, name, pk, id_value) + end + + def update(sql, name = nil) + clear_query_cache + @connection.update(sql, name) + end + + def delete(sql, name = nil) + clear_query_cache + @connection.delete(sql, name) + end + + private + def method_missing(method, *arguments, &proc) + @connection.send(method, *arguments, &proc) + end + end + + class Base + # Set the connection for the class with caching on + class << self + alias_method :connection_without_query_cache=, :connection= + + def connection=(spec) + if spec.is_a?(ConnectionSpecification) and spec.config[:query_cache] + spec = QueryCache.new(self.send(spec.adapter_method, spec.config)) + end + self.connection_without_query_cache = spec + end + end + end + + class AbstractAdapter #:nodoc: + # Stub method to be able to treat the connection the same whether the query cache has been turned on or not + def clear_query_cache + end + end +end +module ActiveRecord + module Reflection # :nodoc: + def self.included(base) + base.extend(ClassMethods) + end + + # Reflection allows you to interrogate Active Record classes and objects about their associations and aggregations. + # This information can, for example, be used in a form builder that took an Active Record object and created input + # fields for all of the attributes depending on their type and displayed the associations to other objects. + # + # You can find the interface for the AggregateReflection and AssociationReflection classes in the abstract MacroReflection class. + module ClassMethods + def create_reflection(macro, name, options, active_record) + case macro + when :has_many, :belongs_to, :has_one, :has_and_belongs_to_many + reflection = AssociationReflection.new(macro, name, options, active_record) + when :composed_of + reflection = AggregateReflection.new(macro, name, options, active_record) + end + write_inheritable_hash :reflections, name => reflection + reflection + end + + def reflections + read_inheritable_attribute(:reflections) or write_inheritable_attribute(:reflections, {}) + end + + # Returns an array of AggregateReflection objects for all the aggregations in the class. + def reflect_on_all_aggregations + reflections.values.select { |reflection| reflection.is_a?(AggregateReflection) } + end + + # Returns the AggregateReflection object for the named +aggregation+ (use the symbol). Example: + # Account.reflect_on_aggregation(:balance) # returns the balance AggregateReflection + def reflect_on_aggregation(aggregation) + reflections[aggregation].is_a?(AggregateReflection) ? reflections[aggregation] : nil + end + + # Returns an array of AssociationReflection objects for all the aggregations in the class. If you only want to reflect on a + # certain association type, pass in the symbol (:has_many, :has_one, :belongs_to) for that as the first parameter. Example: + # Account.reflect_on_all_associations # returns an array of all associations + # Account.reflect_on_all_associations(:has_many) # returns an array of all has_many associations + def reflect_on_all_associations(macro = nil) + association_reflections = reflections.values.select { |reflection| reflection.is_a?(AssociationReflection) } + macro ? association_reflections.select { |reflection| reflection.macro == macro } : association_reflections + end + + # Returns the AssociationReflection object for the named +aggregation+ (use the symbol). Example: + # Account.reflect_on_association(:owner) # returns the owner AssociationReflection + # Invoice.reflect_on_association(:line_items).macro # returns :has_many + def reflect_on_association(association) + reflections[association].is_a?(AssociationReflection) ? reflections[association] : nil + end + end + + + # Abstract base class for AggregateReflection and AssociationReflection that describes the interface available for both of + # those classes. Objects of AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. + class MacroReflection + attr_reader :active_record + def initialize(macro, name, options, active_record) + @macro, @name, @options, @active_record = macro, name, options, active_record + end + + # Returns the name of the macro, so it would return :balance for "composed_of :balance, :class_name => 'Money'" or + # :clients for "has_many :clients". + def name + @name + end + + # Returns the name of the macro, so it would return :composed_of for + # "composed_of :balance, :class_name => 'Money'" or :has_many for "has_many :clients". + def macro + @macro + end + + # Returns the hash of options used for the macro, so it would return { :class_name => "Money" } for + # "composed_of :balance, :class_name => 'Money'" or {} for "has_many :clients". + def options + @options + end + + # Returns the class for the macro, so "composed_of :balance, :class_name => 'Money'" would return the Money class and + # "has_many :clients" would return the Client class. + def klass() end + + def class_name + @class_name ||= name_to_class_name(name.id2name) + end + + def ==(other_aggregation) + name == other_aggregation.name && other_aggregation.options && active_record == other_aggregation.active_record + end + end + + + # Holds all the meta-data about an aggregation as it was specified in the Active Record class. + class AggregateReflection < MacroReflection #:nodoc: + def klass + @klass ||= Object.const_get(options[:class_name] || class_name) + end + + private + def name_to_class_name(name) + name.capitalize.gsub(/_(.)/) { |s| $1.capitalize } + end + end + + # Holds all the meta-data about an association as it was specified in the Active Record class. + class AssociationReflection < MacroReflection #:nodoc: + def klass + @klass ||= active_record.send(:compute_type, class_name) + end + + def table_name + @table_name ||= klass.table_name + end + + def primary_key_name + return @primary_key_name if @primary_key_name + case + when macro == :belongs_to + @primary_key_name = options[:foreign_key] || class_name.foreign_key + when options[:as] + @primary_key_name = options[:foreign_key] || "#{options[:as]}_id" + else + @primary_key_name = options[:foreign_key] || active_record.name.foreign_key + end + end + + def association_foreign_key + @association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key + end + + def counter_cache_column + if options[:counter_cache] == true + "#{active_record.name.underscore.pluralize}_count" + elsif options[:counter_cache] + options[:counter_cache] + end + end + + def through_reflection + @through_reflection ||= options[:through] ? active_record.reflect_on_association(options[:through]) : false + end + + # Gets an array of possible :through source reflection names + # + # [singularized, pluralized] + def source_reflection_names + @source_reflection_names ||= (options[:source] ? [options[:source]] : [name.to_s.singularize, name]).collect { |n| n.to_sym } + end + + # Gets the source of the through reflection. It checks both a singularized and pluralized form for :belongs_to or :has_many. + # (The :tags association on Tagging below) + # + # class Post + # has_many :tags, :through => :taggings + # end + # + def source_reflection + return nil unless through_reflection + @source_reflection ||= source_reflection_names.collect { |name| through_reflection.klass.reflect_on_association(name) }.compact.first + end + + def check_validity! + if options[:through] + if through_reflection.nil? + raise HasManyThroughAssociationNotFoundError.new(self) + end + + if source_reflection.nil? + raise HasManyThroughSourceAssociationNotFoundError.new(self) + end + + if source_reflection.options[:polymorphic] + raise HasManyThroughAssociationPolymorphicError.new(class_name, self, source_reflection) + end + + unless [:belongs_to, :has_many].include?(source_reflection.macro) && source_reflection.options[:through].nil? + raise HasManyThroughSourceAssociationMacroError.new(self) + end + end + end + + private + def name_to_class_name(name) + if name =~ /::/ + name + else + if options[:class_name] + options[:class_name] + elsif through_reflection # get the class_name of the belongs_to association of the through reflection + source_reflection.class_name + else + class_name = name.to_s.camelize + class_name = class_name.singularize if [ :has_many, :has_and_belongs_to_many ].include?(macro) + class_name + end + end + end + end + end +end +module ActiveRecord + # Allows programmers to programmatically define a schema in a portable + # DSL. This means you can define tables, indexes, etc. without using SQL + # directly, so your applications can more easily support multiple + # databases. + # + # Usage: + # + # ActiveRecord::Schema.define do + # create_table :authors do |t| + # t.column :name, :string, :null => false + # end + # + # add_index :authors, :name, :unique + # + # create_table :posts do |t| + # t.column :author_id, :integer, :null => false + # t.column :subject, :string + # t.column :body, :text + # t.column :private, :boolean, :default => false + # end + # + # add_index :posts, :author_id + # end + # + # ActiveRecord::Schema is only supported by database adapters that also + # support migrations, the two features being very similar. + class Schema < Migration + private_class_method :new + + # Eval the given block. All methods available to the current connection + # adapter are available within the block, so you can easily use the + # database definition DSL to build up your schema (#create_table, + # #add_index, etc.). + # + # The +info+ hash is optional, and if given is used to define metadata + # about the current schema (like the schema's version): + # + # ActiveRecord::Schema.define(:version => 15) do + # ... + # end + def self.define(info={}, &block) + instance_eval(&block) + + unless info.empty? + initialize_schema_information + cols = columns('schema_info') + + info = info.map do |k,v| + v = Base.connection.quote(v, cols.detect { |c| c.name == k.to_s }) + "#{k} = #{v}" + end + + Base.connection.update "UPDATE #{Migrator.schema_info_table_name} SET #{info.join(", ")}" + end + end + end +end +module ActiveRecord + # This class is used to dump the database schema for some connection to some + # output format (i.e., ActiveRecord::Schema). + class SchemaDumper #:nodoc: + private_class_method :new + + # A list of tables which should not be dumped to the schema. + # Acceptable values are strings as well as regexp. + # This setting is only used if ActiveRecord::Base.schema_format == :ruby + cattr_accessor :ignore_tables + @@ignore_tables = [] + + def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT) + new(connection).dump(stream) + stream + end + + def dump(stream) + header(stream) + tables(stream) + trailer(stream) + stream + end + + private + + def initialize(connection) + @connection = connection + @types = @connection.native_database_types + @info = @connection.select_one("SELECT * FROM schema_info") rescue nil + end + + def header(stream) + define_params = @info ? ":version => #{@info['version']}" : "" + + stream.puts <<HEADER +# This file is autogenerated. Instead of editing this file, please use the +# migrations feature of ActiveRecord to incrementally modify your database, and +# then regenerate this schema definition. + +ActiveRecord::Schema.define(#{define_params}) do + +HEADER + end + + def trailer(stream) + stream.puts "end" + end + + def tables(stream) + @connection.tables.sort.each do |tbl| + next if ["schema_info", ignore_tables].flatten.any? do |ignored| + case ignored + when String: tbl == ignored + when Regexp: tbl =~ ignored + else + raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.' + end + end + table(tbl, stream) + end + end + + def table(table, stream) + columns = @connection.columns(table) + begin + tbl = StringIO.new + + if @connection.respond_to?(:pk_and_sequence_for) + pk, pk_seq = @connection.pk_and_sequence_for(table) + end + pk ||= 'id' + + tbl.print " create_table #{table.inspect}" + if columns.detect { |c| c.name == pk } + if pk != 'id' + tbl.print %Q(, :primary_key => "#{pk}") + end + else + tbl.print ", :id => false" + end + tbl.print ", :force => true" + tbl.puts " do |t|" + + columns.each do |column| + raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil? + next if column.name == pk + tbl.print " t.column #{column.name.inspect}, #{column.type.inspect}" + tbl.print ", :limit => #{column.limit.inspect}" if column.limit != @types[column.type][:limit] + tbl.print ", :default => #{column.default.inspect}" if !column.default.nil? + tbl.print ", :null => false" if !column.null + tbl.puts + end + + tbl.puts " end" + tbl.puts + + indexes(table, tbl) + + tbl.rewind + stream.print tbl.read + rescue => e + stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}" + stream.puts "# #{e.message}" + stream.puts + end + + stream + end + + def indexes(table, stream) + indexes = @connection.indexes(table) + indexes.each do |index| + stream.print " add_index #{index.table.inspect}, #{index.columns.inspect}, :name => #{index.name.inspect}" + stream.print ", :unique => true" if index.unique + stream.puts + end + stream.puts unless indexes.empty? + end + end +end +module ActiveRecord + # Active Records will automatically record creation and/or update timestamps of database objects + # if fields of the names created_at/created_on or updated_at/updated_on are present. This module is + # automatically included, so you don't need to do that manually. + # + # This behavior can be turned off by setting <tt>ActiveRecord::Base.record_timestamps = false</tt>. + # This behavior by default uses local time, but can use UTC by setting <tt>ActiveRecord::Base.default_timezone = :utc</tt> + module Timestamp + def self.append_features(base) # :nodoc: + super + + base.class_eval do + alias_method :create_without_timestamps, :create + alias_method :create, :create_with_timestamps + + alias_method :update_without_timestamps, :update + alias_method :update, :update_with_timestamps + end + end + + def create_with_timestamps #:nodoc: + if record_timestamps + t = ( self.class.default_timezone == :utc ? Time.now.utc : Time.now ) + write_attribute('created_at', t) if respond_to?(:created_at) && created_at.nil? + write_attribute('created_on', t) if respond_to?(:created_on) && created_on.nil? + + write_attribute('updated_at', t) if respond_to?(:updated_at) + write_attribute('updated_on', t) if respond_to?(:updated_on) + end + create_without_timestamps + end + + def update_with_timestamps #:nodoc: + if record_timestamps + t = ( self.class.default_timezone == :utc ? Time.now.utc : Time.now ) + write_attribute('updated_at', t) if respond_to?(:updated_at) + write_attribute('updated_on', t) if respond_to?(:updated_on) + end + update_without_timestamps + end + end + + class Base + # Records the creation date and possibly time in created_on (date only) or created_at (date and time) and the update date and possibly + # time in updated_on and updated_at. This only happens if the object responds to either of these messages, which they will do automatically + # if the table has columns of either of these names. This feature is turned on by default. + @@record_timestamps = true + cattr_accessor :record_timestamps + + # deprecated: use ActiveRecord::Base.default_timezone instead. + @@timestamps_gmt = false + def self.timestamps_gmt=( gmt ) #:nodoc: + warn "timestamps_gmt= is deprecated. use default_timezone= instead" + self.default_timezone = ( gmt ? :utc : :local ) + end + + def self.timestamps_gmt #:nodoc: + warn "timestamps_gmt is deprecated. use default_timezone instead" + self.default_timezone == :utc + end + end +end +require 'active_record/vendor/simple.rb' +Transaction::Simple.send(:remove_method, :transaction) +require 'thread' + +module ActiveRecord + module Transactions # :nodoc: + TRANSACTION_MUTEX = Mutex.new + + class TransactionError < ActiveRecordError # :nodoc: + end + + def self.append_features(base) + super + base.extend(ClassMethods) + + base.class_eval do + alias_method :destroy_without_transactions, :destroy + alias_method :destroy, :destroy_with_transactions + + alias_method :save_without_transactions, :save + alias_method :save, :save_with_transactions + end + end + + # Transactions are protective blocks where SQL statements are only permanent if they can all succeed as one atomic action. + # The classic example is a transfer between two accounts where you can only have a deposit if the withdrawal succeeded and + # vice versa. Transactions enforce the integrity of the database and guard the data against program errors or database break-downs. + # So basically you should use transaction blocks whenever you have a number of statements that must be executed together or + # not at all. Example: + # + # transaction do + # david.withdrawal(100) + # mary.deposit(100) + # end + # + # This example will only take money from David and give to Mary if neither +withdrawal+ nor +deposit+ raises an exception. + # Exceptions will force a ROLLBACK that returns the database to the state before the transaction was begun. Be aware, though, + # that the objects by default will _not_ have their instance data returned to their pre-transactional state. + # + # == Transactions are not distributed across database connections + # + # A transaction acts on a single database connection. If you have + # multiple class-specific databases, the transaction will not protect + # interaction among them. One workaround is to begin a transaction + # on each class whose models you alter: + # + # Student.transaction do + # Course.transaction do + # course.enroll(student) + # student.units += course.units + # end + # end + # + # This is a poor solution, but full distributed transactions are beyond + # the scope of Active Record. + # + # == Save and destroy are automatically wrapped in a transaction + # + # Both Base#save and Base#destroy come wrapped in a transaction that ensures that whatever you do in validations or callbacks + # will happen under the protected cover of a transaction. So you can use validations to check for values that the transaction + # depend on or you can raise exceptions in the callbacks to rollback. + # + # == Object-level transactions + # + # You can enable object-level transactions for Active Record objects, though. You do this by naming each of the Active Records + # that you want to enable object-level transactions for, like this: + # + # Account.transaction(david, mary) do + # david.withdrawal(100) + # mary.deposit(100) + # end + # + # If the transaction fails, David and Mary will be returned to their pre-transactional state. No money will have changed hands in + # neither object nor database. + # + # == Exception handling + # + # Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you + # should be ready to catch those in your application code. + # + # Tribute: Object-level transactions are implemented by Transaction::Simple by Austin Ziegler. + module ClassMethods + def transaction(*objects, &block) + previous_handler = trap('TERM') { raise TransactionError, "Transaction aborted" } + lock_mutex + + begin + objects.each { |o| o.extend(Transaction::Simple) } + objects.each { |o| o.start_transaction } + + result = connection.transaction(Thread.current['start_db_transaction'], &block) + + objects.each { |o| o.commit_transaction } + return result + rescue Exception => object_transaction_rollback + objects.each { |o| o.abort_transaction } + raise + ensure + unlock_mutex + trap('TERM', previous_handler) + end + end + + def lock_mutex#:nodoc: + Thread.current['open_transactions'] ||= 0 + TRANSACTION_MUTEX.lock if Thread.current['open_transactions'] == 0 + Thread.current['start_db_transaction'] = (Thread.current['open_transactions'] == 0) + Thread.current['open_transactions'] += 1 + end + + def unlock_mutex#:nodoc: + Thread.current['open_transactions'] -= 1 + TRANSACTION_MUTEX.unlock if Thread.current['open_transactions'] == 0 + end + end + + def transaction(*objects, &block) + self.class.transaction(*objects, &block) + end + + def destroy_with_transactions #:nodoc: + transaction { destroy_without_transactions } + end + + def save_with_transactions(perform_validation = true) #:nodoc: + transaction { save_without_transactions(perform_validation) } + end + end +end +module ActiveRecord + # Raised by save! and create! when the record is invalid. Use the + # record method to retrieve the record which did not validate. + # begin + # complex_operation_that_calls_save!_internally + # rescue ActiveRecord::RecordInvalid => invalid + # puts invalid.record.errors + # end + class RecordInvalid < ActiveRecordError #:nodoc: + attr_reader :record + def initialize(record) + @record = record + super("Validation failed: #{@record.errors.full_messages.join(", ")}") + end + end + + # Active Record validation is reported to and from this object, which is used by Base#save to + # determine whether the object in a valid state to be saved. See usage example in Validations. + class Errors + include Enumerable + + def initialize(base) # :nodoc: + @base, @errors = base, {} + end + + @@default_error_messages = { + :inclusion => "is not included in the list", + :exclusion => "is reserved", + :invalid => "is invalid", + :confirmation => "doesn't match confirmation", + :accepted => "must be accepted", + :empty => "can't be empty", + :blank => "can't be blank", + :too_long => "is too long (maximum is %d characters)", + :too_short => "is too short (minimum is %d characters)", + :wrong_length => "is the wrong length (should be %d characters)", + :taken => "has already been taken", + :not_a_number => "is not a number" + } + + # Holds a hash with all the default error messages, such that they can be replaced by your own copy or localizations. + cattr_accessor :default_error_messages + + + # Adds an error to the base object instead of any particular attribute. This is used + # to report errors that don't tie to any specific attribute, but rather to the object + # as a whole. These error messages don't get prepended with any field name when iterating + # with each_full, so they should be complete sentences. + def add_to_base(msg) + add(:base, msg) + end + + # Adds an error message (+msg+) to the +attribute+, which will be returned on a call to <tt>on(attribute)</tt> + # for the same attribute and ensure that this error object returns false when asked if <tt>empty?</tt>. More than one + # error can be added to the same +attribute+ in which case an array will be returned on a call to <tt>on(attribute)</tt>. + # If no +msg+ is supplied, "invalid" is assumed. + def add(attribute, msg = @@default_error_messages[:invalid]) + @errors[attribute.to_s] = [] if @errors[attribute.to_s].nil? + @errors[attribute.to_s] << msg + end + + # Will add an error message to each of the attributes in +attributes+ that is empty. + def add_on_empty(attributes, msg = @@default_error_messages[:empty]) + for attr in [attributes].flatten + value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s] + is_empty = value.respond_to?("empty?") ? value.empty? : false + add(attr, msg) unless !value.nil? && !is_empty + end + end + + # Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?). + def add_on_blank(attributes, msg = @@default_error_messages[:blank]) + for attr in [attributes].flatten + value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s] + add(attr, msg) if value.blank? + end + end + + # Will add an error message to each of the attributes in +attributes+ that has a length outside of the passed boundary +range+. + # If the length is above the boundary, the too_long_msg message will be used. If below, the too_short_msg. + def add_on_boundary_breaking(attributes, range, too_long_msg = @@default_error_messages[:too_long], too_short_msg = @@default_error_messages[:too_short]) + for attr in [attributes].flatten + value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s] + add(attr, too_short_msg % range.begin) if value && value.length < range.begin + add(attr, too_long_msg % range.end) if value && value.length > range.end + end + end + + alias :add_on_boundry_breaking :add_on_boundary_breaking + + # Returns true if the specified +attribute+ has errors associated with it. + def invalid?(attribute) + !@errors[attribute.to_s].nil? + end + + # * Returns nil, if no errors are associated with the specified +attribute+. + # * Returns the error message, if one error is associated with the specified +attribute+. + # * Returns an array of error messages, if more than one error is associated with the specified +attribute+. + def on(attribute) + if @errors[attribute.to_s].nil? + nil + elsif @errors[attribute.to_s].length == 1 + @errors[attribute.to_s].first + else + @errors[attribute.to_s] + end + end + + alias :[] :on + + # Returns errors assigned to base object through add_to_base according to the normal rules of on(attribute). + def on_base + on(:base) + end + + # Yields each attribute and associated message per error added. + def each + @errors.each_key { |attr| @errors[attr].each { |msg| yield attr, msg } } + end + + # Yields each full error message added. So Person.errors.add("first_name", "can't be empty") will be returned + # through iteration as "First name can't be empty". + def each_full + full_messages.each { |msg| yield msg } + end + + # Returns all the full error messages in an array. + def full_messages + full_messages = [] + + @errors.each_key do |attr| + @errors[attr].each do |msg| + next if msg.nil? + + if attr == "base" + full_messages << msg + else + full_messages << @base.class.human_attribute_name(attr) + " " + msg + end + end + end + + return full_messages + end + + # Returns true if no errors have been added. + def empty? + return @errors.empty? + end + + # Removes all the errors that have been added. + def clear + @errors = {} + end + + # Returns the total number of errors added. Two errors added to the same attribute will be counted as such + # with this as well. + def size + error_count = 0 + @errors.each_value { |attribute| error_count += attribute.length } + error_count + end + + alias_method :count, :size + alias_method :length, :size + end + + + # Active Records implement validation by overwriting Base#validate (or the variations, +validate_on_create+ and + # +validate_on_update+). Each of these methods can inspect the state of the object, which usually means ensuring + # that a number of attributes have a certain value (such as not empty, within a given range, matching a certain regular expression). + # + # Example: + # + # class Person < ActiveRecord::Base + # protected + # def validate + # errors.add_on_empty %w( first_name last_name ) + # errors.add("phone_number", "has invalid format") unless phone_number =~ /[0-9]*/ + # end + # + # def validate_on_create # is only run the first time a new object is saved + # unless valid_discount?(membership_discount) + # errors.add("membership_discount", "has expired") + # end + # end + # + # def validate_on_update + # errors.add_to_base("No changes have occurred") if unchanged_attributes? + # end + # end + # + # person = Person.new("first_name" => "David", "phone_number" => "what?") + # person.save # => false (and doesn't do the save) + # person.errors.empty? # => false + # person.errors.count # => 2 + # person.errors.on "last_name" # => "can't be empty" + # person.errors.on "phone_number" # => "has invalid format" + # person.errors.each_full { |msg| puts msg } + # # => "Last name can't be empty\n" + + # "Phone number has invalid format" + # + # person.attributes = { "last_name" => "Heinemeier", "phone_number" => "555-555" } + # person.save # => true (and person is now saved in the database) + # + # An +Errors+ object is automatically created for every Active Record. + # + # Please do have a look at ActiveRecord::Validations::ClassMethods for a higher level of validations. + module Validations + VALIDATIONS = %w( validate validate_on_create validate_on_update ) + + def self.append_features(base) # :nodoc: + super + base.extend ClassMethods + base.class_eval do + alias_method :save_without_validation, :save + alias_method :save, :save_with_validation + + alias_method :save_without_validation!, :save! + alias_method :save!, :save_with_validation! + + alias_method :update_attribute_without_validation_skipping, :update_attribute + alias_method :update_attribute, :update_attribute_with_validation_skipping + end + end + + # All of the following validations are defined in the class scope of the model that you're interested in validating. + # They offer a more declarative way of specifying when the model is valid and when it is not. It is recommended to use + # these over the low-level calls to validate and validate_on_create when possible. + module ClassMethods + DEFAULT_VALIDATION_OPTIONS = { + :on => :save, + :allow_nil => false, + :message => nil + }.freeze + + ALL_RANGE_OPTIONS = [ :is, :within, :in, :minimum, :maximum ].freeze + + def validate(*methods, &block) + methods << block if block_given? + write_inheritable_set(:validate, methods) + end + + def validate_on_create(*methods, &block) + methods << block if block_given? + write_inheritable_set(:validate_on_create, methods) + end + + def validate_on_update(*methods, &block) + methods << block if block_given? + write_inheritable_set(:validate_on_update, methods) + end + + def condition_block?(condition) + condition.respond_to?("call") && (condition.arity == 1 || condition.arity == -1) + end + + # Determine from the given condition (whether a block, procedure, method or string) + # whether or not to validate the record. See #validates_each. + def evaluate_condition(condition, record) + case condition + when Symbol: record.send(condition) + when String: eval(condition, binding) + else + if condition_block?(condition) + condition.call(record) + else + raise( + ActiveRecordError, + "Validations need to be either a symbol, string (to be eval'ed), proc/method, or " + + "class implementing a static validation method" + ) + end + end + end + + # Validates each attribute against a block. + # + # class Person < ActiveRecord::Base + # validates_each :first_name, :last_name do |record, attr, value| + # record.errors.add attr, 'starts with z.' if value[0] == ?z + # end + # end + # + # Options: + # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>allow_nil</tt> - Skip validation if attribute is nil. + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_each(*attrs) + options = attrs.last.is_a?(Hash) ? attrs.pop.symbolize_keys : {} + attrs = attrs.flatten + + # Declare the validation. + send(validation_method(options[:on] || :save)) do |record| + # Don't validate when there is an :if condition and that condition is false + unless options[:if] && !evaluate_condition(options[:if], record) + attrs.each do |attr| + value = record.send(attr) + next if value.nil? && options[:allow_nil] + yield record, attr, value + end + end + end + end + + # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example: + # + # Model: + # class Person < ActiveRecord::Base + # validates_confirmation_of :user_name, :password + # validates_confirmation_of :email_address, :message => "should match confirmation" + # end + # + # View: + # <%= password_field "person", "password" %> + # <%= password_field "person", "password_confirmation" %> + # + # The person has to already have a password attribute (a column in the people table), but the password_confirmation is virtual. + # It exists only as an in-memory variable for validating the password. This check is performed only if password_confirmation + # is not nil and by default on save. + # + # Configuration options: + # * <tt>message</tt> - A custom error message (default is: "doesn't match confirmation") + # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_confirmation_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + attr_accessor *(attr_names.map { |n| "#{n}_confirmation" }) + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation") + end + end + + # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example: + # + # class Person < ActiveRecord::Base + # validates_acceptance_of :terms_of_service + # validates_acceptance_of :eula, :message => "must be abided" + # end + # + # The terms_of_service attribute is entirely virtual. No database column is needed. This check is performed only if + # terms_of_service is not nil and by default on save. + # + # Configuration options: + # * <tt>message</tt> - A custom error message (default is: "must be accepted") + # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>accept</tt> - Specifies value that is considered accepted. The default value is a string "1", which + # makes it easy to relate to an HTML checkbox. + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_acceptance_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + attr_accessor *attr_names + + validates_each(attr_names,configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless value == configuration[:accept] + end + end + + # Validates that the specified attributes are not blank (as defined by Object#blank?). Happens by default on save. Example: + # + # class Person < ActiveRecord::Base + # validates_presence_of :first_name + # end + # + # The first_name attribute must be in the object and it cannot be blank. + # + # Configuration options: + # * <tt>message</tt> - A custom error message (default is: "can't be blank") + # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # + # === Warning + # Validate the presence of the foreign key, not the instance variable itself. + # Do this: + # validate_presence_of :invoice_id + # + # Not this: + # validate_presence_of :invoice + # + # If you validate the presence of the associated object, you will get + # failures on saves when both the parent object and the child object are + # new. + def validates_presence_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:blank], :on => :save } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + # can't use validates_each here, because it cannot cope with nonexistent attributes, + # while errors.add_on_empty can + attr_names.each do |attr_name| + send(validation_method(configuration[:on])) do |record| + unless configuration[:if] and not evaluate_condition(configuration[:if], record) + record.errors.add_on_blank(attr_name,configuration[:message]) + end + end + end + end + + # Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time: + # + # class Person < ActiveRecord::Base + # validates_length_of :first_name, :maximum=>30 + # validates_length_of :last_name, :maximum=>30, :message=>"less than %d if you don't mind" + # validates_length_of :fax, :in => 7..32, :allow_nil => true + # validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name" + # validates_length_of :fav_bra_size, :minimum=>1, :too_short=>"please enter at least %d character" + # validates_length_of :smurf_leader, :is=>4, :message=>"papa is spelled with %d characters... don't play me." + # end + # + # Configuration options: + # * <tt>minimum</tt> - The minimum size of the attribute + # * <tt>maximum</tt> - The maximum size of the attribute + # * <tt>is</tt> - The exact size of the attribute + # * <tt>within</tt> - A range specifying the minimum and maximum size of the attribute + # * <tt>in</tt> - A synonym(or alias) for :within + # * <tt>allow_nil</tt> - Attribute may be nil; skip validation. + # + # * <tt>too_long</tt> - The error message if the attribute goes over the maximum (default is: "is too long (maximum is %d characters)") + # * <tt>too_short</tt> - The error message if the attribute goes under the minimum (default is: "is too short (min is %d characters)") + # * <tt>wrong_length</tt> - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %d characters)") + # * <tt>message</tt> - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message + # * <tt>on</tt> - Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_length_of(*attrs) + # Merge given options with defaults. + options = { + :too_long => ActiveRecord::Errors.default_error_messages[:too_long], + :too_short => ActiveRecord::Errors.default_error_messages[:too_short], + :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length] + }.merge(DEFAULT_VALIDATION_OPTIONS) + options.update(attrs.pop.symbolize_keys) if attrs.last.is_a?(Hash) + + # Ensure that one and only one range option is specified. + range_options = ALL_RANGE_OPTIONS & options.keys + case range_options.size + when 0 + raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.' + when 1 + # Valid number of options; do nothing. + else + raise ArgumentError, 'Too many range options specified. Choose only one.' + end + + # Get range option and value. + option = range_options.first + option_value = options[range_options.first] + + case option + when :within, :in + raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range) + + too_short = options[:too_short] % option_value.begin + too_long = options[:too_long] % option_value.end + + validates_each(attrs, options) do |record, attr, value| + if value.nil? or value.split(//).size < option_value.begin + record.errors.add(attr, too_short) + elsif value.split(//).size > option_value.end + record.errors.add(attr, too_long) + end + end + when :is, :minimum, :maximum + raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0 + + # Declare different validations per option. + validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" } + message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long } + + message = (options[:message] || options[message_options[option]]) % option_value + + validates_each(attrs, options) do |record, attr, value| + if value.kind_of?(String) + record.errors.add(attr, message) unless !value.nil? and value.split(//).size.method(validity_checks[option])[option_value] + else + record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value] + end + end + end + end + + alias_method :validates_size_of, :validates_length_of + + + # Validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user + # can be named "davidhh". + # + # class Person < ActiveRecord::Base + # validates_uniqueness_of :user_name, :scope => :account_id + # end + # + # It can also validate whether the value of the specified attributes are unique based on multiple scope parameters. For example, + # making sure that a teacher can only be on the schedule once per semester for a particular class. + # + # class TeacherSchedule < ActiveRecord::Base + # validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id] + # end + # + # When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified + # attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself. + # + # Configuration options: + # * <tt>message</tt> - Specifies a custom error message (default is: "has already been taken") + # * <tt>scope</tt> - One or more columns by which to limit the scope of the uniquness constraint. + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + + def validates_uniqueness_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + validates_each(attr_names,configuration) do |record, attr_name, value| + condition_sql = "#{record.class.table_name}.#{attr_name} #{attribute_condition(value)}" + condition_params = [value] + if scope = configuration[:scope] + Array(scope).map do |scope_item| + scope_value = record.send(scope_item) + condition_sql << " AND #{record.class.table_name}.#{scope_item} #{attribute_condition(scope_value)}" + condition_params << scope_value + end + end + unless record.new_record? + condition_sql << " AND #{record.class.table_name}.#{record.class.primary_key} <> ?" + condition_params << record.send(:id) + end + if record.class.find(:first, :conditions => [condition_sql, *condition_params]) + record.errors.add(attr_name, configuration[:message]) + end + end + end + + # Validates whether the value of the specified attribute is of the correct form by matching it against the regular expression + # provided. + # + # class Person < ActiveRecord::Base + # validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :on => :create + # end + # + # A regular expression must be provided or else an exception will be raised. + # + # Configuration options: + # * <tt>message</tt> - A custom error message (default is: "is invalid") + # * <tt>with</tt> - The regular expression used to validate the format with (note: must be supplied!) + # * <tt>on</tt> Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_format_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save, :with => nil } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp) + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless value.to_s =~ configuration[:with] + end + end + + # Validates whether the value of the specified attribute is available in a particular enumerable object. + # + # class Person < ActiveRecord::Base + # validates_inclusion_of :gender, :in=>%w( m f ), :message=>"woah! what are you then!??!!" + # validates_inclusion_of :age, :in=>0..99 + # end + # + # Configuration options: + # * <tt>in</tt> - An enumerable object of available items + # * <tt>message</tt> - Specifies a customer error message (default is: "is not included in the list") + # * <tt>allow_nil</tt> - If set to true, skips this validation if the attribute is null (default is: false) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_inclusion_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:inclusion], :on => :save } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + enum = configuration[:in] || configuration[:within] + + raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?") + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless enum.include?(value) + end + end + + # Validates that the value of the specified attribute is not in a particular enumerable object. + # + # class Person < ActiveRecord::Base + # validates_exclusion_of :username, :in => %w( admin superuser ), :message => "You don't belong here" + # validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60" + # end + # + # Configuration options: + # * <tt>in</tt> - An enumerable object of items that the value shouldn't be part of + # * <tt>message</tt> - Specifies a customer error message (default is: "is reserved") + # * <tt>allow_nil</tt> - If set to true, skips this validation if the attribute is null (default is: false) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_exclusion_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:exclusion], :on => :save } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + enum = configuration[:in] || configuration[:within] + + raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?") + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) if enum.include?(value) + end + end + + # Validates whether the associated object or objects are all valid themselves. Works with any kind of association. + # + # class Book < ActiveRecord::Base + # has_many :pages + # belongs_to :library + # + # validates_associated :pages, :library + # end + # + # Warning: If, after the above definition, you then wrote: + # + # class Page < ActiveRecord::Base + # belongs_to :book + # + # validates_associated :book + # end + # + # ...this would specify a circular dependency and cause infinite recursion. + # + # NOTE: This validation will not fail if the association hasn't been assigned. If you want to ensure that the association + # is both present and guaranteed to be valid, you also need to use validates_presence_of. + # + # Configuration options: + # * <tt>on</tt> Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_associated(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless + (value.is_a?(Array) ? value : [value]).all? { |r| r.nil? or r.valid? } + end + end + + # Validates whether the value of the specified attribute is numeric by trying to convert it to + # a float with Kernel.Float (if <tt>integer</tt> is false) or applying it to the regular expression + # <tt>/^[\+\-]?\d+$/</tt> (if <tt>integer</tt> is set to true). + # + # class Person < ActiveRecord::Base + # validates_numericality_of :value, :on => :create + # end + # + # Configuration options: + # * <tt>message</tt> - A custom error message (default is: "is not a number") + # * <tt>on</tt> Specifies when this validation is active (default is :save, other options :create, :update) + # * <tt>only_integer</tt> Specifies whether the value has to be an integer, e.g. an integral value (default is false) + # * <tt>allow_nil</tt> Skip validation if attribute is nil (default is false). Notice that for fixnum and float columns empty strings are converted to nil + # * <tt>if</tt> - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_numericality_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:not_a_number], :on => :save, + :only_integer => false, :allow_nil => false } + configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash) + + if configuration[:only_integer] + validates_each(attr_names,configuration) do |record, attr_name,value| + record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_before_type_cast").to_s =~ /^[+-]?\d+$/ + end + else + validates_each(attr_names,configuration) do |record, attr_name,value| + next if configuration[:allow_nil] and record.send("#{attr_name}_before_type_cast").nil? + begin + Kernel.Float(record.send("#{attr_name}_before_type_cast").to_s) + rescue ArgumentError, TypeError + record.errors.add(attr_name, configuration[:message]) + end + end + end + end + + + # Creates an object just like Base.create but calls save! instead of save + # so an exception is raised if the record is invalid. + def create!(attributes = nil) + if attributes.is_a?(Array) + attributes.collect { |attr| create!(attr) } + else + attributes.reverse_merge!(scope(:create)) if scoped?(:create) + + object = new(attributes) + object.save! + object + end + end + + + private + def write_inheritable_set(key, methods) + existing_methods = read_inheritable_attribute(key) || [] + write_inheritable_attribute(key, methods | existing_methods) + end + + def validation_method(on) + case on + when :save then :validate + when :create then :validate_on_create + when :update then :validate_on_update + end + end + end + + # The validation process on save can be skipped by passing false. The regular Base#save method is + # replaced with this when the validations module is mixed in, which it is by default. + def save_with_validation(perform_validation = true) + if perform_validation && valid? || !perform_validation + save_without_validation + else + false + end + end + + # Attempts to save the record just like Base#save but will raise a RecordInvalid exception instead of returning false + # if the record is not valid. + def save_with_validation! + if valid? + save_without_validation! + else + raise RecordInvalid.new(self) + end + end + + # Updates a single attribute and saves the record without going through the normal validation procedure. + # This is especially useful for boolean flags on existing records. The regular +update_attribute+ method + # in Base is replaced with this when the validations module is mixed in, which it is by default. + def update_attribute_with_validation_skipping(name, value) + send(name.to_s + '=', value) + save(false) + end + + # Runs validate and validate_on_create or validate_on_update and returns true if no errors were added otherwise false. + def valid? + errors.clear + + run_validations(:validate) + validate + + if new_record? + run_validations(:validate_on_create) + validate_on_create + else + run_validations(:validate_on_update) + validate_on_update + end + + errors.empty? + end + + # Returns the Errors object that holds all information about attribute error messages. + def errors + @errors ||= Errors.new(self) + end + + protected + # Overwrite this method for validation checks on all saves and use Errors.add(field, msg) for invalid attributes. + def validate #:doc: + end + + # Overwrite this method for validation checks used only on creation. + def validate_on_create #:doc: + end + + # Overwrite this method for validation checks used only on updates. + def validate_on_update # :doc: + end + + private + def run_validations(validation_method) + validations = self.class.read_inheritable_attribute(validation_method.to_sym) + if validations.nil? then return end + validations.each do |validation| + if validation.is_a?(Symbol) + self.send(validation) + elsif validation.is_a?(String) + eval(validation, binding) + elsif validation_block?(validation) + validation.call(self) + elsif validation_class?(validation, validation_method) + validation.send(validation_method, self) + else + raise( + ActiveRecordError, + "Validations need to be either a symbol, string (to be eval'ed), proc/method, or " + + "class implementing a static validation method" + ) + end + end + end + + def validation_block?(validation) + validation.respond_to?("call") && (validation.arity == 1 || validation.arity == -1) + end + + def validation_class?(validation, validation_method) + validation.respond_to?(validation_method) + end + end +end +require 'db2/db2cli.rb' + +module DB2 + module DB2Util + include DB2CLI + + def free() SQLFreeHandle(@handle_type, @handle); end + def handle() @handle; end + + def check_rc(rc) + if ![SQL_SUCCESS, SQL_SUCCESS_WITH_INFO, SQL_NO_DATA_FOUND].include?(rc) + rec = 1 + msg = '' + loop do + a = SQLGetDiagRec(@handle_type, @handle, rec, 500) + break if a[0] != SQL_SUCCESS + msg << a[3] if !a[3].nil? and a[3] != '' # Create message. + rec += 1 + end + raise "DB2 error: #{msg}" + end + end + end + + class Environment + include DB2Util + + def initialize + @handle_type = SQL_HANDLE_ENV + rc, @handle = SQLAllocHandle(@handle_type, SQL_NULL_HANDLE) + check_rc(rc) + end + + def data_sources(buffer_length = 1024) + retval = [] + max_buffer_length = buffer_length + + a = SQLDataSources(@handle, SQL_FETCH_FIRST, SQL_MAX_DSN_LENGTH + 1, buffer_length) + retval << [a[1], a[3]] + max_buffer_length = [max_buffer_length, a[4]].max + + loop do + a = SQLDataSources(@handle, SQL_FETCH_NEXT, SQL_MAX_DSN_LENGTH + 1, buffer_length) + break if a[0] == SQL_NO_DATA_FOUND + + retval << [a[1], a[3]] + max_buffer_length = [max_buffer_length, a[4]].max + end + + if max_buffer_length > buffer_length + get_data_sources(max_buffer_length) + else + retval + end + end + end + + class Connection + include DB2Util + + def initialize(environment) + @env = environment + @handle_type = SQL_HANDLE_DBC + rc, @handle = SQLAllocHandle(@handle_type, @env.handle) + check_rc(rc) + end + + def connect(server_name, user_name = '', auth = '') + check_rc(SQLConnect(@handle, server_name, user_name.to_s, auth.to_s)) + end + + def set_connect_attr(attr, value) + value += "\0" if value.class == String + check_rc(SQLSetConnectAttr(@handle, attr, value)) + end + + def set_auto_commit_on + set_connect_attr(SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_ON) + end + + def set_auto_commit_off + set_connect_attr(SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF) + end + + def disconnect + check_rc(SQLDisconnect(@handle)) + end + + def rollback + check_rc(SQLEndTran(@handle_type, @handle, SQL_ROLLBACK)) + end + + def commit + check_rc(SQLEndTran(@handle_type, @handle, SQL_COMMIT)) + end + end + + class Statement + include DB2Util + + def initialize(connection) + @conn = connection + @handle_type = SQL_HANDLE_STMT + @parms = [] #yun + @sql = '' #yun + @numParms = 0 #yun + @prepared = false #yun + @parmArray = [] #yun. attributes of the parameter markers + rc, @handle = SQLAllocHandle(@handle_type, @conn.handle) + check_rc(rc) + end + + def columns(table_name, schema_name = '%') + check_rc(SQLColumns(@handle, '', schema_name.upcase, table_name.upcase, '%')) + fetch_all + end + + def tables(schema_name = '%') + check_rc(SQLTables(@handle, '', schema_name.upcase, '%', 'TABLE')) + fetch_all + end + + def indexes(table_name, schema_name = '') + check_rc(SQLStatistics(@handle, '', schema_name.upcase, table_name.upcase, SQL_INDEX_ALL, SQL_ENSURE)) + fetch_all + end + + def prepare(sql) + @sql = sql + check_rc(SQLPrepare(@handle, sql)) + rc, @numParms = SQLNumParams(@handle) #number of question marks + check_rc(rc) + #-------------------------------------------------------------------------- + # parameter attributes are stored in instance variable @parmArray so that + # they are available when execute method is called. + #-------------------------------------------------------------------------- + if @numParms > 0 # get parameter marker attributes + 1.upto(@numParms) do |i| # parameter number starts from 1 + rc, type, size, decimalDigits = SQLDescribeParam(@handle, i) + check_rc(rc) + @parmArray << Parameter.new(type, size, decimalDigits) + end + end + @prepared = true + self + end + + def execute(*parms) + raise "The statement was not prepared" if @prepared == false + + if parms.size == 1 and parms[0].class == Array + parms = parms[0] + end + + if @numParms != parms.size + raise "Number of parameters supplied does not match with the SQL statement" + end + + if @numParms > 0 #need to bind parameters + #-------------------------------------------------------------------- + #calling bindParms may not be safe. Look comment below. + #-------------------------------------------------------------------- + #bindParms(parms) + + valueArray = [] + 1.upto(@numParms) do |i| # parameter number starts from 1 + type = @parmArray[i - 1].class + size = @parmArray[i - 1].size + decimalDigits = @parmArray[i - 1].decimalDigits + + if parms[i - 1].class == String + valueArray << parms[i - 1] + else + valueArray << parms[i - 1].to_s + end + + rc = SQLBindParameter(@handle, i, type, size, decimalDigits, valueArray[i - 1]) + check_rc(rc) + end + end + + check_rc(SQLExecute(@handle)) + + if @numParms != 0 + check_rc(SQLFreeStmt(@handle, SQL_RESET_PARAMS)) # Reset parameters + end + + self + end + + #------------------------------------------------------------------------------- + # The last argument(value) to SQLBindParameter is a deferred argument, that is, + # it should be available when SQLExecute is called. Even though "value" is + # local to bindParms method, it seems that it is available when SQLExecute + # is called. I am not sure whether it would still work if garbage collection + # is done between bindParms call and SQLExecute call inside the execute method + # above. + #------------------------------------------------------------------------------- + def bindParms(parms) # This is the real thing. It uses SQLBindParms + 1.upto(@numParms) do |i| # parameter number starts from 1 + rc, dataType, parmSize, decimalDigits = SQLDescribeParam(@handle, i) + check_rc(rc) + if parms[i - 1].class == String + value = parms[i - 1] + else + value = parms[i - 1].to_s + end + rc = SQLBindParameter(@handle, i, dataType, parmSize, decimalDigits, value) + check_rc(rc) + end + end + + #------------------------------------------------------------------------------ + # bind method does not use DB2's SQLBindParams, but replaces "?" in the + # SQL statement with the value before passing the SQL statement to DB2. + # It is not efficient and can handle only strings since it puts everything in + # quotes. + #------------------------------------------------------------------------------ + def bind(sql, args) #does not use SQLBindParams + arg_index = 0 + result = "" + tokens(sql).each do |part| + case part + when '?' + result << "'" + (args[arg_index]) + "'" #put it into quotes + arg_index += 1 + when '??' + result << "?" + else + result << part + end + end + if arg_index < args.size + raise "Too many SQL parameters" + elsif arg_index > args.size + raise "Not enough SQL parameters" + end + result + end + + ## Break the sql string into parts. + # + # This is NOT a full lexer for SQL. It just breaks up the SQL + # string enough so that question marks, double question marks and + # quoted strings are separated. This is used when binding + # arguments to "?" in the SQL string. Note: comments are not + # handled. + # + def tokens(sql) + toks = sql.scan(/('([^'\\]|''|\\.)*'|"([^"\\]|""|\\.)*"|\?\??|[^'"?]+)/) + toks.collect { |t| t[0] } + end + + def exec_direct(sql) + check_rc(SQLExecDirect(@handle, sql)) + self + end + + def set_cursor_name(name) + check_rc(SQLSetCursorName(@handle, name)) + self + end + + def get_cursor_name + rc, name = SQLGetCursorName(@handle) + check_rc(rc) + name + end + + def row_count + rc, rowcount = SQLRowCount(@handle) + check_rc(rc) + rowcount + end + + def num_result_cols + rc, cols = SQLNumResultCols(@handle) + check_rc(rc) + cols + end + + def fetch_all + if block_given? + while row = fetch do + yield row + end + else + res = [] + while row = fetch do + res << row + end + res + end + end + + def fetch + cols = get_col_desc + rc = SQLFetch(@handle) + if rc == SQL_NO_DATA_FOUND + SQLFreeStmt(@handle, SQL_CLOSE) # Close cursor + SQLFreeStmt(@handle, SQL_RESET_PARAMS) # Reset parameters + return nil + end + raise "ERROR" unless rc == SQL_SUCCESS + + retval = [] + cols.each_with_index do |c, i| + rc, content = SQLGetData(@handle, i + 1, c[1], c[2] + 1) #yun added 1 to c[2] + retval << adjust_content(content) + end + retval + end + + def fetch_as_hash + cols = get_col_desc + rc = SQLFetch(@handle) + if rc == SQL_NO_DATA_FOUND + SQLFreeStmt(@handle, SQL_CLOSE) # Close cursor + SQLFreeStmt(@handle, SQL_RESET_PARAMS) # Reset parameters + return nil + end + raise "ERROR" unless rc == SQL_SUCCESS + + retval = {} + cols.each_with_index do |c, i| + rc, content = SQLGetData(@handle, i + 1, c[1], c[2] + 1) #yun added 1 to c[2] + retval[c[0]] = adjust_content(content) + end + retval + end + + def get_col_desc + rc, nr_cols = SQLNumResultCols(@handle) + cols = (1..nr_cols).collect do |c| + rc, name, bl, type, col_sz = SQLDescribeCol(@handle, c, 1024) + [name.downcase, type, col_sz] + end + end + + def adjust_content(c) + case c.class.to_s + when 'DB2CLI::NullClass' + return nil + when 'DB2CLI::Time' + "%02d:%02d:%02d" % [c.hour, c.minute, c.second] + when 'DB2CLI::Date' + "%04d-%02d-%02d" % [c.year, c.month, c.day] + when 'DB2CLI::Timestamp' + "%04d-%02d-%02d %02d:%02d:%02d" % [c.year, c.month, c.day, c.hour, c.minute, c.second] + else + return c + end + end + end + + class Parameter + attr_reader :type, :size, :decimalDigits + def initialize(type, size, decimalDigits) + @type, @size, @decimalDigits = type, size, decimalDigits + end + end +end +# $Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $ +# +# Copyright (C) 2003-2005 TOMITA Masahiro +# tommy@tmtm.org +# + +class Mysql + + VERSION = "4.0-ruby-0.2.5" + + require "socket" + require "digest/sha1" + + MAX_PACKET_LENGTH = 256*256*256-1 + MAX_ALLOWED_PACKET = 1024*1024*1024 + + MYSQL_UNIX_ADDR = "/tmp/mysql.sock" + MYSQL_PORT = 3306 + PROTOCOL_VERSION = 10 + + # Command + COM_SLEEP = 0 + COM_QUIT = 1 + COM_INIT_DB = 2 + COM_QUERY = 3 + COM_FIELD_LIST = 4 + COM_CREATE_DB = 5 + COM_DROP_DB = 6 + COM_REFRESH = 7 + COM_SHUTDOWN = 8 + COM_STATISTICS = 9 + COM_PROCESS_INFO = 10 + COM_CONNECT = 11 + COM_PROCESS_KILL = 12 + COM_DEBUG = 13 + COM_PING = 14 + COM_TIME = 15 + COM_DELAYED_INSERT = 16 + COM_CHANGE_USER = 17 + COM_BINLOG_DUMP = 18 + COM_TABLE_DUMP = 19 + COM_CONNECT_OUT = 20 + COM_REGISTER_SLAVE = 21 + + # Client flag + CLIENT_LONG_PASSWORD = 1 + CLIENT_FOUND_ROWS = 1 << 1 + CLIENT_LONG_FLAG = 1 << 2 + CLIENT_CONNECT_WITH_DB= 1 << 3 + CLIENT_NO_SCHEMA = 1 << 4 + CLIENT_COMPRESS = 1 << 5 + CLIENT_ODBC = 1 << 6 + CLIENT_LOCAL_FILES = 1 << 7 + CLIENT_IGNORE_SPACE = 1 << 8 + CLIENT_PROTOCOL_41 = 1 << 9 + CLIENT_INTERACTIVE = 1 << 10 + CLIENT_SSL = 1 << 11 + CLIENT_IGNORE_SIGPIPE = 1 << 12 + CLIENT_TRANSACTIONS = 1 << 13 + CLIENT_RESERVED = 1 << 14 + CLIENT_SECURE_CONNECTION = 1 << 15 + CLIENT_CAPABILITIES = CLIENT_LONG_PASSWORD|CLIENT_LONG_FLAG|CLIENT_TRANSACTIONS + PROTO_AUTH41 = CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION + + # Connection Option + OPT_CONNECT_TIMEOUT = 0 + OPT_COMPRESS = 1 + OPT_NAMED_PIPE = 2 + INIT_COMMAND = 3 + READ_DEFAULT_FILE = 4 + READ_DEFAULT_GROUP = 5 + SET_CHARSET_DIR = 6 + SET_CHARSET_NAME = 7 + OPT_LOCAL_INFILE = 8 + + # Server Status + SERVER_STATUS_IN_TRANS = 1 + SERVER_STATUS_AUTOCOMMIT = 2 + + # Refresh parameter + REFRESH_GRANT = 1 + REFRESH_LOG = 2 + REFRESH_TABLES = 4 + REFRESH_HOSTS = 8 + REFRESH_STATUS = 16 + REFRESH_THREADS = 32 + REFRESH_SLAVE = 64 + REFRESH_MASTER = 128 + + def initialize(*args) + @client_flag = 0 + @max_allowed_packet = MAX_ALLOWED_PACKET + @query_with_result = true + @status = :STATUS_READY + if args[0] != :INIT then + real_connect(*args) + end + end + + def real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=nil) + @server_status = SERVER_STATUS_AUTOCOMMIT + if (host == nil or host == "localhost") and defined? UNIXSocket then + unix_socket = socket || ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_ADDR + sock = UNIXSocket::new(unix_socket) + @host_info = Error::err(Error::CR_LOCALHOST_CONNECTION) + @unix_socket = unix_socket + else + sock = TCPSocket::new(host, port||ENV["MYSQL_TCP_PORT"]||(Socket::getservbyname("mysql","tcp") rescue MYSQL_PORT)) + @host_info = sprintf Error::err(Error::CR_TCP_CONNECTION), host + end + @host = host ? host.dup : nil + sock.setsockopt Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true + @net = Net::new sock + + a = read + @protocol_version = a.slice!(0) + @server_version, a = a.split(/\0/,2) + @thread_id, @scramble_buff = a.slice!(0,13).unpack("La8") + if a.size >= 2 then + @server_capabilities, = a.slice!(0,2).unpack("v") + end + if a.size >= 16 then + @server_language, @server_status = a.slice!(0,3).unpack("cv") + end + + flag = 0 if flag == nil + flag |= @client_flag | CLIENT_CAPABILITIES + flag |= CLIENT_CONNECT_WITH_DB if db + + @pre_411 = (0 == @server_capabilities & PROTO_AUTH41) + if @pre_411 + data = Net::int2str(flag)+Net::int3str(@max_allowed_packet)+ + (user||"")+"\0"+ + scramble(passwd, @scramble_buff, @protocol_version==9) + else + dummy, @salt2 = a.unpack("a13a12") + @scramble_buff += @salt2 + flag |= PROTO_AUTH41 + data = Net::int4str(flag) + Net::int4str(@max_allowed_packet) + + ([8] + Array.new(23, 0)).pack("c24") + (user||"")+"\0"+ + scramble41(passwd, @scramble_buff) + end + + if db and @server_capabilities & CLIENT_CONNECT_WITH_DB != 0 + data << "\0" if @pre_411 + data << db + @db = db.dup + end + write data + read + ObjectSpace.define_finalizer(self, Mysql.finalizer(@net)) + self + end + alias :connect :real_connect + + def escape_string(str) + Mysql::escape_string str + end + alias :quote :escape_string + + def get_client_info() + VERSION + end + alias :client_info :get_client_info + + def options(option, arg=nil) + if option == OPT_LOCAL_INFILE then + if arg == false or arg == 0 then + @client_flag &= ~CLIENT_LOCAL_FILES + else + @client_flag |= CLIENT_LOCAL_FILES + end + else + raise "not implemented" + end + end + + def real_query(query) + command COM_QUERY, query, true + read_query_result + self + end + + def use_result() + if @status != :STATUS_GET_RESULT then + error Error::CR_COMMANDS_OUT_OF_SYNC + end + res = Result::new self, @fields, @field_count + @status = :STATUS_USE_RESULT + res + end + + def store_result() + if @status != :STATUS_GET_RESULT then + error Error::CR_COMMANDS_OUT_OF_SYNC + end + @status = :STATUS_READY + data = read_rows @field_count + res = Result::new self, @fields, @field_count, data + @fields = nil + @affected_rows = data.length + res + end + + def change_user(user="", passwd="", db="") + if @pre_411 + data = user+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)+"\0"+db + else + data = user+"\0"+scramble41(passwd, @scramble_buff)+db + end + command COM_CHANGE_USER, data + @user = user + @passwd = passwd + @db = db + end + + def character_set_name() + raise "not implemented" + end + + def close() + @status = :STATUS_READY + command COM_QUIT, nil, true + @net.close + self + end + + def create_db(db) + command COM_CREATE_DB, db + self + end + + def drop_db(db) + command COM_DROP_DB, db + self + end + + def dump_debug_info() + command COM_DEBUG + self + end + + def get_host_info() + @host_info + end + alias :host_info :get_host_info + + def get_proto_info() + @protocol_version + end + alias :proto_info :get_proto_info + + def get_server_info() + @server_version + end + alias :server_info :get_server_info + + def kill(id) + command COM_PROCESS_KILL, Net::int4str(id) + self + end + + def list_dbs(db=nil) + real_query "show databases #{db}" + @status = :STATUS_READY + read_rows(1).flatten + end + + def list_fields(table, field=nil) + command COM_FIELD_LIST, "#{table}\0#{field}", true + if @pre_411 + f = read_rows 6 + else + f = read_rows 7 + end + fields = unpack_fields(f, @server_capabilities & CLIENT_LONG_FLAG != 0) + res = Result::new self, fields, f.length + res.eof = true + res + end + + def list_processes() + data = command COM_PROCESS_INFO + @field_count = get_length data + if @pre_411 + fields = read_rows 5 + else + fields = read_rows 7 + end + @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0) + @status = :STATUS_GET_RESULT + store_result + end + + def list_tables(table=nil) + real_query "show tables #{table}" + @status = :STATUS_READY + read_rows(1).flatten + end + + def ping() + command COM_PING + self + end + + def query(query) + real_query query + if not @query_with_result then + return self + end + if @field_count == 0 then + return nil + end + store_result + end + + def refresh(r) + command COM_REFRESH, r.chr + self + end + + def reload() + refresh REFRESH_GRANT + self + end + + def select_db(db) + command COM_INIT_DB, db + @db = db + self + end + + def shutdown() + command COM_SHUTDOWN + self + end + + def stat() + command COM_STATISTICS + end + + attr_reader :info, :insert_id, :affected_rows, :field_count, :thread_id + attr_accessor :query_with_result, :status + + def read_one_row(field_count) + data = read + if data[0] == 254 and data.length == 1 ## EOF + return + elsif data[0] == 254 and data.length == 5 + return + end + rec = [] + field_count.times do + len = get_length data + if len == nil then + rec << len + else + rec << data.slice!(0,len) + end + end + rec + end + + def skip_result() + if @status == :STATUS_USE_RESULT then + loop do + data = read + break if data[0] == 254 and data.length == 1 + end + @status = :STATUS_READY + end + end + + def inspect() + "#<#{self.class}>" + end + + private + + def read_query_result() + data = read + @field_count = get_length(data) + if @field_count == nil then # LOAD DATA LOCAL INFILE + File::open(data) do |f| + write f.read + end + write "" # mark EOF + data = read + @field_count = get_length(data) + end + if @field_count == 0 then + @affected_rows = get_length(data, true) + @insert_id = get_length(data, true) + if @server_capabilities & CLIENT_TRANSACTIONS != 0 then + a = data.slice!(0,2) + @server_status = a[0]+a[1]*256 + end + if data.size > 0 and get_length(data) then + @info = data + end + else + @extra_info = get_length(data, true) + if @pre_411 + fields = read_rows(5) + else + fields = read_rows(7) + end + @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0) + @status = :STATUS_GET_RESULT + end + self + end + + def unpack_fields(data, long_flag_protocol) + ret = [] + data.each do |f| + if @pre_411 + table = org_table = f[0] + name = f[1] + length = f[2][0]+f[2][1]*256+f[2][2]*256*256 + type = f[3][0] + if long_flag_protocol then + flags = f[4][0]+f[4][1]*256 + decimals = f[4][2] + else + flags = f[4][0] + decimals = f[4][1] + end + def_value = f[5] + max_length = 0 + else + catalog = f[0] + db = f[1] + table = f[2] + org_table = f[3] + name = f[4] + org_name = f[5] + length = f[6][2]+f[6][3]*256+f[6][4]*256*256 + type = f[6][6] + flags = f[6][7]+f[6][8]*256 + decimals = f[6][9] + def_value = "" + max_length = 0 + end + ret << Field::new(table, org_table, name, length, type, flags, decimals, def_value, max_length) + end + ret + end + + def read_rows(field_count) + ret = [] + while rec = read_one_row(field_count) do + ret << rec + end + ret + end + + def get_length(data, longlong=nil) + return if data.length == 0 + c = data.slice!(0) + case c + when 251 + return nil + when 252 + a = data.slice!(0,2) + return a[0]+a[1]*256 + when 253 + a = data.slice!(0,3) + return a[0]+a[1]*256+a[2]*256**2 + when 254 + a = data.slice!(0,8) + if longlong then + return a[0]+a[1]*256+a[2]*256**2+a[3]*256**3+ + a[4]*256**4+a[5]*256**5+a[6]*256**6+a[7]*256**7 + else + return a[0]+a[1]*256+a[2]*256**2+a[3]*256**3 + end + else + c + end + end + + def command(cmd, arg=nil, skip_check=nil) + unless @net then + error Error::CR_SERVER_GONE_ERROR + end + if @status != :STATUS_READY then + error Error::CR_COMMANDS_OUT_OF_SYNC + end + @net.clear + write cmd.chr+(arg||"") + read unless skip_check + end + + def read() + unless @net then + error Error::CR_SERVER_GONE_ERROR + end + a = @net.read + if a[0] == 255 then + if a.length > 3 then + @errno = a[1]+a[2]*256 + @error = a[3 .. -1] + else + @errno = Error::CR_UNKNOWN_ERROR + @error = Error::err @errno + end + raise Error::new(@errno, @error) + end + a + end + + def write(arg) + unless @net then + error Error::CR_SERVER_GONE_ERROR + end + @net.write arg + end + + def hash_password(password) + nr = 1345345333 + add = 7 + nr2 = 0x12345671 + password.each_byte do |i| + next if i == 0x20 or i == 9 + nr ^= (((nr & 63) + add) * i) + (nr << 8) + nr2 += (nr2 << 8) ^ nr + add += i + end + [nr & ((1 << 31) - 1), nr2 & ((1 << 31) - 1)] + end + + def scramble(password, message, old_ver) + return "" if password == nil or password == "" + raise "old version password is not implemented" if old_ver + hash_pass = hash_password password + hash_message = hash_password message + rnd = Random::new hash_pass[0] ^ hash_message[0], hash_pass[1] ^ hash_message[1] + to = [] + 1.upto(message.length) do + to << ((rnd.rnd*31)+64).floor + end + extra = (rnd.rnd*31).floor + to.map! do |t| (t ^ extra).chr end + to.join + end + + def scramble41(password, message) + return 0x00.chr if password.nil? or password.empty? + buf = [0x14] + s1 = Digest::SHA1.new(password).digest + s2 = Digest::SHA1.new(s1).digest + x = Digest::SHA1.new(message + s2).digest + (0..s1.length - 1).each {|i| buf.push(s1[i] ^ x[i])} + buf.pack("C*") + end + + def error(errno) + @errno = errno + @error = Error::err errno + raise Error::new(@errno, @error) + end + + class Result + def initialize(mysql, fields, field_count, data=nil) + @handle = mysql + @fields = fields + @field_count = field_count + @data = data + @current_field = 0 + @current_row = 0 + @eof = false + @row_count = 0 + end + attr_accessor :eof + + def data_seek(n) + @current_row = n + end + + def fetch_field() + return if @current_field >= @field_count + f = @fields[@current_field] + @current_field += 1 + f + end + + def fetch_fields() + @fields + end + + def fetch_field_direct(n) + @fields[n] + end + + def fetch_lengths() + @data ? @data[@current_row].map{|i| i ? i.length : 0} : @lengths + end + + def fetch_row() + if @data then + if @current_row >= @data.length then + @handle.status = :STATUS_READY + return + end + ret = @data[@current_row] + @current_row += 1 + else + return if @eof + ret = @handle.read_one_row @field_count + if ret == nil then + @eof = true + return + end + @lengths = ret.map{|i| i ? i.length : 0} + @row_count += 1 + end + ret + end + + def fetch_hash(with_table=nil) + row = fetch_row + return if row == nil + hash = {} + @fields.each_index do |i| + f = with_table ? @fields[i].table+"."+@fields[i].name : @fields[i].name + hash[f] = row[i] + end + hash + end + + def field_seek(n) + @current_field = n + end + + def field_tell() + @current_field + end + + def free() + @handle.skip_result + @handle = @fields = @data = nil + end + + def num_fields() + @field_count + end + + def num_rows() + @data ? @data.length : @row_count + end + + def row_seek(n) + @current_row = n + end + + def row_tell() + @current_row + end + + def each() + while row = fetch_row do + yield row + end + end + + def each_hash(with_table=nil) + while hash = fetch_hash(with_table) do + yield hash + end + end + + def inspect() + "#<#{self.class}>" + end + + end + + class Field + # Field type + TYPE_DECIMAL = 0 + TYPE_TINY = 1 + TYPE_SHORT = 2 + TYPE_LONG = 3 + TYPE_FLOAT = 4 + TYPE_DOUBLE = 5 + TYPE_NULL = 6 + TYPE_TIMESTAMP = 7 + TYPE_LONGLONG = 8 + TYPE_INT24 = 9 + TYPE_DATE = 10 + TYPE_TIME = 11 + TYPE_DATETIME = 12 + TYPE_YEAR = 13 + TYPE_NEWDATE = 14 + TYPE_ENUM = 247 + TYPE_SET = 248 + TYPE_TINY_BLOB = 249 + TYPE_MEDIUM_BLOB = 250 + TYPE_LONG_BLOB = 251 + TYPE_BLOB = 252 + TYPE_VAR_STRING = 253 + TYPE_STRING = 254 + TYPE_GEOMETRY = 255 + TYPE_CHAR = TYPE_TINY + TYPE_INTERVAL = TYPE_ENUM + + # Flag + NOT_NULL_FLAG = 1 + PRI_KEY_FLAG = 2 + UNIQUE_KEY_FLAG = 4 + MULTIPLE_KEY_FLAG = 8 + BLOB_FLAG = 16 + UNSIGNED_FLAG = 32 + ZEROFILL_FLAG = 64 + BINARY_FLAG = 128 + ENUM_FLAG = 256 + AUTO_INCREMENT_FLAG = 512 + TIMESTAMP_FLAG = 1024 + SET_FLAG = 2048 + NUM_FLAG = 32768 + PART_KEY_FLAG = 16384 + GROUP_FLAG = 32768 + UNIQUE_FLAG = 65536 + + def initialize(table, org_table, name, length, type, flags, decimals, def_value, max_length) + @table = table + @org_table = org_table + @name = name + @length = length + @type = type + @flags = flags + @decimals = decimals + @def = def_value + @max_length = max_length + if (type <= TYPE_INT24 and (type != TYPE_TIMESTAMP or length == 14 or length == 8)) or type == TYPE_YEAR then + @flags |= NUM_FLAG + end + end + attr_reader :table, :org_table, :name, :length, :type, :flags, :decimals, :def, :max_length + + def inspect() + "#<#{self.class}:#{@name}>" + end + end + + class Error < StandardError + # Server Error + ER_HASHCHK = 1000 + ER_NISAMCHK = 1001 + ER_NO = 1002 + ER_YES = 1003 + ER_CANT_CREATE_FILE = 1004 + ER_CANT_CREATE_TABLE = 1005 + ER_CANT_CREATE_DB = 1006 + ER_DB_CREATE_EXISTS = 1007 + ER_DB_DROP_EXISTS = 1008 + ER_DB_DROP_DELETE = 1009 + ER_DB_DROP_RMDIR = 1010 + ER_CANT_DELETE_FILE = 1011 + ER_CANT_FIND_SYSTEM_REC = 1012 + ER_CANT_GET_STAT = 1013 + ER_CANT_GET_WD = 1014 + ER_CANT_LOCK = 1015 + ER_CANT_OPEN_FILE = 1016 + ER_FILE_NOT_FOUND = 1017 + ER_CANT_READ_DIR = 1018 + ER_CANT_SET_WD = 1019 + ER_CHECKREAD = 1020 + ER_DISK_FULL = 1021 + ER_DUP_KEY = 1022 + ER_ERROR_ON_CLOSE = 1023 + ER_ERROR_ON_READ = 1024 + ER_ERROR_ON_RENAME = 1025 + ER_ERROR_ON_WRITE = 1026 + ER_FILE_USED = 1027 + ER_FILSORT_ABORT = 1028 + ER_FORM_NOT_FOUND = 1029 + ER_GET_ERRNO = 1030 + ER_ILLEGAL_HA = 1031 + ER_KEY_NOT_FOUND = 1032 + ER_NOT_FORM_FILE = 1033 + ER_NOT_KEYFILE = 1034 + ER_OLD_KEYFILE = 1035 + ER_OPEN_AS_READONLY = 1036 + ER_OUTOFMEMORY = 1037 + ER_OUT_OF_SORTMEMORY = 1038 + ER_UNEXPECTED_EOF = 1039 + ER_CON_COUNT_ERROR = 1040 + ER_OUT_OF_RESOURCES = 1041 + ER_BAD_HOST_ERROR = 1042 + ER_HANDSHAKE_ERROR = 1043 + ER_DBACCESS_DENIED_ERROR = 1044 + ER_ACCESS_DENIED_ERROR = 1045 + ER_NO_DB_ERROR = 1046 + ER_UNKNOWN_COM_ERROR = 1047 + ER_BAD_NULL_ERROR = 1048 + ER_BAD_DB_ERROR = 1049 + ER_TABLE_EXISTS_ERROR = 1050 + ER_BAD_TABLE_ERROR = 1051 + ER_NON_UNIQ_ERROR = 1052 + ER_SERVER_SHUTDOWN = 1053 + ER_BAD_FIELD_ERROR = 1054 + ER_WRONG_FIELD_WITH_GROUP = 1055 + ER_WRONG_GROUP_FIELD = 1056 + ER_WRONG_SUM_SELECT = 1057 + ER_WRONG_VALUE_COUNT = 1058 + ER_TOO_LONG_IDENT = 1059 + ER_DUP_FIELDNAME = 1060 + ER_DUP_KEYNAME = 1061 + ER_DUP_ENTRY = 1062 + ER_WRONG_FIELD_SPEC = 1063 + ER_PARSE_ERROR = 1064 + ER_EMPTY_QUERY = 1065 + ER_NONUNIQ_TABLE = 1066 + ER_INVALID_DEFAULT = 1067 + ER_MULTIPLE_PRI_KEY = 1068 + ER_TOO_MANY_KEYS = 1069 + ER_TOO_MANY_KEY_PARTS = 1070 + ER_TOO_LONG_KEY = 1071 + ER_KEY_COLUMN_DOES_NOT_EXITS = 1072 + ER_BLOB_USED_AS_KEY = 1073 + ER_TOO_BIG_FIELDLENGTH = 1074 + ER_WRONG_AUTO_KEY = 1075 + ER_READY = 1076 + ER_NORMAL_SHUTDOWN = 1077 + ER_GOT_SIGNAL = 1078 + ER_SHUTDOWN_COMPLETE = 1079 + ER_FORCING_CLOSE = 1080 + ER_IPSOCK_ERROR = 1081 + ER_NO_SUCH_INDEX = 1082 + ER_WRONG_FIELD_TERMINATORS = 1083 + ER_BLOBS_AND_NO_TERMINATED = 1084 + ER_TEXTFILE_NOT_READABLE = 1085 + ER_FILE_EXISTS_ERROR = 1086 + ER_LOAD_INFO = 1087 + ER_ALTER_INFO = 1088 + ER_WRONG_SUB_KEY = 1089 + ER_CANT_REMOVE_ALL_FIELDS = 1090 + ER_CANT_DROP_FIELD_OR_KEY = 1091 + ER_INSERT_INFO = 1092 + ER_INSERT_TABLE_USED = 1093 + ER_NO_SUCH_THREAD = 1094 + ER_KILL_DENIED_ERROR = 1095 + ER_NO_TABLES_USED = 1096 + ER_TOO_BIG_SET = 1097 + ER_NO_UNIQUE_LOGFILE = 1098 + ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099 + ER_TABLE_NOT_LOCKED = 1100 + ER_BLOB_CANT_HAVE_DEFAULT = 1101 + ER_WRONG_DB_NAME = 1102 + ER_WRONG_TABLE_NAME = 1103 + ER_TOO_BIG_SELECT = 1104 + ER_UNKNOWN_ERROR = 1105 + ER_UNKNOWN_PROCEDURE = 1106 + ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107 + ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108 + ER_UNKNOWN_TABLE = 1109 + ER_FIELD_SPECIFIED_TWICE = 1110 + ER_INVALID_GROUP_FUNC_USE = 1111 + ER_UNSUPPORTED_EXTENSION = 1112 + ER_TABLE_MUST_HAVE_COLUMNS = 1113 + ER_RECORD_FILE_FULL = 1114 + ER_UNKNOWN_CHARACTER_SET = 1115 + ER_TOO_MANY_TABLES = 1116 + ER_TOO_MANY_FIELDS = 1117 + ER_TOO_BIG_ROWSIZE = 1118 + ER_STACK_OVERRUN = 1119 + ER_WRONG_OUTER_JOIN = 1120 + ER_NULL_COLUMN_IN_INDEX = 1121 + ER_CANT_FIND_UDF = 1122 + ER_CANT_INITIALIZE_UDF = 1123 + ER_UDF_NO_PATHS = 1124 + ER_UDF_EXISTS = 1125 + ER_CANT_OPEN_LIBRARY = 1126 + ER_CANT_FIND_DL_ENTRY = 1127 + ER_FUNCTION_NOT_DEFINED = 1128 + ER_HOST_IS_BLOCKED = 1129 + ER_HOST_NOT_PRIVILEGED = 1130 + ER_PASSWORD_ANONYMOUS_USER = 1131 + ER_PASSWORD_NOT_ALLOWED = 1132 + ER_PASSWORD_NO_MATCH = 1133 + ER_UPDATE_INFO = 1134 + ER_CANT_CREATE_THREAD = 1135 + ER_WRONG_VALUE_COUNT_ON_ROW = 1136 + ER_CANT_REOPEN_TABLE = 1137 + ER_INVALID_USE_OF_NULL = 1138 + ER_REGEXP_ERROR = 1139 + ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140 + ER_NONEXISTING_GRANT = 1141 + ER_TABLEACCESS_DENIED_ERROR = 1142 + ER_COLUMNACCESS_DENIED_ERROR = 1143 + ER_ILLEGAL_GRANT_FOR_TABLE = 1144 + ER_GRANT_WRONG_HOST_OR_USER = 1145 + ER_NO_SUCH_TABLE = 1146 + ER_NONEXISTING_TABLE_GRANT = 1147 + ER_NOT_ALLOWED_COMMAND = 1148 + ER_SYNTAX_ERROR = 1149 + ER_DELAYED_CANT_CHANGE_LOCK = 1150 + ER_TOO_MANY_DELAYED_THREADS = 1151 + ER_ABORTING_CONNECTION = 1152 + ER_NET_PACKET_TOO_LARGE = 1153 + ER_NET_READ_ERROR_FROM_PIPE = 1154 + ER_NET_FCNTL_ERROR = 1155 + ER_NET_PACKETS_OUT_OF_ORDER = 1156 + ER_NET_UNCOMPRESS_ERROR = 1157 + ER_NET_READ_ERROR = 1158 + ER_NET_READ_INTERRUPTED = 1159 + ER_NET_ERROR_ON_WRITE = 1160 + ER_NET_WRITE_INTERRUPTED = 1161 + ER_TOO_LONG_STRING = 1162 + ER_TABLE_CANT_HANDLE_BLOB = 1163 + ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164 + ER_DELAYED_INSERT_TABLE_LOCKED = 1165 + ER_WRONG_COLUMN_NAME = 1166 + ER_WRONG_KEY_COLUMN = 1167 + ER_WRONG_MRG_TABLE = 1168 + ER_DUP_UNIQUE = 1169 + ER_BLOB_KEY_WITHOUT_LENGTH = 1170 + ER_PRIMARY_CANT_HAVE_NULL = 1171 + ER_TOO_MANY_ROWS = 1172 + ER_REQUIRES_PRIMARY_KEY = 1173 + ER_NO_RAID_COMPILED = 1174 + ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175 + ER_KEY_DOES_NOT_EXITS = 1176 + ER_CHECK_NO_SUCH_TABLE = 1177 + ER_CHECK_NOT_IMPLEMENTED = 1178 + ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179 + ER_ERROR_DURING_COMMIT = 1180 + ER_ERROR_DURING_ROLLBACK = 1181 + ER_ERROR_DURING_FLUSH_LOGS = 1182 + ER_ERROR_DURING_CHECKPOINT = 1183 + ER_NEW_ABORTING_CONNECTION = 1184 + ER_DUMP_NOT_IMPLEMENTED = 1185 + ER_FLUSH_MASTER_BINLOG_CLOSED = 1186 + ER_INDEX_REBUILD = 1187 + ER_MASTER = 1188 + ER_MASTER_NET_READ = 1189 + ER_MASTER_NET_WRITE = 1190 + ER_FT_MATCHING_KEY_NOT_FOUND = 1191 + ER_LOCK_OR_ACTIVE_TRANSACTION = 1192 + ER_UNKNOWN_SYSTEM_VARIABLE = 1193 + ER_CRASHED_ON_USAGE = 1194 + ER_CRASHED_ON_REPAIR = 1195 + ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196 + ER_TRANS_CACHE_FULL = 1197 + ER_SLAVE_MUST_STOP = 1198 + ER_SLAVE_NOT_RUNNING = 1199 + ER_BAD_SLAVE = 1200 + ER_MASTER_INFO = 1201 + ER_SLAVE_THREAD = 1202 + ER_TOO_MANY_USER_CONNECTIONS = 1203 + ER_SET_CONSTANTS_ONLY = 1204 + ER_LOCK_WAIT_TIMEOUT = 1205 + ER_LOCK_TABLE_FULL = 1206 + ER_READ_ONLY_TRANSACTION = 1207 + ER_DROP_DB_WITH_READ_LOCK = 1208 + ER_CREATE_DB_WITH_READ_LOCK = 1209 + ER_WRONG_ARGUMENTS = 1210 + ER_NO_PERMISSION_TO_CREATE_USER = 1211 + ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212 + ER_LOCK_DEADLOCK = 1213 + ER_TABLE_CANT_HANDLE_FULLTEXT = 1214 + ER_CANNOT_ADD_FOREIGN = 1215 + ER_NO_REFERENCED_ROW = 1216 + ER_ROW_IS_REFERENCED = 1217 + ER_CONNECT_TO_MASTER = 1218 + ER_QUERY_ON_MASTER = 1219 + ER_ERROR_WHEN_EXECUTING_COMMAND = 1220 + ER_WRONG_USAGE = 1221 + ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222 + ER_CANT_UPDATE_WITH_READLOCK = 1223 + ER_MIXING_NOT_ALLOWED = 1224 + ER_DUP_ARGUMENT = 1225 + ER_USER_LIMIT_REACHED = 1226 + ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227 + ER_LOCAL_VARIABLE = 1228 + ER_GLOBAL_VARIABLE = 1229 + ER_NO_DEFAULT = 1230 + ER_WRONG_VALUE_FOR_VAR = 1231 + ER_WRONG_TYPE_FOR_VAR = 1232 + ER_VAR_CANT_BE_READ = 1233 + ER_CANT_USE_OPTION_HERE = 1234 + ER_NOT_SUPPORTED_YET = 1235 + ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236 + ER_SLAVE_IGNORED_TABLE = 1237 + ER_ERROR_MESSAGES = 238 + + # Client Error + CR_MIN_ERROR = 2000 + CR_MAX_ERROR = 2999 + CR_UNKNOWN_ERROR = 2000 + CR_SOCKET_CREATE_ERROR = 2001 + CR_CONNECTION_ERROR = 2002 + CR_CONN_HOST_ERROR = 2003 + CR_IPSOCK_ERROR = 2004 + CR_UNKNOWN_HOST = 2005 + CR_SERVER_GONE_ERROR = 2006 + CR_VERSION_ERROR = 2007 + CR_OUT_OF_MEMORY = 2008 + CR_WRONG_HOST_INFO = 2009 + CR_LOCALHOST_CONNECTION = 2010 + CR_TCP_CONNECTION = 2011 + CR_SERVER_HANDSHAKE_ERR = 2012 + CR_SERVER_LOST = 2013 + CR_COMMANDS_OUT_OF_SYNC = 2014 + CR_NAMEDPIPE_CONNECTION = 2015 + CR_NAMEDPIPEWAIT_ERROR = 2016 + CR_NAMEDPIPEOPEN_ERROR = 2017 + CR_NAMEDPIPESETSTATE_ERROR = 2018 + CR_CANT_READ_CHARSET = 2019 + CR_NET_PACKET_TOO_LARGE = 2020 + CR_EMBEDDED_CONNECTION = 2021 + CR_PROBE_SLAVE_STATUS = 2022 + CR_PROBE_SLAVE_HOSTS = 2023 + CR_PROBE_SLAVE_CONNECT = 2024 + CR_PROBE_MASTER_CONNECT = 2025 + CR_SSL_CONNECTION_ERROR = 2026 + CR_MALFORMED_PACKET = 2027 + + CLIENT_ERRORS = [ + "Unknown MySQL error", + "Can't create UNIX socket (%d)", + "Can't connect to local MySQL server through socket '%-.64s' (%d)", + "Can't connect to MySQL server on '%-.64s' (%d)", + "Can't create TCP/IP socket (%d)", + "Unknown MySQL Server Host '%-.64s' (%d)", + "MySQL server has gone away", + "Protocol mismatch. Server Version = %d Client Version = %d", + "MySQL client run out of memory", + "Wrong host info", + "Localhost via UNIX socket", + "%-.64s via TCP/IP", + "Error in server handshake", + "Lost connection to MySQL server during query", + "Commands out of sync; You can't run this command now", + "%-.64s via named pipe", + "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)", + "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)", + "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)", + "Can't initialize character set %-.64s (path: %-.64s)", + "Got packet bigger than 'max_allowed_packet'", + "Embedded server", + "Error on SHOW SLAVE STATUS:", + "Error on SHOW SLAVE HOSTS:", + "Error connecting to slave:", + "Error connecting to master:", + "SSL connection error", + "Malformed packet" + ] + + def initialize(errno, error) + @errno = errno + @error = error + super error + end + attr_reader :errno, :error + + def Error::err(errno) + CLIENT_ERRORS[errno - Error::CR_MIN_ERROR] + end + end + + class Net + def initialize(sock) + @sock = sock + @pkt_nr = 0 + end + + def clear() + @pkt_nr = 0 + end + + def read() + buf = [] + len = nil + @sock.sync = false + while len == nil or len == MAX_PACKET_LENGTH do + a = @sock.read(4) + len = a[0]+a[1]*256+a[2]*256*256 + pkt_nr = a[3] + if @pkt_nr != pkt_nr then + raise "Packets out of order: #{@pkt_nr}<>#{pkt_nr}" + end + @pkt_nr = @pkt_nr + 1 & 0xff + buf << @sock.read(len) + end + @sock.sync = true + buf.join + rescue + errno = Error::CR_SERVER_LOST + raise Error::new(errno, Error::err(errno)) + end + + def write(data) + if data.is_a? Array then + data = data.join + end + @sock.sync = false + ptr = 0 + while data.length >= MAX_PACKET_LENGTH do + @sock.write Net::int3str(MAX_PACKET_LENGTH)+@pkt_nr.chr+data[ptr, MAX_PACKET_LENGTH] + @pkt_nr = @pkt_nr + 1 & 0xff + ptr += MAX_PACKET_LENGTH + end + @sock.write Net::int3str(data.length-ptr)+@pkt_nr.chr+data[ptr .. -1] + @pkt_nr = @pkt_nr + 1 & 0xff + @sock.sync = true + @sock.flush + rescue + errno = Error::CR_SERVER_LOST + raise Error::new(errno, Error::err(errno)) + end + + def close() + @sock.close + end + + def Net::int2str(n) + [n].pack("v") + end + + def Net::int3str(n) + [n%256, n>>8].pack("cv") + end + + def Net::int4str(n) + [n].pack("V") + end + + end + + class Random + def initialize(seed1, seed2) + @max_value = 0x3FFFFFFF + @seed1 = seed1 % @max_value + @seed2 = seed2 % @max_value + end + + def rnd() + @seed1 = (@seed1*3+@seed2) % @max_value + @seed2 = (@seed1+@seed2+33) % @max_value + @seed1.to_f / @max_value + end + end + +end + +class << Mysql + def init() + Mysql::new :INIT + end + + def real_connect(*args) + Mysql::new(*args) + end + alias :connect :real_connect + + def finalizer(net) + proc { + net.clear + net.write Mysql::COM_QUIT.chr + } + end + + def escape_string(str) + str.gsub(/([\0\n\r\032\'\"\\])/) do + case $1 + when "\0" then "\\0" + when "\n" then "\\n" + when "\r" then "\\r" + when "\032" then "\\Z" + else "\\"+$1 + end + end + end + alias :quote :escape_string + + def get_client_info() + Mysql::VERSION + end + alias :client_info :get_client_info + + def debug(str) + raise "not implemented" + end +end + +# +# for compatibility +# + +MysqlRes = Mysql::Result +MysqlField = Mysql::Field +MysqlError = Mysql::Error +# :title: Transaction::Simple -- Active Object Transaction Support for Ruby +# :main: Transaction::Simple +# +# == Licence +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +#-- +# Transaction::Simple +# Simple object transaction support for Ruby +# Version 1.3.0 +# +# Copyright (c) 2003 - 2005 Austin Ziegler +# +# $Id: simple.rb,v 1.5 2005/05/05 16:16:49 austin Exp $ +#++ + # The "Transaction" namespace can be used for additional transaction + # support objects and modules. +module Transaction + # A standard exception for transaction errors. + class TransactionError < StandardError; end + # The TransactionAborted exception is used to indicate when a + # transaction has been aborted in the block form. + class TransactionAborted < Exception; end + # The TransactionCommitted exception is used to indicate when a + # transaction has been committed in the block form. + class TransactionCommitted < Exception; end + + te = "Transaction Error: %s" + + Messages = { + :bad_debug_object => + te % "the transaction debug object must respond to #<<.", + :unique_names => + te % "named transactions must be unique.", + :no_transaction_open => + te % "no transaction open.", + :cannot_rewind_no_transaction => + te % "cannot rewind; there is no current transaction.", + :cannot_rewind_named_transaction => + te % "cannot rewind to transaction %s because it does not exist.", + :cannot_rewind_transaction_before_block => + te % "cannot rewind a transaction started before the execution block.", + :cannot_abort_no_transaction => + te % "cannot abort; there is no current transaction.", + :cannot_abort_transaction_before_block => + te % "cannot abort a transaction started before the execution block.", + :cannot_abort_named_transaction => + te % "cannot abort nonexistant transaction %s.", + :cannot_commit_no_transaction => + te % "cannot commit; there is no current transaction.", + :cannot_commit_transaction_before_block => + te % "cannot commit a transaction started before the execution block.", + :cannot_commit_named_transaction => + te % "cannot commit nonexistant transaction %s.", + :cannot_start_empty_block_transaction => + te % "cannot start a block transaction with no objects.", + :cannot_obtain_transaction_lock => + te % "cannot obtain transaction lock for #%s.", + } + + # = Transaction::Simple for Ruby + # Simple object transaction support for Ruby + # + # == Introduction + # Transaction::Simple provides a generic way to add active transaction + # support to objects. The transaction methods added by this module will + # work with most objects, excluding those that cannot be + # <i>Marshal</i>ed (bindings, procedure objects, IO instances, or + # singleton objects). + # + # The transactions supported by Transaction::Simple are not backed + # transactions; they are not associated with any sort of data store. + # They are "live" transactions occurring in memory and in the object + # itself. This is to allow "test" changes to be made to an object + # before making the changes permanent. + # + # Transaction::Simple can handle an "infinite" number of transaction + # levels (limited only by memory). If I open two transactions, commit + # the second, but abort the first, the object will revert to the + # original version. + # + # Transaction::Simple supports "named" transactions, so that multiple + # levels of transactions can be committed, aborted, or rewound by + # referring to the appropriate name of the transaction. Names may be any + # object *except* +nil+. As with Hash keys, String names will be + # duplicated and frozen before using. + # + # Copyright:: Copyright © 2003 - 2005 by Austin Ziegler + # Version:: 1.3.0 + # Licence:: MIT-Style + # + # Thanks to David Black for help with the initial concept that led to + # this library. + # + # == Usage + # include 'transaction/simple' + # + # v = "Hello, you." # -> "Hello, you." + # v.extend(Transaction::Simple) # -> "Hello, you." + # + # v.start_transaction # -> ... (a Marshal string) + # v.transaction_open? # -> true + # v.gsub!(/you/, "world") # -> "Hello, world." + # + # v.rewind_transaction # -> "Hello, you." + # v.transaction_open? # -> true + # + # v.gsub!(/you/, "HAL") # -> "Hello, HAL." + # v.abort_transaction # -> "Hello, you." + # v.transaction_open? # -> false + # + # v.start_transaction # -> ... (a Marshal string) + # v.start_transaction # -> ... (a Marshal string) + # + # v.transaction_open? # -> true + # v.gsub!(/you/, "HAL") # -> "Hello, HAL." + # + # v.commit_transaction # -> "Hello, HAL." + # v.transaction_open? # -> true + # v.abort_transaction # -> "Hello, you." + # v.transaction_open? # -> false + # + # == Named Transaction Usage + # v = "Hello, you." # -> "Hello, you." + # v.extend(Transaction::Simple) # -> "Hello, you." + # + # v.start_transaction(:first) # -> ... (a Marshal string) + # v.transaction_open? # -> true + # v.transaction_open?(:first) # -> true + # v.transaction_open?(:second) # -> false + # v.gsub!(/you/, "world") # -> "Hello, world." + # + # v.start_transaction(:second) # -> ... (a Marshal string) + # v.gsub!(/world/, "HAL") # -> "Hello, HAL." + # v.rewind_transaction(:first) # -> "Hello, you." + # v.transaction_open? # -> true + # v.transaction_open?(:first) # -> true + # v.transaction_open?(:second) # -> false + # + # v.gsub!(/you/, "world") # -> "Hello, world." + # v.start_transaction(:second) # -> ... (a Marshal string) + # v.gsub!(/world/, "HAL") # -> "Hello, HAL." + # v.transaction_name # -> :second + # v.abort_transaction(:first) # -> "Hello, you." + # v.transaction_open? # -> false + # + # v.start_transaction(:first) # -> ... (a Marshal string) + # v.gsub!(/you/, "world") # -> "Hello, world." + # v.start_transaction(:second) # -> ... (a Marshal string) + # v.gsub!(/world/, "HAL") # -> "Hello, HAL." + # + # v.commit_transaction(:first) # -> "Hello, HAL." + # v.transaction_open? # -> false + # + # == Block Usage + # v = "Hello, you." # -> "Hello, you." + # Transaction::Simple.start(v) do |tv| + # # v has been extended with Transaction::Simple and an unnamed + # # transaction has been started. + # tv.transaction_open? # -> true + # tv.gsub!(/you/, "world") # -> "Hello, world." + # + # tv.rewind_transaction # -> "Hello, you." + # tv.transaction_open? # -> true + # + # tv.gsub!(/you/, "HAL") # -> "Hello, HAL." + # # The following breaks out of the transaction block after + # # aborting the transaction. + # tv.abort_transaction # -> "Hello, you." + # end + # # v still has Transaction::Simple applied from here on out. + # v.transaction_open? # -> false + # + # Transaction::Simple.start(v) do |tv| + # tv.start_transaction # -> ... (a Marshal string) + # + # tv.transaction_open? # -> true + # tv.gsub!(/you/, "HAL") # -> "Hello, HAL." + # + # # If #commit_transaction were called without having started a + # # second transaction, then it would break out of the transaction + # # block after committing the transaction. + # tv.commit_transaction # -> "Hello, HAL." + # tv.transaction_open? # -> true + # tv.abort_transaction # -> "Hello, you." + # end + # v.transaction_open? # -> false + # + # == Named Transaction Usage + # v = "Hello, you." # -> "Hello, you." + # v.extend(Transaction::Simple) # -> "Hello, you." + # + # v.start_transaction(:first) # -> ... (a Marshal string) + # v.transaction_open? # -> true + # v.transaction_open?(:first) # -> true + # v.transaction_open?(:second) # -> false + # v.gsub!(/you/, "world") # -> "Hello, world." + # + # v.start_transaction(:second) # -> ... (a Marshal string) + # v.gsub!(/world/, "HAL") # -> "Hello, HAL." + # v.rewind_transaction(:first) # -> "Hello, you." + # v.transaction_open? # -> true + # v.transaction_open?(:first) # -> true + # v.transaction_open?(:second) # -> false + # + # v.gsub!(/you/, "world") # -> "Hello, world." + # v.start_transaction(:second) # -> ... (a Marshal string) + # v.gsub!(/world/, "HAL") # -> "Hello, HAL." + # v.transaction_name # -> :second + # v.abort_transaction(:first) # -> "Hello, you." + # v.transaction_open? # -> false + # + # v.start_transaction(:first) # -> ... (a Marshal string) + # v.gsub!(/you/, "world") # -> "Hello, world." + # v.start_transaction(:second) # -> ... (a Marshal string) + # v.gsub!(/world/, "HAL") # -> "Hello, HAL." + # + # v.commit_transaction(:first) # -> "Hello, HAL." + # v.transaction_open? # -> false + # + # == Thread Safety + # Threadsafe version of Transaction::Simple and + # Transaction::Simple::Group exist; these are loaded from + # 'transaction/simple/threadsafe' and + # 'transaction/simple/threadsafe/group', respectively, and are + # represented in Ruby code as Transaction::Simple::ThreadSafe and + # Transaction::Simple::ThreadSafe::Group, respectively. + # + # == Contraindications + # While Transaction::Simple is very useful, it has some severe + # limitations that must be understood. Transaction::Simple: + # + # * uses Marshal. Thus, any object which cannot be <i>Marshal</i>ed + # cannot use Transaction::Simple. In my experience, this affects + # singleton objects more often than any other object. It may be that + # Ruby 2.0 will solve this problem. + # * does not manage resources. Resources external to the object and its + # instance variables are not managed at all. However, all instance + # variables and objects "belonging" to those instance variables are + # managed. If there are object reference counts to be handled, + # Transaction::Simple will probably cause problems. + # * is not inherently thread-safe. In the ACID ("atomic, consistent, + # isolated, durable") test, Transaction::Simple provides CD, but it is + # up to the user of Transaction::Simple to provide isolation and + # atomicity. Transactions should be considered "critical sections" in + # multi-threaded applications. If thread safety and atomicity is + # absolutely required, use Transaction::Simple::ThreadSafe, which uses + # a Mutex object to synchronize the accesses on the object during the + # transaction operations. + # * does not necessarily maintain Object#__id__ values on rewind or + # abort. This may change for future versions that will be Ruby 1.8 or + # better *only*. Certain objects that support #replace will maintain + # Object#__id__. + # * Can be a memory hog if you use many levels of transactions on many + # objects. + # + module Simple + TRANSACTION_SIMPLE_VERSION = '1.3.0' + + # Sets the Transaction::Simple debug object. It must respond to #<<. + # Sets the transaction debug object. Debugging will be performed + # automatically if there's a debug object. The generic transaction + # error class. + def self.debug_io=(io) + if io.nil? + @tdi = nil + @debugging = false + else + unless io.respond_to?(:<<) + raise TransactionError, Messages[:bad_debug_object] + end + @tdi = io + @debugging = true + end + end + + # Returns +true+ if we are debugging. + def self.debugging? + @debugging + end + + # Returns the Transaction::Simple debug object. It must respond to + # #<<. + def self.debug_io + @tdi ||= "" + @tdi + end + + # If +name+ is +nil+ (default), then returns +true+ if there is + # currently a transaction open. + # + # If +name+ is specified, then returns +true+ if there is currently a + # transaction that responds to +name+ open. + def transaction_open?(name = nil) + if name.nil? + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "Transaction " << + "[#{(@__transaction_checkpoint__.nil?) ? 'closed' : 'open'}]\n" + end + return (not @__transaction_checkpoint__.nil?) + else + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "Transaction(#{name.inspect}) " << + "[#{(@__transaction_checkpoint__.nil?) ? 'closed' : 'open'}]\n" + end + return ((not @__transaction_checkpoint__.nil?) and @__transaction_names__.include?(name)) + end + end + + # Returns the current name of the transaction. Transactions not + # explicitly named are named +nil+. + def transaction_name + if @__transaction_checkpoint__.nil? + raise TransactionError, Messages[:no_transaction_open] + end + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'|' * @__transaction_level__} " << + "Transaction Name: #{@__transaction_names__[-1].inspect}\n" + end + if @__transaction_names__[-1].kind_of?(String) + @__transaction_names__[-1].dup + else + @__transaction_names__[-1] + end + end + + # Starts a transaction. Stores the current object state. If a + # transaction name is specified, the transaction will be named. + # Transaction names must be unique. Transaction names of +nil+ will be + # treated as unnamed transactions. + def start_transaction(name = nil) + @__transaction_level__ ||= 0 + @__transaction_names__ ||= [] + + if name.nil? + @__transaction_names__ << nil + ss = "" if Transaction::Simple.debugging? + else + if @__transaction_names__.include?(name) + raise TransactionError, Messages[:unique_names] + end + name = name.dup.freeze if name.kind_of?(String) + @__transaction_names__ << name + ss = "(#{name.inspect})" if Transaction::Simple.debugging? + end + + @__transaction_level__ += 1 + + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'>' * @__transaction_level__} " << + "Start Transaction#{ss}\n" + end + + @__transaction_checkpoint__ = Marshal.dump(self) + end + + # Rewinds the transaction. If +name+ is specified, then the + # intervening transactions will be aborted and the named transaction + # will be rewound. Otherwise, only the current transaction is rewound. + def rewind_transaction(name = nil) + if @__transaction_checkpoint__.nil? + raise TransactionError, Messages[:cannot_rewind_no_transaction] + end + + # Check to see if we are trying to rewind a transaction that is + # outside of the current transaction block. + if @__transaction_block__ and name + nix = @__transaction_names__.index(name) + 1 + if nix < @__transaction_block__ + raise TransactionError, Messages[:cannot_rewind_transaction_before_block] + end + end + + if name.nil? + __rewind_this_transaction + ss = "" if Transaction::Simple.debugging? + else + unless @__transaction_names__.include?(name) + raise TransactionError, Messages[:cannot_rewind_named_transaction] % name.inspect + end + ss = "(#{name})" if Transaction::Simple.debugging? + + while @__transaction_names__[-1] != name + @__transaction_checkpoint__ = __rewind_this_transaction + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'|' * @__transaction_level__} " << + "Rewind Transaction#{ss}\n" + end + @__transaction_level__ -= 1 + @__transaction_names__.pop + end + __rewind_this_transaction + end + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'|' * @__transaction_level__} " << + "Rewind Transaction#{ss}\n" + end + self + end + + # Aborts the transaction. Resets the object state to what it was + # before the transaction was started and closes the transaction. If + # +name+ is specified, then the intervening transactions and the named + # transaction will be aborted. Otherwise, only the current transaction + # is aborted. + # + # If the current or named transaction has been started by a block + # (Transaction::Simple.start), then the execution of the block will be + # halted with +break+ +self+. + def abort_transaction(name = nil) + if @__transaction_checkpoint__.nil? + raise TransactionError, Messages[:cannot_abort_no_transaction] + end + + # Check to see if we are trying to abort a transaction that is + # outside of the current transaction block. Otherwise, raise + # TransactionAborted if they are the same. + if @__transaction_block__ and name + nix = @__transaction_names__.index(name) + 1 + if nix < @__transaction_block__ + raise TransactionError, Messages[:cannot_abort_transaction_before_block] + end + + raise TransactionAborted if @__transaction_block__ == nix + end + + raise TransactionAborted if @__transaction_block__ == @__transaction_level__ + + if name.nil? + __abort_transaction(name) + else + unless @__transaction_names__.include?(name) + raise TransactionError, Messages[:cannot_abort_named_transaction] % name.inspect + end + __abort_transaction(name) while @__transaction_names__.include?(name) + end + self + end + + # If +name+ is +nil+ (default), the current transaction level is + # closed out and the changes are committed. + # + # If +name+ is specified and +name+ is in the list of named + # transactions, then all transactions are closed and committed until + # the named transaction is reached. + def commit_transaction(name = nil) + if @__transaction_checkpoint__.nil? + raise TransactionError, Messages[:cannot_commit_no_transaction] + end + @__transaction_block__ ||= nil + + # Check to see if we are trying to commit a transaction that is + # outside of the current transaction block. Otherwise, raise + # TransactionCommitted if they are the same. + if @__transaction_block__ and name + nix = @__transaction_names__.index(name) + 1 + if nix < @__transaction_block__ + raise TransactionError, Messages[:cannot_commit_transaction_before_block] + end + + raise TransactionCommitted if @__transaction_block__ == nix + end + + raise TransactionCommitted if @__transaction_block__ == @__transaction_level__ + + if name.nil? + ss = "" if Transaction::Simple.debugging? + __commit_transaction + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << + "Commit Transaction#{ss}\n" + end + else + unless @__transaction_names__.include?(name) + raise TransactionError, Messages[:cannot_commit_named_transaction] % name.inspect + end + ss = "(#{name})" if Transaction::Simple.debugging? + + while @__transaction_names__[-1] != name + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << + "Commit Transaction#{ss}\n" + end + __commit_transaction + end + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << + "Commit Transaction#{ss}\n" + end + __commit_transaction + end + + self + end + + # Alternative method for calling the transaction methods. An optional + # name can be specified for named transaction support. + # + # #transaction(:start):: #start_transaction + # #transaction(:rewind):: #rewind_transaction + # #transaction(:abort):: #abort_transaction + # #transaction(:commit):: #commit_transaction + # #transaction(:name):: #transaction_name + # #transaction:: #transaction_open? + def transaction(action = nil, name = nil) + case action + when :start + start_transaction(name) + when :rewind + rewind_transaction(name) + when :abort + abort_transaction(name) + when :commit + commit_transaction(name) + when :name + transaction_name + when nil + transaction_open?(name) + end + end + + # Allows specific variables to be excluded from transaction support. + # Must be done after extending the object but before starting the + # first transaction on the object. + # + # vv.transaction_exclusions << "@io" + def transaction_exclusions + @transaction_exclusions ||= [] + end + + class << self + def __common_start(name, vars, &block) + if vars.empty? + raise TransactionError, Messages[:cannot_start_empty_block_transaction] + end + + if block + begin + vlevel = {} + + vars.each do |vv| + vv.extend(Transaction::Simple) + vv.start_transaction(name) + vlevel[vv.__id__] = vv.instance_variable_get(:@__transaction_level__) + vv.instance_variable_set(:@__transaction_block__, vlevel[vv.__id__]) + end + + yield(*vars) + rescue TransactionAborted + vars.each do |vv| + if name.nil? and vv.transaction_open? + loop do + tlevel = vv.instance_variable_get(:@__transaction_level__) || -1 + vv.instance_variable_set(:@__transaction_block__, -1) + break if tlevel < vlevel[vv.__id__] + vv.abort_transaction if vv.transaction_open? + end + elsif vv.transaction_open?(name) + vv.instance_variable_set(:@__transaction_block__, -1) + vv.abort_transaction(name) + end + end + rescue TransactionCommitted + nil + ensure + vars.each do |vv| + if name.nil? and vv.transaction_open? + loop do + tlevel = vv.instance_variable_get(:@__transaction_level__) || -1 + break if tlevel < vlevel[vv.__id__] + vv.instance_variable_set(:@__transaction_block__, -1) + vv.commit_transaction if vv.transaction_open? + end + elsif vv.transaction_open?(name) + vv.instance_variable_set(:@__transaction_block__, -1) + vv.commit_transaction(name) + end + end + end + else + vars.each do |vv| + vv.extend(Transaction::Simple) + vv.start_transaction(name) + end + end + end + private :__common_start + + def start_named(name, *vars, &block) + __common_start(name, vars, &block) + end + + def start(*vars, &block) + __common_start(nil, vars, &block) + end + end + + def __abort_transaction(name = nil) #:nodoc: + @__transaction_checkpoint__ = __rewind_this_transaction + + if name.nil? + ss = "" if Transaction::Simple.debugging? + else + ss = "(#{name.inspect})" if Transaction::Simple.debugging? + end + + if Transaction::Simple.debugging? + Transaction::Simple.debug_io << "#{'<' * @__transaction_level__} " << + "Abort Transaction#{ss}\n" + end + @__transaction_level__ -= 1 + @__transaction_names__.pop + if @__transaction_level__ < 1 + @__transaction_level__ = 0 + @__transaction_names__ = [] + end + end + + TRANSACTION_CHECKPOINT = "@__transaction_checkpoint__" #:nodoc: + SKIP_TRANSACTION_VARS = [TRANSACTION_CHECKPOINT, "@__transaction_level__"] #:nodoc: + + def __rewind_this_transaction #:nodoc: + rr = Marshal.restore(@__transaction_checkpoint__) + + begin + self.replace(rr) if respond_to?(:replace) + rescue + nil + end + + rr.instance_variables.each do |vv| + next if SKIP_TRANSACTION_VARS.include?(vv) + next if self.transaction_exclusions.include?(vv) + if respond_to?(:instance_variable_get) + instance_variable_set(vv, rr.instance_variable_get(vv)) + else + instance_eval(%q|#{vv} = rr.instance_eval("#{vv}")|) + end + end + + new_ivar = instance_variables - rr.instance_variables - SKIP_TRANSACTION_VARS + new_ivar.each do |vv| + if respond_to?(:instance_variable_set) + instance_variable_set(vv, nil) + else + instance_eval(%q|#{vv} = nil|) + end + end + + if respond_to?(:instance_variable_get) + rr.instance_variable_get(TRANSACTION_CHECKPOINT) + else + rr.instance_eval(TRANSACTION_CHECKPOINT) + end + end + + def __commit_transaction #:nodoc: + if respond_to?(:instance_variable_get) + @__transaction_checkpoint__ = Marshal.restore(@__transaction_checkpoint__).instance_variable_get(TRANSACTION_CHECKPOINT) + else + @__transaction_checkpoint__ = Marshal.restore(@__transaction_checkpoint__).instance_eval(TRANSACTION_CHECKPOINT) + end + + @__transaction_level__ -= 1 + @__transaction_names__.pop + + if @__transaction_level__ < 1 + @__transaction_level__ = 0 + @__transaction_names__ = [] + end + end + + private :__abort_transaction + private :__rewind_this_transaction + private :__commit_transaction + end +end +module ActiveRecord + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 14 + TINY = 4 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end +require 'yaml' + +module ActiveRecord + module Wrappings #:nodoc: + class YamlWrapper < AbstractWrapper #:nodoc: + def wrap(attribute) attribute.to_yaml end + def unwrap(attribute) YAML::load(attribute) end + end + + module ClassMethods #:nodoc: + # Wraps the attribute in Yaml encoding + def wrap_in_yaml(*attributes) wrap_with(YamlWrapper, attributes) end + end + end +endmodule ActiveRecord + # A plugin framework for wrapping attribute values before they go in and unwrapping them after they go out of the database. + # This was intended primarily for YAML wrapping of arrays and hashes, but this behavior is now native in the Base class. + # So for now this framework is laying dormant until a need pops up. + module Wrappings #:nodoc: + module ClassMethods #:nodoc: + def wrap_with(wrapper, *attributes) + [ attributes ].flat.each { |attribute| wrapper.wrap(attribute) } + end + end + + def self.append_features(base) + super + base.extend(ClassMethods) + end + + class AbstractWrapper #:nodoc: + def self.wrap(attribute, record_binding) #:nodoc: + %w( before_save after_save after_initialize ).each do |callback| + eval "#{callback} #{name}.new('#{attribute}')", record_binding + end + end + + def initialize(attribute) #:nodoc: + @attribute = attribute + end + + def save_wrapped_attribute(record) #:nodoc: + if record.attribute_present?(@attribute) + record.send( + "write_attribute", + @attribute, + wrap(record.send("read_attribute", @attribute)) + ) + end + end + + def load_wrapped_attribute(record) #:nodoc: + if record.attribute_present?(@attribute) + record.send( + "write_attribute", + @attribute, + unwrap(record.send("read_attribute", @attribute)) + ) + end + end + + alias_method :before_save, :save_wrapped_attribute #:nodoc: + alias_method :after_save, :load_wrapped_attribute #:nodoc: + alias_method :after_initialize, :after_save #:nodoc: + + # Overwrite to implement the logic that'll take the regular attribute and wrap it. + def wrap(attribute) end + + # Overwrite to implement the logic that'll take the wrapped attribute and unwrap it. + def unwrap(attribute) end + end + end +end +#-- +# Copyright (c) 2004 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +$:.unshift(File.dirname(__FILE__)) unless + $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__))) + +unless defined?(ActiveSupport) + begin + $:.unshift(File.dirname(__FILE__) + "/../../activesupport/lib") + require 'active_support' + rescue LoadError + require 'rubygems' + require_gem 'activesupport' + end +end + +require 'active_record/base' +require 'active_record/observer' +require 'active_record/validations' +require 'active_record/callbacks' +require 'active_record/reflection' +require 'active_record/associations' +require 'active_record/aggregations' +require 'active_record/transactions' +require 'active_record/timestamp' +require 'active_record/acts/list' +require 'active_record/acts/tree' +require 'active_record/acts/nested_set' +require 'active_record/locking' +require 'active_record/migration' +require 'active_record/schema' +require 'active_record/calculations' + +ActiveRecord::Base.class_eval do + include ActiveRecord::Validations + include ActiveRecord::Locking + include ActiveRecord::Callbacks + include ActiveRecord::Observing + include ActiveRecord::Timestamp + include ActiveRecord::Associations + include ActiveRecord::Aggregations + include ActiveRecord::Transactions + include ActiveRecord::Reflection + include ActiveRecord::Acts::Tree + include ActiveRecord::Acts::List + include ActiveRecord::Acts::NestedSet + include ActiveRecord::Calculations +end + +unless defined?(RAILS_CONNECTION_ADAPTERS) + RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird sqlserver db2 oracle sybase openbase ) +end + +RAILS_CONNECTION_ADAPTERS.each do |adapter| + require "active_record/connection_adapters/" + adapter + "_adapter" +end + +require 'active_record/query_cache' +require 'active_record/schema_dumper' +# The filename begins with "aaa" to ensure this is the first test. +require 'abstract_unit' + +class AAACreateTablesTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + def setup + @base_path = "#{File.dirname(__FILE__)}/fixtures/db_definitions" + end + + def test_drop_and_create_main_tables + recreate ActiveRecord::Base + assert true + end + + def test_load_schema + eval(File.read("#{File.dirname(__FILE__)}/fixtures/db_definitions/schema.rb")) + assert true + end + + def test_drop_and_create_courses_table + recreate Course, '2' + assert true + end + + private + def recreate(base, suffix = nil) + connection = base.connection + adapter_name = connection.adapter_name.downcase + suffix.to_s + execute_sql_file "#{@base_path}/#{adapter_name}.drop.sql", connection + execute_sql_file "#{@base_path}/#{adapter_name}.sql", connection + end + + def execute_sql_file(path, connection) + # OpenBase has a different format for sql files + if current_adapter?(:OpenBaseAdapter) then + File.read(path).split("go").each_with_index do |sql, i| + begin + # OpenBase does not support comments embedded in sql + connection.execute(sql,"SQL statement ##{i}") unless sql.blank? + rescue ActiveRecord::StatementInvalid + #$stderr.puts "warning: #{$!}" + end + end + else + File.read(path).split(';').each_with_index do |sql, i| + begin + connection.execute("\n\n-- statement ##{i}\n#{sql}\n") unless sql.blank? + rescue ActiveRecord::StatementInvalid + #$stderr.puts "warning: #{$!}" + end + end + end + end +end +$:.unshift(File.dirname(__FILE__) + '/../lib') +$:.unshift(File.dirname(__FILE__) + '/../../activesupport/lib') + +require 'test/unit' +require 'active_record' +require 'active_record/fixtures' +require 'active_support/binding_of_caller' +require 'active_support/breakpoint' +require 'connection' + +QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE) + +class Test::Unit::TestCase #:nodoc: + self.fixture_path = File.dirname(__FILE__) + "/fixtures/" + self.use_instantiated_fixtures = false + self.use_transactional_fixtures = (ENV['AR_NO_TX_FIXTURES'] != "yes") + + def create_fixtures(*table_names, &block) + Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names, {}, &block) + end + + def assert_date_from_db(expected, actual, message = nil) + # SQL Server doesn't have a separate column type just for dates, + # so the time is in the string and incorrectly formatted + if current_adapter?(:SQLServerAdapter) + assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00") + elsif current_adapter?(:SybaseAdapter) + assert_equal expected.to_s, actual.to_date.to_s, message + else + assert_equal expected.to_s, actual.to_s, message + end + end + + def assert_queries(num = 1) + ActiveRecord::Base.connection.class.class_eval do + self.query_count = 0 + alias_method :execute, :execute_with_query_counting + end + yield + ensure + ActiveRecord::Base.connection.class.class_eval do + alias_method :execute, :execute_without_query_counting + end + assert_equal num, ActiveRecord::Base.connection.query_count, "#{ActiveRecord::Base.connection.query_count} instead of #{num} queries were executed." + end + + def assert_no_queries(&block) + assert_queries(0, &block) + end +end + +def current_adapter?(type) + ActiveRecord::ConnectionAdapters.const_defined?(type) && + ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type)) +end + +ActiveRecord::Base.connection.class.class_eval do + cattr_accessor :query_count + alias_method :execute_without_query_counting, :execute + def execute_with_query_counting(sql, name = nil) + self.query_count += 1 + execute_without_query_counting(sql, name) + end +end + +#ActiveRecord::Base.logger = Logger.new(STDOUT) +#ActiveRecord::Base.colorize_logging = false +require 'abstract_unit' + +class ActiveSchemaTest < Test::Unit::TestCase + def setup + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :real_execute, :execute + def execute(sql, name = nil) return sql end + end + end + + def teardown + ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:alias_method, :execute, :real_execute) + end + + def test_drop_table + assert_equal "DROP TABLE people", drop_table(:people) + end + + def test_add_column + assert_equal "ALTER TABLE people ADD last_name varchar(255)", add_column(:people, :last_name, :string) + end + + def test_add_column_with_limit + assert_equal "ALTER TABLE people ADD key varchar(32)", add_column(:people, :key, :string, :limit => 32) + end + + private + def method_missing(method_symbol, *arguments) + ActiveRecord::Base.connection.send(method_symbol, *arguments) + end +endrequire 'abstract_unit' + +class AdapterTest < Test::Unit::TestCase + def setup + @connection = ActiveRecord::Base.connection + end + + def test_tables + if @connection.respond_to?(:tables) + tables = @connection.tables + assert tables.include?("accounts") + assert tables.include?("authors") + assert tables.include?("tasks") + assert tables.include?("topics") + else + warn "#{@connection.class} does not respond to #tables" + end + end + + def test_indexes + idx_name = "accounts_idx" + + if @connection.respond_to?(:indexes) + indexes = @connection.indexes("accounts") + assert indexes.empty? + + @connection.add_index :accounts, :firm_id, :name => idx_name + indexes = @connection.indexes("accounts") + assert_equal "accounts", indexes.first.table + # OpenBase does not have the concept of a named index + # Indexes are merely properties of columns. + assert_equal idx_name, indexes.first.name unless current_adapter?(:OpenBaseAdapter) + assert !indexes.first.unique + assert_equal ["firm_id"], indexes.first.columns + else + warn "#{@connection.class} does not respond to #indexes" + end + + ensure + @connection.remove_index(:accounts, :name => idx_name) rescue nil + end + + def test_current_database + if @connection.respond_to?(:current_database) + assert_equal ENV['ARUNIT_DB_NAME'] || "activerecord_unittest", @connection.current_database + end + end + + def test_table_alias + def @connection.test_table_alias_length() 10; end + class << @connection + alias_method :old_table_alias_length, :table_alias_length + alias_method :table_alias_length, :test_table_alias_length + end + + assert_equal 'posts', @connection.table_alias_for('posts') + assert_equal 'posts_comm', @connection.table_alias_for('posts_comments') + assert_equal 'dbo_posts', @connection.table_alias_for('dbo.posts') + + class << @connection + alias_method :table_alias_length, :old_table_alias_length + end + end + + # test resetting sequences in odd tables in postgreSQL + if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!) + require 'fixtures/movie' + require 'fixtures/subscriber' + def test_reset_empty_table_with_custom_pk + Movie.delete_all + Movie.connection.reset_pk_sequence! 'movies' + assert_equal 1, Movie.create(:name => 'fight club').id + end + + def test_reset_table_with_non_integer_pk + Subscriber.delete_all + Subscriber.connection.reset_pk_sequence! 'subscribers' + + sub = Subscriber.new(:name => 'robert drake') + sub.id = 'bob drake' + assert_nothing_raised { sub.save! } + end + end + +end +require 'abstract_unit' +require 'fixtures/customer' + +class AggregationsTest < Test::Unit::TestCase + fixtures :customers + + def test_find_single_value_object + assert_equal 50, customers(:david).balance.amount + assert_kind_of Money, customers(:david).balance + assert_equal 300, customers(:david).balance.exchange_to("DKK").amount + end + + def test_find_multiple_value_object + assert_equal customers(:david).address_street, customers(:david).address.street + assert( + customers(:david).address.close_to?(Address.new("Different Street", customers(:david).address_city, customers(:david).address_country)) + ) + end + + def test_change_single_value_object + customers(:david).balance = Money.new(100) + customers(:david).save + assert_equal 100, Customer.find(1).balance.amount + end + + def test_immutable_value_objects + customers(:david).balance = Money.new(100) + assert_raises(TypeError) { customers(:david).balance.instance_eval { @amount = 20 } } + end + + def test_inferred_mapping + assert_equal "35.544623640962634", customers(:david).gps_location.latitude + assert_equal "-105.9309951055148", customers(:david).gps_location.longitude + + customers(:david).gps_location = GpsLocation.new("39x-110") + + assert_equal "39", customers(:david).gps_location.latitude + assert_equal "-110", customers(:david).gps_location.longitude + + customers(:david).save + + customers(:david).reload + + assert_equal "39", customers(:david).gps_location.latitude + assert_equal "-110", customers(:david).gps_location.longitude + end + + def test_reloaded_instance_refreshes_aggregations + assert_equal "35.544623640962634", customers(:david).gps_location.latitude + assert_equal "-105.9309951055148", customers(:david).gps_location.longitude + + Customer.update_all("gps_location = '24x113'") + customers(:david).reload + assert_equal '24x113', customers(:david)['gps_location'] + + assert_equal GpsLocation.new('24x113'), customers(:david).gps_location + end + + def test_gps_equality + assert GpsLocation.new('39x110') == GpsLocation.new('39x110') + end + + def test_gps_inequality + assert GpsLocation.new('39x110') != GpsLocation.new('39x111') + end +end +require 'abstract_unit' +require "#{File.dirname(__FILE__)}/../lib/active_record/schema" + +if ActiveRecord::Base.connection.supports_migrations? + + class ActiveRecordSchemaTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + def setup + @connection = ActiveRecord::Base.connection + end + + def teardown + @connection.drop_table :fruits rescue nil + end + + def test_schema_define + ActiveRecord::Schema.define(:version => 7) do + create_table :fruits do |t| + t.column :color, :string + t.column :fruit_size, :string # NOTE: "size" is reserved in Oracle + t.column :texture, :string + t.column :flavor, :string + end + end + + assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" } + assert_nothing_raised { @connection.select_all "SELECT * FROM schema_info" } + assert_equal 7, @connection.select_one("SELECT version FROM schema_info")['version'].to_i + end + end + +end +require 'abstract_unit' +require 'fixtures/post' +require 'fixtures/comment' +require 'fixtures/author' +require 'fixtures/category' +require 'fixtures/project' +require 'fixtures/developer' + +class AssociationCallbacksTest < Test::Unit::TestCase + fixtures :posts, :authors, :projects, :developers + + def setup + @david = authors(:david) + @thinking = posts(:thinking) + @authorless = posts(:authorless) + assert @david.post_log.empty? + end + + def test_adding_macro_callbacks + @david.posts_with_callbacks << @thinking + assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}"], @david.post_log + @david.posts_with_callbacks << @thinking + assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}", + "after_adding#{@thinking.id}"], @david.post_log + end + + def test_adding_with_proc_callbacks + @david.posts_with_proc_callbacks << @thinking + assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}"], @david.post_log + @david.posts_with_proc_callbacks << @thinking + assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}", + "after_adding#{@thinking.id}"], @david.post_log + end + + def test_removing_with_macro_callbacks + first_post, second_post = @david.posts_with_callbacks[0, 2] + @david.posts_with_callbacks.delete(first_post) + assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}"], @david.post_log + @david.posts_with_callbacks.delete(second_post) + assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}", + "after_removing#{second_post.id}"], @david.post_log + end + + def test_removing_with_proc_callbacks + first_post, second_post = @david.posts_with_callbacks[0, 2] + @david.posts_with_proc_callbacks.delete(first_post) + assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}"], @david.post_log + @david.posts_with_proc_callbacks.delete(second_post) + assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}", + "after_removing#{second_post.id}"], @david.post_log + end + + def test_multiple_callbacks + @david.posts_with_multiple_callbacks << @thinking + assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}", + "after_adding_proc#{@thinking.id}"], @david.post_log + @david.posts_with_multiple_callbacks << @thinking + assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}", + "after_adding_proc#{@thinking.id}", "before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", + "after_adding#{@thinking.id}", "after_adding_proc#{@thinking.id}"], @david.post_log + end + + def test_has_and_belongs_to_many_add_callback + david = developers(:david) + ar = projects(:active_record) + assert ar.developers_log.empty? + ar.developers_with_callbacks << david + assert_equal ["before_adding#{david.id}", "after_adding#{david.id}"], ar.developers_log + ar.developers_with_callbacks << david + assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}", + "after_adding#{david.id}"], ar.developers_log + end + + def test_has_and_belongs_to_many_remove_callback + david = developers(:david) + jamis = developers(:jamis) + activerecord = projects(:active_record) + assert activerecord.developers_log.empty? + activerecord.developers_with_callbacks.delete(david) + assert_equal ["before_removing#{david.id}", "after_removing#{david.id}"], activerecord.developers_log + + activerecord.developers_with_callbacks.delete(jamis) + assert_equal ["before_removing#{david.id}", "after_removing#{david.id}", "before_removing#{jamis.id}", + "after_removing#{jamis.id}"], activerecord.developers_log + end + + def test_has_and_belongs_to_many_remove_callback_on_clear + activerecord = projects(:active_record) + assert activerecord.developers_log.empty? + if activerecord.developers_with_callbacks.size == 0 + activerecord.developers << developers(:david) + activerecord.developers << developers(:jamis) + activerecord.reload + assert activerecord.developers_with_callbacks.size == 2 + end + log_array = activerecord.developers_with_callbacks.collect {|d| ["before_removing#{d.id}","after_removing#{d.id}"]}.flatten.sort + assert activerecord.developers_with_callbacks.clear + assert_equal log_array, activerecord.developers_log.sort + end + + def test_dont_add_if_before_callback_raises_exception + assert !@david.unchangable_posts.include?(@authorless) + begin + @david.unchangable_posts << @authorless + rescue Exception => e + end + assert @david.post_log.empty? + assert !@david.unchangable_posts.include?(@authorless) + @david.reload + assert !@david.unchangable_posts.include?(@authorless) + end + + def test_push_with_attributes + david = developers(:david) + activerecord = projects(:active_record) + assert activerecord.developers_log.empty? + activerecord.developers_with_callbacks.push_with_attributes(david, {}) + assert_equal ["before_adding#{david.id}", "after_adding#{david.id}"], activerecord.developers_log + activerecord.developers_with_callbacks.push_with_attributes(david, {}) + assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}", + "after_adding#{david.id}"], activerecord.developers_log + end +end + +require 'abstract_unit' +require 'fixtures/company' + +class AssociationInheritanceReloadTest < Test::Unit::TestCase + fixtures :companies + + def test_set_attributes + assert_equal ["errors.add_on_empty('name', \"can't be empty\")"], Firm.read_inheritable_attribute("validate"), "Second run" + # ActiveRecord::Base.reset_column_information_and_inheritable_attributes_for_all_subclasses + remove_subclass_of(ActiveRecord::Base) + load 'fixtures/company.rb' + assert_equal ["errors.add_on_empty('name', \"can't be empty\")"], Firm.read_inheritable_attribute("validate"), "Second run" + end +endrequire 'abstract_unit' +require 'active_record/acts/list' +require 'fixtures/post' +require 'fixtures/comment' +require 'fixtures/author' +require 'fixtures/category' +require 'fixtures/categorization' +require 'fixtures/mixin' +require 'fixtures/company' +require 'fixtures/topic' +require 'fixtures/reply' + +class CascadedEagerLoadingTest < Test::Unit::TestCase + fixtures :authors, :mixins, :companies, :posts, :categorizations, :topics + + def test_eager_association_loading_with_cascaded_two_levels + authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id") + assert_equal 2, authors.size + assert_equal 5, authors[0].posts.size + assert_equal 1, authors[1].posts.size + assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} + end + + def test_eager_association_loading_with_cascaded_two_levels_and_one_level + authors = Author.find(:all, :include=>[{:posts=>:comments}, :categorizations], :order=>"authors.id") + assert_equal 2, authors.size + assert_equal 5, authors[0].posts.size + assert_equal 1, authors[1].posts.size + assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} + assert_equal 1, authors[0].categorizations.size + assert_equal 1, authors[1].categorizations.size + end + + def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations + authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id") + assert_equal 2, authors.size + assert_equal 5, authors[0].posts.size + assert_equal 1, authors[1].posts.size + assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i} + end + + def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference + authors = Author.find(:all, :include=>{:posts=>[:comments, :author]}, :order=>"authors.id") + assert_equal 2, authors.size + assert_equal 5, authors[0].posts.size + assert_equal authors(:david).name, authors[0].name + assert_equal [authors(:david).name], authors[0].posts.collect{|post| post.author.name}.uniq + end + + def test_eager_association_loading_with_cascaded_two_levels_with_condition + authors = Author.find(:all, :include=>{:posts=>:comments}, :conditions=>"authors.id=1", :order=>"authors.id") + assert_equal 1, authors.size + assert_equal 5, authors[0].posts.size + end + + def test_eager_association_loading_with_acts_as_tree + roots = TreeMixin.find(:all, :include=>"children", :conditions=>"mixins.parent_id IS NULL", :order=>"mixins.id") + assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], roots + assert_no_queries do + assert_equal 2, roots[0].children.size + assert_equal 0, roots[1].children.size + assert_equal 0, roots[2].children.size + end + end + + def test_eager_association_loading_with_cascaded_three_levels_by_ping_pong + firms = Firm.find(:all, :include=>{:account=>{:firm=>:account}}, :order=>"companies.id") + assert_equal 2, firms.size + assert_equal firms.first.account, firms.first.account.firm.account + assert_equal companies(:first_firm).account, assert_no_queries { firms.first.account.firm.account } + assert_equal companies(:first_firm).account.firm.account, assert_no_queries { firms.first.account.firm.account } + end + + def test_eager_association_loading_with_has_many_sti + topics = Topic.find(:all, :include => :replies, :order => 'topics.id') + assert_equal [topics(:first), topics(:second)], topics + assert_no_queries do + assert_equal 1, topics[0].replies.size + assert_equal 0, topics[1].replies.size + end + end + + def test_eager_association_loading_with_belongs_to_sti + replies = Reply.find(:all, :include => :topic, :order => 'topics.id') + assert_equal [topics(:second)], replies + assert_equal topics(:first), assert_no_queries { replies.first.topic } + end + + def test_eager_association_loading_with_multiple_stis_and_order + author = Author.find(:first, :include => { :posts => [ :special_comments , :very_special_comment ] }, :order => 'authors.name, comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4') + assert_equal authors(:david), author + assert_no_queries do + author.posts.first.special_comments + author.posts.first.very_special_comment + end + end + + def test_eager_association_loading_of_stis_with_multiple_references + authors = Author.find(:all, :include => { :posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } } }, :order => 'comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4') + assert_equal [authors(:david)], authors + assert_no_queries do + authors.first.posts.first.special_comments.first.post.special_comments + authors.first.posts.first.special_comments.first.post.very_special_comment + end + end +end +require 'abstract_unit' +require 'fixtures/post' +require 'fixtures/comment' +require 'fixtures/project' +require 'fixtures/developer' + +class AssociationsExtensionsTest < Test::Unit::TestCase + fixtures :projects, :developers, :developers_projects, :comments, :posts + + def test_extension_on_has_many + assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent + end + + def test_extension_on_habtm + assert_equal projects(:action_controller), developers(:david).projects.find_most_recent + end + + def test_named_extension_on_habtm + assert_equal projects(:action_controller), developers(:david).projects_extended_by_name.find_most_recent + end + + def test_marshalling_extensions + david = developers(:david) + assert_equal projects(:action_controller), david.projects.find_most_recent + + david = Marshal.load(Marshal.dump(david)) + assert_equal projects(:action_controller), david.projects.find_most_recent + end + + def test_marshalling_named_extensions + david = developers(:david) + assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent + + david = Marshal.load(Marshal.dump(david)) + assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent + end +endrequire 'abstract_unit' +require 'fixtures/post' +require 'fixtures/comment' +require 'fixtures/author' +require 'fixtures/category' +require 'fixtures/company' +require 'fixtures/person' +require 'fixtures/reader' + +class EagerAssociationTest < Test::Unit::TestCase + fixtures :posts, :comments, :authors, :categories, :categories_posts, + :companies, :accounts, :tags, :people, :readers + + def test_loading_with_one_association + posts = Post.find(:all, :include => :comments) + post = posts.find { |p| p.id == 1 } + assert_equal 2, post.comments.size + assert post.comments.include?(comments(:greetings)) + + post = Post.find(:first, :include => :comments, :conditions => "posts.title = 'Welcome to the weblog'") + assert_equal 2, post.comments.size + assert post.comments.include?(comments(:greetings)) + end + + def test_loading_conditions_with_or + posts = authors(:david).posts.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'") + assert_nil posts.detect { |p| p.author_id != authors(:david).id }, + "expected to find only david's posts" + end + + def test_with_ordering + list = Post.find(:all, :include => :comments, :order => "posts.id DESC") + [:eager_other, :sti_habtm, :sti_post_and_comments, :sti_comments, + :authorless, :thinking, :welcome + ].each_with_index do |post, index| + assert_equal posts(post), list[index] + end + end + + def test_loading_with_multiple_associations + posts = Post.find(:all, :include => [ :comments, :author, :categories ], :order => "posts.id") + assert_equal 2, posts.first.comments.size + assert_equal 2, posts.first.categories.size + assert posts.first.comments.include?(comments(:greetings)) + end + + def test_loading_from_an_association + posts = authors(:david).posts.find(:all, :include => :comments, :order => "posts.id") + assert_equal 2, posts.first.comments.size + end + + def test_loading_with_no_associations + assert_nil Post.find(posts(:authorless).id, :include => :author).author + end + + def test_eager_association_loading_with_belongs_to + comments = Comment.find(:all, :include => :post) + assert_equal 10, comments.length + titles = comments.map { |c| c.post.title } + assert titles.include?(posts(:welcome).title) + assert titles.include?(posts(:sti_post_and_comments).title) + end + + def test_eager_association_loading_with_belongs_to_and_limit + comments = Comment.find(:all, :include => :post, :limit => 5, :order => 'comments.id') + assert_equal 5, comments.length + assert_equal [1,2,3,5,6], comments.collect { |c| c.id } + end + + def test_eager_association_loading_with_belongs_to_and_limit_and_conditions + comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :order => 'comments.id') + assert_equal 3, comments.length + assert_equal [5,6,7], comments.collect { |c| c.id } + end + + def test_eager_association_loading_with_belongs_to_and_limit_and_offset + comments = Comment.find(:all, :include => :post, :limit => 3, :offset => 2, :order => 'comments.id') + assert_equal 3, comments.length + assert_equal [3,5,6], comments.collect { |c| c.id } + end + + def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions + comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id') + assert_equal 3, comments.length + assert_equal [6,7,8], comments.collect { |c| c.id } + end + + def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array + comments = Comment.find(:all, :include => :post, :conditions => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id') + assert_equal 3, comments.length + assert_equal [6,7,8], comments.collect { |c| c.id } + end + + def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations + posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :order => 'posts.id') + assert_equal 1, posts.length + assert_equal [1], posts.collect { |p| p.id } + end + + def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations + posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id') + assert_equal 1, posts.length + assert_equal [2], posts.collect { |p| p.id } + end + + def test_eager_with_has_many_through + posts_with_comments = people(:michael).posts.find(:all, :include => :comments ) + posts_with_author = people(:michael).posts.find(:all, :include => :author ) + posts_with_comments_and_author = people(:michael).posts.find(:all, :include => [ :comments, :author ]) + assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum += post.comments.size } + assert_equal authors(:david), assert_no_queries { posts_with_author.first.author } + assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author } + end + + def test_eager_with_has_many_and_limit + posts = Post.find(:all, :order => 'posts.id asc', :include => [ :author, :comments ], :limit => 2) + assert_equal 2, posts.size + assert_equal 3, posts.inject(0) { |sum, post| sum += post.comments.size } + end + + def test_eager_with_has_many_and_limit_and_conditions + posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.body = 'hello'", :order => "posts.id") + assert_equal 2, posts.size + assert_equal [4,5], posts.collect { |p| p.id } + end + + def test_eager_with_has_many_and_limit_and_conditions_array + posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "posts.body = ?", 'hello' ], :order => "posts.id") + assert_equal 2, posts.size + assert_equal [4,5], posts.collect { |p| p.id } + end + + def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers + posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ]) + assert_equal 2, posts.size + + count = Post.count(:include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ]) + assert_equal count, posts.size + end + + def test_eager_with_has_many_and_limit_ond_high_offset + posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ]) + assert_equal 0, posts.size + end + + def test_count_eager_with_has_many_and_limit_ond_high_offset + posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ]) + assert_equal 0, posts + end + + def test_eager_with_has_many_and_limit_with_no_results + posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'") + assert_equal 0, posts.size + end + + def test_eager_with_has_and_belongs_to_many_and_limit + posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3) + assert_equal 3, posts.size + assert_equal 2, posts[0].categories.size + assert_equal 1, posts[1].categories.size + assert_equal 0, posts[2].categories.size + assert posts[0].categories.include?(categories(:technology)) + assert posts[1].categories.include?(categories(:general)) + end + + def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers + posts = authors(:david).posts.find(:all, + :include => :comments, + :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'", + :limit => 2 + ) + assert_equal 2, posts.size + + count = Post.count( + :include => [ :comments, :author ], + :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')", + :limit => 2 + ) + assert_equal count, posts.size + end + + def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers + posts = nil + Post.with_scope(:find => { + :include => :comments, + :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'" + }) do + posts = authors(:david).posts.find(:all, :limit => 2) + assert_equal 2, posts.size + end + + Post.with_scope(:find => { + :include => [ :comments, :author ], + :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')" + }) do + count = Post.count(:limit => 2) + assert_equal count, posts.size + end + end + + def test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the_eagers + Post.with_scope(:find => { :conditions => "1=1" }) do + posts = authors(:david).posts.find(:all, + :include => :comments, + :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'", + :limit => 2 + ) + assert_equal 2, posts.size + + count = Post.count( + :include => [ :comments, :author ], + :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')", + :limit => 2 + ) + assert_equal count, posts.size + end + end + def test_eager_association_loading_with_habtm + posts = Post.find(:all, :include => :categories, :order => "posts.id") + assert_equal 2, posts[0].categories.size + assert_equal 1, posts[1].categories.size + assert_equal 0, posts[2].categories.size + assert posts[0].categories.include?(categories(:technology)) + assert posts[1].categories.include?(categories(:general)) + end + + def test_eager_with_inheritance + posts = SpecialPost.find(:all, :include => [ :comments ]) + end + + def test_eager_has_one_with_association_inheritance + post = Post.find(4, :include => [ :very_special_comment ]) + assert_equal "VerySpecialComment", post.very_special_comment.class.to_s + end + + def test_eager_has_many_with_association_inheritance + post = Post.find(4, :include => [ :special_comments ]) + post.special_comments.each do |special_comment| + assert_equal "SpecialComment", special_comment.class.to_s + end + end + + def test_eager_habtm_with_association_inheritance + post = Post.find(6, :include => [ :special_categories ]) + assert_equal 1, post.special_categories.size + post.special_categories.each do |special_category| + assert_equal "SpecialCategory", special_category.class.to_s + end + end + + def test_eager_with_has_one_dependent_does_not_destroy_dependent + assert_not_nil companies(:first_firm).account + f = Firm.find(:first, :include => :account, + :conditions => ["companies.name = ?", "37signals"]) + assert_not_nil f.account + assert_equal companies(:first_firm, :reload).account, f.account + end + + def test_eager_with_invalid_association_reference + assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { + post = Post.find(6, :include=> :monkeys ) + } + assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { + post = Post.find(6, :include=>[ :monkeys ]) + } + assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { + post = Post.find(6, :include=>[ 'monkeys' ]) + } + assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") { + post = Post.find(6, :include=>[ :monkeys, :elephants ]) + } + end + + def find_all_ordered(className, include=nil) + className.find(:all, :order=>"#{className.table_name}.#{className.primary_key}", :include=>include) + end + + def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm + # Eager includes of has many and habtm associations aren't necessarily sorted in the same way + def assert_equal_after_sort(item1, item2, item3 = nil) + assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) + assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3 + end + # Test regular association, association with conditions, association with + # STI, and association with conditions assured not to be true + post_types = [:posts, :hello_posts, :special_posts, :nonexistent_posts] + # test both has_many and has_and_belongs_to_many + [Author, Category].each do |className| + d1 = find_all_ordered(className) + # test including all post types at once + d2 = find_all_ordered(className, post_types) + d1.each_index do |i| + assert_equal(d1[i], d2[i]) + assert_equal_after_sort(d1[i].posts, d2[i].posts) + post_types[1..-1].each do |post_type| + # test including post_types together + d3 = find_all_ordered(className, [:posts, post_type]) + assert_equal(d1[i], d3[i]) + assert_equal_after_sort(d1[i].posts, d3[i].posts) + assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type)) + end + end + end + end + + def test_eager_with_multiple_associations_with_same_table_has_one + d1 = find_all_ordered(Firm) + d2 = find_all_ordered(Firm, :account) + d1.each_index do |i| + assert_equal(d1[i], d2[i]) + assert_equal(d1[i].account, d2[i].account) + end + end + + def test_eager_with_multiple_associations_with_same_table_belongs_to + firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition] + d1 = find_all_ordered(Client) + d2 = find_all_ordered(Client, firm_types) + d1.each_index do |i| + assert_equal(d1[i], d2[i]) + firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) } + end + end + def test_eager_with_valid_association_as_string_not_symbol + assert_nothing_raised { Post.find(:all, :include => 'comments') } + end + + def test_preconfigured_includes_with_belongs_to + author = posts(:welcome).author_with_posts + assert_equal 5, author.posts.size + end + + def test_preconfigured_includes_with_has_one + comment = posts(:sti_comments).very_special_comment_with_post + assert_equal posts(:sti_comments), comment.post + end + + def test_preconfigured_includes_with_has_many + posts = authors(:david).posts_with_comments + one = posts.detect { |p| p.id == 1 } + assert_equal 5, posts.size + assert_equal 2, one.comments.size + end + + def test_preconfigured_includes_with_habtm + posts = authors(:david).posts_with_categories + one = posts.detect { |p| p.id == 1 } + assert_equal 5, posts.size + assert_equal 2, one.categories.size + end + + def test_preconfigured_includes_with_has_many_and_habtm + posts = authors(:david).posts_with_comments_and_categories + one = posts.detect { |p| p.id == 1 } + assert_equal 5, posts.size + assert_equal 2, one.comments.size + assert_equal 2, one.categories.size + end +end +require 'abstract_unit' +require 'fixtures/tag' +require 'fixtures/tagging' +require 'fixtures/post' +require 'fixtures/comment' +require 'fixtures/author' +require 'fixtures/category' +require 'fixtures/categorization' + +class AssociationsJoinModelTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites + + def test_has_many + assert_equal categories(:general), authors(:david).categories.first + end + + def test_has_many_inherited + assert_equal categories(:sti_test), authors(:mary).categories.first + end + + def test_inherited_has_many + assert_equal authors(:mary), categories(:sti_test).authors.first + end + + def test_polymorphic_has_many + assert_equal taggings(:welcome_general), posts(:welcome).taggings.first + end + + def test_polymorphic_has_one + assert_equal taggings(:welcome_general), posts(:welcome).tagging + end + + def test_polymorphic_belongs_to + assert_equal posts(:welcome), posts(:welcome).taggings.first.taggable + end + + def test_polymorphic_has_many_going_through_join_model + assert_equal tags(:general), tag = posts(:welcome).tags.first + assert_no_queries do + tag.tagging + end + end + + def test_count_polymorphic_has_many + assert_equal 1, posts(:welcome).taggings.count + assert_equal 1, posts(:welcome).tags.count + end + + def test_polymorphic_has_many_going_through_join_model_with_find + assert_equal tags(:general), tag = posts(:welcome).tags.find(:first) + assert_no_queries do + tag.tagging + end + end + + def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection + assert_equal tags(:general), tag = posts(:welcome).funky_tags.first + assert_no_queries do + tag.tagging + end + end + + def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find + assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first) + assert_no_queries do + tag.tagging + end + end + + def test_polymorphic_has_many_going_through_join_model_with_disabled_include + assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first + assert_queries 1 do + tag.tagging + end + end + + def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins + assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first + tag.author_id + end + + def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key + assert_equal tags(:misc), taggings(:welcome_general).super_tag + assert_equal tags(:misc), posts(:welcome).super_tags.first + end + + def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class + post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body' + assert_instance_of SubStiPost, post + + tagging = tags(:misc).taggings.create(:taggable => post) + assert_equal "SubStiPost", tagging.taggable_type + end + + def test_polymorphic_has_many_going_through_join_model_with_inheritance + assert_equal tags(:general), posts(:thinking).tags.first + end + + def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name + assert_equal tags(:general), posts(:thinking).funky_tags.first + end + + def test_polymorphic_has_many_create_model_with_inheritance + post = posts(:thinking) + assert_instance_of SpecialPost, post + + tagging = tags(:misc).taggings.create(:taggable => post) + assert_equal "Post", tagging.taggable_type + end + + def test_polymorphic_has_one_create_model_with_inheritance + tagging = tags(:misc).create_tagging(:taggable => posts(:thinking)) + assert_equal "Post", tagging.taggable_type + end + + def test_set_polymorphic_has_many + tagging = tags(:misc).taggings.create + posts(:thinking).taggings << tagging + assert_equal "Post", tagging.taggable_type + end + + def test_set_polymorphic_has_one + tagging = tags(:misc).taggings.create + posts(:thinking).tagging = tagging + assert_equal "Post", tagging.taggable_type + end + + def test_create_polymorphic_has_many_with_scope + old_count = posts(:welcome).taggings.count + tagging = posts(:welcome).taggings.create(:tag => tags(:misc)) + assert_equal "Post", tagging.taggable_type + assert_equal old_count+1, posts(:welcome).taggings.count + end + + def test_create_polymorphic_has_one_with_scope + old_count = Tagging.count + tagging = posts(:welcome).tagging.create(:tag => tags(:misc)) + assert_equal "Post", tagging.taggable_type + assert_equal old_count+1, Tagging.count + end + + def test_delete_polymorphic_has_many_with_delete_all + assert_equal 1, posts(:welcome).taggings.count + posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDeleteAll' + post = find_post_with_dependency(1, :has_many, :taggings, :delete_all) + + old_count = Tagging.count + post.destroy + assert_equal old_count-1, Tagging.count + assert_equal 0, posts(:welcome).taggings.count + end + + def test_delete_polymorphic_has_many_with_destroy + assert_equal 1, posts(:welcome).taggings.count + posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDestroy' + post = find_post_with_dependency(1, :has_many, :taggings, :destroy) + + old_count = Tagging.count + post.destroy + assert_equal old_count-1, Tagging.count + assert_equal 0, posts(:welcome).taggings.count + end + + def test_delete_polymorphic_has_many_with_nullify + assert_equal 1, posts(:welcome).taggings.count + posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyNullify' + post = find_post_with_dependency(1, :has_many, :taggings, :nullify) + + old_count = Tagging.count + post.destroy + assert_equal old_count, Tagging.count + assert_equal 0, posts(:welcome).taggings.count + end + + def test_delete_polymorphic_has_one_with_destroy + assert posts(:welcome).tagging + posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneDestroy' + post = find_post_with_dependency(1, :has_one, :tagging, :destroy) + + old_count = Tagging.count + post.destroy + assert_equal old_count-1, Tagging.count + assert_nil posts(:welcome).tagging(true) + end + + def test_delete_polymorphic_has_one_with_nullify + assert posts(:welcome).tagging + posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneNullify' + post = find_post_with_dependency(1, :has_one, :tagging, :nullify) + + old_count = Tagging.count + post.destroy + assert_equal old_count, Tagging.count + assert_nil posts(:welcome).tagging(true) + end + + def test_has_many_with_piggyback + assert_equal "2", categories(:sti_test).authors.first.post_id.to_s + end + + def test_include_has_many_through + posts = Post.find(:all, :order => 'posts.id') + posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id') + assert_equal posts.length, posts_with_authors.length + posts.length.times do |i| + assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length } + end + end + + def test_include_polymorphic_has_one + post = Post.find_by_id(posts(:welcome).id, :include => :tagging) + tagging = taggings(:welcome_general) + assert_no_queries do + assert_equal tagging, post.tagging + end + end + + def test_include_polymorphic_has_many_through + posts = Post.find(:all, :order => 'posts.id') + posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id') + assert_equal posts.length, posts_with_tags.length + posts.length.times do |i| + assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length } + end + end + + def test_include_polymorphic_has_many + posts = Post.find(:all, :order => 'posts.id') + posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id') + assert_equal posts.length, posts_with_taggings.length + posts.length.times do |i| + assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length } + end + end + + def test_has_many_find_all + assert_equal [categories(:general)], authors(:david).categories.find(:all) + end + + def test_has_many_find_first + assert_equal categories(:general), authors(:david).categories.find(:first) + end + + def test_has_many_find_conditions + assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'") + assert_equal nil, authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'") + end + + def test_has_many_class_methods_called_by_method_missing + assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first +# assert_equal nil, authors(:david).categories.find_by_name('Technology') + end + + def test_has_many_going_through_join_model_with_custom_foreign_key + assert_equal [], posts(:thinking).authors + assert_equal [authors(:mary)], posts(:authorless).authors + end + + def test_belongs_to_polymorphic_with_counter_cache + assert_equal 0, posts(:welcome)[:taggings_count] + tagging = posts(:welcome).taggings.create(:tag => tags(:general)) + assert_equal 1, posts(:welcome, :reload)[:taggings_count] + tagging.destroy + assert posts(:welcome, :reload)[:taggings_count].zero? + end + + def test_unavailable_through_reflection + assert_raises (ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings } + end + + def test_has_many_through_join_model_with_conditions + assert_equal [], posts(:welcome).invalid_taggings + assert_equal [], posts(:welcome).invalid_tags + end + + def test_has_many_polymorphic + assert_raises ActiveRecord::HasManyThroughAssociationPolymorphicError do + assert_equal [posts(:welcome), posts(:thinking)], tags(:general).taggables + end + assert_raises ActiveRecord::EagerLoadPolymorphicError do + assert_equal [posts(:welcome), posts(:thinking)], tags(:general).taggings.find(:all, :include => :taggable) + end + end + + def test_has_many_through_has_many_find_all + assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first + end + + def test_has_many_through_has_many_find_all_with_custom_class + assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first + end + + def test_has_many_through_has_many_find_first + assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id') + end + + def test_has_many_through_has_many_find_conditions + assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, :conditions => "comments.type='SpecialComment'", :order => 'comments.id') + end + + def test_has_many_through_has_many_find_by_id + assert_equal comments(:more_greetings), authors(:david).comments.find(2) + end + + def test_has_many_through_polymorphic_has_one + assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tagging } + end + + def test_has_many_through_polymorphic_has_many + assert_equal [taggings(:welcome_general), taggings(:thinking_general)], authors(:david).taggings.uniq.sort_by { |t| t.id } + end + + def test_include_has_many_through_polymorphic_has_many + author = Author.find_by_id(authors(:david).id, :include => :taggings) + expected_taggings = [taggings(:welcome_general), taggings(:thinking_general)] + assert_no_queries do + assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id } + end + end + + def test_has_many_through_has_many_through + assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags } + end + + def test_has_many_through_habtm + assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories } + end + + def test_eager_load_has_many_through_has_many + author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id' + SpecialComment.new; VerySpecialComment.new + assert_no_queries do + assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id) + end + end + + def test_eager_belongs_to_and_has_one_not_singularized + assert_nothing_raised do + Author.find(:first, :include => :author_address) + AuthorAddress.find(:first, :include => :author) + end + end + + def test_self_referential_has_many_through + assert_equal [authors(:mary)], authors(:david).favorite_authors + assert_equal [], authors(:mary).favorite_authors + end + + def test_add_to_self_referential_has_many_through + new_author = Author.create(:name => "Bob") + authors(:david).author_favorites.create :favorite_author => new_author + assert_equal new_author, authors(:david).reload.favorite_authors.first + end + + def test_has_many_through_uses_correct_attributes + assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"] + end + + private + # create dynamic Post models to allow different dependency options + def find_post_with_dependency(post_id, association, association_name, dependency) + class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}" + Post.find(post_id).update_attribute :type, class_name + klass = Object.const_set(class_name, Class.new(ActiveRecord::Base)) + klass.set_table_name 'posts' + klass.send(association, association_name, :as => :taggable, :dependent => dependency) + klass.find(post_id) + end +end +require 'abstract_unit' +require 'fixtures/developer' +require 'fixtures/project' +require 'fixtures/company' +require 'fixtures/topic' +require 'fixtures/reply' +require 'fixtures/computer' +require 'fixtures/customer' +require 'fixtures/order' +require 'fixtures/category' +require 'fixtures/post' +require 'fixtures/author' + +# Can't declare new classes in test case methods, so tests before that +bad_collection_keys = false +begin + class Car < ActiveRecord::Base; has_many :wheels, :name => "wheels"; end +rescue ArgumentError + bad_collection_keys = true +end +raise "ActiveRecord should have barked on bad collection keys" unless bad_collection_keys + + +class AssociationsTest < Test::Unit::TestCase + fixtures :accounts, :companies, :developers, :projects, :developers_projects, + :computers + + def test_force_reload + firm = Firm.new("name" => "A New Firm, Inc") + firm.save + firm.clients.each {|c|} # forcing to load all clients + assert firm.clients.empty?, "New firm shouldn't have client objects" + assert !firm.has_clients?, "New firm shouldn't have clients" + assert_equal 0, firm.clients.size, "New firm should have 0 clients" + + client = Client.new("name" => "TheClient.com", "firm_id" => firm.id) + client.save + + assert firm.clients.empty?, "New firm should have cached no client objects" + assert !firm.has_clients?, "New firm should have cached a no-clients response" + assert_equal 0, firm.clients.size, "New firm should have cached 0 clients count" + + assert !firm.clients(true).empty?, "New firm should have reloaded client objects" + assert_equal 1, firm.clients(true).size, "New firm should have reloaded clients count" + end + + def test_storing_in_pstore + require "tmpdir" + store_filename = File.join(Dir.tmpdir, "ar-pstore-association-test") + File.delete(store_filename) if File.exists?(store_filename) + require "pstore" + apple = Firm.create("name" => "Apple") + natural = Client.new("name" => "Natural Company") + apple.clients << natural + + db = PStore.new(store_filename) + db.transaction do + db["apple"] = apple + end + + db = PStore.new(store_filename) + db.transaction do + assert_equal "Natural Company", db["apple"].clients.first.name + end + end +end + +class HasOneAssociationsTest < Test::Unit::TestCase + fixtures :accounts, :companies, :developers, :projects, :developers_projects + + def test_has_one + assert_equal companies(:first_firm).account, Account.find(1) + assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit + end + + def test_proxy_assignment + company = companies(:first_firm) + assert_nothing_raised { company.account = company.account } + end + + def test_triple_equality + assert Account === companies(:first_firm).account + assert companies(:first_firm).account === Account + end + + def test_type_mismatch + assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = 1 } + assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = Project.find(1) } + end + + def test_natural_assignment + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + apple.account = citibank + assert_equal apple.id, citibank.firm_id + end + + def test_natural_assignment_to_nil + old_account_id = companies(:first_firm).account.id + companies(:first_firm).account = nil + companies(:first_firm).save + assert_nil companies(:first_firm).account + # account is dependent, therefore is destroyed when reference to owner is lost + assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) } + end + + def test_assignment_without_replacement + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + apple.account = citibank + assert_equal apple.id, citibank.firm_id + + hsbc = apple.build_account({ :credit_limit => 20}, false) + assert_equal apple.id, hsbc.firm_id + hsbc.save + assert_equal apple.id, citibank.firm_id + + nykredit = apple.create_account({ :credit_limit => 30}, false) + assert_equal apple.id, nykredit.firm_id + assert_equal apple.id, citibank.firm_id + assert_equal apple.id, hsbc.firm_id + end + + def test_assignment_without_replacement_on_create + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + apple.account = citibank + assert_equal apple.id, citibank.firm_id + + hsbc = apple.create_account({:credit_limit => 10}, false) + assert_equal apple.id, hsbc.firm_id + hsbc.save + assert_equal apple.id, citibank.firm_id + end + + def test_dependence + num_accounts = Account.count + firm = Firm.find(1) + assert !firm.account.nil? + firm.destroy + assert_equal num_accounts - 1, Account.count + end + + def test_succesful_build_association + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + + account = firm.build_account("credit_limit" => 1000) + assert account.save + assert_equal account, firm.account + end + + def test_failing_build_association + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + + account = firm.build_account + assert !account.save + assert_equal "can't be empty", account.errors.on("credit_limit") + end + + def test_build_association_twice_without_saving_affects_nothing + count_of_account = Account.count + firm = Firm.find(:first) + account1 = firm.build_account("credit_limit" => 1000) + account2 = firm.build_account("credit_limit" => 2000) + + assert_equal count_of_account, Account.count + end + + def test_create_association + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + assert_equal firm.create_account("credit_limit" => 1000), firm.account + end + + def test_build + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + + firm.account = account = Account.new("credit_limit" => 1000) + assert_equal account, firm.account + assert account.save + assert_equal account, firm.account + end + + def test_build_before_child_saved + firm = Firm.find(1) + + account = firm.account.build("credit_limit" => 1000) + assert_equal account, firm.account + assert account.new_record? + assert firm.save + assert_equal account, firm.account + assert !account.new_record? + end + + def test_build_before_either_saved + firm = Firm.new("name" => "GlobalMegaCorp") + + firm.account = account = Account.new("credit_limit" => 1000) + assert_equal account, firm.account + assert account.new_record? + assert firm.save + assert_equal account, firm.account + assert !account.new_record? + end + + def test_failing_build_association + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + + firm.account = account = Account.new + assert_equal account, firm.account + assert !account.save + assert_equal account, firm.account + assert_equal "can't be empty", account.errors.on("credit_limit") + end + + def test_create + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + firm.account = account = Account.create("credit_limit" => 1000) + assert_equal account, firm.account + end + + def test_create_before_save + firm = Firm.new("name" => "GlobalMegaCorp") + firm.account = account = Account.create("credit_limit" => 1000) + assert_equal account, firm.account + end + + def test_dependence_with_missing_association + Account.destroy_all + firm = Firm.find(1) + assert firm.account.nil? + firm.destroy + end + + def test_assignment_before_parent_saved + firm = Firm.new("name" => "GlobalMegaCorp") + firm.account = a = Account.find(1) + assert firm.new_record? + assert_equal a, firm.account + assert firm.save + assert_equal a, firm.account + assert_equal a, firm.account(true) + end + + def test_assignment_before_child_saved + firm = Firm.find(1) + firm.account = a = Account.new("credit_limit" => 1000) + assert !a.new_record? + assert_equal a, firm.account + assert_equal a, firm.account + assert_equal a, firm.account(true) + end + + def test_assignment_before_either_saved + firm = Firm.new("name" => "GlobalMegaCorp") + firm.account = a = Account.new("credit_limit" => 1000) + assert firm.new_record? + assert a.new_record? + assert_equal a, firm.account + assert firm.save + assert !firm.new_record? + assert !a.new_record? + assert_equal a, firm.account + assert_equal a, firm.account(true) + end +end + + +class HasManyAssociationsTest < Test::Unit::TestCase + fixtures :accounts, :companies, :developers, :projects, + :developers_projects, :topics + + def setup + Client.destroyed_client_ids.clear + end + + def force_signal37_to_load_all_clients_of_firm + companies(:first_firm).clients_of_firm.each {|f| } + end + + def test_counting + assert_equal 2, Firm.find(:first).clients.count + end + + def test_finding + assert_equal 2, Firm.find(:first).clients.length + end + + def test_find_many_with_merged_options + assert_equal 1, companies(:first_firm).limited_clients.size + assert_equal 1, companies(:first_firm).limited_clients.find(:all).size + assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size + end + + def test_triple_equality + assert !(Array === Firm.find(:first).clients) + assert Firm.find(:first).clients === Array + end + + def test_finding_default_orders + assert_equal "Summit", Firm.find(:first).clients.first.name + end + + def test_finding_with_different_class_name_and_order + assert_equal "Microsoft", Firm.find(:first).clients_sorted_desc.first.name + end + + def test_finding_with_foreign_key + assert_equal "Microsoft", Firm.find(:first).clients_of_firm.first.name + end + + def test_finding_with_condition + assert_equal "Microsoft", Firm.find(:first).clients_like_ms.first.name + end + + def test_finding_using_sql + firm = Firm.find(:first) + first_client = firm.clients_using_sql.first + assert_not_nil first_client + assert_equal "Microsoft", first_client.name + assert_equal 1, firm.clients_using_sql.size + assert_equal 1, Firm.find(:first).clients_using_sql.size + end + + def test_counting_using_sql + assert_equal 1, Firm.find(:first).clients_using_counter_sql.size + assert_equal 0, Firm.find(:first).clients_using_zero_counter_sql.size + end + + def test_counting_non_existant_items_using_sql + assert_equal 0, Firm.find(:first).no_clients_using_counter_sql.size + end + + def test_belongs_to_sanity + c = Client.new + assert_nil c.firm + + if c.firm + assert false, "belongs_to failed if check" + end + + unless c.firm + else + assert false, "belongs_to failed unless check" + end + end + + def test_find_ids + firm = Firm.find(:first) + + assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find } + + client = firm.clients.find(2) + assert_kind_of Client, client + + client_ary = firm.clients.find([2]) + assert_kind_of Array, client_ary + assert_equal client, client_ary.first + + client_ary = firm.clients.find(2, 3) + assert_kind_of Array, client_ary + assert_equal 2, client_ary.size + assert_equal client, client_ary.first + + assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) } + end + + def test_find_all + firm = Firm.find_first + assert_equal firm.clients, firm.clients.find_all + assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length + assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length + end + + def test_find_all_sanitized + firm = Firm.find_first + assert_equal firm.clients.find_all("name = 'Summit'"), firm.clients.find_all(["name = '%s'", "Summit"]) + summit = firm.clients.find(:all, :conditions => "name = 'Summit'") + assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"]) + assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }]) + end + + def test_find_first + firm = Firm.find_first + client2 = Client.find(2) + assert_equal firm.clients.first, firm.clients.find_first + assert_equal client2, firm.clients.find_first("#{QUOTED_TYPE} = 'Client'") + assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'") + end + + def test_find_first_sanitized + firm = Firm.find_first + client2 = Client.find(2) + assert_equal client2, firm.clients.find_first(["#{QUOTED_TYPE} = ?", "Client"]) + assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client']) + assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }]) + end + + def test_find_in_collection + assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name + assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) } + end + + def test_find_grouped + all_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1") + grouped_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count') + assert_equal 2, all_clients_of_firm1.size + assert_equal 1, grouped_clients_of_firm1.size + end + + def test_adding + force_signal37_to_load_all_clients_of_firm + natural = Client.new("name" => "Natural Company") + companies(:first_firm).clients_of_firm << natural + assert_equal 2, companies(:first_firm).clients_of_firm.size # checking via the collection + assert_equal 2, companies(:first_firm).clients_of_firm(true).size # checking using the db + assert_equal natural, companies(:first_firm).clients_of_firm.last + end + + def test_adding_a_mismatch_class + assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil } + assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 } + assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) } + end + + def test_adding_a_collection + force_signal37_to_load_all_clients_of_firm + companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")]) + assert_equal 3, companies(:first_firm).clients_of_firm.size + assert_equal 3, companies(:first_firm).clients_of_firm(true).size + end + + def test_adding_before_save + no_of_firms = Firm.count + no_of_clients = Client.count + new_firm = Firm.new("name" => "A New Firm, Inc") + new_firm.clients_of_firm.push Client.new("name" => "Natural Company") + new_firm.clients_of_firm << (c = Client.new("name" => "Apple")) + assert new_firm.new_record? + assert c.new_record? + assert_equal 2, new_firm.clients_of_firm.size + assert_equal no_of_firms, Firm.count # Firm was not saved to database. + assert_equal no_of_clients, Client.count # Clients were not saved to database. + assert new_firm.save + assert !new_firm.new_record? + assert !c.new_record? + assert_equal new_firm, c.firm + assert_equal no_of_firms+1, Firm.count # Firm was saved to database. + assert_equal no_of_clients+2, Client.count # Clients were saved to database. + assert_equal 2, new_firm.clients_of_firm.size + assert_equal 2, new_firm.clients_of_firm(true).size + end + + def test_invalid_adding + firm = Firm.find(1) + assert !(firm.clients_of_firm << c = Client.new) + assert c.new_record? + assert !firm.valid? + assert !firm.save + assert c.new_record? + end + + def test_invalid_adding_before_save + no_of_firms = Firm.count + no_of_clients = Client.count + new_firm = Firm.new("name" => "A New Firm, Inc") + new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")]) + assert c.new_record? + assert !c.valid? + assert !new_firm.valid? + assert !new_firm.save + assert c.new_record? + assert new_firm.new_record? + end + + def test_build + new_client = companies(:first_firm).clients_of_firm.build("name" => "Another Client") + assert_equal "Another Client", new_client.name + assert new_client.new_record? + assert_equal new_client, companies(:first_firm).clients_of_firm.last + assert companies(:first_firm).save + assert !new_client.new_record? + assert_equal 2, companies(:first_firm).clients_of_firm(true).size + end + + def test_build_many + new_clients = companies(:first_firm).clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) + assert_equal 2, new_clients.size + + assert companies(:first_firm).save + assert_equal 3, companies(:first_firm).clients_of_firm(true).size + end + + def test_invalid_build + new_client = companies(:first_firm).clients_of_firm.build + assert new_client.new_record? + assert !new_client.valid? + assert_equal new_client, companies(:first_firm).clients_of_firm.last + assert !companies(:first_firm).save + assert new_client.new_record? + assert_equal 1, companies(:first_firm).clients_of_firm(true).size + end + + def test_create + force_signal37_to_load_all_clients_of_firm + new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client") + assert !new_client.new_record? + assert_equal new_client, companies(:first_firm).clients_of_firm.last + assert_equal new_client, companies(:first_firm).clients_of_firm(true).last + end + + def test_create_many + companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}]) + assert_equal 3, companies(:first_firm).clients_of_firm(true).size + end + + def test_find_or_create + number_of_clients = companies(:first_firm).clients.size + the_client = companies(:first_firm).clients.find_or_create_by_name("Yet another client") + assert_equal number_of_clients + 1, companies(:first_firm, :refresh).clients.size + assert_equal the_client, companies(:first_firm).clients.find_or_create_by_name("Yet another client") + assert_equal number_of_clients + 1, companies(:first_firm, :refresh).clients.size + end + + def test_deleting + force_signal37_to_load_all_clients_of_firm + companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first) + assert_equal 0, companies(:first_firm).clients_of_firm.size + assert_equal 0, companies(:first_firm).clients_of_firm(true).size + end + + def test_deleting_before_save + new_firm = Firm.new("name" => "A New Firm, Inc.") + new_client = new_firm.clients_of_firm.build("name" => "Another Client") + assert_equal 1, new_firm.clients_of_firm.size + new_firm.clients_of_firm.delete(new_client) + assert_equal 0, new_firm.clients_of_firm.size + end + + def test_deleting_a_collection + force_signal37_to_load_all_clients_of_firm + companies(:first_firm).clients_of_firm.create("name" => "Another Client") + assert_equal 2, companies(:first_firm).clients_of_firm.size + companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]]) + assert_equal 0, companies(:first_firm).clients_of_firm.size + assert_equal 0, companies(:first_firm).clients_of_firm(true).size + end + + def test_delete_all + force_signal37_to_load_all_clients_of_firm + companies(:first_firm).clients_of_firm.create("name" => "Another Client") + assert_equal 2, companies(:first_firm).clients_of_firm.size + companies(:first_firm).clients_of_firm.delete_all + assert_equal 0, companies(:first_firm).clients_of_firm.size + assert_equal 0, companies(:first_firm).clients_of_firm(true).size + end + + def test_delete_all_with_not_yet_loaded_association_collection + force_signal37_to_load_all_clients_of_firm + companies(:first_firm).clients_of_firm.create("name" => "Another Client") + assert_equal 2, companies(:first_firm).clients_of_firm.size + companies(:first_firm).clients_of_firm.reset + companies(:first_firm).clients_of_firm.delete_all + assert_equal 0, companies(:first_firm).clients_of_firm.size + assert_equal 0, companies(:first_firm).clients_of_firm(true).size + end + + def test_clearing_an_association_collection + firm = companies(:first_firm) + client_id = firm.clients_of_firm.first.id + assert_equal 1, firm.clients_of_firm.size + + firm.clients_of_firm.clear + + assert_equal 0, firm.clients_of_firm.size + assert_equal 0, firm.clients_of_firm(true).size + assert_equal [], Client.destroyed_client_ids[firm.id] + + # Should not be destroyed since the association is not dependent. + assert_nothing_raised do + assert Client.find(client_id).firm.nil? + end + end + + def test_clearing_a_dependent_association_collection + firm = companies(:first_firm) + client_id = firm.dependent_clients_of_firm.first.id + assert_equal 1, firm.dependent_clients_of_firm.size + + # :dependent means destroy is called on each client + firm.dependent_clients_of_firm.clear + + assert_equal 0, firm.dependent_clients_of_firm.size + assert_equal 0, firm.dependent_clients_of_firm(true).size + assert_equal [client_id], Client.destroyed_client_ids[firm.id] + + # Should be destroyed since the association is dependent. + assert Client.find_by_id(client_id).nil? + end + + def test_clearing_an_exclusively_dependent_association_collection + firm = companies(:first_firm) + client_id = firm.exclusively_dependent_clients_of_firm.first.id + assert_equal 1, firm.exclusively_dependent_clients_of_firm.size + + assert_equal [], Client.destroyed_client_ids[firm.id] + + # :exclusively_dependent means each client is deleted directly from + # the database without looping through them calling destroy. + firm.exclusively_dependent_clients_of_firm.clear + + assert_equal 0, firm.exclusively_dependent_clients_of_firm.size + assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size + assert_equal [3], Client.destroyed_client_ids[firm.id] + + # Should be destroyed since the association is exclusively dependent. + assert Client.find_by_id(client_id).nil? + end + + def test_clearing_without_initial_access + firm = companies(:first_firm) + + firm.clients_of_firm.clear + + assert_equal 0, firm.clients_of_firm.size + assert_equal 0, firm.clients_of_firm(true).size + end + + def test_deleting_a_item_which_is_not_in_the_collection + force_signal37_to_load_all_clients_of_firm + summit = Client.find_first("name = 'Summit'") + companies(:first_firm).clients_of_firm.delete(summit) + assert_equal 1, companies(:first_firm).clients_of_firm.size + assert_equal 1, companies(:first_firm).clients_of_firm(true).size + assert_equal 2, summit.client_of + end + + def test_deleting_type_mismatch + david = Developer.find(1) + david.projects.reload + assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) } + end + + def test_deleting_self_type_mismatch + david = Developer.find(1) + david.projects.reload + assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) } + end + + def test_destroy_all + force_signal37_to_load_all_clients_of_firm + assert !companies(:first_firm).clients_of_firm.empty?, "37signals has clients after load" + companies(:first_firm).clients_of_firm.destroy_all + assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all" + assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh" + end + + def test_dependence + firm = companies(:first_firm) + assert_equal 2, firm.clients.size + firm.destroy + assert Client.find(:all, :conditions => "firm_id=#{firm.id}").empty? + end + + def test_destroy_dependent_when_deleted_from_association + firm = Firm.find(:first) + assert_equal 2, firm.clients.size + + client = firm.clients.first + firm.clients.delete(client) + + assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) } + assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) } + assert_equal 1, firm.clients.size + end + + def test_three_levels_of_dependence + topic = Topic.create "title" => "neat and simple" + reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it" + silly_reply = reply.replies.create "title" => "neat and simple", "content" => "ain't complaining" + + assert_nothing_raised { topic.destroy } + end + + uses_transaction :test_dependence_with_transaction_support_on_failure + def test_dependence_with_transaction_support_on_failure + firm = companies(:first_firm) + clients = firm.clients + assert_equal 2, clients.length + clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end } + + firm.destroy rescue "do nothing" + + assert_equal 2, Client.find(:all, :conditions => "firm_id=#{firm.id}").size + end + + def test_dependence_on_account + num_accounts = Account.count + companies(:first_firm).destroy + assert_equal num_accounts - 1, Account.count + end + + def test_depends_and_nullify + num_accounts = Account.count + num_companies = Company.count + + core = companies(:rails_core) + assert_equal accounts(:rails_core_account), core.account + assert_equal [companies(:leetsoft), companies(:jadedpixel)], core.companies + core.destroy + assert_nil accounts(:rails_core_account).reload.firm_id + assert_nil companies(:leetsoft).reload.client_of + assert_nil companies(:jadedpixel).reload.client_of + + + assert_equal num_accounts, Account.count + end + + def test_included_in_collection + assert companies(:first_firm).clients.include?(Client.find(2)) + end + + def test_adding_array_and_collection + assert_nothing_raised { Firm.find(:first).clients + Firm.find(:all).last.clients } + end + + def test_find_all_without_conditions + firm = companies(:first_firm) + assert_equal 2, firm.clients.find(:all).length + end + + def test_replace_with_less + firm = Firm.find(:first) + firm.clients = [companies(:first_client)] + assert firm.save, "Could not save firm" + firm.reload + assert_equal 1, firm.clients.length + end + + + def test_replace_with_new + firm = Firm.find(:first) + new_client = Client.new("name" => "New Client") + firm.clients = [companies(:second_client),new_client] + firm.save + firm.reload + assert_equal 2, firm.clients.length + assert !firm.clients.include?(:first_client) + end + + def test_replace_on_new_object + firm = Firm.new("name" => "New Firm") + firm.clients = [companies(:second_client), Client.new("name" => "New Client")] + assert firm.save + firm.reload + assert_equal 2, firm.clients.length + assert firm.clients.include?(Client.find_by_name("New Client")) + end + + def test_assign_ids + firm = Firm.new("name" => "Apple") + firm.client_ids = [companies(:first_client).id, companies(:second_client).id] + firm.save + firm.reload + assert_equal 2, firm.clients.length + assert firm.clients.include?(companies(:second_client)) + end +end + +class BelongsToAssociationsTest < Test::Unit::TestCase + fixtures :accounts, :companies, :developers, :projects, :topics, + :developers_projects, :computers, :authors, :posts + + def test_belongs_to + Client.find(3).firm.name + assert_equal companies(:first_firm).name, Client.find(3).firm.name + assert !Client.find(3).firm.nil?, "Microsoft should have a firm" + end + + def test_proxy_assignment + account = Account.find(1) + assert_nothing_raised { account.firm = account.firm } + end + + def test_triple_equality + assert Client.find(3).firm === Firm + assert Firm === Client.find(3).firm + end + + def test_type_mismatch + assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 } + assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) } + end + + def test_natural_assignment + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + citibank.firm = apple + assert_equal apple.id, citibank.firm_id + end + + def test_creating_the_belonging_object + citibank = Account.create("credit_limit" => 10) + apple = citibank.create_firm("name" => "Apple") + assert_equal apple, citibank.firm + citibank.save + citibank.reload + assert_equal apple, citibank.firm + end + + def test_building_the_belonging_object + citibank = Account.create("credit_limit" => 10) + apple = citibank.build_firm("name" => "Apple") + citibank.save + assert_equal apple.id, citibank.firm_id + end + + def test_natural_assignment_to_nil + client = Client.find(3) + client.firm = nil + client.save + assert_nil client.firm(true) + assert_nil client.client_of + end + + def test_with_different_class_name + assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name + assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm" + end + + def test_with_condition + assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name + assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm" + end + + def test_belongs_to_counter + debate = Topic.create("title" => "debate") + assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet" + + trash = debate.replies.create("title" => "blah!", "content" => "world around!") + assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created" + + trash.destroy + assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted" + end + + def test_belongs_to_counter_with_reassigning + t1 = Topic.create("title" => "t1") + t2 = Topic.create("title" => "t2") + r1 = Reply.new("title" => "r1", "content" => "r1") + r1.topic = t1 + + assert r1.save + assert_equal 1, Topic.find(t1.id).replies.size + assert_equal 0, Topic.find(t2.id).replies.size + + r1.topic = Topic.find(t2.id) + + assert r1.save + assert_equal 0, Topic.find(t1.id).replies.size + assert_equal 1, Topic.find(t2.id).replies.size + + r1.topic = nil + + assert_equal 0, Topic.find(t1.id).replies.size + assert_equal 0, Topic.find(t2.id).replies.size + + r1.topic = t1 + + assert_equal 1, Topic.find(t1.id).replies.size + assert_equal 0, Topic.find(t2.id).replies.size + + r1.destroy + + assert_equal 0, Topic.find(t1.id).replies.size + assert_equal 0, Topic.find(t2.id).replies.size + end + + def test_assignment_before_parent_saved + client = Client.find(:first) + apple = Firm.new("name" => "Apple") + client.firm = apple + assert_equal apple, client.firm + assert apple.new_record? + assert client.save + assert apple.save + assert !apple.new_record? + assert_equal apple, client.firm + assert_equal apple, client.firm(true) + end + + def test_assignment_before_child_saved + final_cut = Client.new("name" => "Final Cut") + firm = Firm.find(1) + final_cut.firm = firm + assert final_cut.new_record? + assert final_cut.save + assert !final_cut.new_record? + assert !firm.new_record? + assert_equal firm, final_cut.firm + assert_equal firm, final_cut.firm(true) + end + + def test_assignment_before_either_saved + final_cut = Client.new("name" => "Final Cut") + apple = Firm.new("name" => "Apple") + final_cut.firm = apple + assert final_cut.new_record? + assert apple.new_record? + assert final_cut.save + assert !final_cut.new_record? + assert !apple.new_record? + assert_equal apple, final_cut.firm + assert_equal apple, final_cut.firm(true) + end + + def test_new_record_with_foreign_key_but_no_object + c = Client.new("firm_id" => 1) + assert_equal Firm.find(:first), c.firm_with_basic_id + end + + def test_forgetting_the_load_when_foreign_key_enters_late + c = Client.new + assert_nil c.firm_with_basic_id + + c.firm_id = 1 + assert_equal Firm.find(:first), c.firm_with_basic_id + end + + def test_field_name_same_as_foreign_key + computer = Computer.find(1) + assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # ' + end + + def test_counter_cache + topic = Topic.create :title => "Zoom-zoom-zoom" + assert_equal 0, topic[:replies_count] + + reply = Reply.create(:title => "re: zoom", :content => "speedy quick!") + reply.topic = topic + + assert_equal 1, topic.reload[:replies_count] + assert_equal 1, topic.replies.size + + topic[:replies_count] = 15 + assert_equal 15, topic.replies.size + end + + def test_custom_counter_cache + reply = Reply.create(:title => "re: zoom", :content => "speedy quick!") + assert_equal 0, reply[:replies_count] + + silly = SillyReply.create(:title => "gaga", :content => "boo-boo") + silly.reply = reply + + assert_equal 1, reply.reload[:replies_count] + assert_equal 1, reply.replies.size + + reply[:replies_count] = 17 + assert_equal 17, reply.replies.size + end + + def test_store_two_association_with_one_save + num_orders = Order.count + num_customers = Customer.count + order = Order.new + + customer1 = order.billing = Customer.new + customer2 = order.shipping = Customer.new + assert order.save + assert_equal customer1, order.billing + assert_equal customer2, order.shipping + + order.reload + + assert_equal customer1, order.billing + assert_equal customer2, order.shipping + + assert_equal num_orders +1, Order.count + assert_equal num_customers +2, Customer.count + end + + + def test_store_association_in_two_relations_with_one_save + num_orders = Order.count + num_customers = Customer.count + order = Order.new + + customer = order.billing = order.shipping = Customer.new + assert order.save + assert_equal customer, order.billing + assert_equal customer, order.shipping + + order.reload + + assert_equal customer, order.billing + assert_equal customer, order.shipping + + assert_equal num_orders +1, Order.count + assert_equal num_customers +1, Customer.count + end + + def test_store_association_in_two_relations_with_one_save_in_existing_object + num_orders = Order.count + num_customers = Customer.count + order = Order.create + + customer = order.billing = order.shipping = Customer.new + assert order.save + assert_equal customer, order.billing + assert_equal customer, order.shipping + + order.reload + + assert_equal customer, order.billing + assert_equal customer, order.shipping + + assert_equal num_orders +1, Order.count + assert_equal num_customers +1, Customer.count + end + + def test_store_association_in_two_relations_with_one_save_in_existing_object_with_values + num_orders = Order.count + num_customers = Customer.count + order = Order.create + + customer = order.billing = order.shipping = Customer.new + assert order.save + assert_equal customer, order.billing + assert_equal customer, order.shipping + + order.reload + + customer = order.billing = order.shipping = Customer.new + + assert order.save + order.reload + + assert_equal customer, order.billing + assert_equal customer, order.shipping + + assert_equal num_orders +1, Order.count + assert_equal num_customers +2, Customer.count + end + + + def test_association_assignment_sticks + post = Post.find(:first) + + author1, author2 = Author.find(:all, :limit => 2) + assert_not_nil author1 + assert_not_nil author2 + + # make sure the association is loaded + post.author + + # set the association by id, directly + post.author_id = author2.id + + # save and reload + post.save! + post.reload + + # the author id of the post should be the id we set + assert_equal post.author_id, author2.id + end + +end + + +class ProjectWithAfterCreateHook < ActiveRecord::Base + set_table_name 'projects' + has_and_belongs_to_many :developers, + :class_name => "DeveloperForProjectWithAfterCreateHook", + :join_table => "developers_projects", + :foreign_key => "project_id", + :association_foreign_key => "developer_id" + + after_create :add_david + + def add_david + david = DeveloperForProjectWithAfterCreateHook.find_by_name('David') + david.projects << self + end +end + +class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base + set_table_name 'developers' + has_and_belongs_to_many :projects, + :class_name => "ProjectWithAfterCreateHook", + :join_table => "developers_projects", + :association_foreign_key => "project_id", + :foreign_key => "developer_id" +end + + +class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase + fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects + + def test_has_and_belongs_to_many + david = Developer.find(1) + + assert !david.projects.empty? + assert_equal 2, david.projects.size + + active_record = Project.find(1) + assert !active_record.developers.empty? + assert_equal 3, active_record.developers.size + assert active_record.developers.include?(david) + end + + def test_triple_equality + assert !(Array === Developer.find(1).projects) + assert Developer.find(1).projects === Array + end + + def test_adding_single + jamis = Developer.find(2) + jamis.projects.reload # causing the collection to load + action_controller = Project.find(2) + assert_equal 1, jamis.projects.size + assert_equal 1, action_controller.developers.size + + jamis.projects << action_controller + + assert_equal 2, jamis.projects.size + assert_equal 2, jamis.projects(true).size + assert_equal 2, action_controller.developers(true).size + end + + def test_adding_type_mismatch + jamis = Developer.find(2) + assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil } + assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 } + end + + def test_adding_from_the_project + jamis = Developer.find(2) + action_controller = Project.find(2) + action_controller.developers.reload + assert_equal 1, jamis.projects.size + assert_equal 1, action_controller.developers.size + + action_controller.developers << jamis + + assert_equal 2, jamis.projects(true).size + assert_equal 2, action_controller.developers.size + assert_equal 2, action_controller.developers(true).size + end + + def test_adding_from_the_project_fixed_timestamp + jamis = Developer.find(2) + action_controller = Project.find(2) + action_controller.developers.reload + assert_equal 1, jamis.projects.size + assert_equal 1, action_controller.developers.size + updated_at = jamis.updated_at + + action_controller.developers << jamis + + assert_equal updated_at, jamis.updated_at + assert_equal 2, jamis.projects(true).size + assert_equal 2, action_controller.developers.size + assert_equal 2, action_controller.developers(true).size + end + + def test_adding_multiple + aredridel = Developer.new("name" => "Aredridel") + aredridel.save + aredridel.projects.reload + aredridel.projects.push(Project.find(1), Project.find(2)) + assert_equal 2, aredridel.projects.size + assert_equal 2, aredridel.projects(true).size + end + + def test_adding_a_collection + aredridel = Developer.new("name" => "Aredridel") + aredridel.save + aredridel.projects.reload + aredridel.projects.concat([Project.find(1), Project.find(2)]) + assert_equal 2, aredridel.projects.size + assert_equal 2, aredridel.projects(true).size + end + + def test_adding_uses_default_values_on_join_table + ac = projects(:action_controller) + assert !developers(:jamis).projects.include?(ac) + developers(:jamis).projects << ac + + assert developers(:jamis, :reload).projects.include?(ac) + project = developers(:jamis).projects.detect { |p| p == ac } + assert_equal 1, project.access_level.to_i + end + + def test_adding_uses_explicit_values_on_join_table + ac = projects(:action_controller) + assert !developers(:jamis).projects.include?(ac) + developers(:jamis).projects.push_with_attributes(ac, :access_level => 3) + + assert developers(:jamis, :reload).projects.include?(ac) + project = developers(:jamis).projects.detect { |p| p == ac } + assert_equal 3, project.access_level.to_i + end + + def test_hatbm_attribute_access_and_respond_to + project = developers(:jamis).projects[0] + assert project.has_attribute?("name") + assert project.has_attribute?("joined_on") + assert project.has_attribute?("access_level") + assert project.respond_to?("name") + assert project.respond_to?("name=") + assert project.respond_to?("name?") + assert project.respond_to?("joined_on") + assert project.respond_to?("joined_on=") + assert project.respond_to?("joined_on?") + assert project.respond_to?("access_level") + assert project.respond_to?("access_level=") + assert project.respond_to?("access_level?") + end + + def test_habtm_adding_before_save + no_of_devels = Developer.count + no_of_projects = Project.count + aredridel = Developer.new("name" => "Aredridel") + aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")]) + assert aredridel.new_record? + assert p.new_record? + assert aredridel.save + assert !aredridel.new_record? + assert_equal no_of_devels+1, Developer.count + assert_equal no_of_projects+1, Project.count + assert_equal 2, aredridel.projects.size + assert_equal 2, aredridel.projects(true).size + end + + def test_habtm_adding_before_save_with_join_attributes + no_of_devels = Developer.count + no_of_projects = Project.count + now = Date.today + ken = Developer.new("name" => "Ken") + ken.projects.push_with_attributes( Project.find(1), :joined_on => now ) + p = Project.new("name" => "Foomatic") + ken.projects.push_with_attributes( p, :joined_on => now ) + assert ken.new_record? + assert p.new_record? + assert ken.save + assert !ken.new_record? + assert_equal no_of_devels+1, Developer.count + assert_equal no_of_projects+1, Project.count + assert_equal 2, ken.projects.size + assert_equal 2, ken.projects(true).size + + kenReloaded = Developer.find_by_name 'Ken' + kenReloaded.projects.each {|prj| assert_date_from_db(now, prj.joined_on)} + end + + def test_habtm_saving_multiple_relationships + new_project = Project.new("name" => "Grimetime") + amount_of_developers = 4 + developers = (0..amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") } + + new_project.developer_ids = [developers[0].id, developers[1].id] + new_project.developers_with_callback_ids = [developers[2].id, developers[3].id] + assert new_project.save + + new_project.reload + assert_equal amount_of_developers, new_project.developers.size + amount_of_developers.times do |i| + assert_equal developers[i].name, new_project.developers[i].name + end + end + + def test_build + devel = Developer.find(1) + proj = devel.projects.build("name" => "Projekt") + assert_equal devel.projects.last, proj + assert proj.new_record? + devel.save + assert !proj.new_record? + assert_equal devel.projects.last, proj + end + + def test_create + devel = Developer.find(1) + proj = devel.projects.create("name" => "Projekt") + assert_equal devel.projects.last, proj + assert !proj.new_record? + end + + def test_uniq_after_the_fact + developers(:jamis).projects << projects(:active_record) + developers(:jamis).projects << projects(:active_record) + assert_equal 3, developers(:jamis).projects.size + assert_equal 1, developers(:jamis).projects.uniq.size + end + + def test_uniq_before_the_fact + projects(:active_record).developers << developers(:jamis) + projects(:active_record).developers << developers(:david) + assert_equal 3, projects(:active_record, :reload).developers.size + end + + def test_deleting + david = Developer.find(1) + active_record = Project.find(1) + david.projects.reload + assert_equal 2, david.projects.size + assert_equal 3, active_record.developers.size + + david.projects.delete(active_record) + + assert_equal 1, david.projects.size + assert_equal 1, david.projects(true).size + assert_equal 2, active_record.developers(true).size + end + + def test_deleting_array + david = Developer.find(1) + david.projects.reload + david.projects.delete(Project.find(:all)) + assert_equal 0, david.projects.size + assert_equal 0, david.projects(true).size + end + + def test_deleting_with_sql + david = Developer.find(1) + active_record = Project.find(1) + active_record.developers.reload + assert_equal 3, active_record.developers_by_sql.size + + active_record.developers_by_sql.delete(david) + assert_equal 2, active_record.developers_by_sql(true).size + end + + def test_deleting_array_with_sql + active_record = Project.find(1) + active_record.developers.reload + assert_equal 3, active_record.developers_by_sql.size + + active_record.developers_by_sql.delete(Developer.find(:all)) + assert_equal 0, active_record.developers_by_sql(true).size + end + + def test_deleting_all + david = Developer.find(1) + david.projects.reload + david.projects.clear + assert_equal 0, david.projects.size + assert_equal 0, david.projects(true).size + end + + def test_removing_associations_on_destroy + david = DeveloperWithBeforeDestroyRaise.find(1) + assert !david.projects.empty? + assert_nothing_raised { david.destroy } + assert david.projects.empty? + assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty? + end + + def test_additional_columns_from_join_table + assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on + end + + def test_destroy_all + david = Developer.find(1) + david.projects.reload + assert !david.projects.empty? + david.projects.destroy_all + assert david.projects.empty? + assert david.projects(true).empty? + end + + def test_rich_association + jamis = developers(:jamis) + jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today) + + assert_date_from_db Date.today, jamis.projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on + assert_date_from_db Date.today, developers(:jamis).projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on + end + + def test_associations_with_conditions + assert_equal 3, projects(:active_record).developers.size + assert_equal 1, projects(:active_record).developers_named_david.size + + assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id) + assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id) + + projects(:active_record).developers_named_david.clear + assert_equal 2, projects(:active_record, :reload).developers.size + end + + def test_find_in_association + # Using sql + assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find" + + # Using ruby + active_record = projects(:active_record) + active_record.developers.reload + assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find" + end + + def test_find_in_association_with_custom_finder_sql + assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find" + + active_record = projects(:active_record) + active_record.developers_with_finder_sql.reload + assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find" + end + + def test_find_in_association_with_custom_finder_sql_and_string_id + assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find" + end + + def test_find_with_merged_options + assert_equal 1, projects(:active_record).limited_developers.size + assert_equal 1, projects(:active_record).limited_developers.find(:all).size + assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size + end + + def test_new_with_values_in_collection + jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis') + david = DeveloperForProjectWithAfterCreateHook.find_by_name('David') + project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie") + project.developers << jamis + project.save! + project.reload + + assert project.developers.include?(jamis) + assert project.developers.include?(david) + end + + def test_find_in_association_with_options + developers = projects(:active_record).developers.find(:all) + assert_equal 3, developers.size + + assert_equal developers(:poor_jamis), projects(:active_record).developers.find(:first, :conditions => "salary < 10000") + assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC") + end + + def test_replace_with_less + david = developers(:david) + david.projects = [projects(:action_controller)] + assert david.save + assert_equal 1, david.projects.length + end + + def test_replace_with_new + david = developers(:david) + david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")] + david.save + assert_equal 2, david.projects.length + assert !david.projects.include?(projects(:active_record)) + end + + def test_replace_on_new_object + new_developer = Developer.new("name" => "Matz") + new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")] + new_developer.save + assert_equal 2, new_developer.projects.length + end + + def test_consider_type + developer = Developer.find(:first) + special_project = SpecialProject.create("name" => "Special Project") + + other_project = developer.projects.first + developer.special_projects << special_project + developer.reload + + assert developer.projects.include?(special_project) + assert developer.special_projects.include?(special_project) + assert !developer.special_projects.include?(other_project) + end + + def test_update_attributes_after_push_without_duplicate_join_table_rows + developer = Developer.new("name" => "Kano") + project = SpecialProject.create("name" => "Special Project") + assert developer.save + developer.projects << project + developer.update_attribute("name", "Bruza") + assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i + SELECT count(*) FROM developers_projects + WHERE project_id = #{project.id} + AND developer_id = #{developer.id} + end_sql + end + + def test_updating_attributes_on_non_rich_associations + welcome = categories(:technology).posts.first + welcome.title = "Something else" + assert welcome.save! + end + + def test_updating_attributes_on_rich_associations + david = projects(:action_controller).developers.first + david.name = "DHH" + assert_raises(ActiveRecord::ReadOnlyRecord) { david.save! } + end + + + def test_updating_attributes_on_rich_associations_with_limited_find + david = projects(:action_controller).developers.find(:all, :select => "developers.*").first + david.name = "DHH" + assert david.save! + end + + def test_join_table_alias + assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size + end +end +require 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/reply' +require 'fixtures/company' +require 'fixtures/customer' +require 'fixtures/developer' +require 'fixtures/project' +require 'fixtures/default' +require 'fixtures/auto_id' +require 'fixtures/column_name' +require 'fixtures/subscriber' +require 'fixtures/keyboard' + +class Category < ActiveRecord::Base; end +class Smarts < ActiveRecord::Base; end +class CreditCard < ActiveRecord::Base; end +class MasterCreditCard < ActiveRecord::Base; end +class Post < ActiveRecord::Base; end +class Computer < ActiveRecord::Base; end +class NonExistentTable < ActiveRecord::Base; end +class TestOracleDefault < ActiveRecord::Base; end + +class LoosePerson < ActiveRecord::Base + attr_protected :credit_rating, :administrator + self.abstract_class = true +end + +class LooseDescendant < LoosePerson + attr_protected :phone_number +end + +class TightPerson < ActiveRecord::Base + attr_accessible :name, :address +end + +class TightDescendant < TightPerson + attr_accessible :phone_number +end + +class Booleantest < ActiveRecord::Base; end + +class Task < ActiveRecord::Base + attr_protected :starting +end + +class BasicsTest < Test::Unit::TestCase + fixtures :topics, :companies, :developers, :projects, :computers + + def test_table_exists + assert !NonExistentTable.table_exists? + assert Topic.table_exists? + end + + def test_set_attributes + topic = Topic.find(1) + topic.attributes = { "title" => "Budget", "author_name" => "Jason" } + topic.save + assert_equal("Budget", topic.title) + assert_equal("Jason", topic.author_name) + assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address) + end + + def test_integers_as_nil + test = AutoId.create('value' => '') + assert_nil AutoId.find(test.id).value + end + + def test_set_attributes_with_block + topic = Topic.new do |t| + t.title = "Budget" + t.author_name = "Jason" + end + + assert_equal("Budget", topic.title) + assert_equal("Jason", topic.author_name) + end + + def test_respond_to? + topic = Topic.find(1) + assert topic.respond_to?("title") + assert topic.respond_to?("title?") + assert topic.respond_to?("title=") + assert topic.respond_to?(:title) + assert topic.respond_to?(:title?) + assert topic.respond_to?(:title=) + assert topic.respond_to?("author_name") + assert topic.respond_to?("attribute_names") + assert !topic.respond_to?("nothingness") + assert !topic.respond_to?(:nothingness) + end + + def test_array_content + topic = Topic.new + topic.content = %w( one two three ) + topic.save + + assert_equal(%w( one two three ), Topic.find(topic.id).content) + end + + def test_hash_content + topic = Topic.new + topic.content = { "one" => 1, "two" => 2 } + topic.save + + assert_equal 2, Topic.find(topic.id).content["two"] + + topic.content["three"] = 3 + topic.save + + assert_equal 3, Topic.find(topic.id).content["three"] + end + + def test_update_array_content + topic = Topic.new + topic.content = %w( one two three ) + + topic.content.push "four" + assert_equal(%w( one two three four ), topic.content) + + topic.save + + topic = Topic.find(topic.id) + topic.content << "five" + assert_equal(%w( one two three four five ), topic.content) + end + + def test_case_sensitive_attributes_hash + # DB2 is not case-sensitive + return true if current_adapter?(:DB2Adapter) + + assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.find(:first).attributes + end + + def test_create + topic = Topic.new + topic.title = "New Topic" + topic.save + topic_reloaded = Topic.find(topic.id) + assert_equal("New Topic", topic_reloaded.title) + end + + def test_save! + topic = Topic.new(:title => "New Topic") + assert topic.save! + end + + def test_hashes_not_mangled + new_topic = { :title => "New Topic" } + new_topic_values = { :title => "AnotherTopic" } + + topic = Topic.new(new_topic) + assert_equal new_topic[:title], topic.title + + topic.attributes= new_topic_values + assert_equal new_topic_values[:title], topic.title + end + + def test_create_many + topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) + assert_equal 2, topics.size + assert_equal "first", topics.first.title + end + + def test_create_columns_not_equal_attributes + topic = Topic.new + topic.title = 'Another New Topic' + topic.send :write_attribute, 'does_not_exist', 'test' + assert_nothing_raised { topic.save } + end + + def test_create_through_factory + topic = Topic.create("title" => "New Topic") + topicReloaded = Topic.find(topic.id) + assert_equal(topic, topicReloaded) + end + + def test_update + topic = Topic.new + topic.title = "Another New Topic" + topic.written_on = "2003-12-12 23:23:00" + topic.save + topicReloaded = Topic.find(topic.id) + assert_equal("Another New Topic", topicReloaded.title) + + topicReloaded.title = "Updated topic" + topicReloaded.save + + topicReloadedAgain = Topic.find(topic.id) + + assert_equal("Updated topic", topicReloadedAgain.title) + end + + def test_update_columns_not_equal_attributes + topic = Topic.new + topic.title = "Still another topic" + topic.save + + topicReloaded = Topic.find(topic.id) + topicReloaded.title = "A New Topic" + topicReloaded.send :write_attribute, 'does_not_exist', 'test' + assert_nothing_raised { topicReloaded.save } + end + + def test_write_attribute + topic = Topic.new + topic.send(:write_attribute, :title, "Still another topic") + assert_equal "Still another topic", topic.title + + topic.send(:write_attribute, "title", "Still another topic: part 2") + assert_equal "Still another topic: part 2", topic.title + end + + def test_read_attribute + topic = Topic.new + topic.title = "Don't change the topic" + assert_equal "Don't change the topic", topic.send(:read_attribute, "title") + assert_equal "Don't change the topic", topic["title"] + + assert_equal "Don't change the topic", topic.send(:read_attribute, :title) + assert_equal "Don't change the topic", topic[:title] + end + + def test_read_attribute_when_false + topic = topics(:first) + topic.approved = false + assert !topic.approved?, "approved should be false" + topic.approved = "false" + assert !topic.approved?, "approved should be false" + end + + def test_read_attribute_when_true + topic = topics(:first) + topic.approved = true + assert topic.approved?, "approved should be true" + topic.approved = "true" + assert topic.approved?, "approved should be true" + end + + def test_read_write_boolean_attribute + topic = Topic.new + # puts "" + # puts "New Topic" + # puts topic.inspect + topic.approved = "false" + # puts "Expecting false" + # puts topic.inspect + assert !topic.approved?, "approved should be false" + topic.approved = "false" + # puts "Expecting false" + # puts topic.inspect + assert !topic.approved?, "approved should be false" + topic.approved = "true" + # puts "Expecting true" + # puts topic.inspect + assert topic.approved?, "approved should be true" + topic.approved = "true" + # puts "Expecting true" + # puts topic.inspect + assert topic.approved?, "approved should be true" + # puts "" + end + + def test_reader_generation + Topic.find(:first).title + Firm.find(:first).name + Client.find(:first).name + if ActiveRecord::Base.generate_read_methods + assert_readers(Topic, %w(type replies_count)) + assert_readers(Firm, %w(type)) + assert_readers(Client, %w(type ruby_type rating?)) + else + [Topic, Firm, Client].each {|klass| assert_equal klass.read_methods, {}} + end + end + + def test_reader_for_invalid_column_names + # column names which aren't legal ruby ids + topic = Topic.find(:first) + topic.send(:define_read_method, "mumub-jumbo".to_sym, "mumub-jumbo", nil) + assert !Topic.read_methods.include?("mumub-jumbo") + end + + def test_non_attribute_access_and_assignment + topic = Topic.new + assert !topic.respond_to?("mumbo") + assert_raises(NoMethodError) { topic.mumbo } + assert_raises(NoMethodError) { topic.mumbo = 5 } + end + + def test_preserving_date_objects + # SQL Server doesn't have a separate column type just for dates, so all are returned as time + return true if current_adapter?(:SQLServerAdapter) + + if current_adapter?(:SybaseAdapter) + # Sybase ctlib does not (yet?) support the date type; use datetime instead. + assert_kind_of( + Time, Topic.find(1).last_read, + "The last_read attribute should be of the Time class" + ) + else + assert_kind_of( + Date, Topic.find(1).last_read, + "The last_read attribute should be of the Date class" + ) + end + end + + def test_preserving_time_objects + assert_kind_of( + Time, Topic.find(1).bonus_time, + "The bonus_time attribute should be of the Time class" + ) + + assert_kind_of( + Time, Topic.find(1).written_on, + "The written_on attribute should be of the Time class" + ) + end + + def test_destroy + topic = Topic.new + topic.title = "Yet Another New Topic" + topic.written_on = "2003-12-12 23:23:00" + topic.save + topic.destroy + assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) } + end + + def test_destroy_returns_self + topic = Topic.new("title" => "Yet Another Title") + assert topic.save + assert_equal topic, topic.destroy, "destroy did not return destroyed object" + end + + def test_record_not_found_exception + assert_raises(ActiveRecord::RecordNotFound) { topicReloaded = Topic.find(99999) } + end + + def test_initialize_with_attributes + topic = Topic.new({ + "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23" + }) + + assert_equal("initialized from attributes", topic.title) + end + + def test_initialize_with_invalid_attribute + begin + topic = Topic.new({ "title" => "test", + "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"}) + rescue ActiveRecord::MultiparameterAssignmentErrors => ex + assert_equal(1, ex.errors.size) + assert_equal("last_read", ex.errors[0].attribute) + end + end + + def test_load + topics = Topic.find(:all, :order => 'id') + assert_equal(2, topics.size) + assert_equal(topics(:first).title, topics.first.title) + end + + def test_load_with_condition + topics = Topic.find(:all, :conditions => "author_name = 'Mary'") + + assert_equal(1, topics.size) + assert_equal(topics(:second).title, topics.first.title) + end + + def test_table_name_guesses + assert_equal "topics", Topic.table_name + + assert_equal "categories", Category.table_name + assert_equal "smarts", Smarts.table_name + assert_equal "credit_cards", CreditCard.table_name + assert_equal "master_credit_cards", MasterCreditCard.table_name + + ActiveRecord::Base.pluralize_table_names = false + [Category, Smarts, CreditCard, MasterCreditCard].each{|c| c.reset_table_name} + assert_equal "category", Category.table_name + assert_equal "smarts", Smarts.table_name + assert_equal "credit_card", CreditCard.table_name + assert_equal "master_credit_card", MasterCreditCard.table_name + ActiveRecord::Base.pluralize_table_names = true + [Category, Smarts, CreditCard, MasterCreditCard].each{|c| c.reset_table_name} + + ActiveRecord::Base.table_name_prefix = "test_" + Category.reset_table_name + assert_equal "test_categories", Category.table_name + ActiveRecord::Base.table_name_suffix = "_test" + Category.reset_table_name + assert_equal "test_categories_test", Category.table_name + ActiveRecord::Base.table_name_prefix = "" + Category.reset_table_name + assert_equal "categories_test", Category.table_name + ActiveRecord::Base.table_name_suffix = "" + Category.reset_table_name + assert_equal "categories", Category.table_name + + ActiveRecord::Base.pluralize_table_names = false + ActiveRecord::Base.table_name_prefix = "test_" + Category.reset_table_name + assert_equal "test_category", Category.table_name + ActiveRecord::Base.table_name_suffix = "_test" + Category.reset_table_name + assert_equal "test_category_test", Category.table_name + ActiveRecord::Base.table_name_prefix = "" + Category.reset_table_name + assert_equal "category_test", Category.table_name + ActiveRecord::Base.table_name_suffix = "" + Category.reset_table_name + assert_equal "category", Category.table_name + ActiveRecord::Base.pluralize_table_names = true + [Category, Smarts, CreditCard, MasterCreditCard].each{|c| c.reset_table_name} + end + + def test_destroy_all + assert_equal 2, Topic.count + + Topic.destroy_all "author_name = 'Mary'" + assert_equal 1, Topic.count + end + + def test_destroy_many + assert_equal 3, Client.count + Client.destroy([2, 3]) + assert_equal 1, Client.count + end + + def test_delete_many + Topic.delete([1, 2]) + assert_equal 0, Topic.count + end + + def test_boolean_attributes + assert ! Topic.find(1).approved? + assert Topic.find(2).approved? + end + + def test_increment_counter + Topic.increment_counter("replies_count", 1) + assert_equal 1, Topic.find(1).replies_count + + Topic.increment_counter("replies_count", 1) + assert_equal 2, Topic.find(1).replies_count + end + + def test_decrement_counter + Topic.decrement_counter("replies_count", 2) + assert_equal 1, Topic.find(2).replies_count + + Topic.decrement_counter("replies_count", 2) + assert_equal 0, Topic.find(1).replies_count + end + + def test_update_all + # The ADO library doesn't support the number of affected rows + return true if current_adapter?(:SQLServerAdapter) + + assert_equal 2, Topic.update_all("content = 'bulk updated!'") + assert_equal "bulk updated!", Topic.find(1).content + assert_equal "bulk updated!", Topic.find(2).content + assert_equal 2, Topic.update_all(['content = ?', 'bulk updated again!']) + assert_equal "bulk updated again!", Topic.find(1).content + assert_equal "bulk updated again!", Topic.find(2).content + end + + def test_update_many + topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } } + updated = Topic.update(topic_data.keys, topic_data.values) + + assert_equal 2, updated.size + assert_equal "1 updated", Topic.find(1).content + assert_equal "2 updated", Topic.find(2).content + end + + def test_delete_all + # The ADO library doesn't support the number of affected rows + return true if current_adapter?(:SQLServerAdapter) + + assert_equal 2, Topic.delete_all + end + + def test_update_by_condition + Topic.update_all "content = 'bulk updated!'", ["approved = ?", true] + assert_equal "Have a nice day", Topic.find(1).content + assert_equal "bulk updated!", Topic.find(2).content + end + + def test_attribute_present + t = Topic.new + t.title = "hello there!" + t.written_on = Time.now + assert t.attribute_present?("title") + assert t.attribute_present?("written_on") + assert !t.attribute_present?("content") + end + + def test_attribute_keys_on_new_instance + t = Topic.new + assert_equal nil, t.title, "The topics table has a title column, so it should be nil" + assert_raise(NoMethodError) { t.title2 } + end + + def test_class_name + assert_equal "Firm", ActiveRecord::Base.class_name("firms") + assert_equal "Category", ActiveRecord::Base.class_name("categories") + assert_equal "AccountHolder", ActiveRecord::Base.class_name("account_holder") + + ActiveRecord::Base.pluralize_table_names = false + assert_equal "Firms", ActiveRecord::Base.class_name( "firms" ) + ActiveRecord::Base.pluralize_table_names = true + + ActiveRecord::Base.table_name_prefix = "test_" + assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms" ) + ActiveRecord::Base.table_name_suffix = "_tests" + assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms_tests" ) + ActiveRecord::Base.table_name_prefix = "" + assert_equal "Firm", ActiveRecord::Base.class_name( "firms_tests" ) + ActiveRecord::Base.table_name_suffix = "" + assert_equal "Firm", ActiveRecord::Base.class_name( "firms" ) + end + + def test_null_fields + assert_nil Topic.find(1).parent_id + assert_nil Topic.create("title" => "Hey you").parent_id + end + + def test_default_values + topic = Topic.new + assert topic.approved? + assert_nil topic.written_on + assert_nil topic.bonus_time + assert_nil topic.last_read + + topic.save + + topic = Topic.find(topic.id) + assert topic.approved? + assert_nil topic.last_read + + # Oracle has some funky default handling, so it requires a bit of + # extra testing. See ticket #2788. + if current_adapter?(:OracleAdapter) + test = TestOracleDefault.new + assert_equal "X", test.test_char + assert_equal "hello", test.test_string + assert_equal 3, test.test_int + end + end + + def test_utc_as_time_zone + # Oracle and SQLServer do not have a TIME datatype. + return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) + + Topic.default_timezone = :utc + attributes = { "bonus_time" => "5:42:00AM" } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time + Topic.default_timezone = :local + end + + def test_default_values_on_empty_strings + topic = Topic.new + topic.approved = nil + topic.last_read = nil + + topic.save + + topic = Topic.find(topic.id) + assert_nil topic.last_read + + # Sybase adapter does not allow nulls in boolean columns + if current_adapter?(:SybaseAdapter) + assert topic.approved == false + else + assert_nil topic.approved + end + end + + def test_equality + assert_equal Topic.find(1), Topic.find(2).topic + end + + def test_equality_of_new_records + assert_not_equal Topic.new, Topic.new + end + + def test_hashing + assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ] + end + + def test_destroy_new_record + client = Client.new + client.destroy + assert client.frozen? + end + + def test_destroy_record_with_associations + client = Client.find(3) + client.destroy + assert client.frozen? + assert_kind_of Firm, client.firm + assert_raises(TypeError) { client.name = "something else" } + end + + def test_update_attribute + assert !Topic.find(1).approved? + Topic.find(1).update_attribute("approved", true) + assert Topic.find(1).approved? + + Topic.find(1).update_attribute(:approved, false) + assert !Topic.find(1).approved? + end + + def test_mass_assignment_protection + firm = Firm.new + firm.attributes = { "name" => "Next Angle", "rating" => 5 } + assert_equal 1, firm.rating + end + + def test_customized_primary_key_remains_protected + subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try') + assert_nil subscriber.id + + keyboard = Keyboard.new(:key_number => 9, :name => 'nice try') + assert_nil keyboard.id + end + + def test_customized_primary_key_remains_protected_when_refered_to_as_id + subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try') + assert_nil subscriber.id + + keyboard = Keyboard.new(:id => 9, :name => 'nice try') + assert_nil keyboard.id + end + + def test_mass_assignment_protection_on_defaults + firm = Firm.new + firm.attributes = { "id" => 5, "type" => "Client" } + assert_nil firm.id + assert_equal "Firm", firm[:type] + end + + def test_mass_assignment_accessible + reply = Reply.new("title" => "hello", "content" => "world", "approved" => true) + reply.save + + assert reply.approved? + + reply.approved = false + reply.save + + assert !reply.approved? + end + + def test_mass_assignment_protection_inheritance + assert_nil LoosePerson.accessible_attributes + assert_equal [ :credit_rating, :administrator ], LoosePerson.protected_attributes + + assert_nil LooseDescendant.accessible_attributes + assert_equal [ :credit_rating, :administrator, :phone_number ], LooseDescendant.protected_attributes + + assert_nil TightPerson.protected_attributes + assert_equal [ :name, :address ], TightPerson.accessible_attributes + + assert_nil TightDescendant.protected_attributes + assert_equal [ :name, :address, :phone_number ], TightDescendant.accessible_attributes + end + + def test_multiparameter_attributes_on_date + attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" } + topic = Topic.find(1) + topic.attributes = attributes + # note that extra #to_date call allows test to pass for Oracle, which + # treats dates/times the same + assert_date_from_db Date.new(2004, 6, 24), topic.last_read.to_date + end + + def test_multiparameter_attributes_on_date_with_empty_date + attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" } + topic = Topic.find(1) + topic.attributes = attributes + # note that extra #to_date call allows test to pass for Oracle, which + # treats dates/times the same + assert_date_from_db Date.new(2004, 6, 1), topic.last_read.to_date + end + + def test_multiparameter_attributes_on_date_with_all_empty + attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "" } + topic = Topic.find(1) + topic.attributes = attributes + assert_nil topic.last_read + end + + def test_multiparameter_attributes_on_time + attributes = { + "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", + "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on + end + + def test_multiparameter_attributes_on_time_with_empty_seconds + attributes = { + "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", + "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on + end + + def test_multiparameter_mass_assignment_protector + task = Task.new + time = Time.mktime(2000, 1, 1, 1) + task.starting = time + attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" } + task.attributes = attributes + assert_equal time, task.starting + end + + def test_multiparameter_assignment_of_aggregation + customer = Customer.new + address = Address.new("The Street", "The City", "The Country") + attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country } + customer.attributes = attributes + assert_equal address, customer.address + end + + def test_attributes_on_dummy_time + # Oracle and SQL Server do not have a TIME datatype. + return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) + + attributes = { + "bonus_time" => "5:42:00AM" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time + end + + def test_boolean + b_false = Booleantest.create({ "value" => false }) + false_id = b_false.id + b_true = Booleantest.create({ "value" => true }) + true_id = b_true.id + + b_false = Booleantest.find(false_id) + assert !b_false.value? + b_true = Booleantest.find(true_id) + assert b_true.value? + end + + def test_boolean_cast_from_string + b_false = Booleantest.create({ "value" => "0" }) + false_id = b_false.id + b_true = Booleantest.create({ "value" => "1" }) + true_id = b_true.id + + b_false = Booleantest.find(false_id) + assert !b_false.value? + b_true = Booleantest.find(true_id) + assert b_true.value? + end + + def test_clone + topic = Topic.find(1) + cloned_topic = nil + assert_nothing_raised { cloned_topic = topic.clone } + assert_equal topic.title, cloned_topic.title + assert cloned_topic.new_record? + + # test if the attributes have been cloned + topic.title = "a" + cloned_topic.title = "b" + assert_equal "a", topic.title + assert_equal "b", cloned_topic.title + + # test if the attribute values have been cloned + topic.title = {"a" => "b"} + cloned_topic = topic.clone + cloned_topic.title["a"] = "c" + assert_equal "b", topic.title["a"] + + cloned_topic.save + assert !cloned_topic.new_record? + assert cloned_topic.id != topic.id + end + + def test_clone_with_aggregate_of_same_name_as_attribute + dev = DeveloperWithAggregate.find(1) + assert_kind_of DeveloperSalary, dev.salary + + clone = nil + assert_nothing_raised { clone = dev.clone } + assert_kind_of DeveloperSalary, clone.salary + assert_equal dev.salary.amount, clone.salary.amount + assert clone.new_record? + + # test if the attributes have been cloned + original_amount = clone.salary.amount + dev.salary.amount = 1 + assert_equal original_amount, clone.salary.amount + + assert clone.save + assert !clone.new_record? + assert clone.id != dev.id + end + + def test_clone_preserves_subtype + clone = nil + assert_nothing_raised { clone = Company.find(3).clone } + assert_kind_of Client, clone + end + + def test_bignum + company = Company.find(1) + company.rating = 2147483647 + company.save + company = Company.find(1) + assert_equal 2147483647, company.rating + end + + # TODO: extend defaults tests to other databases! + if current_adapter?(:PostgreSQLAdapter) + def test_default + default = Default.new + + # fixed dates / times + assert_equal Date.new(2004, 1, 1), default.fixed_date + assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time + + # char types + assert_equal 'Y', default.char1 + assert_equal 'a varchar field', default.char2 + assert_equal 'a text field', default.char3 + end + + class Geometric < ActiveRecord::Base; end + def test_geometric_content + + # accepted format notes: + # ()'s aren't required + # values can be a mix of float or integer + + g = Geometric.new( + :a_point => '(5.0, 6.1)', + #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql + :a_line_segment => '(2.0, 3), (5.5, 7.0)', + :a_box => '2.0, 3, 5.5, 7.0', + :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path + :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', + :a_circle => '<(5.3, 10.4), 2>' + ) + + assert g.save + + # Reload and check that we have all the geometric attributes. + h = Geometric.find(g.id) + + assert_equal '(5,6.1)', h.a_point + assert_equal '[(2,3),(5.5,7)]', h.a_line_segment + assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner + assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path + assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon + assert_equal '<(5.3,10.4),2>', h.a_circle + + # use a geometric function to test for an open path + objs = Geometric.find_by_sql ["select isopen(a_path) from geometrics where id = ?", g.id] + assert_equal objs[0].isopen, 't' + + # test alternate formats when defining the geometric types + + g = Geometric.new( + :a_point => '5.0, 6.1', + #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql + :a_line_segment => '((2.0, 3), (5.5, 7.0))', + :a_box => '(2.0, 3), (5.5, 7.0)', + :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path + :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0', + :a_circle => '((5.3, 10.4), 2)' + ) + + assert g.save + + # Reload and check that we have all the geometric attributes. + h = Geometric.find(g.id) + + assert_equal '(5,6.1)', h.a_point + assert_equal '[(2,3),(5.5,7)]', h.a_line_segment + assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner + assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path + assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon + assert_equal '<(5.3,10.4),2>', h.a_circle + + # use a geometric function to test for an closed path + objs = Geometric.find_by_sql ["select isclosed(a_path) from geometrics where id = ?", g.id] + assert_equal objs[0].isclosed, 't' + end + end + + def test_auto_id + auto = AutoId.new + auto.save + assert (auto.id > 0) + end + + def quote_column_name(name) + "<#{name}>" + end + + def test_quote_keys + ar = AutoId.new + source = {"foo" => "bar", "baz" => "quux"} + actual = ar.send(:quote_columns, self, source) + inverted = actual.invert + assert_equal("<foo>", inverted["bar"]) + assert_equal("<baz>", inverted["quux"]) + end + + def test_sql_injection_via_find + assert_raises(ActiveRecord::RecordNotFound) do + Topic.find("123456 OR id > 0") + end + + assert_raises(ActiveRecord::RecordNotFound) do + Topic.find(";;; this should raise an RecordNotFound error") + end + end + + def test_column_name_properly_quoted + col_record = ColumnName.new + col_record.references = 40 + assert col_record.save + col_record.references = 41 + assert col_record.save + assert_not_nil c2 = ColumnName.find(col_record.id) + assert_equal(41, c2.references) + end + + MyObject = Struct.new :attribute1, :attribute2 + + def test_serialized_attribute + myobj = MyObject.new('value1', 'value2') + topic = Topic.create("content" => myobj) + Topic.serialize("content", MyObject) + assert_equal(myobj, topic.content) + end + + def test_serialized_attribute_with_class_constraint + myobj = MyObject.new('value1', 'value2') + topic = Topic.create("content" => myobj) + Topic.serialize(:content, Hash) + + assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content } + + settings = { "color" => "blue" } + Topic.find(topic.id).update_attribute("content", settings) + assert_equal(settings, Topic.find(topic.id).content) + Topic.serialize(:content) + end + + def test_quote + author_name = "\\ \001 ' \n \\n \"" + topic = Topic.create('author_name' => author_name) + assert_equal author_name, Topic.find(topic.id).author_name + end + + def test_class_level_destroy + should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world") + Topic.find(1).replies << should_be_destroyed_reply + + Topic.destroy(1) + assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) } + assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) } + end + + def test_class_level_delete + should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world") + Topic.find(1).replies << should_be_destroyed_reply + + Topic.delete(1) + assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) } + assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) } + end + + def test_increment_attribute + assert_equal 0, topics(:first).replies_count + topics(:first).increment! :replies_count + assert_equal 1, topics(:first, :reload).replies_count + + topics(:first).increment(:replies_count).increment!(:replies_count) + assert_equal 3, topics(:first, :reload).replies_count + end + + def test_increment_nil_attribute + assert_nil topics(:first).parent_id + topics(:first).increment! :parent_id + assert_equal 1, topics(:first).parent_id + end + + def test_decrement_attribute + topics(:first).increment(:replies_count).increment!(:replies_count) + assert_equal 2, topics(:first).replies_count + + topics(:first).decrement!(:replies_count) + assert_equal 1, topics(:first, :reload).replies_count + + topics(:first).decrement(:replies_count).decrement!(:replies_count) + assert_equal -1, topics(:first, :reload).replies_count + end + + def test_toggle_attribute + assert !topics(:first).approved? + topics(:first).toggle!(:approved) + assert topics(:first).approved? + topic = topics(:first) + topic.toggle(:approved) + assert !topic.approved? + topic.reload + assert topic.approved? + end + + def test_reload + t1 = Topic.find(1) + t2 = Topic.find(1) + t1.title = "something else" + t1.save + t2.reload + assert_equal t1.title, t2.title + end + + def test_define_attr_method_with_value + k = Class.new( ActiveRecord::Base ) + k.send(:define_attr_method, :table_name, "foo") + assert_equal "foo", k.table_name + end + + def test_define_attr_method_with_block + k = Class.new( ActiveRecord::Base ) + k.send(:define_attr_method, :primary_key) { "sys_" + original_primary_key } + assert_equal "sys_id", k.primary_key + end + + def test_set_table_name_with_value + k = Class.new( ActiveRecord::Base ) + k.table_name = "foo" + assert_equal "foo", k.table_name + k.set_table_name "bar" + assert_equal "bar", k.table_name + end + + def test_set_table_name_with_block + k = Class.new( ActiveRecord::Base ) + k.set_table_name { "ks" } + assert_equal "ks", k.table_name + end + + def test_set_primary_key_with_value + k = Class.new( ActiveRecord::Base ) + k.primary_key = "foo" + assert_equal "foo", k.primary_key + k.set_primary_key "bar" + assert_equal "bar", k.primary_key + end + + def test_set_primary_key_with_block + k = Class.new( ActiveRecord::Base ) + k.set_primary_key { "sys_" + original_primary_key } + assert_equal "sys_id", k.primary_key + end + + def test_set_inheritance_column_with_value + k = Class.new( ActiveRecord::Base ) + k.inheritance_column = "foo" + assert_equal "foo", k.inheritance_column + k.set_inheritance_column "bar" + assert_equal "bar", k.inheritance_column + end + + def test_set_inheritance_column_with_block + k = Class.new( ActiveRecord::Base ) + k.set_inheritance_column { original_inheritance_column + "_id" } + assert_equal "type_id", k.inheritance_column + end + + def test_count_with_join + res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'" + res2 = nil + assert_nothing_raised do + res2 = Post.count("posts.#{QUOTED_TYPE} = 'Post'", + "LEFT JOIN comments ON posts.id=comments.post_id") + end + assert_equal res, res2 + + res3 = nil + assert_nothing_raised do + res3 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'", + :joins => "LEFT JOIN comments ON posts.id=comments.post_id") + end + assert_equal res, res3 + + res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments c WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id" + res5 = nil + assert_nothing_raised do + res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id", + :joins => "p, comments c", + :select => "p.id") + end + + assert_equal res4, res5 + + res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments c WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id" + res7 = nil + assert_nothing_raised do + res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id", + :joins => "p, comments c", + :select => "p.id", + :distinct => true) + end + assert_equal res6, res7 + end + + def test_clear_association_cache_stored + firm = Firm.find(1) + assert_kind_of Firm, firm + + firm.clear_association_cache + assert_equal Firm.find(1).clients.collect{ |x| x.name }.sort, firm.clients.collect{ |x| x.name }.sort + end + + def test_clear_association_cache_new_record + firm = Firm.new + client_stored = Client.find(3) + client_new = Client.new + client_new.name = "The Joneses" + clients = [ client_stored, client_new ] + + firm.clients << clients + + firm.clear_association_cache + + assert_equal firm.clients.collect{ |x| x.name }.sort, clients.collect{ |x| x.name }.sort + end + + def test_interpolate_sql + assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo@bar') } + assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar) baz') } + assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar} baz') } + end + + def test_scoped_find_conditions + scoped_developers = Developer.with_scope(:find => { :conditions => 'salary > 90000' }) do + Developer.find(:all, :conditions => 'id < 5') + end + assert !scoped_developers.include?(developers(:david)) # David's salary is less than 90,000 + assert_equal 3, scoped_developers.size + end + + def test_scoped_find_limit_offset + scoped_developers = Developer.with_scope(:find => { :limit => 3, :offset => 2 }) do + Developer.find(:all, :order => 'id') + end + assert !scoped_developers.include?(developers(:david)) + assert !scoped_developers.include?(developers(:jamis)) + assert_equal 3, scoped_developers.size + + # Test without scoped find conditions to ensure we get the whole thing + developers = Developer.find(:all, :order => 'id') + assert_equal Developer.count, developers.size + end + + def test_base_class + assert LoosePerson.abstract_class? + assert !LooseDescendant.abstract_class? + assert_equal LoosePerson, LoosePerson.base_class + assert_equal LooseDescendant, LooseDescendant.base_class + assert_equal TightPerson, TightPerson.base_class + assert_equal TightPerson, TightDescendant.base_class + end + + def test_assert_queries + query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' } + assert_queries(2) { 2.times { query.call } } + assert_queries 1, &query + assert_no_queries { assert true } + end + + def test_to_xml + xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true) + bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema + written_on_in_current_timezone = topics(:first).written_on.xmlschema + last_read_in_current_timezone = topics(:first).last_read.xmlschema + assert_equal "<topic>", xml.first(7) + assert xml.include?(%(<title>The First Topic</title>)) + assert xml.include?(%(<author-name>David</author-name>)) + assert xml.include?(%(<id type="integer">1</id>)) + assert xml.include?(%(<replies-count type="integer">0</replies-count>)) + assert xml.include?(%(<written-on type="datetime">#{written_on_in_current_timezone}</written-on>)) + assert xml.include?(%(<content>Have a nice day</content>)) + assert xml.include?(%(<author-email-address>david@loudthinking.com</author-email-address>)) + assert xml.include?(%(<parent-id></parent-id>)) + if current_adapter?(:SybaseAdapter) or current_adapter?(:SQLServerAdapter) + assert xml.include?(%(<last-read type="datetime">#{last_read_in_current_timezone}</last-read>)) + else + assert xml.include?(%(<last-read type="date">2004-04-15</last-read>)) + end + # Oracle and DB2 don't have true boolean or time-only fields + unless current_adapter?(:OracleAdapter) || current_adapter?(:DB2Adapter) + assert xml.include?(%(<approved type="boolean">false</approved>)), "Approved should be a boolean" + assert xml.include?(%(<bonus-time type="datetime">#{bonus_time_in_current_timezone}</bonus-time>)) + end + end + + def test_to_xml_skipping_attributes + xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => :title) + assert_equal "<topic>", xml.first(7) + assert !xml.include?(%(<title>The First Topic</title>)) + assert xml.include?(%(<author-name>David</author-name>)) + + xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [ :title, :author_name ]) + assert !xml.include?(%(<title>The First Topic</title>)) + assert !xml.include?(%(<author-name>David</author-name>)) + end + + def test_to_xml_including_has_many_association + xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies) + assert_equal "<topic>", xml.first(7) + assert xml.include?(%(<replies><reply>)) + assert xml.include?(%(<title>The Second Topic's of the day</title>)) + end + + def test_to_xml_including_belongs_to_association + xml = companies(:first_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm) + assert !xml.include?("<firm>") + + xml = companies(:second_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm) + assert xml.include?("<firm>") + end + + def test_to_xml_including_multiple_associations + xml = companies(:first_firm).to_xml(:indent => 0, :skip_instruct => true, :include => [ :clients, :account ]) + assert_equal "<firm>", xml.first(6) + assert xml.include?(%(<account>)) + assert xml.include?(%(<clients><client>)) + end + + def test_to_xml_including_multiple_associations_with_options + xml = companies(:first_firm).to_xml( + :indent => 0, :skip_instruct => true, + :include => { :clients => { :only => :name } } + ) + + assert_equal "<firm>", xml.first(6) + assert xml.include?(%(<client><name>Summit</name></client>)) + assert xml.include?(%(<clients><client>)) + end + + def test_except_attributes + assert_equal( + %w( author_name type id approved replies_count bonus_time written_on content author_email_address parent_id last_read), + topics(:first).attributes(:except => :title).keys + ) + + assert_equal( + %w( replies_count bonus_time written_on content author_email_address parent_id last_read), + topics(:first).attributes(:except => [ :title, :id, :type, :approved, :author_name ]).keys + ) + end + + def test_include_attributes + assert_equal(%w( title ), topics(:first).attributes(:only => :title).keys) + assert_equal(%w( title author_name type id approved ), topics(:first).attributes(:only => [ :title, :id, :type, :approved, :author_name ]).keys) + end + + def test_type_name_with_module_should_handle_beginning + assert_equal 'ActiveRecord::Person', ActiveRecord::Base.send(:type_name_with_module, 'Person') + assert_equal '::Person', ActiveRecord::Base.send(:type_name_with_module, '::Person') + end + + # FIXME: this test ought to run, but it needs to run sandboxed so that it + # doesn't b0rk the current test environment by undefing everything. + # + #def test_dev_mode_memory_leak + # counts = [] + # 2.times do + # require_dependency 'fixtures/company' + # Firm.find(:first) + # Dependencies.clear + # ActiveRecord::Base.reset_subclasses + # Dependencies.remove_subclasses_for(ActiveRecord::Base) + # + # GC.start + # + # count = 0 + # ObjectSpace.each_object(Proc) { count += 1 } + # counts << count + # end + # assert counts.last <= counts.first, + # "expected last count (#{counts.last}) to be <= first count (#{counts.first})" + #end + + private + def assert_readers(model, exceptions) + expected_readers = Set.new(model.column_names - (model.serialized_attributes.keys + ['id'])) + expected_readers += expected_readers.map { |col| "#{col}?" } + expected_readers -= exceptions + assert_equal expected_readers, model.read_methods + end +end +require 'abstract_unit' +require 'fixtures/binary' + +class BinaryTest < Test::Unit::TestCase + BINARY_FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures/flowers.jpg' + + def setup + Binary.connection.execute 'DELETE FROM binaries' + @data = File.read(BINARY_FIXTURE_PATH).freeze + end + + def test_truth + assert true + end + + # Without using prepared statements, it makes no sense to test + # BLOB data with SQL Server, because the length of a statement is + # limited to 8KB. + # + # Without using prepared statements, it makes no sense to test + # BLOB data with DB2 or Firebird, because the length of a statement + # is limited to 32KB. + unless %w(SQLServer Sybase DB2 Oracle Firebird).include? ActiveRecord::Base.connection.adapter_name + def test_load_save + bin = Binary.new + bin.data = @data + + assert @data == bin.data, 'Newly assigned data differs from original' + + bin.save + assert @data == bin.data, 'Data differs from original after save' + + db_bin = Binary.find(bin.id) + assert @data == db_bin.data, 'Reloaded data differs from original' + end + end +end +require 'abstract_unit' +require 'fixtures/company' +require 'fixtures/topic' + +Company.has_many :accounts + +class CalculationsTest < Test::Unit::TestCase + fixtures :companies, :accounts, :topics + + def test_should_sum_field + assert_equal 265, Account.sum(:credit_limit) + end + + def test_should_average_field + value = Account.average(:credit_limit) + assert_equal 53, value + assert_kind_of Float, value + end + + def test_should_get_maximum_of_field + assert_equal 60, Account.maximum(:credit_limit) + end + + def test_should_get_minimum_of_field + assert_equal 50, Account.minimum(:credit_limit) + end + + def test_should_group_by_field + c = Account.sum(:credit_limit, :group => :firm_id) + [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) } + end + + def test_should_group_by_summed_field + c = Account.sum(:credit_limit, :group => :firm_id) + assert_equal 50, c[1] + assert_equal 105, c[6] + assert_equal 60, c[2] + end + + def test_should_order_by_grouped_field + c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id") + assert_equal [1, 2, 6], c.keys.compact + end + + def test_should_order_by_calculation + c = Account.sum(:credit_limit, :group => :firm_id, :order => "sum_credit_limit desc, firm_id") + assert_equal [105, 60, 50, 50], c.keys.collect { |k| c[k] } + assert_equal [6, 2, 1], c.keys.compact + end + + def test_should_limit_calculation + c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL", + :group => :firm_id, :order => "firm_id", :limit => 2) + assert_equal [1, 2], c.keys.compact + end + + def test_should_limit_calculation_with_offset + c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL", + :group => :firm_id, :order => "firm_id", :limit => 2, :offset => 1) + assert_equal [2, 6], c.keys.compact + end + + def test_should_group_by_summed_field_having_condition + c = Account.sum(:credit_limit, :group => :firm_id, + :having => 'sum(credit_limit) > 50') + assert_nil c[1] + assert_equal 105, c[6] + assert_equal 60, c[2] + end + + def test_should_group_by_summed_association + c = Account.sum(:credit_limit, :group => :firm) + assert_equal 50, c[companies(:first_firm)] + assert_equal 105, c[companies(:rails_core)] + assert_equal 60, c[companies(:first_client)] + end + + def test_should_sum_field_with_conditions + assert_equal 105, Account.sum(:credit_limit, :conditions => 'firm_id = 6') + end + + def test_should_group_by_summed_field_with_conditions + c = Account.sum(:credit_limit, :conditions => 'firm_id > 1', + :group => :firm_id) + assert_nil c[1] + assert_equal 105, c[6] + assert_equal 60, c[2] + end + + def test_should_group_by_summed_field_with_conditions_and_having + c = Account.sum(:credit_limit, :conditions => 'firm_id > 1', + :group => :firm_id, + :having => 'sum(credit_limit) > 60') + assert_nil c[1] + assert_equal 105, c[6] + assert_nil c[2] + end + + def test_should_group_by_fields_with_table_alias + c = Account.sum(:credit_limit, :group => 'accounts.firm_id') + assert_equal 50, c[1] + assert_equal 105, c[6] + assert_equal 60, c[2] + end + + def test_should_calculate_with_invalid_field + assert_equal 5, Account.calculate(:count, '*') + assert_equal 5, Account.calculate(:count, :all) + end + + def test_should_calculate_grouped_with_invalid_field + c = Account.count(:all, :group => 'accounts.firm_id') + assert_equal 1, c[1] + assert_equal 2, c[6] + assert_equal 1, c[2] + end + + def test_should_calculate_grouped_association_with_invalid_field + c = Account.count(:all, :group => :firm) + assert_equal 1, c[companies(:first_firm)] + assert_equal 2, c[companies(:rails_core)] + assert_equal 1, c[companies(:first_client)] + end + + def test_should_calculate_grouped_by_function + c = Company.count(:all, :group => 'UPPER(type)') + assert_equal 2, c[nil] + assert_equal 1, c['DEPENDENTFIRM'] + assert_equal 3, c['CLIENT'] + assert_equal 2, c['FIRM'] + end + + def test_should_calculate_grouped_by_function_with_table_alias + c = Company.count(:all, :group => 'UPPER(companies.type)') + assert_equal 2, c[nil] + assert_equal 1, c['DEPENDENTFIRM'] + assert_equal 3, c['CLIENT'] + assert_equal 2, c['FIRM'] + end + + def test_should_sum_scoped_field + assert_equal 15, companies(:rails_core).companies.sum(:id) + end + + def test_should_sum_scoped_field_with_conditions + assert_equal 8, companies(:rails_core).companies.sum(:id, :conditions => 'id > 7') + end + + def test_should_group_by_scoped_field + c = companies(:rails_core).companies.sum(:id, :group => :name) + assert_equal 7, c['Leetsoft'] + assert_equal 8, c['Jadedpixel'] + end + + def test_should_group_by_summed_field_with_conditions_and_having + c = companies(:rails_core).companies.sum(:id, :group => :name, + :having => 'sum(id) > 7') + assert_nil c['Leetsoft'] + assert_equal 8, c['Jadedpixel'] + end + + def test_should_reject_invalid_options + assert_nothing_raised do + [:count, :sum].each do |func| + # empty options are valid + Company.send(:validate_calculation_options, func) + # these options are valid for all calculations + [:select, :conditions, :joins, :order, :group, :having, :distinct].each do |opt| + Company.send(:validate_calculation_options, func, opt => true) + end + end + + # :include is only valid on :count + Company.send(:validate_calculation_options, :count, :include => true) + end + + assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :sum, :include => :posts) } + assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :sum, :foo => :bar) } + assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :count, :foo => :bar) } + end +end +require 'abstract_unit' + +class CallbackDeveloper < ActiveRecord::Base + set_table_name 'developers' + + class << self + def callback_string(callback_method) + "history << [#{callback_method.to_sym.inspect}, :string]" + end + + def callback_proc(callback_method) + Proc.new { |model| model.history << [callback_method, :proc] } + end + + def define_callback_method(callback_method) + define_method("#{callback_method}_method") do |model| + model.history << [callback_method, :method] + end + end + + def callback_object(callback_method) + klass = Class.new + klass.send(:define_method, callback_method) do |model| + model.history << [callback_method, :object] + end + klass.new + end + end + + ActiveRecord::Callbacks::CALLBACKS.each do |callback_method| + callback_method_sym = callback_method.to_sym + define_callback_method(callback_method_sym) + send(callback_method, callback_method_sym) + send(callback_method, callback_string(callback_method_sym)) + send(callback_method, callback_proc(callback_method_sym)) + send(callback_method, callback_object(callback_method_sym)) + send(callback_method) { |model| model.history << [callback_method_sym, :block] } + end + + def history + @history ||= [] + end + + # after_initialize and after_find are invoked only if instance methods have been defined. + def after_initialize + end + + def after_find + end +end + +class RecursiveCallbackDeveloper < ActiveRecord::Base + set_table_name 'developers' + + before_save :on_before_save + after_save :on_after_save + + attr_reader :on_before_save_called, :on_after_save_called + + def on_before_save + @on_before_save_called ||= 0 + @on_before_save_called += 1 + save unless @on_before_save_called > 1 + end + + def on_after_save + @on_after_save_called ||= 0 + @on_after_save_called += 1 + save unless @on_after_save_called > 1 + end +end + +class ImmutableDeveloper < ActiveRecord::Base + set_table_name 'developers' + + validates_inclusion_of :salary, :in => 50000..200000 + + before_save :cancel + before_destroy :cancel + + def cancelled? + @cancelled == true + end + + private + def cancel + @cancelled = true + false + end +end + +class ImmutableMethodDeveloper < ActiveRecord::Base + set_table_name 'developers' + + validates_inclusion_of :salary, :in => 50000..200000 + + def cancelled? + @cancelled == true + end + + def before_save + @cancelled = true + false + end + + def before_destroy + @cancelled = true + false + end +end + +class CallbacksTest < Test::Unit::TestCase + fixtures :developers + + def test_initialize + david = CallbackDeveloper.new + assert_equal [ + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + ], david.history + end + + def test_find + david = CallbackDeveloper.find(1) + assert_equal [ + [ :after_find, :string ], + [ :after_find, :proc ], + [ :after_find, :object ], + [ :after_find, :block ], + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + ], david.history + end + + def test_new_valid? + david = CallbackDeveloper.new + david.valid? + assert_equal [ + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + [ :before_validation, :string ], + [ :before_validation, :proc ], + [ :before_validation, :object ], + [ :before_validation, :block ], + [ :before_validation_on_create, :string ], + [ :before_validation_on_create, :proc ], + [ :before_validation_on_create, :object ], + [ :before_validation_on_create, :block ], + [ :after_validation, :string ], + [ :after_validation, :proc ], + [ :after_validation, :object ], + [ :after_validation, :block ], + [ :after_validation_on_create, :string ], + [ :after_validation_on_create, :proc ], + [ :after_validation_on_create, :object ], + [ :after_validation_on_create, :block ] + ], david.history + end + + def test_existing_valid? + david = CallbackDeveloper.find(1) + david.valid? + assert_equal [ + [ :after_find, :string ], + [ :after_find, :proc ], + [ :after_find, :object ], + [ :after_find, :block ], + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + [ :before_validation, :string ], + [ :before_validation, :proc ], + [ :before_validation, :object ], + [ :before_validation, :block ], + [ :before_validation_on_update, :string ], + [ :before_validation_on_update, :proc ], + [ :before_validation_on_update, :object ], + [ :before_validation_on_update, :block ], + [ :after_validation, :string ], + [ :after_validation, :proc ], + [ :after_validation, :object ], + [ :after_validation, :block ], + [ :after_validation_on_update, :string ], + [ :after_validation_on_update, :proc ], + [ :after_validation_on_update, :object ], + [ :after_validation_on_update, :block ] + ], david.history + end + + def test_create + david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000) + assert_equal [ + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + [ :before_validation, :string ], + [ :before_validation, :proc ], + [ :before_validation, :object ], + [ :before_validation, :block ], + [ :before_validation_on_create, :string ], + [ :before_validation_on_create, :proc ], + [ :before_validation_on_create, :object ], + [ :before_validation_on_create, :block ], + [ :after_validation, :string ], + [ :after_validation, :proc ], + [ :after_validation, :object ], + [ :after_validation, :block ], + [ :after_validation_on_create, :string ], + [ :after_validation_on_create, :proc ], + [ :after_validation_on_create, :object ], + [ :after_validation_on_create, :block ], + [ :before_save, :string ], + [ :before_save, :proc ], + [ :before_save, :object ], + [ :before_save, :block ], + [ :before_create, :string ], + [ :before_create, :proc ], + [ :before_create, :object ], + [ :before_create, :block ], + [ :after_create, :string ], + [ :after_create, :proc ], + [ :after_create, :object ], + [ :after_create, :block ], + [ :after_save, :string ], + [ :after_save, :proc ], + [ :after_save, :object ], + [ :after_save, :block ] + ], david.history + end + + def test_save + david = CallbackDeveloper.find(1) + david.save + assert_equal [ + [ :after_find, :string ], + [ :after_find, :proc ], + [ :after_find, :object ], + [ :after_find, :block ], + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + [ :before_validation, :string ], + [ :before_validation, :proc ], + [ :before_validation, :object ], + [ :before_validation, :block ], + [ :before_validation_on_update, :string ], + [ :before_validation_on_update, :proc ], + [ :before_validation_on_update, :object ], + [ :before_validation_on_update, :block ], + [ :after_validation, :string ], + [ :after_validation, :proc ], + [ :after_validation, :object ], + [ :after_validation, :block ], + [ :after_validation_on_update, :string ], + [ :after_validation_on_update, :proc ], + [ :after_validation_on_update, :object ], + [ :after_validation_on_update, :block ], + [ :before_save, :string ], + [ :before_save, :proc ], + [ :before_save, :object ], + [ :before_save, :block ], + [ :before_update, :string ], + [ :before_update, :proc ], + [ :before_update, :object ], + [ :before_update, :block ], + [ :after_update, :string ], + [ :after_update, :proc ], + [ :after_update, :object ], + [ :after_update, :block ], + [ :after_save, :string ], + [ :after_save, :proc ], + [ :after_save, :object ], + [ :after_save, :block ] + ], david.history + end + + def test_destroy + david = CallbackDeveloper.find(1) + david.destroy + assert_equal [ + [ :after_find, :string ], + [ :after_find, :proc ], + [ :after_find, :object ], + [ :after_find, :block ], + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + [ :before_destroy, :string ], + [ :before_destroy, :proc ], + [ :before_destroy, :object ], + [ :before_destroy, :block ], + [ :after_destroy, :string ], + [ :after_destroy, :proc ], + [ :after_destroy, :object ], + [ :after_destroy, :block ] + ], david.history + end + + def test_delete + david = CallbackDeveloper.find(1) + CallbackDeveloper.delete(david.id) + assert_equal [ + [ :after_find, :string ], + [ :after_find, :proc ], + [ :after_find, :object ], + [ :after_find, :block ], + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + ], david.history + end + + def test_before_save_returning_false + david = ImmutableDeveloper.find(1) + assert david.valid? + assert !david.save + assert_raises(ActiveRecord::RecordNotSaved) { david.save! } + + david = ImmutableDeveloper.find(1) + david.salary = 10_000_000 + assert !david.valid? + assert !david.save + assert_raises(ActiveRecord::RecordInvalid) { david.save! } + end + + def test_before_destroy_returning_false + david = ImmutableDeveloper.find(1) + assert !david.destroy + assert_not_nil ImmutableDeveloper.find_by_id(1) + end + + def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper + david = CallbackDeveloper.find(1) + CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false } + CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] } + david.save + assert_equal [ + [ :after_find, :string ], + [ :after_find, :proc ], + [ :after_find, :object ], + [ :after_find, :block ], + [ :after_initialize, :string ], + [ :after_initialize, :proc ], + [ :after_initialize, :object ], + [ :after_initialize, :block ], + [ :before_validation, :string ], + [ :before_validation, :proc ], + [ :before_validation, :object ], + [ :before_validation, :block ], + [ :before_validation, :returning_false ] + ], david.history + end +end +require 'test/unit' +require 'abstract_unit' +require 'active_support/core_ext/class/inheritable_attributes' + +class A + include ClassInheritableAttributes +end + +class B < A + write_inheritable_array "first", [ :one, :two ] +end + +class C < A + write_inheritable_array "first", [ :three ] +end + +class D < B + write_inheritable_array "first", [ :four ] +end + + +class ClassInheritableAttributesTest < Test::Unit::TestCase + def test_first_level + assert_equal [ :one, :two ], B.read_inheritable_attribute("first") + assert_equal [ :three ], C.read_inheritable_attribute("first") + end + + def test_second_level + assert_equal [ :one, :two, :four ], D.read_inheritable_attribute("first") + assert_equal [ :one, :two ], B.read_inheritable_attribute("first") + end +end +require 'abstract_unit' +require 'fixtures/topic' + +class TestColumnAlias < Test::Unit::TestCase + fixtures :topics + + QUERY = if 'Oracle' == ActiveRecord::Base.connection.adapter_name + 'SELECT id AS pk FROM topics WHERE ROWNUM < 2' + else + 'SELECT id AS pk FROM topics' + end + + def test_column_alias + records = Topic.connection.select_all(QUERY) + assert_equal 'pk', records[0].keys[0] + end +end +print "Using native DB2\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'arunit' +db2 = 'arunit2' + +ActiveRecord::Base.establish_connection( + :adapter => "db2", + :host => "localhost", + :username => "arunit", + :password => "arunit", + :database => db1 +) + +Course.establish_connection( + :adapter => "db2", + :host => "localhost", + :username => "arunit2", + :password => "arunit2", + :database => db2 +) +print "Using native Firebird\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'activerecord_unittest' +db2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "firebird", + :host => "localhost", + :username => "rails", + :password => "rails", + :database => db1 +) + +Course.establish_connection( + :adapter => "firebird", + :host => "localhost", + :username => "rails", + :password => "rails", + :database => db2 +) +print "Using native MySQL\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'activerecord_unittest' +db2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "mysql", + :username => "rails", + :encoding => "utf8", + :database => db1 +) + +Course.establish_connection( + :adapter => "mysql", + :username => "rails", + :database => db2 +) +print "Using native OpenBase\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'activerecord_unittest' +db2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "openbase", + :username => "admin", + :password => "", + :database => db1 +) + +Course.establish_connection( + :adapter => "openbase", + :username => "admin", + :password => "", + :database => db2 +) +print "Using Oracle\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new STDOUT +ActiveRecord::Base.logger.level = Logger::WARN + +# Set these to your database connection strings +db = ENV['ARUNIT_DB'] || 'activerecord_unittest' + +ActiveRecord::Base.establish_connection( + :adapter => 'oracle', + :username => 'arunit', + :password => 'arunit', + :database => db +) + +Course.establish_connection( + :adapter => 'oracle', + :username => 'arunit2', + :password => 'arunit2', + :database => db +) +print "Using native PostgreSQL\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'activerecord_unittest' +db2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "postgresql", + :username => "postgres", + :password => "postgres", + :database => db1, + :min_messages => "warning" +) + +Course.establish_connection( + :adapter => "postgresql", + :username => "postgres", + :password => "postgres", + :database => db2, + :min_messages => "warning" +) +print "Using native SQlite\n" +require_dependency 'fixtures/course' +require 'logger' +ActiveRecord::Base.logger = Logger.new("debug.log") + +class SqliteError < StandardError +end + +BASE_DIR = File.expand_path(File.dirname(__FILE__) + '/../../fixtures') +sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite" +sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite" + +def make_connection(clazz, db_file, db_definitions_file) + unless File.exist?(db_file) + puts "SQLite database not found at #{db_file}. Rebuilding it." + sqlite_command = %Q{sqlite #{db_file} "create table a (a integer); drop table a;"} + puts "Executing '#{sqlite_command}'" + raise SqliteError.new("Seems that there is no sqlite executable available") unless system(sqlite_command) + clazz.establish_connection( + :adapter => "sqlite", + :database => db_file) + script = File.read("#{BASE_DIR}/db_definitions/#{db_definitions_file}") + # SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time + script.split(';').each do + |command| + clazz.connection.execute(command) unless command.strip.empty? + end + else + clazz.establish_connection( + :adapter => "sqlite", + :database => db_file) + end +end + +make_connection(ActiveRecord::Base, sqlite_test_db, 'sqlite.sql') +make_connection(Course, sqlite_test_db2, 'sqlite2.sql') +load(File.join(BASE_DIR, 'db_definitions', 'schema.rb')) +print "Using native SQLite3\n" +require_dependency 'fixtures/course' +require 'logger' +ActiveRecord::Base.logger = Logger.new("debug.log") + +class SqliteError < StandardError +end + +BASE_DIR = File.expand_path(File.dirname(__FILE__) + '/../../fixtures') +sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite3" +sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite3" + +def make_connection(clazz, db_file, db_definitions_file) + unless File.exist?(db_file) + puts "SQLite3 database not found at #{db_file}. Rebuilding it." + sqlite_command = %Q{sqlite3 #{db_file} "create table a (a integer); drop table a;"} + puts "Executing '#{sqlite_command}'" + raise SqliteError.new("Seems that there is no sqlite3 executable available") unless system(sqlite_command) + clazz.establish_connection( + :adapter => "sqlite3", + :database => db_file) + script = File.read("#{BASE_DIR}/db_definitions/#{db_definitions_file}") + # SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time + script.split(';').each do + |command| + clazz.connection.execute(command) unless command.strip.empty? + end + else + clazz.establish_connection( + :adapter => "sqlite3", + :database => db_file) + end +end + +make_connection(ActiveRecord::Base, sqlite_test_db, 'sqlite.sql') +make_connection(Course, sqlite_test_db2, 'sqlite2.sql') +load(File.join(BASE_DIR, 'db_definitions', 'schema.rb')) +print "Using native SQLite3\n" +require_dependency 'fixtures/course' +require 'logger' +ActiveRecord::Base.logger = Logger.new("debug.log") + +class SqliteError < StandardError +end + +def make_connection(clazz, db_definitions_file) + clazz.establish_connection(:adapter => 'sqlite3', :database => ':memory:') + File.read("#{File.dirname(__FILE__)}/../../fixtures/db_definitions/#{db_definitions_file}").split(';').each do |command| + clazz.connection.execute(command) unless command.strip.empty? + end +end + +make_connection(ActiveRecord::Base, 'sqlite.sql') +make_connection(Course, 'sqlite2.sql') + load("#{File.dirname(__FILE__)}/../../fixtures/db_definitions/schema.rb")) +print "Using native SQLServer\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'activerecord_unittest' +db2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "sqlserver", + :host => "localhost", + :username => "sa", + :password => "", + :database => db1 +) + +Course.establish_connection( + :adapter => "sqlserver", + :host => "localhost", + :username => "sa", + :password => "", + :database => db2 +) +print "Using native SQLServer via ODBC\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +dsn1 = 'activerecord_unittest' +dsn2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "sqlserver", + :mode => "ODBC", + :host => "localhost", + :username => "sa", + :password => "", + :dsn => dsn1 +) + +Course.establish_connection( + :adapter => "sqlserver", + :mode => "ODBC", + :host => "localhost", + :username => "sa", + :password => "", + :dsn => dsn2 +) +print "Using native Sybase Open Client\n" +require_dependency 'fixtures/course' +require 'logger' + +ActiveRecord::Base.logger = Logger.new("debug.log") + +db1 = 'activerecord_unittest' +db2 = 'activerecord_unittest2' + +ActiveRecord::Base.establish_connection( + :adapter => "sybase", + :host => "database_ASE", + :username => "sa", + :password => "", + :database => db1 +) + +Course.establish_connection( + :adapter => "sybase", + :host => "database_ASE", + :username => "sa", + :password => "", + :database => db2 +) +require 'abstract_unit' + +class CopyTableTest < Test::Unit::TestCase + fixtures :companies, :comments + + def setup + @connection = ActiveRecord::Base.connection + class << @connection + public :copy_table, :table_structure, :indexes + end + end + + def test_copy_table(from = 'companies', to = 'companies2', options = {}) + assert_nothing_raised {copy_table(from, to, options)} + assert_equal row_count(from), row_count(to) + + if block_given? + yield from, to, options + else + assert_equal column_names(from), column_names(to) + end + + @connection.drop_table(to) rescue nil + end + + def test_copy_table_renaming_column + test_copy_table('companies', 'companies2', + :rename => {'client_of' => 'fan_of'}) do |from, to, options| + assert_equal column_values(from, 'client_of').compact.sort, + column_values(to, 'fan_of').compact.sort + end + end + + def test_copy_table_with_index + test_copy_table('comments', 'comments_with_index') do + @connection.add_index('comments_with_index', ['post_id', 'type']) + test_copy_table('comments_with_index', 'comments_with_index2') do + assert_equal table_indexes_without_name('comments_with_index'), + table_indexes_without_name('comments_with_index2') + end + end + end + +protected + def copy_table(from, to, options = {}) + @connection.copy_table(from, to, {:temporary => true}.merge(options)) + end + + def column_names(table) + @connection.table_structure(table).map {|column| column['name']} + end + + def column_values(table, column) + @connection.select_all("SELECT #{column} FROM #{table}").map {|row| row[column]} + end + + def table_indexes_without_name(table) + @connection.indexes('comments_with_index').delete(:name) + end + + def row_count(table) + @connection.select_one("SELECT COUNT(*) AS count FROM #{table}")['count'] + end +end +require 'abstract_unit' +require 'fixtures/default' + +class DefaultTest < Test::Unit::TestCase + def test_default_timestamp + default = Default.new + assert_instance_of(Time, default.default_timestamp) + assert_equal(:datetime, default.column_for_attribute(:default_timestamp).type) + + # Variance should be small; increase if required -- e.g., if test db is on + # remote host and clocks aren't synchronized. + t1 = Time.new + accepted_variance = 1.0 + assert_in_delta(t1.to_f, default.default_timestamp.to_f, accepted_variance) + end +end +require 'abstract_unit' +require 'fixtures/default' + +class DefaultsTest < Test::Unit::TestCase + if %w(PostgreSQL).include? ActiveRecord::Base.connection.adapter_name + def test_default_integers + default = Default.new + assert_instance_of(Fixnum, default.positive_integer) + assert_equal(default.positive_integer, 1) + assert_instance_of(Fixnum, default.negative_integer) + assert_equal(default.negative_integer, -1) + end + else + def test_dummy + assert true + end + end +end +require 'abstract_unit' +require 'fixtures/developer' +require 'fixtures/project' +require 'fixtures/company' +require 'fixtures/topic' +require 'fixtures/reply' + +# Can't declare new classes in test case methods, so tests before that +bad_collection_keys = false +begin + class Car < ActiveRecord::Base; has_many :wheels, :name => "wheels"; end +rescue ArgumentError + bad_collection_keys = true +end +raise "ActiveRecord should have barked on bad collection keys" unless bad_collection_keys + + +class DeprecatedAssociationsTest < Test::Unit::TestCase + fixtures :accounts, :companies, :developers, :projects, :topics, + :developers_projects + + def test_has_many_find + assert_equal 2, Firm.find_first.clients.length + end + + def test_has_many_orders + assert_equal "Summit", Firm.find_first.clients.first.name + end + + def test_has_many_class_name + assert_equal "Microsoft", Firm.find_first.clients_sorted_desc.first.name + end + + def test_has_many_foreign_key + assert_equal "Microsoft", Firm.find_first.clients_of_firm.first.name + end + + def test_has_many_conditions + assert_equal "Microsoft", Firm.find_first.clients_like_ms.first.name + end + + def test_has_many_sql + firm = Firm.find_first + assert_equal "Microsoft", firm.clients_using_sql.first.name + assert_equal 1, firm.clients_using_sql_count + assert_equal 1, Firm.find_first.clients_using_sql_count + end + + def test_has_many_counter_sql + assert_equal 1, Firm.find_first.clients_using_counter_sql_count + end + + def test_has_many_queries + assert Firm.find_first.has_clients? + firm = Firm.find_first + assert_equal 2, firm.clients_count # tests using class count + firm.clients + assert firm.has_clients? + assert_equal 2, firm.clients_count # tests using collection length + end + + def test_has_many_dependence + assert_equal 3, Client.find_all.length + Firm.find_first.destroy + assert_equal 1, Client.find_all.length + end + + uses_transaction :test_has_many_dependence_with_transaction_support_on_failure + def test_has_many_dependence_with_transaction_support_on_failure + assert_equal 3, Client.find_all.length + + firm = Firm.find_first + clients = firm.clients + clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end } + + firm.destroy rescue "do nothing" + + assert_equal 3, Client.find_all.length + end + + def test_has_one_dependence + num_accounts = Account.count + firm = Firm.find(1) + assert firm.has_account? + firm.destroy + assert_equal num_accounts - 1, Account.count + end + + def test_has_one_dependence_with_missing_association + Account.destroy_all + firm = Firm.find(1) + assert !firm.has_account? + firm.destroy + end + + def test_belongs_to + assert_equal companies(:first_firm).name, Client.find(3).firm.name + assert Client.find(3).has_firm?, "Microsoft should have a firm" + # assert !Company.find(1).has_firm?, "37signals shouldn't have a firm" + end + + def test_belongs_to_with_different_class_name + assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name + assert Company.find(3).has_firm_with_other_name?, "Microsoft should have a firm" + end + + def test_belongs_to_with_condition + assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name + assert Company.find(3).has_firm_with_condition?, "Microsoft should have a firm" + end + + def test_belongs_to_equality + assert Company.find(3).firm?(Company.find(1)), "Microsoft should have 37signals as firm" + assert_raises(RuntimeError) { !Company.find(3).firm?(Company.find(3)) } # "Summit shouldn't have itself as firm" + end + + def test_has_one + assert companies(:first_firm).account?(Account.find(1)) + assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit + assert companies(:first_firm).has_account?, "37signals should have an account" + assert Account.find(1).firm?(companies(:first_firm)), "37signals account should be able to backtrack" + assert Account.find(1).has_firm?, "37signals account should be able to backtrack" + + assert !Account.find(2).has_firm?, "Unknown isn't linked" + assert !Account.find(2).firm?(companies(:first_firm)), "Unknown isn't linked" + end + + def test_has_many_dependence_on_account + num_accounts = Account.count + companies(:first_firm).destroy + assert_equal num_accounts - 1, Account.count + end + + def test_find_in + assert_equal Client.find(2).name, companies(:first_firm).find_in_clients(2).name + assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).find_in_clients(6) } + end + + def test_force_reload + firm = Firm.new("name" => "A New Firm, Inc") + firm.save + firm.clients.each {|c|} # forcing to load all clients + assert firm.clients.empty?, "New firm shouldn't have client objects" + assert !firm.has_clients?, "New firm shouldn't have clients" + assert_equal 0, firm.clients_count, "New firm should have 0 clients" + + client = Client.new("name" => "TheClient.com", "firm_id" => firm.id) + client.save + + assert firm.clients.empty?, "New firm should have cached no client objects" + assert !firm.has_clients?, "New firm should have cached a no-clients response" + assert_equal 0, firm.clients_count, "New firm should have cached 0 clients count" + + assert !firm.clients(true).empty?, "New firm should have reloaded client objects" + assert firm.has_clients?(true), "New firm should have reloaded with a have-clients response" + assert_equal 1, firm.clients_count(true), "New firm should have reloaded clients count" + end + + def test_included_in_collection + assert companies(:first_firm).clients.include?(Client.find(2)) + end + + def test_build_to_collection + assert_equal 1, companies(:first_firm).clients_of_firm_count + new_client = companies(:first_firm).build_to_clients_of_firm("name" => "Another Client") + assert_equal "Another Client", new_client.name + assert new_client.save + + assert new_client.firm?(companies(:first_firm)) + assert_equal 2, companies(:first_firm).clients_of_firm_count(true) + end + + def test_create_in_collection + assert_equal companies(:first_firm).create_in_clients_of_firm("name" => "Another Client"), companies(:first_firm).clients_of_firm(true).last + end + + def test_has_and_belongs_to_many + david = Developer.find(1) + assert david.has_projects? + assert_equal 2, david.projects_count + + active_record = Project.find(1) + assert active_record.has_developers? + assert_equal 3, active_record.developers_count + assert active_record.developers.include?(david) + end + + def test_has_and_belongs_to_many_removing + david = Developer.find(1) + active_record = Project.find(1) + + david.remove_projects(active_record) + + assert_equal 1, david.projects_count + assert_equal 2, active_record.developers_count + end + + def test_has_and_belongs_to_many_zero + david = Developer.find(1) + david.remove_projects(Project.find_all) + + assert_equal 0, david.projects_count + assert !david.has_projects? + end + + def test_has_and_belongs_to_many_adding + jamis = Developer.find(2) + action_controller = Project.find(2) + + jamis.add_projects(action_controller) + + assert_equal 2, jamis.projects_count + assert_equal 2, action_controller.developers_count + end + + def test_has_and_belongs_to_many_adding_from_the_project + jamis = Developer.find(2) + action_controller = Project.find(2) + + action_controller.add_developers(jamis) + + assert_equal 2, jamis.projects_count + assert_equal 2, action_controller.developers_count + end + + def test_has_and_belongs_to_many_adding_a_collection + aredridel = Developer.new("name" => "Aredridel") + aredridel.save + + aredridel.add_projects([ Project.find(1), Project.find(2) ]) + assert_equal 2, aredridel.projects_count + end + + def test_belongs_to_counter + topic = Topic.create("title" => "Apple", "content" => "hello world") + assert_equal 0, topic.send(:read_attribute, "replies_count"), "No replies yet" + + reply = topic.create_in_replies("title" => "I'm saying no!", "content" => "over here") + assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count"), "First reply created" + + reply.destroy + assert_equal 0, Topic.find(topic.id).send(:read_attribute, "replies_count"), "First reply deleted" + end + + def test_natural_assignment_of_has_one + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + apple.account = citibank + assert_equal apple.id, citibank.firm_id + end + + def test_natural_assignment_of_belongs_to + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + citibank.firm = apple + assert_equal apple.id, citibank.firm_id + end + + def test_natural_assignment_of_has_many + apple = Firm.create("name" => "Apple") + natural = Client.create("name" => "Natural Company") + apple.clients << natural + assert_equal apple.id, natural.firm_id + assert_equal Client.find(natural.id), Firm.find(apple.id).clients.find(natural.id) + apple.clients.delete natural + assert_raises(ActiveRecord::RecordNotFound) { + Firm.find(apple.id).clients.find(natural.id) + } + end + + def test_natural_adding_of_has_and_belongs_to_many + rails = Project.create("name" => "Rails") + ap = Project.create("name" => "Action Pack") + john = Developer.create("name" => "John") + mike = Developer.create("name" => "Mike") + rails.developers << john + rails.developers << mike + + assert_equal Developer.find(john.id), Project.find(rails.id).developers.find(john.id) + assert_equal Developer.find(mike.id), Project.find(rails.id).developers.find(mike.id) + assert_equal Project.find(rails.id), Developer.find(mike.id).projects.find(rails.id) + assert_equal Project.find(rails.id), Developer.find(john.id).projects.find(rails.id) + ap.developers << john + assert_equal Developer.find(john.id), Project.find(ap.id).developers.find(john.id) + assert_equal Project.find(ap.id), Developer.find(john.id).projects.find(ap.id) + + ap.developers.delete john + assert_raises(ActiveRecord::RecordNotFound) { + Project.find(ap.id).developers.find(john.id) + } + assert_raises(ActiveRecord::RecordNotFound) { + Developer.find(john.id).projects.find(ap.id) + } + end + + def test_storing_in_pstore + require "pstore" + require "tmpdir" + apple = Firm.create("name" => "Apple") + natural = Client.new("name" => "Natural Company") + apple.clients << natural + + db = PStore.new(File.join(Dir.tmpdir, "ar-pstore-association-test")) + db.transaction do + db["apple"] = apple + end + + db = PStore.new(File.join(Dir.tmpdir, "ar-pstore-association-test")) + db.transaction do + assert_equal "Natural Company", db["apple"].clients.first.name + end + end + + def test_has_many_find_all + assert_equal 2, Firm.find_first.find_all_in_clients("#{QUOTED_TYPE} = 'Client'").length + assert_equal 1, Firm.find_first.find_all_in_clients("name = 'Summit'").length + end + + def test_has_one + assert companies(:first_firm).account?(Account.find(1)) + assert companies(:first_firm).has_account?, "37signals should have an account" + assert Account.find(1).firm?(companies(:first_firm)), "37signals account should be able to backtrack" + assert Account.find(1).has_firm?, "37signals account should be able to backtrack" + + assert !Account.find(2).has_firm?, "Unknown isn't linked" + assert !Account.find(2).firm?(companies(:first_firm)), "Unknown isn't linked" + end + + def test_has_one_build + firm = Firm.new("name" => "GlobalMegaCorp") + assert firm.save + + account = firm.build_account("credit_limit" => 1000) + assert account.save + assert_equal account, firm.account + end + + def test_has_one_failing_build_association + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + + account = firm.build_account + assert !account.save + assert_equal "can't be empty", account.errors.on("credit_limit") + end + + def test_has_one_create + firm = Firm.new("name" => "GlobalMegaCorp") + firm.save + assert_equal firm.create_account("credit_limit" => 1000), firm.account + end +end +require 'abstract_unit' +require 'fixtures/company' +require 'fixtures/topic' +require 'fixtures/entrant' +require 'fixtures/developer' + +class DeprecatedFinderTest < Test::Unit::TestCase + fixtures :companies, :topics, :entrants, :developers + + def test_find_all_with_limit + entrants = Entrant.find_all nil, "id ASC", 2 + + assert_equal(2, entrants.size) + assert_equal(entrants(:first).name, entrants.first.name) + end + + def test_find_all_with_prepared_limit_and_offset + entrants = Entrant.find_all nil, "id ASC", [2, 1] + + assert_equal(2, entrants.size) + assert_equal(entrants(:second).name, entrants.first.name) + end + + def test_find_first + first = Topic.find_first "title = 'The First Topic'" + assert_equal(topics(:first).title, first.title) + end + + def test_find_first_failing + first = Topic.find_first "title = 'The First Topic!'" + assert_nil(first) + end + + def test_deprecated_find_on_conditions + assert Topic.find_on_conditions(1, ["approved = ?", false]) + assert_raises(ActiveRecord::RecordNotFound) { Topic.find_on_conditions(1, ["approved = ?", true]) } + end + + def test_condition_interpolation + assert_kind_of Firm, Company.find_first(["name = '%s'", "37signals"]) + assert_nil Company.find_first(["name = '%s'", "37signals!"]) + assert_nil Company.find_first(["name = '%s'", "37signals!' OR 1=1"]) + assert_kind_of Time, Topic.find_first(["id = %d", 1]).written_on + end + + def test_bind_variables + assert_kind_of Firm, Company.find_first(["name = ?", "37signals"]) + assert_nil Company.find_first(["name = ?", "37signals!"]) + assert_nil Company.find_first(["name = ?", "37signals!' OR 1=1"]) + assert_kind_of Time, Topic.find_first(["id = ?", 1]).written_on + assert_raises(ActiveRecord::PreparedStatementInvalid) { + Company.find_first(["id=? AND name = ?", 2]) + } + assert_raises(ActiveRecord::PreparedStatementInvalid) { + Company.find_first(["id=?", 2, 3, 4]) + } + end + + def test_bind_variables_with_quotes + Company.create("name" => "37signals' go'es agains") + assert Company.find_first(["name = ?", "37signals' go'es agains"]) + end + + def test_named_bind_variables_with_quotes + Company.create("name" => "37signals' go'es agains") + assert Company.find_first(["name = :name", {:name => "37signals' go'es agains"}]) + end + + def test_named_bind_variables + assert_equal '1', bind(':a', :a => 1) # ' ruby-mode + assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode + + assert_kind_of Firm, Company.find_first(["name = :name", { :name => "37signals" }]) + assert_nil Company.find_first(["name = :name", { :name => "37signals!" }]) + assert_nil Company.find_first(["name = :name", { :name => "37signals!' OR 1=1" }]) + assert_kind_of Time, Topic.find_first(["id = :id", { :id => 1 }]).written_on + end + + def test_count + assert_equal(0, Entrant.count("id > 3")) + assert_equal(1, Entrant.count(["id > ?", 2])) + assert_equal(2, Entrant.count(["id > ?", 1])) + end + + def test_count_by_sql + assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3")) + assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2])) + assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1])) + end + + def test_find_all_with_limit + first_five_developers = Developer.find_all nil, 'id ASC', 5 + assert_equal 5, first_five_developers.length + assert_equal 'David', first_five_developers.first.name + assert_equal 'fixture_5', first_five_developers.last.name + + no_developers = Developer.find_all nil, 'id ASC', 0 + assert_equal 0, no_developers.length + + assert_equal first_five_developers, Developer.find_all(nil, 'id ASC', [5]) + assert_equal no_developers, Developer.find_all(nil, 'id ASC', [0]) + end + + def test_find_all_with_limit_and_offset + first_three_developers = Developer.find_all nil, 'id ASC', [3, 0] + second_three_developers = Developer.find_all nil, 'id ASC', [3, 3] + last_two_developers = Developer.find_all nil, 'id ASC', [2, 8] + + assert_equal 3, first_three_developers.length + assert_equal 3, second_three_developers.length + assert_equal 2, last_two_developers.length + + assert_equal 'David', first_three_developers.first.name + assert_equal 'fixture_4', second_three_developers.first.name + assert_equal 'fixture_9', last_two_developers.first.name + end + + def test_find_all_by_one_attribute_with_options + topics = Topic.find_all_by_content("Have a nice day", "id DESC") + assert topics(:first), topics.last + + topics = Topic.find_all_by_content("Have a nice day", "id DESC") + assert topics(:first), topics.first + end + + protected + def bind(statement, *vars) + if vars.first.is_a?(Hash) + ActiveRecord::Base.send(:replace_named_bind_variables, statement, vars.first) + else + ActiveRecord::Base.send(:replace_bind_variables, statement, vars) + end + end +end +require 'abstract_unit' +require 'fixtures/company' +require 'fixtures/topic' +require 'fixtures/reply' +require 'fixtures/entrant' +require 'fixtures/developer' +require 'fixtures/post' + +class FinderTest < Test::Unit::TestCase + fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :accounts + + def test_find + assert_equal(topics(:first).title, Topic.find(1).title) + end + + def test_exists + assert (Topic.exists?(1)) + assert !(Topic.exists?(45)) + assert !(Topic.exists?("foo")) + assert !(Topic.exists?([1,2])) + end + + def test_find_by_array_of_one_id + assert_kind_of(Array, Topic.find([ 1 ])) + assert_equal(1, Topic.find([ 1 ]).length) + end + + def test_find_by_ids + assert_equal(2, Topic.find(1, 2).length) + assert_equal(topics(:second).title, Topic.find([ 2 ]).first.title) + end + + def test_find_an_empty_array + assert_equal [], Topic.find([]) + end + + def test_find_by_ids_missing_one + assert_raises(ActiveRecord::RecordNotFound) { + Topic.find(1, 2, 45) + } + end + + def test_find_all_with_limit + entrants = Entrant.find(:all, :order => "id ASC", :limit => 2) + + assert_equal(2, entrants.size) + assert_equal(entrants(:first).name, entrants.first.name) + end + + def test_find_all_with_prepared_limit_and_offset + entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 1) + + assert_equal(2, entrants.size) + assert_equal(entrants(:second).name, entrants.first.name) + + entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 2) + assert_equal(1, entrants.size) + assert_equal(entrants(:third).name, entrants.first.name) + end + + def test_find_all_with_limit_and_offset_and_multiple_orderings + developers = Developer.find(:all, :order => "salary ASC, id DESC", :limit => 3, :offset => 1) + assert_equal ["David", "fixture_10", "fixture_9"], developers.collect {|d| d.name} + end + + def test_find_with_limit_and_condition + developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7) + assert_equal(1, developers.size) + assert_equal("fixture_3", developers.first.name) + end + + def test_find_with_entire_select_statement + topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'" + + assert_equal(1, topics.size) + assert_equal(topics(:second).title, topics.first.title) + end + + def test_find_with_prepared_select_statement + topics = Topic.find_by_sql ["SELECT * FROM topics WHERE author_name = ?", "Mary"] + + assert_equal(1, topics.size) + assert_equal(topics(:second).title, topics.first.title) + end + + def test_find_first + first = Topic.find(:first, :conditions => "title = 'The First Topic'") + assert_equal(topics(:first).title, first.title) + end + + def test_find_first_failing + first = Topic.find(:first, :conditions => "title = 'The First Topic!'") + assert_nil(first) + end + + def test_unexisting_record_exception_handling + assert_raises(ActiveRecord::RecordNotFound) { + Topic.find(1).parent + } + + Topic.find(2).topic + end + + def test_find_only_some_columns + topic = Topic.find(1, :select => "author_name") + assert_raises(NoMethodError) { topic.title } + assert_equal "David", topic.author_name + assert !topic.attribute_present?("title") + assert !topic.respond_to?("title") + assert topic.attribute_present?("author_name") + assert topic.respond_to?("author_name") + end + + def test_find_on_conditions + assert Topic.find(1, :conditions => ["approved = ?", false]) + assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => ["approved = ?", true]) } + end + + def test_condition_interpolation + assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"]) + assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"]) + assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!' OR 1=1"]) + assert_kind_of Time, Topic.find(:first, :conditions => ["id = %d", 1]).written_on + end + + def test_bind_variables + assert_kind_of Firm, Company.find(:first, :conditions => ["name = ?", "37signals"]) + assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!"]) + assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!' OR 1=1"]) + assert_kind_of Time, Topic.find(:first, :conditions => ["id = ?", 1]).written_on + assert_raises(ActiveRecord::PreparedStatementInvalid) { + Company.find(:first, :conditions => ["id=? AND name = ?", 2]) + } + assert_raises(ActiveRecord::PreparedStatementInvalid) { + Company.find(:first, :conditions => ["id=?", 2, 3, 4]) + } + end + + def test_bind_variables_with_quotes + Company.create("name" => "37signals' go'es agains") + assert Company.find(:first, :conditions => ["name = ?", "37signals' go'es agains"]) + end + + def test_named_bind_variables_with_quotes + Company.create("name" => "37signals' go'es agains") + assert Company.find(:first, :conditions => ["name = :name", {:name => "37signals' go'es agains"}]) + end + + def test_bind_arity + assert_nothing_raised { bind '' } + assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '', 1 } + + assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?' } + assert_nothing_raised { bind '?', 1 } + assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?', 1, 1 } + end + + def test_named_bind_variables + assert_equal '1', bind(':a', :a => 1) # ' ruby-mode + assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode + + assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }]) + assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }]) + assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!' OR 1=1" }]) + assert_kind_of Time, Topic.find(:first, :conditions => ["id = :id", { :id => 1 }]).written_on + end + + def test_bind_enumerable + assert_equal '1,2,3', bind('?', [1, 2, 3]) + assert_equal %('a','b','c'), bind('?', %w(a b c)) + + assert_equal '1,2,3', bind(':a', :a => [1, 2, 3]) + assert_equal %('a','b','c'), bind(':a', :a => %w(a b c)) # ' + + require 'set' + assert_equal '1,2,3', bind('?', Set.new([1, 2, 3])) + assert_equal %('a','b','c'), bind('?', Set.new(%w(a b c))) + + assert_equal '1,2,3', bind(':a', :a => Set.new([1, 2, 3])) + assert_equal %('a','b','c'), bind(':a', :a => Set.new(%w(a b c))) # ' + end + + def test_bind_string + assert_equal "''", bind('?', '') + end + + def test_string_sanitation + assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1") + assert_equal "'something; select table'", ActiveRecord::Base.sanitize("something; select table") + end + + def test_count + assert_equal(0, Entrant.count("id > 3")) + assert_equal(1, Entrant.count(["id > ?", 2])) + assert_equal(2, Entrant.count(["id > ?", 1])) + end + + def test_count_by_sql + assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3")) + assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2])) + assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1])) + end + + def test_find_by_one_attribute + assert_equal topics(:first), Topic.find_by_title("The First Topic") + assert_nil Topic.find_by_title("The First Topic!") + end + + def test_find_by_one_attribute_with_order_option + assert_equal accounts(:signals37), Account.find_by_credit_limit(50, :order => 'id') + assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :order => 'id DESC') + end + + def test_find_by_one_attribute_with_conditions + assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6]) + end + + def test_find_by_one_attribute_with_several_options + assert_equal accounts(:unknown), Account.find_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3]) + end + + def test_find_by_one_missing_attribute + assert_raises(NoMethodError) { Topic.find_by_undertitle("The First Topic!") } + end + + def test_find_by_two_attributes + assert_equal topics(:first), Topic.find_by_title_and_author_name("The First Topic", "David") + assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary") + end + + def test_find_all_by_one_attribute + topics = Topic.find_all_by_content("Have a nice day") + assert_equal 2, topics.size + assert topics.include?(topics(:first)) + + assert_equal [], Topic.find_all_by_title("The First Topic!!") + end + + def test_find_all_by_one_attribute_with_options + topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC") + assert topics(:first), topics.last + + topics = Topic.find_all_by_content("Have a nice day", :order => "id") + assert topics(:first), topics.first + end + + def test_find_all_by_array_attribute + assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic's of the day"]).size + end + + def test_find_all_by_boolean_attribute + topics = Topic.find_all_by_approved(false) + assert_equal 1, topics.size + assert topics.include?(topics(:first)) + + topics = Topic.find_all_by_approved(true) + assert_equal 1, topics.size + assert topics.include?(topics(:second)) + end + + def test_find_by_nil_attribute + topic = Topic.find_by_last_read nil + assert_not_nil topic + assert_nil topic.last_read + end + + def test_find_all_by_nil_attribute + topics = Topic.find_all_by_last_read nil + assert_equal 1, topics.size + assert_nil topics[0].last_read + end + + def test_find_by_nil_and_not_nil_attributes + topic = Topic.find_by_last_read_and_author_name nil, "Mary" + assert_equal "Mary", topic.author_name + end + + def test_find_all_by_nil_and_not_nil_attributes + topics = Topic.find_all_by_last_read_and_author_name nil, "Mary" + assert_equal 1, topics.size + assert_equal "Mary", topics[0].author_name + end + + def test_find_or_create_from_one_attribute + number_of_companies = Company.count + sig38 = Company.find_or_create_by_name("38signals") + assert_equal number_of_companies + 1, Company.count + assert_equal sig38, Company.find_or_create_by_name("38signals") + end + + def test_find_or_create_from_two_attributes + number_of_topics = Topic.count + another = Topic.find_or_create_by_title_and_author_name("Another topic","John") + assert_equal number_of_topics + 1, Topic.count + assert_equal another, Topic.find_or_create_by_title_and_author_name("Another topic", "John") + end + + def test_find_with_bad_sql + assert_raises(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" } + end + + def test_find_with_invalid_params + assert_raises(ArgumentError) { Topic.find :first, :join => "It should be `joins'" } + assert_raises(ArgumentError) { Topic.find :first, :conditions => '1 = 1', :join => "It should be `joins'" } + end + + def test_find_all_with_limit + first_five_developers = Developer.find :all, :order => 'id ASC', :limit => 5 + assert_equal 5, first_five_developers.length + assert_equal 'David', first_five_developers.first.name + assert_equal 'fixture_5', first_five_developers.last.name + + no_developers = Developer.find :all, :order => 'id ASC', :limit => 0 + assert_equal 0, no_developers.length + end + + def test_find_all_with_limit_and_offset + first_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 0 + second_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 3 + last_two_developers = Developer.find :all, :order => 'id ASC', :limit => 2, :offset => 8 + + assert_equal 3, first_three_developers.length + assert_equal 3, second_three_developers.length + assert_equal 2, last_two_developers.length + + assert_equal 'David', first_three_developers.first.name + assert_equal 'fixture_4', second_three_developers.first.name + assert_equal 'fixture_9', last_two_developers.first.name + end + + def test_find_all_with_limit_and_offset_and_multiple_order_clauses + first_three_posts = Post.find :all, :order => 'author_id, id', :limit => 3, :offset => 0 + second_three_posts = Post.find :all, :order => ' author_id,id ', :limit => 3, :offset => 3 + last_posts = Post.find :all, :order => ' author_id, id ', :limit => 3, :offset => 6 + + assert_equal [[0,3],[1,1],[1,2]], first_three_posts.map { |p| [p.author_id, p.id] } + assert_equal [[1,4],[1,5],[1,6]], second_three_posts.map { |p| [p.author_id, p.id] } + assert_equal [[2,7]], last_posts.map { |p| [p.author_id, p.id] } + end + + def test_find_all_with_join + developers_on_project_one = Developer.find( + :all, + :joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id', + :conditions => 'project_id=1' + ) + assert_equal 3, developers_on_project_one.length + developer_names = developers_on_project_one.map { |d| d.name } + assert developer_names.include?('David') + assert developer_names.include?('Jamis') + end + + def test_find_by_id_with_conditions_with_or + assert_nothing_raised do + Post.find([1,2,3], + :conditions => "posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'") + end + end + + def test_select_value + assert_equal "37signals", Company.connection.select_value("SELECT name FROM companies WHERE id = 1") + assert_nil Company.connection.select_value("SELECT name FROM companies WHERE id = -1") + # make sure we didn't break count... + assert_equal 0, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = 'Halliburton'") + assert_equal 1, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = '37signals'") + end + + def test_select_values + assert_equal ["1","2","3","4","5","6","7","8"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s } + assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel"], Company.connection.select_values("SELECT name FROM companies ORDER BY id") + end + + protected + def bind(statement, *vars) + if vars.first.is_a?(Hash) + ActiveRecord::Base.send(:replace_named_bind_variables, statement, vars.first) + else + ActiveRecord::Base.send(:replace_bind_variables, statement, vars) + end + end +end +class Author < ActiveRecord::Base + has_many :posts + has_many :posts_with_comments, :include => :comments, :class_name => "Post" + has_many :posts_with_categories, :include => :categories, :class_name => "Post" + has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post" + has_many :comments, :through => :posts + has_many :funky_comments, :through => :posts, :source => :comments + + has_many :special_posts, :class_name => "Post" + has_many :hello_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'hello'" + has_many :nonexistent_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'nonexistent'" + has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding, + :after_add => :log_after_adding, + :before_remove => :log_before_removing, + :after_remove => :log_after_removing + has_many :posts_with_proc_callbacks, :class_name => "Post", + :before_add => Proc.new {|o, r| o.post_log << "before_adding#{r.id}"}, + :after_add => Proc.new {|o, r| o.post_log << "after_adding#{r.id}"}, + :before_remove => Proc.new {|o, r| o.post_log << "before_removing#{r.id}"}, + :after_remove => Proc.new {|o, r| o.post_log << "after_removing#{r.id}"} + has_many :posts_with_multiple_callbacks, :class_name => "Post", + :before_add => [:log_before_adding, Proc.new {|o, r| o.post_log << "before_adding_proc#{r.id}"}], + :after_add => [:log_after_adding, Proc.new {|o, r| o.post_log << "after_adding_proc#{r.id}"}] + has_many :unchangable_posts, :class_name => "Post", :before_add => :raise_exception, :after_add => :log_after_adding + + has_many :categorizations + has_many :categories, :through => :categorizations + + has_many :nothings, :through => :kateggorisatons, :class_name => 'Category' + + has_many :author_favorites + has_many :favorite_authors, :through => :author_favorites, :order => 'name' + + has_many :tagging, :through => :posts # through polymorphic has_one + has_many :taggings, :through => :posts, :source => :taggings # through polymorphic has_many + has_many :tags, :through => :posts # through has_many :through + has_many :post_categories, :through => :posts, :source => :categories + + belongs_to :author_address + + attr_accessor :post_log + + def after_initialize + @post_log = [] + end + + private + def log_before_adding(object) + @post_log << "before_adding#{object.id}" + end + + def log_after_adding(object) + @post_log << "after_adding#{object.id}" + end + + def log_before_removing(object) + @post_log << "before_removing#{object.id}" + end + + def log_after_removing(object) + @post_log << "after_removing#{object.id}" + end + + def raise_exception(object) + raise Exception.new("You can't add a post") + end +end + +class AuthorAddress < ActiveRecord::Base + has_one :author +end + +class AuthorFavorite < ActiveRecord::Base + belongs_to :author + belongs_to :favorite_author, :class_name => "Author", :foreign_key => 'favorite_author_id' +endclass AutoId < ActiveRecord::Base + def self.table_name () "auto_id_tests" end + def self.primary_key () "auto_id" end +end +class Binary < ActiveRecord::Base +endclass Categorization < ActiveRecord::Base + belongs_to :post + belongs_to :category + belongs_to :author +endclass Category < ActiveRecord::Base + has_and_belongs_to_many :posts + has_and_belongs_to_many :special_posts, :class_name => "Post" + has_and_belongs_to_many :hello_posts, :class_name => "Post", :conditions => "\#{aliased_table_name}.body = 'hello'" + has_and_belongs_to_many :nonexistent_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'nonexistent'" + + def self.what_are_you + 'a category...' + end + + has_many :categorizations + has_many :authors, :through => :categorizations, :select => 'authors.*, categorizations.post_id' +end + +class SpecialCategory < Category + + def self.what_are_you + 'a special category...' + end + +end +class ColumnName < ActiveRecord::Base + def self.table_name () "colnametests" end +endclass Comment < ActiveRecord::Base + belongs_to :post + + def self.what_are_you + 'a comment...' + end + + def self.search_by_type(q) + self.find(:all, :conditions => ["#{QUOTED_TYPE} = ?", q]) + end +end + +class SpecialComment < Comment + def self.what_are_you + 'a special comment...' + end +end + +class VerySpecialComment < Comment + def self.what_are_you + 'a very special comment...' + end +endclass Company < ActiveRecord::Base + attr_protected :rating + set_sequence_name :companies_nonstd_seq + + validates_presence_of :name + + has_one :dummy_account, :foreign_key => "firm_id", :class_name => "Account" +end + + +class Firm < Company + has_many :clients, :order => "id", :dependent => :destroy, :counter_sql => + "SELECT COUNT(*) FROM companies WHERE firm_id = 1 " + + "AND (#{QUOTED_TYPE} = 'Client' OR #{QUOTED_TYPE} = 'SpecialClient' OR #{QUOTED_TYPE} = 'VerySpecialClient' )" + has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC" + has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id" + has_many :dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :destroy + has_many :exclusively_dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all + has_many :limited_clients, :class_name => "Client", :order => "id", :limit => 1 + has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id" + has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}' + has_many :clients_using_counter_sql, :class_name => "Client", + :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}', + :counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = #{id}' + has_many :clients_using_zero_counter_sql, :class_name => "Client", + :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}', + :counter_sql => 'SELECT 0 FROM companies WHERE client_of = #{id}' + has_many :no_clients_using_counter_sql, :class_name => "Client", + :finder_sql => 'SELECT * FROM companies WHERE client_of = 1000', + :counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = 1000' + + has_one :account, :foreign_key => "firm_id", :dependent => :destroy +end + +class DependentFirm < Company + has_one :account, :foreign_key => "firm_id", :dependent => :nullify + has_many :companies, :foreign_key => 'client_of', :order => "id", :dependent => :nullify +end + + +class Client < Company + belongs_to :firm, :foreign_key => "client_of" + belongs_to :firm_with_basic_id, :class_name => "Firm", :foreign_key => "firm_id" + belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of" + belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1] + + # Record destruction so we can test whether firm.clients.clear has + # is calling client.destroy, deleting from the database, or setting + # foreign keys to NULL. + def self.destroyed_client_ids + @destroyed_client_ids ||= Hash.new { |h,k| h[k] = [] } + end + + before_destroy do |client| + if client.firm + Client.destroyed_client_ids[client.firm.id] << client.id + end + true + end + + # Used to test that read and question methods are not generated for these attributes + def ruby_type + read_attribute :ruby_type + end + + def rating? + query_attribute :rating + end +end + + +class SpecialClient < Client +end + +class VerySpecialClient < SpecialClient +end + +class Account < ActiveRecord::Base + belongs_to :firm + + protected + def validate + errors.add_on_empty "credit_limit" + end +endmodule MyApplication + module Business + class Company < ActiveRecord::Base + attr_protected :rating + end + + class Firm < Company + has_many :clients, :order => "id", :dependent => :destroy + has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC" + has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id" + has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id" + has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}' + + has_one :account, :dependent => :destroy + end + + class Client < Company + belongs_to :firm, :foreign_key => "client_of" + belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of" + end + + class Developer < ActiveRecord::Base + has_and_belongs_to_many :projects + + protected + def validate + errors.add_on_boundary_breaking("name", 3..20) + end + end + + class Project < ActiveRecord::Base + has_and_belongs_to_many :developers + end + + end + + module Billing + class Firm < ActiveRecord::Base + self.table_name = 'companies' + end + + module Nested + class Firm < ActiveRecord::Base + self.table_name = 'companies' + end + end + + class Account < ActiveRecord::Base + belongs_to :firm, :class_name => 'MyApplication::Business::Firm' + belongs_to :qualified_billing_firm, :class_name => 'MyApplication::Billing::Firm' + belongs_to :unqualified_billing_firm, :class_name => 'Firm' + belongs_to :nested_qualified_billing_firm, :class_name => 'MyApplication::Billing::Nested::Firm' + belongs_to :nested_unqualified_billing_firm, :class_name => 'Nested::Firm' + + protected + def validate + errors.add_on_empty "credit_limit" + end + end + end +end +class Computer < ActiveRecord::Base + belongs_to :developer, :foreign_key=>'developer' +end +class Course < ActiveRecord::Base + has_many :entrants +end +class Customer < ActiveRecord::Base + composed_of :address, :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] + composed_of :balance, :class_name => "Money", :mapping => %w(balance amount) + composed_of :gps_location +end + +class Address + attr_reader :street, :city, :country + + def initialize(street, city, country) + @street, @city, @country = street, city, country + end + + def close_to?(other_address) + city == other_address.city && country == other_address.country + end + + def ==(other) + other.is_a?(self.class) && other.street == street && other.city == city && other.country == country + end +end + +class Money + attr_reader :amount, :currency + + EXCHANGE_RATES = { "USD_TO_DKK" => 6, "DKK_TO_USD" => 0.6 } + + def initialize(amount, currency = "USD") + @amount, @currency = amount, currency + end + + def exchange_to(other_currency) + Money.new((amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]).floor, other_currency) + end +end + +class GpsLocation + attr_reader :gps_location + + def initialize(gps_location) + @gps_location = gps_location + end + + def latitude + gps_location.split("x").first + end + + def longitude + gps_location.split("x").last + end + + def ==(other) + self.latitude == other.latitude && self.longitude == other.longitude + end +endActiveRecord::Schema.define do + + create_table :taggings, :force => true do |t| + t.column :tag_id, :integer + t.column :super_tag_id, :integer + t.column :taggable_type, :string + t.column :taggable_id, :integer + end + + create_table :tags, :force => true do |t| + t.column :name, :string + t.column :taggings_count, :integer, :default => 0 + end + + create_table :categorizations, :force => true do |t| + t.column :category_id, :integer + t.column :post_id, :integer + t.column :author_id, :integer + end + + add_column :posts, :taggings_count, :integer, :default => 0 + add_column :authors, :author_address_id, :integer + + create_table :author_addresses, :force => true do |t| + t.column :author_address_id, :integer + end + + create_table :author_favorites, :force => true do |t| + t.column :author_id, :integer + t.column :favorite_author_id, :integer + end +endclass Default < ActiveRecord::Base +end +module DeveloperProjectsAssociationExtension + def find_most_recent + find(:first, :order => "id DESC") + end +end + +class Developer < ActiveRecord::Base + has_and_belongs_to_many :projects do + def find_most_recent + find(:first, :order => "id DESC") + end + end + + has_and_belongs_to_many :projects_extended_by_name, + :class_name => "Project", + :join_table => "developers_projects", + :association_foreign_key => "project_id", + :extend => DeveloperProjectsAssociationExtension + + has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id' + + validates_inclusion_of :salary, :in => 50000..200000 + validates_length_of :name, :within => 3..20 +end + +DeveloperSalary = Struct.new(:amount) +class DeveloperWithAggregate < ActiveRecord::Base + self.table_name = 'developers' + composed_of :salary, :class_name => 'DeveloperSalary', :mapping => [%w(salary amount)] +end + +class DeveloperWithBeforeDestroyRaise < ActiveRecord::Base + self.table_name = 'developers' + has_and_belongs_to_many :projects, :join_table => 'developers_projects', :foreign_key => 'developer_id' + before_destroy :raise_if_projects_empty! + + def raise_if_projects_empty! + raise if projects.empty? + end +end +class Entrant < ActiveRecord::Base + belongs_to :course +end +class Joke < ActiveRecord::Base + set_table_name 'funny_jokes' +end +class Joke < ActiveRecord::Base + set_table_name 'funny_jokes' +endclass Keyboard < ActiveRecord::Base + set_primary_key 'key_number' +end +class LegacyThing < ActiveRecord::Base + set_locking_column :version +end +class PeopleHaveLastNames < ActiveRecord::Migration + def self.up + add_column "people", "last_name", :string + end + + def self.down + remove_column "people", "last_name" + end +endclass WeNeedReminders < ActiveRecord::Migration + def self.up + create_table("reminders") do |t| + t.column :content, :text + t.column :remind_at, :datetime + end + end + + def self.down + drop_table "reminders" + end +endclass InnocentJointable < ActiveRecord::Migration + def self.up + create_table("people_reminders", :id => false) do |t| + t.column :reminder_id, :integer + t.column :person_id, :integer + end + end + + def self.down + drop_table "people_reminders" + end +endclass PeopleHaveLastNames < ActiveRecord::Migration + def self.up + add_column "people", "last_name", :string + end + + def self.down + remove_column "people", "last_name" + end +endclass WeNeedReminders < ActiveRecord::Migration + def self.up + create_table("reminders") do |t| + t.column :content, :text + t.column :remind_at, :datetime + end + end + + def self.down + drop_table "reminders" + end +endclass Foo < ActiveRecord::Migration + def self.up + end + + def self.down + end +endclass InnocentJointable < ActiveRecord::Migration + def self.up + create_table("people_reminders", :id => false) do |t| + t.column :reminder_id, :integer + t.column :person_id, :integer + end + end + + def self.down + drop_table "people_reminders" + end +endclass Mixin < ActiveRecord::Base + +end + +class TreeMixin < Mixin + acts_as_tree :foreign_key => "parent_id", :order => "id" +end + +class TreeMixinWithoutOrder < Mixin + acts_as_tree :foreign_key => "parent_id" +end + +class ListMixin < Mixin + acts_as_list :column => "pos", :scope => :parent + + def self.table_name() "mixins" end +end + +class ListMixinSub1 < ListMixin +end + +class ListMixinSub2 < ListMixin +end + + +class ListWithStringScopeMixin < ActiveRecord::Base + acts_as_list :column => "pos", :scope => 'parent_id = #{parent_id}' + + def self.table_name() "mixins" end +end + +class NestedSet < Mixin + acts_as_nested_set :scope => "root_id IS NULL" + + def self.table_name() "mixins" end +end + +class NestedSetWithStringScope < Mixin + acts_as_nested_set :scope => 'root_id = #{root_id}' + + def self.table_name() "mixins" end +end + +class NestedSetWithSymbolScope < Mixin + acts_as_nested_set :scope => :root + + def self.table_name() "mixins" end +end +class Movie < ActiveRecord::Base + def self.primary_key + "movieid" + end +end +class Order < ActiveRecord::Base + belongs_to :billing, :class_name => 'Customer', :foreign_key => 'billing_customer_id' + belongs_to :shipping, :class_name => 'Customer', :foreign_key => 'shipping_customer_id' +end +class Person < ActiveRecord::Base + has_many :readers + has_many :posts, :through => :readers +end +class Post < ActiveRecord::Base + belongs_to :author do + def greeting + "hello" + end + end + + belongs_to :author_with_posts, :class_name => "Author", :include => :posts + + has_many :comments, :order => "body" do + def find_most_recent + find(:first, :order => "id DESC") + end + end + + has_one :very_special_comment + has_one :very_special_comment_with_post, :class_name => "VerySpecialComment", :include => :post + has_many :special_comments + + has_and_belongs_to_many :categories + has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id' + + has_many :taggings, :as => :taggable + has_many :tags, :through => :taggings, :include => :tagging do + def add_joins_and_select + find :all, :select => 'tags.*, authors.id as author_id', :include => false, + :joins => 'left outer join posts on taggings.taggable_id = posts.id left outer join authors on posts.author_id = authors.id' + end + end + + has_many :funky_tags, :through => :taggings, :source => :tag + has_many :super_tags, :through => :taggings + has_one :tagging, :as => :taggable + + has_many :invalid_taggings, :as => :taggable, :class_name => "Tagging", :conditions => 'taggings.id < 0' + has_many :invalid_tags, :through => :invalid_taggings, :source => :tag + + has_many :categorizations, :foreign_key => :category_id + has_many :authors, :through => :categorizations + + has_many :readers + has_many :people, :through => :readers + + def self.what_are_you + 'a post...' + end +end + +class SpecialPost < Post; end; + +class StiPost < Post + self.abstract_class = true + has_one :special_comment, :class_name => "SpecialComment" +end + +class SubStiPost < StiPost +end +class Project < ActiveRecord::Base + has_and_belongs_to_many :developers, :uniq => true + has_and_belongs_to_many :limited_developers, :class_name => "Developer", :limit => 1 + has_and_belongs_to_many :developers_named_david, :class_name => "Developer", :conditions => "name = 'David'", :uniq => true + has_and_belongs_to_many :salaried_developers, :class_name => "Developer", :conditions => "salary > 0" + has_and_belongs_to_many :developers_with_finder_sql, :class_name => "Developer", :finder_sql => 'SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id}' + has_and_belongs_to_many :developers_by_sql, :class_name => "Developer", :delete_sql => "DELETE FROM developers_projects WHERE project_id = \#{id} AND developer_id = \#{record.id}" + has_and_belongs_to_many :developers_with_callbacks, :class_name => "Developer", :before_add => Proc.new {|o, r| o.developers_log << "before_adding#{r.id}"}, + :after_add => Proc.new {|o, r| o.developers_log << "after_adding#{r.id}"}, + :before_remove => Proc.new {|o, r| o.developers_log << "before_removing#{r.id}"}, + :after_remove => Proc.new {|o, r| o.developers_log << "after_removing#{r.id}"} + + attr_accessor :developers_log + + def after_initialize + @developers_log = [] + end + +end + +class SpecialProject < Project + def hello_world + "hello there!" + end +end +class Reader < ActiveRecord::Base + belongs_to :post + belongs_to :person +end +require 'fixtures/topic' + +class Reply < Topic + belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true + has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id" + + validate :errors_on_empty_content + validate_on_create :title_is_wrong_create + + attr_accessible :title, :author_name, :author_email_address, :written_on, :content, :last_read + + def validate + errors.add("title", "Empty") unless attribute_present? "title" + end + + def errors_on_empty_content + errors.add("content", "Empty") unless attribute_present? "content" + end + + def validate_on_create + if attribute_present?("title") && attribute_present?("content") && content == "Mismatch" + errors.add("title", "is Content Mismatch") + end + end + + def title_is_wrong_create + errors.add("title", "is Wrong Create") if attribute_present?("title") && title == "Wrong Create" + end + + def validate_on_update + errors.add("title", "is Wrong Update") if attribute_present?("title") && title == "Wrong Update" + end +end + +class SillyReply < Reply + belongs_to :reply, :foreign_key => "parent_id", :counter_cache => :replies_count +end +# used for OracleSynonymTest, see test/synonym_test_oci.rb +# +class Subject < ActiveRecord::Base +end +class Subscriber < ActiveRecord::Base + set_primary_key 'nick' +end + +class SpecialSubscriber < Subscriber +end +class Tag < ActiveRecord::Base + has_many :taggings + has_many :taggables, :through => :taggings + has_one :tagging +endclass Tagging < ActiveRecord::Base + belongs_to :tag, :include => :tagging + belongs_to :super_tag, :class_name => 'Tag', :foreign_key => 'super_tag_id' + belongs_to :invalid_tag, :class_name => 'Tag', :foreign_key => 'tag_id' + belongs_to :taggable, :polymorphic => true, :counter_cache => true +endclass Task < ActiveRecord::Base + +end +class Topic < ActiveRecord::Base + has_many :replies, :dependent => :destroy, :foreign_key => "parent_id" + serialize :content + + before_create :default_written_on + before_destroy :destroy_children + + def parent + Topic.find(parent_id) + end + + protected + def default_written_on + self.written_on = Time.now unless attribute_present?("written_on") + end + + def destroy_children + self.class.delete_all "parent_id = #{id}" + end +endrequire 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/developer' +require 'fixtures/company' +require 'fixtures/task' +require 'fixtures/reply' +require 'fixtures/joke' +require 'fixtures/category' + +class FixturesTest < Test::Unit::TestCase + self.use_instantiated_fixtures = true + self.use_transactional_fixtures = false + + fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes + + FIXTURES = %w( accounts companies customers + developers developers_projects entrants + movies projects subscribers topics tasks ) + MATCH_ATTRIBUTE_NAME = /[a-zA-Z][-_\w]*/ + + def test_clean_fixtures + FIXTURES.each do |name| + fixtures = nil + assert_nothing_raised { fixtures = create_fixtures(name) } + assert_kind_of(Fixtures, fixtures) + fixtures.each { |name, fixture| + fixture.each { |key, value| + assert_match(MATCH_ATTRIBUTE_NAME, key) + } + } + end + end + + def test_multiple_clean_fixtures + fixtures_array = nil + assert_nothing_raised { fixtures_array = create_fixtures(*FIXTURES) } + assert_kind_of(Array, fixtures_array) + fixtures_array.each { |fixtures| assert_kind_of(Fixtures, fixtures) } + end + + def test_attributes + topics = create_fixtures("topics") + assert_equal("The First Topic", topics["first"]["title"]) + assert_nil(topics["second"]["author_email_address"]) + end + + def test_inserts + topics = create_fixtures("topics") + firstRow = ActiveRecord::Base.connection.select_one("SELECT * FROM topics WHERE author_name = 'David'") + assert_equal("The First Topic", firstRow["title"]) + + secondRow = ActiveRecord::Base.connection.select_one("SELECT * FROM topics WHERE author_name = 'Mary'") + assert_nil(secondRow["author_email_address"]) + end + + if ActiveRecord::Base.connection.supports_migrations? + def test_inserts_with_pre_and_suffix + ActiveRecord::Base.connection.create_table :prefix_topics_suffix do |t| + t.column :title, :string + t.column :author_name, :string + t.column :author_email_address, :string + t.column :written_on, :datetime + t.column :bonus_time, :time + t.column :last_read, :date + t.column :content, :string + t.column :approved, :boolean, :default => true + t.column :replies_count, :integer, :default => 0 + t.column :parent_id, :integer + t.column :type, :string, :limit => 50 + end + + # Store existing prefix/suffix + old_prefix = ActiveRecord::Base.table_name_prefix + old_suffix = ActiveRecord::Base.table_name_suffix + + # Set a prefix/suffix we can test against + ActiveRecord::Base.table_name_prefix = 'prefix_' + ActiveRecord::Base.table_name_suffix = '_suffix' + + topics = create_fixtures("topics") + + firstRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'David'") + assert_equal("The First Topic", firstRow["title"]) + + secondRow = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'") + assert_nil(secondRow["author_email_address"]) + ensure + # Restore prefix/suffix to its previous values + ActiveRecord::Base.table_name_prefix = old_prefix + ActiveRecord::Base.table_name_suffix = old_suffix + + ActiveRecord::Base.connection.drop_table :prefix_topics_suffix rescue nil + end + end + + def test_insert_with_datetime + topics = create_fixtures("tasks") + first = Task.find(1) + assert first + end + + + def test_bad_format + path = File.join(File.dirname(__FILE__), 'fixtures', 'bad_fixtures') + Dir.entries(path).each do |file| + next unless File.file?(file) and file !~ Fixtures::DEFAULT_FILTER_RE + assert_raise(Fixture::FormatError) { + Fixture.new(bad_fixtures_path, file) + } + end + end + + def test_deprecated_yaml_extension + assert_raise(Fixture::FormatError) { + Fixtures.new(nil, 'bad_extension', 'BadExtension', File.join(File.dirname(__FILE__), 'fixtures')) + } + end + + def test_logger_level_invariant + level = ActiveRecord::Base.logger.level + create_fixtures('topics') + assert_equal level, ActiveRecord::Base.logger.level + end + + def test_instantiation + topics = create_fixtures("topics") + assert_kind_of Topic, topics["first"].find + end + + def test_complete_instantiation + assert_equal 2, @topics.size + assert_equal "The First Topic", @first.title + end + + def test_fixtures_from_root_yml_with_instantiation + # assert_equal 2, @accounts.size + assert_equal 50, @unknown.credit_limit + end + + def test_erb_in_fixtures + assert_equal 11, @developers.size + assert_equal "fixture_5", @dev_5.name + end + + def test_empty_yaml_fixture + assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', File.dirname(__FILE__) + "/fixtures/naked/yml/accounts") + end + + def test_empty_yaml_fixture_with_a_comment_in_it + assert_not_nil Fixtures.new( Account.connection, "companies", 'Company', File.dirname(__FILE__) + "/fixtures/naked/yml/companies") + end + + def test_dirty_dirty_yaml_file + assert_raises(Fixture::FormatError) do + Fixtures.new( Account.connection, "courses", 'Course', File.dirname(__FILE__) + "/fixtures/naked/yml/courses") + end + end + + def test_empty_csv_fixtures + assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', File.dirname(__FILE__) + "/fixtures/naked/csv/accounts") + end + + def test_omap_fixtures + assert_nothing_raised do + fixtures = Fixtures.new(Account.connection, 'categories', 'Category', File.dirname(__FILE__) + '/fixtures/categories_ordered') + + i = 0 + fixtures.each do |name, fixture| + assert_equal "fixture_no_#{i}", name + assert_equal "Category #{i}", fixture['name'] + i += 1 + end + end + end + + + def test_yml_file_in_subdirectory + assert_equal(categories(:sub_special_1).name, "A special category in a subdir file") + assert_equal(categories(:sub_special_1).class, SpecialCategory) + end + + def test_subsubdir_file_with_arbitrary_name + assert_equal(categories(:sub_special_3).name, "A special category in an arbitrarily named subsubdir file") + assert_equal(categories(:sub_special_3).class, SpecialCategory) + end + + +end + +if Account.connection.respond_to?(:reset_pk_sequence!) + class FixturesResetPkSequenceTest < Test::Unit::TestCase + fixtures :accounts + fixtures :companies + + def setup + @instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting')] + end + + def test_resets_to_min_pk_with_specified_pk_and_sequence + @instances.each do |instance| + model = instance.class + model.delete_all + model.connection.reset_pk_sequence!(model.table_name, model.primary_key, model.sequence_name) + + instance.save! + assert_equal 1, instance.id, "Sequence reset for #{model.table_name} failed." + end + end + + def test_resets_to_min_pk_with_default_pk_and_sequence + @instances.each do |instance| + model = instance.class + model.delete_all + model.connection.reset_pk_sequence!(model.table_name) + + instance.save! + assert_equal 1, instance.id, "Sequence reset for #{model.table_name} failed." + end + end + + def test_create_fixtures_resets_sequences + @instances.each do |instance| + max_id = create_fixtures(instance.class.table_name).inject(0) do |max_id, (name, fixture)| + fixture_id = fixture['id'].to_i + fixture_id > max_id ? fixture_id : max_id + end + + # Clone the last fixture to check that it gets the next greatest id. + instance.save! + assert_equal max_id + 1, instance.id, "Sequence reset for #{instance.class.table_name} failed." + end + end + end +end + + +class FixturesWithoutInstantiationTest < Test::Unit::TestCase + self.use_instantiated_fixtures = false + fixtures :topics, :developers, :accounts + + def test_without_complete_instantiation + assert_nil @first + assert_nil @topics + assert_nil @developers + assert_nil @accounts + end + + def test_fixtures_from_root_yml_without_instantiation + assert_nil @unknown + end + + def test_accessor_methods + assert_equal "The First Topic", topics(:first).title + assert_equal "Jamis", developers(:jamis).name + assert_equal 50, accounts(:signals37).credit_limit + end +end + + +class FixturesWithoutInstanceInstantiationTest < Test::Unit::TestCase + self.use_instantiated_fixtures = true + self.use_instantiated_fixtures = :no_instances + + fixtures :topics, :developers, :accounts + + def test_without_instance_instantiation + assert_nil @first + assert_not_nil @topics + assert_not_nil @developers + assert_not_nil @accounts + end +end + + +class TransactionalFixturesTest < Test::Unit::TestCase + self.use_instantiated_fixtures = true + self.use_transactional_fixtures = true + + fixtures :topics + + def test_destroy + assert_not_nil @first + @first.destroy + end + + def test_destroy_just_kidding + assert_not_nil @first + end +end + + +class MultipleFixturesTest < Test::Unit::TestCase + fixtures :topics + fixtures :developers, :accounts + + def test_fixture_table_names + assert_equal %w(topics developers accounts), fixture_table_names + end +end + + +class OverlappingFixturesTest < Test::Unit::TestCase + fixtures :topics, :developers + fixtures :developers, :accounts + + def test_fixture_table_names + assert_equal %w(topics developers accounts), fixture_table_names + end +end + + +class ForeignKeyFixturesTest < Test::Unit::TestCase + fixtures :fk_test_has_pk, :fk_test_has_fk + + # if foreign keys are implemented and fixtures + # are not deleted in reverse order then this test + # case will raise StatementInvalid + + def test_number1 + assert true + end + + def test_number2 + assert true + end +end + +class SetTableNameFixturesTest < Test::Unit::TestCase + set_fixture_class :funny_jokes => 'Joke' + fixtures :funny_jokes + + def test_table_method + assert_kind_of Joke, funny_jokes(:a_joke) + end +end + +class InvalidTableNameFixturesTest < Test::Unit::TestCase + fixtures :funny_jokes + + def test_raises_error + assert_raises FixtureClassNotFound do + funny_jokes(:a_joke) + end + end +end +require 'abstract_unit' +require 'fixtures/company' +require 'fixtures/project' +require 'fixtures/subscriber' + +class InheritanceTest < Test::Unit::TestCase + fixtures :companies, :projects, :subscribers + + def test_a_bad_type_column + #SQLServer need to turn Identity Insert On before manually inserting into the Identity column + if current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) + Company.connection.execute "SET IDENTITY_INSERT companies ON" + end + Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')" + + #We then need to turn it back Off before continuing. + if current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) + Company.connection.execute "SET IDENTITY_INSERT companies OFF" + end + assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) } + end + + def test_inheritance_find + assert Company.find(1).kind_of?(Firm), "37signals should be a firm" + assert Firm.find(1).kind_of?(Firm), "37signals should be a firm" + assert Company.find(2).kind_of?(Client), "Summit should be a client" + assert Client.find(2).kind_of?(Client), "Summit should be a client" + end + + def test_alt_inheritance_find + switch_to_alt_inheritance_column + test_inheritance_find + end + + def test_inheritance_find_all + companies = Company.find(:all, :order => 'id') + assert companies[0].kind_of?(Firm), "37signals should be a firm" + assert companies[1].kind_of?(Client), "Summit should be a client" + end + + def test_alt_inheritance_find_all + switch_to_alt_inheritance_column + test_inheritance_find_all + end + + def test_inheritance_save + firm = Firm.new + firm.name = "Next Angle" + firm.save + + next_angle = Company.find(firm.id) + assert next_angle.kind_of?(Firm), "Next Angle should be a firm" + end + + def test_alt_inheritance_save + switch_to_alt_inheritance_column + test_inheritance_save + end + + def test_inheritance_condition + assert_equal 8, Company.count + assert_equal 2, Firm.count + assert_equal 3, Client.count + end + + def test_alt_inheritance_condition + switch_to_alt_inheritance_column + test_inheritance_condition + end + + def test_finding_incorrect_type_data + assert_raises(ActiveRecord::RecordNotFound) { Firm.find(2) } + assert_nothing_raised { Firm.find(1) } + end + + def test_alt_finding_incorrect_type_data + switch_to_alt_inheritance_column + test_finding_incorrect_type_data + end + + def test_update_all_within_inheritance + Client.update_all "name = 'I am a client'" + assert_equal "I am a client", Client.find(:all).first.name + assert_equal "37signals", Firm.find(:all).first.name + end + + def test_alt_update_all_within_inheritance + switch_to_alt_inheritance_column + test_update_all_within_inheritance + end + + def test_destroy_all_within_inheritance + Client.destroy_all + assert_equal 0, Client.count + assert_equal 2, Firm.count + end + + def test_alt_destroy_all_within_inheritance + switch_to_alt_inheritance_column + test_destroy_all_within_inheritance + end + + def test_find_first_within_inheritance + assert_kind_of Firm, Company.find(:first, :conditions => "name = '37signals'") + assert_kind_of Firm, Firm.find(:first, :conditions => "name = '37signals'") + assert_nil Client.find(:first, :conditions => "name = '37signals'") + end + + def test_alt_find_first_within_inheritance + switch_to_alt_inheritance_column + test_find_first_within_inheritance + end + + def test_complex_inheritance + very_special_client = VerySpecialClient.create("name" => "veryspecial") + assert_equal very_special_client, VerySpecialClient.find(:first, :conditions => "name = 'veryspecial'") + assert_equal very_special_client, SpecialClient.find(:first, :conditions => "name = 'veryspecial'") + assert_equal very_special_client, Company.find(:first, :conditions => "name = 'veryspecial'") + assert_equal very_special_client, Client.find(:first, :conditions => "name = 'veryspecial'") + assert_equal 1, Client.find(:all, :conditions => "name = 'Summit'").size + assert_equal very_special_client, Client.find(very_special_client.id) + end + + def test_alt_complex_inheritance + switch_to_alt_inheritance_column + test_complex_inheritance + end + + def test_inheritance_without_mapping + assert_kind_of SpecialSubscriber, SpecialSubscriber.find("webster132") + assert_nothing_raised { s = SpecialSubscriber.new("name" => "And breaaaaathe!"); s.id = 'roger'; s.save } + end + + private + def switch_to_alt_inheritance_column + # we don't want misleading test results, so get rid of the values in the type column + Company.find(:all, :order => 'id').each do |c| + c['type'] = nil + c.save + end + + def Company.inheritance_column() "ruby_type" end + end +end +require 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/developer' +require 'fixtures/reply' + +class Topic; def after_find() end end +class Developer; def after_find() end end +class SpecialDeveloper < Developer; end + +class TopicManualObserver + include Singleton + + attr_reader :action, :object, :callbacks + + def initialize + Topic.add_observer(self) + @callbacks = [] + end + + def update(callback_method, object) + @callbacks << { "callback_method" => callback_method, "object" => object } + end + + def has_been_notified? + !@callbacks.empty? + end +end + +class TopicaObserver < ActiveRecord::Observer + def self.observed_class() Topic end + + attr_reader :topic + + def after_find(topic) + @topic = topic + end +end + +class TopicObserver < ActiveRecord::Observer + attr_reader :topic + + def after_find(topic) + @topic = topic + end +end + +class MultiObserver < ActiveRecord::Observer + attr_reader :record + + def self.observed_class() [ Topic, Developer ] end + + def after_find(record) + @record = record + end + +end + +class LifecycleTest < Test::Unit::TestCase + fixtures :topics, :developers + + def test_before_destroy + assert_equal 2, Topic.count + Topic.find(1).destroy + assert_equal 0, Topic.count + end + + def test_after_save + ActiveRecord::Base.observers = :topic_manual_observer + + topic = Topic.find(1) + topic.title = "hello" + topic.save + + assert TopicManualObserver.instance.has_been_notified? + assert_equal :after_save, TopicManualObserver.instance.callbacks.last["callback_method"] + end + + def test_observer_update_on_save + ActiveRecord::Base.observers = TopicManualObserver + + topic = Topic.find(1) + assert TopicManualObserver.instance.has_been_notified? + assert_equal :after_find, TopicManualObserver.instance.callbacks.first["callback_method"] + end + + def test_auto_observer + topic_observer = TopicaObserver.instance + + topic = Topic.find(1) + assert_equal topic_observer.topic.title, topic.title + end + + def test_infered_auto_observer + topic_observer = TopicObserver.instance + + topic = Topic.find(1) + assert_equal topic_observer.topic.title, topic.title + end + + def test_observing_two_classes + multi_observer = MultiObserver.instance + + topic = Topic.find(1) + assert_equal multi_observer.record.title, topic.title + + developer = Developer.find(1) + assert_equal multi_observer.record.name, developer.name + end + + def test_observing_subclasses + multi_observer = MultiObserver.instance + + developer = SpecialDeveloper.find(1) + assert_equal multi_observer.record.name, developer.name + end +end +require 'abstract_unit' +require 'fixtures/person' +require 'fixtures/legacy_thing' + +class LockingTest < Test::Unit::TestCase + fixtures :people, :legacy_things + + def test_lock_existing + p1 = Person.find(1) + p2 = Person.find(1) + + p1.first_name = "Michael" + p1.save + + assert_raises(ActiveRecord::StaleObjectError) { + p2.first_name = "should fail" + p2.save + } + end + + def test_lock_new + p1 = Person.create({ "first_name"=>"anika"}) + p2 = Person.find(p1.id) + assert_equal p1.id, p2.id + p1.first_name = "Anika" + p1.save + + assert_raises(ActiveRecord::StaleObjectError) { + p2.first_name = "should fail" + p2.save + } + end + + def test_lock_column_name_existing + t1 = LegacyThing.find(1) + t2 = LegacyThing.find(1) + t1.tps_report_number = 400 + t1.save + + assert_raises(ActiveRecord::StaleObjectError) { + t2.tps_report_number = 300 + t2.save + } + end + +end +require 'abstract_unit' +require 'fixtures/developer' +require 'fixtures/project' +require 'fixtures/comment' +require 'fixtures/post' +require 'fixtures/category' + +class MethodScopingTest < Test::Unit::TestCase + fixtures :developers, :projects, :comments, :posts + + def test_set_conditions + Developer.with_scope(:find => { :conditions => 'just a test...' }) do + assert_equal 'just a test...', Developer.send(:current_scoped_methods)[:find][:conditions] + end + end + + def test_scoped_find + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + assert_nothing_raised { Developer.find(1) } + end + end + + def test_scoped_find_first + Developer.with_scope(:find => { :conditions => "salary = 100000" }) do + assert_equal Developer.find(10), Developer.find(:first, :order => 'name') + end + end + + def test_scoped_find_combines_conditions + Developer.with_scope(:find => { :conditions => "salary = 9000" }) do + assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => "name = 'Jamis'") + end + end + + def test_scoped_find_sanitizes_conditions + Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do + assert_equal developers(:poor_jamis), Developer.find(:first) + end + end + + def test_scoped_find_combines_and_sanitizes_conditions + Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do + assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => ['name = ?', 'Jamis']) + end + end + + def test_scoped_find_all + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + assert_equal [developers(:david)], Developer.find(:all) + end + end + + def test_scoped_count + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + assert_equal 1, Developer.count + end + + Developer.with_scope(:find => { :conditions => 'salary = 100000' }) do + assert_equal 8, Developer.count + assert_equal 1, Developer.count("name LIKE 'fixture_1%'") + end + end + + def test_scoped_find_include + # with the include, will retrieve only developers for the given project + scoped_developers = Developer.with_scope(:find => { :include => :projects }) do + Developer.find(:all, :conditions => 'projects.id = 2') + end + assert scoped_developers.include?(developers(:david)) + assert !scoped_developers.include?(developers(:jamis)) + assert_equal 1, scoped_developers.size + end + + def test_scoped_count_include + # with the include, will retrieve only developers for the given project + Developer.with_scope(:find => { :include => :projects }) do + assert_equal 1, Developer.count('projects.id = 2') + end + end + + def test_scoped_create + new_comment = nil + + VerySpecialComment.with_scope(:create => { :post_id => 1 }) do + assert_equal({ :post_id => 1 }, VerySpecialComment.send(:current_scoped_methods)[:create]) + new_comment = VerySpecialComment.create :body => "Wonderful world" + end + + assert Post.find(1).comments.include?(new_comment) + end + + def test_immutable_scope + options = { :conditions => "name = 'David'" } + Developer.with_scope(:find => options) do + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + options[:conditions] = "name != 'David'" + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + end + + scope = { :find => { :conditions => "name = 'David'" }} + Developer.with_scope(scope) do + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + scope[:find][:conditions] = "name != 'David'" + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + end + end + + def test_scoped_with_duck_typing + scoping = Struct.new(:method_scoping).new(:find => { :conditions => ["name = ?", 'David'] }) + Developer.with_scope(scoping) do + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + end + end + + def test_ensure_that_method_scoping_is_correctly_restored + scoped_methods = Developer.instance_eval('current_scoped_methods') + + begin + Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do + raise "an exception" + end + rescue + end + assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods') + end +end + +class NestedScopingTest < Test::Unit::TestCase + fixtures :developers, :projects, :comments, :posts + + def test_merge_options + Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do + Developer.with_scope(:find => { :limit => 10 }) do + merged_option = Developer.instance_eval('current_scoped_methods')[:find] + assert_equal({ :conditions => 'salary = 80000', :limit => 10 }, merged_option) + end + end + end + + def test_replace_options + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + Developer.with_exclusive_scope(:find => { :conditions => "name = 'Jamis'" }) do + assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.instance_eval('current_scoped_methods')) + assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.send(:scoped_methods)[-1]) + end + end + end + + def test_append_conditions + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do + appended_condition = Developer.instance_eval('current_scoped_methods')[:find][:conditions] + assert_equal("( name = 'David' ) AND ( salary = 80000 )", appended_condition) + assert_equal(1, Developer.count) + end + Developer.with_scope(:find => { :conditions => "name = 'Maiha'" }) do + assert_equal(0, Developer.count) + end + end + end + + def test_merge_and_append_options + Developer.with_scope(:find => { :conditions => 'salary = 80000', :limit => 10 }) do + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + merged_option = Developer.instance_eval('current_scoped_methods')[:find] + assert_equal({ :conditions => "( salary = 80000 ) AND ( name = 'David' )", :limit => 10 }, merged_option) + end + end + end + + def test_nested_scoped_find + Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do + Developer.with_exclusive_scope(:find => { :conditions => "name = 'David'" }) do + assert_nothing_raised { Developer.find(1) } + assert_equal('David', Developer.find(:first).name) + end + assert_equal('Jamis', Developer.find(:first).name) + end + end + + def test_nested_scoped_find_include + Developer.with_scope(:find => { :include => :projects }) do + Developer.with_scope(:find => { :conditions => "projects.id = 2" }) do + assert_nothing_raised { Developer.find(1) } + assert_equal('David', Developer.find(:first).name) + end + end + end + + def test_nested_scoped_find_merged_include + # :include's remain unique and don't "double up" when merging + Developer.with_scope(:find => { :include => :projects, :conditions => "projects.id = 2" }) do + Developer.with_scope(:find => { :include => :projects }) do + assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length + assert_equal('David', Developer.find(:first).name) + end + end + + # the nested scope doesn't remove the first :include + Developer.with_scope(:find => { :include => :projects, :conditions => "projects.id = 2" }) do + Developer.with_scope(:find => { :include => [] }) do + assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length + assert_equal('David', Developer.find(:first).name) + end + end + + # mixing array and symbol include's will merge correctly + Developer.with_scope(:find => { :include => [:projects], :conditions => "projects.id = 2" }) do + Developer.with_scope(:find => { :include => :projects }) do + assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length + assert_equal('David', Developer.find(:first).name) + end + end + end + + def test_nested_scoped_find_replace_include + Developer.with_scope(:find => { :include => :projects }) do + Developer.with_exclusive_scope(:find => { :include => [] }) do + assert_equal 0, Developer.instance_eval('current_scoped_methods')[:find][:include].length + end + end + end + + def test_three_level_nested_exclusive_scoped_find + Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do + assert_equal('Jamis', Developer.find(:first).name) + + Developer.with_exclusive_scope(:find => { :conditions => "name = 'David'" }) do + assert_equal('David', Developer.find(:first).name) + + Developer.with_exclusive_scope(:find => { :conditions => "name = 'Maiha'" }) do + assert_equal(nil, Developer.find(:first)) + end + + # ensure that scoping is restored + assert_equal('David', Developer.find(:first).name) + end + + # ensure that scoping is restored + assert_equal('Jamis', Developer.find(:first).name) + end + end + + def test_merged_scoped_find + poor_jamis = developers(:poor_jamis) + Developer.with_scope(:find => { :conditions => "salary < 100000" }) do + Developer.with_scope(:find => { :offset => 1 }) do + assert_equal(poor_jamis, Developer.find(:first, :order => 'id asc')) + end + end + end + + def test_merged_scoped_find_sanitizes_conditions + Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do + Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do + assert_raise(ActiveRecord::RecordNotFound) { developers(:poor_jamis) } + end + end + end + + def test_nested_scoped_find_combines_and_sanitizes_conditions + Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do + Developer.with_exclusive_scope(:find => { :conditions => ['salary = ?', 9000] }) do + assert_equal developers(:poor_jamis), Developer.find(:first) + assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => ['name = ?', 'Jamis']) + end + end + end + + def test_merged_scoped_find_combines_and_sanitizes_conditions + Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do + Developer.with_scope(:find => { :conditions => ['salary > ?', 9000] }) do + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + end + end + end + + def test_immutable_nested_scope + options1 = { :conditions => "name = 'Jamis'" } + options2 = { :conditions => "name = 'David'" } + Developer.with_scope(:find => options1) do + Developer.with_exclusive_scope(:find => options2) do + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + options1[:conditions] = options2[:conditions] = nil + assert_equal %w(David), Developer.find(:all).map { |d| d.name } + end + end + end + + def test_immutable_merged_scope + options1 = { :conditions => "name = 'Jamis'" } + options2 = { :conditions => "salary > 10000" } + Developer.with_scope(:find => options1) do + Developer.with_scope(:find => options2) do + assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name } + options1[:conditions] = options2[:conditions] = nil + assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name } + end + end + end + + def test_ensure_that_method_scoping_is_correctly_restored + Developer.with_scope(:find => { :conditions => "name = 'David'" }) do + scoped_methods = Developer.instance_eval('current_scoped_methods') + begin + Developer.with_scope(:find => { :conditions => "name = 'Maiha'" }) do + raise "an exception" + end + rescue + end + assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods') + end + end +end + +class HasManyScopingTest< Test::Unit::TestCase + fixtures :comments, :posts + + def setup + @welcome = Post.find(1) + end + + def test_forwarding_of_static_methods + assert_equal 'a comment...', Comment.what_are_you + assert_equal 'a comment...', @welcome.comments.what_are_you + end + + def test_forwarding_to_scoped + assert_equal 4, Comment.search_by_type('Comment').size + assert_equal 2, @welcome.comments.search_by_type('Comment').size + end + + def test_forwarding_to_dynamic_finders + assert_equal 4, Comment.find_all_by_type('Comment').size + assert_equal 2, @welcome.comments.find_all_by_type('Comment').size + end + + def test_nested_scope + Comment.with_scope(:find => { :conditions => '1=1' }) do + assert_equal 'a comment...', @welcome.comments.what_are_you + end + end +end + + +class HasAndBelongsToManyScopingTest< Test::Unit::TestCase + fixtures :posts, :categories, :categories_posts + + def setup + @welcome = Post.find(1) + end + + def test_forwarding_of_static_methods + assert_equal 'a category...', Category.what_are_you + assert_equal 'a category...', @welcome.categories.what_are_you + end + + def test_forwarding_to_dynamic_finders + assert_equal 4, Category.find_all_by_type('SpecialCategory').size + assert_equal 0, @welcome.categories.find_all_by_type('SpecialCategory').size + assert_equal 2, @welcome.categories.find_all_by_type('Category').size + end + + def test_nested_scope + Category.with_scope(:find => { :conditions => '1=1' }) do + assert_equal 'a comment...', @welcome.comments.what_are_you + end + end +end + + +=begin +# We disabled the scoping for has_one and belongs_to as we can't think of a proper use case + + +class BelongsToScopingTest< Test::Unit::TestCase + fixtures :comments, :posts + + def setup + @greetings = Comment.find(1) + end + + def test_forwarding_of_static_method + assert_equal 'a post...', Post.what_are_you + assert_equal 'a post...', @greetings.post.what_are_you + end + + def test_forwarding_to_dynamic_finders + assert_equal 4, Post.find_all_by_type('Post').size + assert_equal 1, @greetings.post.find_all_by_type('Post').size + end + +end + + +class HasOneScopingTest< Test::Unit::TestCase + fixtures :comments, :posts + + def setup + @sti_comments = Post.find(4) + end + + def test_forwarding_of_static_methods + assert_equal 'a comment...', Comment.what_are_you + assert_equal 'a very special comment...', @sti_comments.very_special_comment.what_are_you + end + + def test_forwarding_to_dynamic_finders + assert_equal 1, Comment.find_all_by_type('VerySpecialComment').size + assert_equal 1, @sti_comments.very_special_comment.find_all_by_type('VerySpecialComment').size + assert_equal 0, @sti_comments.very_special_comment.find_all_by_type('Comment').size + end + +end + +=end +require 'abstract_unit' +require 'fixtures/person' +require File.dirname(__FILE__) + '/fixtures/migrations/1_people_have_last_names' +require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders' + +if ActiveRecord::Base.connection.supports_migrations? + class Reminder < ActiveRecord::Base; end + + class ActiveRecord::Migration + class <<self + attr_accessor :message_count + def puts(text="") + self.message_count ||= 0 + self.message_count += 1 + end + end + end + + class MigrationTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + def setup + ActiveRecord::Migration.verbose = true + PeopleHaveLastNames.message_count = 0 + end + + def teardown + ActiveRecord::Base.connection.initialize_schema_information + ActiveRecord::Base.connection.update "UPDATE #{ActiveRecord::Migrator.schema_info_table_name} SET version = 0" + + Reminder.connection.drop_table("reminders") rescue nil + Reminder.connection.drop_table("people_reminders") rescue nil + Reminder.connection.drop_table("prefix_reminders_suffix") rescue nil + Reminder.reset_column_information + + Person.connection.remove_column("people", "last_name") rescue nil + Person.connection.remove_column("people", "key") rescue nil + Person.connection.remove_column("people", "bio") rescue nil + Person.connection.remove_column("people", "age") rescue nil + Person.connection.remove_column("people", "height") rescue nil + Person.connection.remove_column("people", "birthday") rescue nil + Person.connection.remove_column("people", "favorite_day") rescue nil + Person.connection.remove_column("people", "male") rescue nil + Person.connection.remove_column("people", "administrator") rescue nil + Person.reset_column_information + end + + def test_add_index + Person.connection.add_column "people", "last_name", :string + Person.connection.add_column "people", "administrator", :boolean + Person.connection.add_column "people", "key", :string + + assert_nothing_raised { Person.connection.add_index("people", "last_name") } + assert_nothing_raised { Person.connection.remove_index("people", "last_name") } + + assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) } + assert_nothing_raised { Person.connection.remove_index("people", "last_name") } + + # quoting + assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key", :unique => true) } + assert_nothing_raised { Person.connection.remove_index("people", :name => "key") } + + # Sybase adapter does not support indexes on :boolean columns + unless current_adapter?(:SybaseAdapter) + assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") } + assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") } + end + end + + def test_create_table_adds_id + Person.connection.create_table :testings do |t| + t.column :foo, :string + end + + assert_equal %w(foo id), + Person.connection.columns(:testings).map { |c| c.name }.sort + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_create_table_with_not_null_column + Person.connection.create_table :testings do |t| + t.column :foo, :string, :null => false + end + + assert_raises(ActiveRecord::StatementInvalid) do + Person.connection.execute "insert into testings (foo) values (NULL)" + end + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_create_table_with_defaults + Person.connection.create_table :testings do |t| + t.column :one, :string, :default => "hello" + t.column :two, :boolean, :default => true + t.column :three, :boolean, :default => false + t.column :four, :integer, :default => 1 + end + + columns = Person.connection.columns(:testings) + one = columns.detect { |c| c.name == "one" } + two = columns.detect { |c| c.name == "two" } + three = columns.detect { |c| c.name == "three" } + four = columns.detect { |c| c.name == "four" } + + assert_equal "hello", one.default + if current_adapter?(:OracleAdapter) + # Oracle doesn't support native booleans + assert_equal true, two.default == 1 + assert_equal false, three.default != 0 + else + assert_equal true, two.default + assert_equal false, three.default + end + assert_equal 1, four.default + + ensure + Person.connection.drop_table :testings rescue nil + end + + # SQL Server and Sybase will not allow you to add a NOT NULL column + # to a table without specifying a default value, so the + # following test must be skipped + unless current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter) + def test_add_column_not_null_without_default + Person.connection.create_table :testings do |t| + t.column :foo, :string + end + Person.connection.add_column :testings, :bar, :string, :null => false + + assert_raises(ActiveRecord::StatementInvalid) do + Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)" + end + ensure + Person.connection.drop_table :testings rescue nil + end + end + + def test_add_column_not_null_with_default + Person.connection.create_table :testings do |t| + t.column :foo, :string + end + Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" + + assert_raises(ActiveRecord::StatementInvalid) do + Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)" + end + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_native_types + Person.delete_all + Person.connection.add_column "people", "last_name", :string + Person.connection.add_column "people", "bio", :text + Person.connection.add_column "people", "age", :integer + Person.connection.add_column "people", "height", :float + Person.connection.add_column "people", "birthday", :datetime + Person.connection.add_column "people", "favorite_day", :date + Person.connection.add_column "people", "male", :boolean + assert_nothing_raised { Person.create :first_name => 'bob', :last_name => 'bobsen', :bio => "I was born ....", :age => 18, :height => 1.78, :birthday => 18.years.ago, :favorite_day => 10.days.ago, :male => true } + bob = Person.find(:first) + + assert_equal bob.first_name, 'bob' + assert_equal bob.last_name, 'bobsen' + assert_equal bob.bio, "I was born ...." + assert_equal bob.age, 18 + assert_equal bob.male?, true + + assert_equal String, bob.first_name.class + assert_equal String, bob.last_name.class + assert_equal String, bob.bio.class + assert_equal Fixnum, bob.age.class + assert_equal Time, bob.birthday.class + + if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) || current_adapter?(:SybaseAdapter) + # SQL Server, Sybase, and Oracle don't differentiate between date/time + assert_equal Time, bob.favorite_day.class + else + assert_equal Date, bob.favorite_day.class + end + + assert_equal TrueClass, bob.male?.class + end + + def test_add_remove_single_field_using_string_arguments + assert !Person.column_methods_hash.include?(:last_name) + + ActiveRecord::Migration.add_column 'people', 'last_name', :string + + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + + ActiveRecord::Migration.remove_column 'people', 'last_name' + + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + end + + def test_add_remove_single_field_using_symbol_arguments + assert !Person.column_methods_hash.include?(:last_name) + + ActiveRecord::Migration.add_column :people, :last_name, :string + + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + + ActiveRecord::Migration.remove_column :people, :last_name + + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + end + + def test_add_rename + Person.delete_all + + begin + Person.connection.add_column "people", "girlfriend", :string + Person.create :girlfriend => 'bobette' + + Person.connection.rename_column "people", "girlfriend", "exgirlfriend" + + Person.reset_column_information + bob = Person.find(:first) + + assert_equal "bobette", bob.exgirlfriend + ensure + Person.connection.remove_column("people", "girlfriend") rescue nil + Person.connection.remove_column("people", "exgirlfriend") rescue nil + end + + end + + def test_rename_column_using_symbol_arguments + begin + Person.connection.rename_column :people, :first_name, :nick_name + Person.reset_column_information + assert Person.column_names.include?("nick_name") + ensure + Person.connection.remove_column("people","nick_name") + Person.connection.add_column("people","first_name", :string) + end + end + + def test_rename_column + begin + Person.connection.rename_column "people", "first_name", "nick_name" + Person.reset_column_information + assert Person.column_names.include?("nick_name") + ensure + Person.connection.remove_column("people","nick_name") + Person.connection.add_column("people","first_name", :string) + end + end + + def test_rename_table + begin + ActiveRecord::Base.connection.create_table :octopuses do |t| + t.column :url, :string + end + ActiveRecord::Base.connection.rename_table :octopuses, :octopi + + assert_nothing_raised do + if current_adapter?(:OracleAdapter) + # Oracle requires the explicit sequence value for the pk + ActiveRecord::Base.connection.execute "INSERT INTO octopi (id, url) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" + else + ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')" + end + end + + assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1") + + ensure + ActiveRecord::Base.connection.drop_table :octopuses rescue nil + ActiveRecord::Base.connection.drop_table :octopi rescue nil + end + end + + def test_change_column + Person.connection.add_column 'people', 'age', :integer + old_columns = Person.connection.columns(Person.table_name, "#{name} Columns") + assert old_columns.find { |c| c.name == 'age' and c.type == :integer } + + assert_nothing_raised { Person.connection.change_column "people", "age", :string } + + new_columns = Person.connection.columns(Person.table_name, "#{name} Columns") + assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer } + assert new_columns.find { |c| c.name == 'age' and c.type == :string } + end + + def test_change_column_with_new_default + Person.connection.add_column "people", "administrator", :boolean, :default => 1 + Person.reset_column_information + assert Person.new.administrator? + + assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => 0 } + Person.reset_column_information + assert !Person.new.administrator? + end + + def test_add_table + assert !Reminder.table_exists? + + WeNeedReminders.up + + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + + WeNeedReminders.down + assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + end + + def test_migrator + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/') + + assert_equal 3, ActiveRecord::Migrator.current_version + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/') + + assert_equal 0, ActiveRecord::Migrator.current_version + Person.reset_column_information + assert !Person.column_methods_hash.include?(:last_name) + assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + end + + def test_migrator_one_up + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 2) + + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + end + + def test_migrator_one_down + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/') + + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + end + + def test_migrator_one_up_one_down + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) + + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + end + + def test_migrator_verbosity + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + assert PeopleHaveLastNames.message_count > 0 + PeopleHaveLastNames.message_count = 0 + + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) + assert PeopleHaveLastNames.message_count > 0 + PeopleHaveLastNames.message_count = 0 + end + + def test_migrator_verbosity_off + PeopleHaveLastNames.verbose = false + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + assert PeopleHaveLastNames.message_count.zero? + ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0) + assert PeopleHaveLastNames.message_count.zero? + end + + def test_migrator_going_down_due_to_version_target + ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1) + ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0) + + assert !Person.column_methods_hash.include?(:last_name) + assert !Reminder.table_exists? + + ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/') + + Person.reset_column_information + assert Person.column_methods_hash.include?(:last_name) + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + end + + def test_schema_info_table_name + ActiveRecord::Base.table_name_prefix = "prefix_" + ActiveRecord::Base.table_name_suffix = "_suffix" + Reminder.reset_table_name + assert_equal "prefix_schema_info_suffix", ActiveRecord::Migrator.schema_info_table_name + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + Reminder.reset_table_name + assert_equal "schema_info", ActiveRecord::Migrator.schema_info_table_name + ensure + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + end + + def test_proper_table_name + assert_equal "table", ActiveRecord::Migrator.proper_table_name('table') + assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table) + assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder) + Reminder.reset_table_name + assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder) + + # Use the model's own prefix/suffix if a model is given + ActiveRecord::Base.table_name_prefix = "ARprefix_" + ActiveRecord::Base.table_name_suffix = "_ARsuffix" + Reminder.table_name_prefix = 'prefix_' + Reminder.table_name_suffix = '_suffix' + Reminder.reset_table_name + assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder) + Reminder.table_name_prefix = '' + Reminder.table_name_suffix = '' + Reminder.reset_table_name + + # Use AR::Base's prefix/suffix if string or symbol is given + ActiveRecord::Base.table_name_prefix = "prefix_" + ActiveRecord::Base.table_name_suffix = "_suffix" + Reminder.reset_table_name + assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table') + assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table) + ActiveRecord::Base.table_name_prefix = "" + ActiveRecord::Base.table_name_suffix = "" + Reminder.reset_table_name + end + + def test_add_drop_table_with_prefix_and_suffix + assert !Reminder.table_exists? + ActiveRecord::Base.table_name_prefix = 'prefix_' + ActiveRecord::Base.table_name_suffix = '_suffix' + Reminder.reset_table_name + Reminder.reset_sequence_name + WeNeedReminders.up + assert Reminder.create("content" => "hello world", "remind_at" => Time.now) + assert_equal "hello world", Reminder.find(:first).content + + WeNeedReminders.down + assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) } + ensure + ActiveRecord::Base.table_name_prefix = '' + ActiveRecord::Base.table_name_suffix = '' + Reminder.reset_table_name + Reminder.reset_sequence_name + end + + def test_create_table_with_binary_column + Person.connection.drop_table :binary_testings rescue nil + + assert_nothing_raised { + Person.connection.create_table :binary_testings do |t| + t.column "data", :binary, :default => "", :null => false + end + } + + columns = Person.connection.columns(:binary_testings) + data_column = columns.detect { |c| c.name == "data" } + + if current_adapter?(:OracleAdapter) + assert_equal "empty_blob()", data_column.default + else + assert_equal "", data_column.default + end + + Person.connection.drop_table :binary_testings rescue nil + end + + def test_migrator_with_duplicates + assert_raises(ActiveRecord::DuplicateMigrationVersionError) do + ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil) + end + end + end +end +require 'abstract_unit' +require 'active_record/acts/nested_set' +require 'fixtures/mixin' +require 'pp' + +class MixinNestedSetTest < Test::Unit::TestCase + fixtures :mixins + + def test_mixing_in_methods + ns = NestedSet.new + assert( ns.respond_to?( :all_children ) ) + assert_equal( ns.scope_condition, "root_id IS NULL" ) + + check_method_mixins ns + end + + def test_string_scope + ns = NestedSetWithStringScope.new + + ns.root_id = 1 + assert_equal( ns.scope_condition, "root_id = 1" ) + ns.root_id = 42 + assert_equal( ns.scope_condition, "root_id = 42" ) + check_method_mixins ns + end + + def test_symbol_scope + ns = NestedSetWithSymbolScope.new + ns.root_id = 1 + assert_equal( ns.scope_condition, "root_id = 1" ) + ns.root_id = 42 + assert_equal( ns.scope_condition, "root_id = 42" ) + check_method_mixins ns + end + + def check_method_mixins( obj ) + [:scope_condition, :left_col_name, :right_col_name, :parent_column, :root?, :add_child, + :children_count, :full_set, :all_children, :direct_children].each { |symbol| assert( obj.respond_to?(symbol)) } + end + + def set( id ) + NestedSet.find( 3000 + id ) + end + + def test_adding_children + assert( set(1).unknown? ) + assert( set(2).unknown? ) + set(1).add_child set(2) + + # Did we maintain adding the parent_ids? + assert( set(1).root? ) + assert( set(2).child? ) + assert( set(2).parent_id == set(1).id ) + + # Check boundies + assert_equal( set(1).lft, 1 ) + assert_equal( set(2).lft, 2 ) + assert_equal( set(2).rgt, 3 ) + assert_equal( set(1).rgt, 4 ) + + # Check children cound + assert_equal( set(1).children_count, 1 ) + + set(1).add_child set(3) + + #check boundries + assert_equal( set(1).lft, 1 ) + assert_equal( set(2).lft, 2 ) + assert_equal( set(2).rgt, 3 ) + assert_equal( set(3).lft, 4 ) + assert_equal( set(3).rgt, 5 ) + assert_equal( set(1).rgt, 6 ) + + # How is the count looking? + assert_equal( set(1).children_count, 2 ) + + set(2).add_child set(4) + + # boundries + assert_equal( set(1).lft, 1 ) + assert_equal( set(2).lft, 2 ) + assert_equal( set(4).lft, 3 ) + assert_equal( set(4).rgt, 4 ) + assert_equal( set(2).rgt, 5 ) + assert_equal( set(3).lft, 6 ) + assert_equal( set(3).rgt, 7 ) + assert_equal( set(1).rgt, 8 ) + + # Children count + assert_equal( set(1).children_count, 3 ) + assert_equal( set(2).children_count, 1 ) + assert_equal( set(3).children_count, 0 ) + assert_equal( set(4).children_count, 0 ) + + set(2).add_child set(5) + set(4).add_child set(6) + + assert_equal( set(2).children_count, 3 ) + + + # Children accessors + assert_equal( set(1).full_set.length, 6 ) + assert_equal( set(2).full_set.length, 4 ) + assert_equal( set(4).full_set.length, 2 ) + + assert_equal( set(1).all_children.length, 5 ) + assert_equal( set(6).all_children.length, 0 ) + + assert_equal( set(1).direct_children.length, 2 ) + + end + + def test_snipping_tree + big_tree = NestedSetWithStringScope.find( 4001 ) + + # Make sure we have the right one + assert_equal( 3, big_tree.direct_children.length ) + assert_equal( 10, big_tree.full_set.length ) + + NestedSetWithStringScope.find( 4005 ).destroy + + big_tree = NestedSetWithStringScope.find( 4001 ) + + assert_equal( 7, big_tree.full_set.length ) + assert_equal( 2, big_tree.direct_children.length ) + + assert_equal( 1, NestedSetWithStringScope.find(4001).lft ) + assert_equal( 2, NestedSetWithStringScope.find(4002).lft ) + assert_equal( 3, NestedSetWithStringScope.find(4003).lft ) + assert_equal( 4, NestedSetWithStringScope.find(4003).rgt ) + assert_equal( 5, NestedSetWithStringScope.find(4004).lft ) + assert_equal( 6, NestedSetWithStringScope.find(4004).rgt ) + assert_equal( 7, NestedSetWithStringScope.find(4002).rgt ) + assert_equal( 8, NestedSetWithStringScope.find(4008).lft ) + assert_equal( 9, NestedSetWithStringScope.find(4009).lft ) + assert_equal(10, NestedSetWithStringScope.find(4009).rgt ) + assert_equal(11, NestedSetWithStringScope.find(4010).lft ) + assert_equal(12, NestedSetWithStringScope.find(4010).rgt ) + assert_equal(13, NestedSetWithStringScope.find(4008).rgt ) + assert_equal(14, NestedSetWithStringScope.find(4001).rgt ) + end + + def test_deleting_root + NestedSetWithStringScope.find(4001).destroy + + assert( NestedSetWithStringScope.count == 0 ) + end + + def test_common_usage + mixins(:set_1).add_child( mixins(:set_2) ) + assert_equal( 1, mixins(:set_1).direct_children.length ) + + mixins(:set_2).add_child( mixins(:set_3) ) + assert_equal( 1, mixins(:set_1).direct_children.length ) + + # Local cache is now out of date! + # Problem: the update_alls update all objects up the tree + mixins(:set_1).reload + assert_equal( 2, mixins(:set_1).all_children.length ) + + assert_equal( 1, mixins(:set_1).lft ) + assert_equal( 2, mixins(:set_2).lft ) + assert_equal( 3, mixins(:set_3).lft ) + assert_equal( 4, mixins(:set_3).rgt ) + assert_equal( 5, mixins(:set_2).rgt ) + assert_equal( 6, mixins(:set_1).rgt ) + + assert( mixins(:set_1).root? ) + + begin + mixins(:set_4).add_child( mixins(:set_1) ) + fail + rescue + end + + assert_equal( 2, mixins(:set_1).all_children.length ) + + mixins(:set_1).add_child mixins(:set_4) + + assert_equal( 3, mixins(:set_1).all_children.length ) + + + end +end +require 'abstract_unit' +require 'active_record/acts/tree' +require 'active_record/acts/list' +require 'active_record/acts/nested_set' +require 'fixtures/mixin' + +class ListTest < Test::Unit::TestCase + fixtures :mixins + + def test_reordering + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_2).move_lower + + assert_equal [mixins(:list_1), + mixins(:list_3), + mixins(:list_2), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_2).move_higher + + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_1).move_to_bottom + + assert_equal [mixins(:list_2), + mixins(:list_3), + mixins(:list_4), + mixins(:list_1)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_1).move_to_top + + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + + mixins(:list_2).move_to_bottom + + assert_equal [mixins(:list_1), + mixins(:list_3), + mixins(:list_4), + mixins(:list_2)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_4).move_to_top + + assert_equal [mixins(:list_4), + mixins(:list_1), + mixins(:list_3), + mixins(:list_2)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + end + + def test_move_to_bottom_with_next_to_last_item + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_3).move_to_bottom + + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_4), + mixins(:list_3)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + end + + def test_next_prev + assert_equal mixins(:list_2), mixins(:list_1).lower_item + assert_nil mixins(:list_1).higher_item + assert_equal mixins(:list_3), mixins(:list_4).higher_item + assert_nil mixins(:list_4).lower_item + end + + + def test_injection + item = ListMixin.new("parent_id"=>1) + assert_equal "parent_id = 1", item.scope_condition + assert_equal "pos", item.position_column + end + + def test_insert + new = ListMixin.create("parent_id"=>20) + assert_equal 1, new.pos + assert new.first? + assert new.last? + + new = ListMixin.create("parent_id"=>20) + assert_equal 2, new.pos + assert !new.first? + assert new.last? + + new = ListMixin.create("parent_id"=>20) + assert_equal 3, new.pos + assert !new.first? + assert new.last? + + new = ListMixin.create("parent_id"=>0) + assert_equal 1, new.pos + assert new.first? + assert new.last? + end + + def test_insert_at + new = ListMixin.create("parent_id" => 20) + assert_equal 1, new.pos + + new = ListMixin.create("parent_id" => 20) + assert_equal 2, new.pos + + new = ListMixin.create("parent_id" => 20) + assert_equal 3, new.pos + + new4 = ListMixin.create("parent_id" => 20) + assert_equal 4, new4.pos + + new4.insert_at(3) + assert_equal 3, new4.pos + + new.reload + assert_equal 4, new.pos + + new.insert_at(2) + assert_equal 2, new.pos + + new4.reload + assert_equal 4, new4.pos + + new5 = ListMixin.create("parent_id" => 20) + assert_equal 5, new5.pos + + new5.insert_at(1) + assert_equal 1, new5.pos + + new4.reload + assert_equal 5, new4.pos + end + + def test_delete_middle + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_2).destroy + + assert_equal [mixins(:list_1, :reload), + mixins(:list_3, :reload), + mixins(:list_4, :reload)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + assert_equal 1, mixins(:list_1).pos + assert_equal 2, mixins(:list_3).pos + assert_equal 3, mixins(:list_4).pos + + mixins(:list_1).destroy + + assert_equal [mixins(:list_3, :reload), + mixins(:list_4, :reload)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + assert_equal 1, mixins(:list_3).pos + assert_equal 2, mixins(:list_4).pos + + end + + def test_with_string_based_scope + new = ListWithStringScopeMixin.create("parent_id"=>500) + assert_equal 1, new.pos + assert new.first? + assert new.last? + end + + def test_nil_scope + new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create + new2.move_higher + assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos') + end + +end + +class TreeTest < Test::Unit::TestCase + fixtures :mixins + + def test_has_child + assert_equal true, mixins(:tree_1).has_children? + assert_equal true, mixins(:tree_2).has_children? + assert_equal false, mixins(:tree_3).has_children? + assert_equal false, mixins(:tree_4).has_children? + end + + def test_children + assert_equal mixins(:tree_1).children, [mixins(:tree_2), mixins(:tree_4)] + assert_equal mixins(:tree_2).children, [mixins(:tree_3)] + assert_equal mixins(:tree_3).children, [] + assert_equal mixins(:tree_4).children, [] + end + + def test_has_parent + assert_equal false, mixins(:tree_1).has_parent? + assert_equal true, mixins(:tree_2).has_parent? + assert_equal true, mixins(:tree_3).has_parent? + assert_equal true, mixins(:tree_4).has_parent? + end + + def test_parent + assert_equal mixins(:tree_2).parent, mixins(:tree_1) + assert_equal mixins(:tree_2).parent, mixins(:tree_4).parent + assert_nil mixins(:tree_1).parent + end + + def test_delete + assert_equal 6, TreeMixin.count + mixins(:tree_1).destroy + assert_equal 2, TreeMixin.count + mixins(:tree2_1).destroy + mixins(:tree3_1).destroy + assert_equal 0, TreeMixin.count + end + + def test_insert + @extra = mixins(:tree_1).children.create + + assert @extra + + assert_equal @extra.parent, mixins(:tree_1) + + assert_equal 3, mixins(:tree_1).children.size + assert mixins(:tree_1).children.include?(@extra) + assert mixins(:tree_1).children.include?(mixins(:tree_2)) + assert mixins(:tree_1).children.include?(mixins(:tree_4)) + end + + def test_ancestors + assert_equal [], mixins(:tree_1).ancestors + assert_equal [mixins(:tree_1)], mixins(:tree_2).ancestors + assert_equal [mixins(:tree_2), mixins(:tree_1)], mixins(:tree_3).ancestors + assert_equal [mixins(:tree_1)], mixins(:tree_4).ancestors + assert_equal [], mixins(:tree2_1).ancestors + assert_equal [], mixins(:tree3_1).ancestors + end + + def test_root + assert_equal mixins(:tree_1), TreeMixin.root + assert_equal mixins(:tree_1), mixins(:tree_1).root + assert_equal mixins(:tree_1), mixins(:tree_2).root + assert_equal mixins(:tree_1), mixins(:tree_3).root + assert_equal mixins(:tree_1), mixins(:tree_4).root + assert_equal mixins(:tree2_1), mixins(:tree2_1).root + assert_equal mixins(:tree3_1), mixins(:tree3_1).root + end + + def test_roots + assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], TreeMixin.roots + end + + def test_siblings + assert_equal [mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).siblings + assert_equal [mixins(:tree_4)], mixins(:tree_2).siblings + assert_equal [], mixins(:tree_3).siblings + assert_equal [mixins(:tree_2)], mixins(:tree_4).siblings + assert_equal [mixins(:tree_1), mixins(:tree3_1)], mixins(:tree2_1).siblings + assert_equal [mixins(:tree_1), mixins(:tree2_1)], mixins(:tree3_1).siblings + end + + def test_self_and_siblings + assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).self_and_siblings + assert_equal [mixins(:tree_2), mixins(:tree_4)], mixins(:tree_2).self_and_siblings + assert_equal [mixins(:tree_3)], mixins(:tree_3).self_and_siblings + assert_equal [mixins(:tree_2), mixins(:tree_4)], mixins(:tree_4).self_and_siblings + assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree2_1).self_and_siblings + assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree3_1).self_and_siblings + end +end + +class TreeTestWithoutOrder < Test::Unit::TestCase + fixtures :mixins + + def test_root + assert [mixins(:tree_without_order_1), mixins(:tree_without_order_2)].include?(TreeMixinWithoutOrder.root) + end + + def test_roots + assert_equal [], [mixins(:tree_without_order_1), mixins(:tree_without_order_2)] - TreeMixinWithoutOrder.roots + end +end + +class TouchTest < Test::Unit::TestCase + fixtures :mixins + + def test_update + stamped = Mixin.new + + assert_nil stamped.updated_at + assert_nil stamped.created_at + stamped.save + assert_not_nil stamped.updated_at + assert_not_nil stamped.created_at + end + + def test_create + @obj = Mixin.create + assert_not_nil @obj.updated_at + assert_not_nil @obj.created_at + end + + def test_many_updates + stamped = Mixin.new + + assert_nil stamped.updated_at + assert_nil stamped.created_at + stamped.save + assert_not_nil stamped.created_at + assert_not_nil stamped.updated_at + + old_updated_at = stamped.updated_at + + sleep 1 + stamped.save + assert_not_equal stamped.created_at, stamped.updated_at + assert_not_equal old_updated_at, stamped.updated_at + + end + + def test_create_turned_off + Mixin.record_timestamps = false + + assert_nil mixins(:tree_1).updated_at + mixins(:tree_1).save + assert_nil mixins(:tree_1).updated_at + + Mixin.record_timestamps = true + end + +end + + +class ListSubTest < Test::Unit::TestCase + fixtures :mixins + + def test_reordering + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_2), + mixins(:list_sub_3), + mixins(:list_sub_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_2).move_lower + + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_3), + mixins(:list_sub_2), + mixins(:list_sub_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_2).move_higher + + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_2), + mixins(:list_sub_3), + mixins(:list_sub_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_1).move_to_bottom + + assert_equal [mixins(:list_sub_2), + mixins(:list_sub_3), + mixins(:list_sub_4), + mixins(:list_sub_1)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_1).move_to_top + + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_2), + mixins(:list_sub_3), + mixins(:list_sub_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + + mixins(:list_sub_2).move_to_bottom + + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_3), + mixins(:list_sub_4), + mixins(:list_sub_2)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_4).move_to_top + + assert_equal [mixins(:list_sub_4), + mixins(:list_sub_1), + mixins(:list_sub_3), + mixins(:list_sub_2)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + end + + def test_move_to_bottom_with_next_to_last_item + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_2), + mixins(:list_sub_3), + mixins(:list_sub_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_3).move_to_bottom + + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_2), + mixins(:list_sub_4), + mixins(:list_sub_3)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + end + + def test_next_prev + assert_equal mixins(:list_sub_2), mixins(:list_sub_1).lower_item + assert_nil mixins(:list_sub_1).higher_item + assert_equal mixins(:list_sub_3), mixins(:list_sub_4).higher_item + assert_nil mixins(:list_sub_4).lower_item + end + + + def test_injection + item = ListMixin.new("parent_id"=>1) + assert_equal "parent_id = 1", item.scope_condition + assert_equal "pos", item.position_column + end + + + def test_insert_at + new = ListMixin.create("parent_id" => 20) + assert_equal 1, new.pos + + new = ListMixinSub1.create("parent_id" => 20) + assert_equal 2, new.pos + + new = ListMixinSub2.create("parent_id" => 20) + assert_equal 3, new.pos + + new4 = ListMixin.create("parent_id" => 20) + assert_equal 4, new4.pos + + new4.insert_at(3) + assert_equal 3, new4.pos + + new.reload + assert_equal 4, new.pos + + new.insert_at(2) + assert_equal 2, new.pos + + new4.reload + assert_equal 4, new4.pos + + new5 = ListMixinSub1.create("parent_id" => 20) + assert_equal 5, new5.pos + + new5.insert_at(1) + assert_equal 1, new5.pos + + new4.reload + assert_equal 5, new4.pos + end + + def test_delete_middle + assert_equal [mixins(:list_sub_1), + mixins(:list_sub_2), + mixins(:list_sub_3), + mixins(:list_sub_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + mixins(:list_sub_2).destroy + + assert_equal [mixins(:list_sub_1, :reload), + mixins(:list_sub_3, :reload), + mixins(:list_sub_4, :reload)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + assert_equal 1, mixins(:list_sub_1).pos + assert_equal 2, mixins(:list_sub_3).pos + assert_equal 3, mixins(:list_sub_4).pos + + mixins(:list_sub_1).destroy + + assert_equal [mixins(:list_sub_3, :reload), + mixins(:list_sub_4, :reload)], + ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos') + + assert_equal 1, mixins(:list_sub_3).pos + assert_equal 2, mixins(:list_sub_4).pos + + end + +end + +require 'abstract_unit' +require 'fixtures/company_in_module' + +class ModulesTest < Test::Unit::TestCase + fixtures :accounts, :companies, :projects, :developers + + def test_module_spanning_associations + assert MyApplication::Business::Firm.find(:first).has_clients?, "Firm should have clients" + firm = MyApplication::Business::Firm.find(:first) + assert_nil firm.class.table_name.match('::'), "Firm shouldn't have the module appear in its table name" + assert_equal 2, firm.clients_count, "Firm should have two clients" + end + + def test_module_spanning_has_and_belongs_to_many_associations + project = MyApplication::Business::Project.find(:first) + project.developers << MyApplication::Business::Developer.create("name" => "John") + assert "John", project.developers.last.name + end + + def test_associations_spanning_cross_modules + account = MyApplication::Billing::Account.find(:first, :order => 'id') + assert_kind_of MyApplication::Business::Firm, account.firm + assert_kind_of MyApplication::Billing::Firm, account.qualified_billing_firm + assert_kind_of MyApplication::Billing::Firm, account.unqualified_billing_firm + assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_qualified_billing_firm + assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_unqualified_billing_firm + end +end +require 'abstract_unit' +require 'fixtures/entrant' + +# So we can test whether Course.connection survives a reload. +require_dependency 'fixtures/course' + +class MultipleDbTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + def setup + @courses = create_fixtures("courses") { Course.retrieve_connection } + @entrants = create_fixtures("entrants") + end + + def test_connected + assert_not_nil Entrant.connection + assert_not_nil Course.connection + end + + def test_proper_connection + assert_not_equal(Entrant.connection, Course.connection) + assert_equal(Entrant.connection, Entrant.retrieve_connection) + assert_equal(Course.connection, Course.retrieve_connection) + assert_equal(ActiveRecord::Base.connection, Entrant.connection) + end + + def test_find + c1 = Course.find(1) + assert_equal "Ruby Development", c1.name + c2 = Course.find(2) + assert_equal "Java Development", c2.name + e1 = Entrant.find(1) + assert_equal "Ruby Developer", e1.name + e2 = Entrant.find(2) + assert_equal "Ruby Guru", e2.name + e3 = Entrant.find(3) + assert_equal "Java Lover", e3.name + end + + def test_associations + c1 = Course.find(1) + assert_equal 2, c1.entrants_count + e1 = Entrant.find(1) + assert_equal e1.course.id, c1.id + c2 = Course.find(2) + assert_equal 1, c2.entrants_count + e3 = Entrant.find(3) + assert_equal e3.course.id, c2.id + end + + def test_course_connection_should_survive_dependency_reload + assert Course.connection + + Dependencies.clear + Object.send(:remove_const, :Course) + require_dependency 'fixtures/course' + + assert Course.connection + end +end +require "#{File.dirname(__FILE__)}/abstract_unit" +require 'fixtures/topic' +require 'fixtures/subscriber' +require 'fixtures/movie' +require 'fixtures/keyboard' + +class PrimaryKeysTest < Test::Unit::TestCase + fixtures :topics, :subscribers, :movies + + def test_integer_key + topic = Topic.find(1) + assert_equal(topics(:first).author_name, topic.author_name) + topic = Topic.find(2) + assert_equal(topics(:second).author_name, topic.author_name) + + topic = Topic.new + topic.title = "New Topic" + assert_equal(nil, topic.id) + assert_nothing_raised { topic.save! } + id = topic.id + + topicReloaded = Topic.find(id) + assert_equal("New Topic", topicReloaded.title) + end + + def test_customized_primary_key_auto_assigns_on_save + Keyboard.delete_all + keyboard = Keyboard.new(:name => 'HHKB') + assert_nothing_raised { keyboard.save! } + assert_equal keyboard.id, Keyboard.find_by_name('HHKB').id + end + + def test_customized_primary_key_can_be_get_before_saving + keyboard = Keyboard.new + assert_nil keyboard.id + assert_nothing_raised { assert_nil keyboard.key_number } + end + + def test_customized_string_primary_key_settable_before_save + subscriber = Subscriber.new + assert_nothing_raised { subscriber.id = 'webster123' } + assert_equal 'webster123', subscriber.id + assert_equal 'webster123', subscriber.nick + end + + def test_string_key + subscriber = Subscriber.find(subscribers(:first).nick) + assert_equal(subscribers(:first).name, subscriber.name) + subscriber = Subscriber.find(subscribers(:second).nick) + assert_equal(subscribers(:second).name, subscriber.name) + + subscriber = Subscriber.new + subscriber.id = "jdoe" + assert_equal("jdoe", subscriber.id) + subscriber.name = "John Doe" + assert_nothing_raised { subscriber.save! } + assert_equal("jdoe", subscriber.id) + + subscriberReloaded = Subscriber.find("jdoe") + assert_equal("John Doe", subscriberReloaded.name) + end + + def test_find_with_more_than_one_string_key + assert_equal 2, Subscriber.find(subscribers(:first).nick, subscribers(:second).nick).length + end + + def test_primary_key_prefix + ActiveRecord::Base.primary_key_prefix_type = :table_name + Topic.reset_primary_key + assert_equal "topicid", Topic.primary_key + + ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore + Topic.reset_primary_key + assert_equal "topic_id", Topic.primary_key + + ActiveRecord::Base.primary_key_prefix_type = nil + Topic.reset_primary_key + assert_equal "id", Topic.primary_key + end +end +require 'abstract_unit' +require 'fixtures/post' +require 'fixtures/comment' +require 'fixtures/developer' +require 'fixtures/project' +require 'fixtures/reader' +require 'fixtures/person' + +# Dummy class methods to test implicit association scoping. +def Comment.foo() find :first end +def Project.foo() find :first end + + +class ReadOnlyTest < Test::Unit::TestCase + fixtures :posts, :comments, :developers, :projects, :developers_projects + + def test_cant_save_readonly_record + dev = Developer.find(1) + assert !dev.readonly? + + dev.readonly! + assert dev.readonly? + + assert_nothing_raised do + dev.name = 'Luscious forbidden fruit.' + assert !dev.save + dev.name = 'Forbidden.' + end + assert_raise(ActiveRecord::ReadOnlyRecord) { dev.save } + assert_raise(ActiveRecord::ReadOnlyRecord) { dev.save! } + end + + + def test_find_with_readonly_option + Developer.find(:all).each { |d| assert !d.readonly? } + Developer.find(:all, :readonly => false).each { |d| assert !d.readonly? } + Developer.find(:all, :readonly => true).each { |d| assert d.readonly? } + end + + + def test_find_with_joins_option_implies_readonly + # Blank joins don't count. + Developer.find(:all, :joins => ' ').each { |d| assert !d.readonly? } + Developer.find(:all, :joins => ' ', :readonly => false).each { |d| assert !d.readonly? } + + # Others do. + Developer.find(:all, :joins => ', projects').each { |d| assert d.readonly? } + Developer.find(:all, :joins => ', projects', :readonly => false).each { |d| assert !d.readonly? } + end + + + def test_habtm_find_readonly + dev = Developer.find(1) + assert !dev.projects.empty? + assert dev.projects.all?(&:readonly?) + assert dev.projects.find(:all).all?(&:readonly?) + assert dev.projects.find(:all, :readonly => true).all?(&:readonly?) + end + + def test_has_many_find_readonly + post = Post.find(1) + assert !post.comments.empty? + assert !post.comments.any?(&:readonly?) + assert !post.comments.find(:all).any?(&:readonly?) + assert post.comments.find(:all, :readonly => true).all?(&:readonly?) + end + + def test_has_many_with_through_is_not_implicitly_marked_readonly + assert people = Post.find(1).people + assert !people.any?(&:readonly?) + end + + def test_readonly_scoping + Post.with_scope(:find => { :conditions => '1=1' }) do + assert !Post.find(1).readonly? + assert Post.find(1, :readonly => true).readonly? + assert !Post.find(1, :readonly => false).readonly? + end + + Post.with_scope(:find => { :joins => ' ' }) do + assert !Post.find(1).readonly? + assert Post.find(1, :readonly => true).readonly? + assert !Post.find(1, :readonly => false).readonly? + end + + # Oracle barfs on this because the join includes unqualified and + # conflicting column names + unless current_adapter?(:OracleAdapter) + Post.with_scope(:find => { :joins => ', developers' }) do + assert Post.find(1).readonly? + assert Post.find(1, :readonly => true).readonly? + assert !Post.find(1, :readonly => false).readonly? + end + end + + Post.with_scope(:find => { :readonly => true }) do + assert Post.find(1).readonly? + assert Post.find(1, :readonly => true).readonly? + assert !Post.find(1, :readonly => false).readonly? + end + end + + def test_association_collection_method_missing_scoping_not_readonly + assert !Developer.find(1).projects.foo.readonly? + assert !Post.find(1).comments.foo.readonly? + end +end +require 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/customer' +require 'fixtures/company' +require 'fixtures/company_in_module' +require 'fixtures/subscriber' + +class ReflectionTest < Test::Unit::TestCase + fixtures :topics, :customers, :companies, :subscribers + + def setup + @first = Topic.find(1) + end + + def test_column_null_not_null + subscriber = Subscriber.find(:first) + assert subscriber.column_for_attribute("name").null + assert !subscriber.column_for_attribute("nick").null + end + + def test_read_attribute_names + assert_equal( + %w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id type ).sort, + @first.attribute_names + ) + end + + def test_columns + assert_equal 12, Topic.columns.length + end + + def test_columns_are_returned_in_the_order_they_were_declared + column_names = Topic.columns.map { |column| column.name } + assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id type), column_names + end + + def test_content_columns + content_columns = Topic.content_columns + content_column_names = content_columns.map {|column| column.name} + assert_equal 8, content_columns.length + assert_equal %w(title author_name author_email_address written_on bonus_time last_read content approved).sort, content_column_names.sort + end + + def test_column_string_type_and_limit + assert_equal :string, @first.column_for_attribute("title").type + assert_equal 255, @first.column_for_attribute("title").limit + end + + def test_human_name_for_column + assert_equal "Author name", @first.column_for_attribute("author_name").human_name + end + + def test_integer_columns + assert_equal :integer, @first.column_for_attribute("id").type + end + + def test_aggregation_reflection + reflection_for_address = ActiveRecord::Reflection::AggregateReflection.new( + :composed_of, :address, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer + ) + + reflection_for_balance = ActiveRecord::Reflection::AggregateReflection.new( + :composed_of, :balance, { :class_name => "Money", :mapping => %w(balance amount) }, Customer + ) + + reflection_for_gps_location = ActiveRecord::Reflection::AggregateReflection.new( + :composed_of, :gps_location, { }, Customer + ) + + assert Customer.reflect_on_all_aggregations.include?(reflection_for_gps_location) + assert Customer.reflect_on_all_aggregations.include?(reflection_for_balance) + assert Customer.reflect_on_all_aggregations.include?(reflection_for_address) + + assert_equal reflection_for_address, Customer.reflect_on_aggregation(:address) + + assert_equal Address, Customer.reflect_on_aggregation(:address).klass + + assert_equal Money, Customer.reflect_on_aggregation(:balance).klass + end + + def test_has_many_reflection + reflection_for_clients = ActiveRecord::Reflection::AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm) + + assert_equal reflection_for_clients, Firm.reflect_on_association(:clients) + + assert_equal Client, Firm.reflect_on_association(:clients).klass + assert_equal 'companies', Firm.reflect_on_association(:clients).table_name + + assert_equal Client, Firm.reflect_on_association(:clients_of_firm).klass + assert_equal 'companies', Firm.reflect_on_association(:clients_of_firm).table_name + end + + def test_has_one_reflection + reflection_for_account = ActiveRecord::Reflection::AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm) + assert_equal reflection_for_account, Firm.reflect_on_association(:account) + + assert_equal Account, Firm.reflect_on_association(:account).klass + assert_equal 'accounts', Firm.reflect_on_association(:account).table_name + end + + def test_association_reflection_in_modules + assert_reflection MyApplication::Business::Firm, + :clients_of_firm, + :klass => MyApplication::Business::Client, + :class_name => 'Client', + :table_name => 'companies' + + assert_reflection MyApplication::Billing::Account, + :firm, + :klass => MyApplication::Business::Firm, + :class_name => 'MyApplication::Business::Firm', + :table_name => 'companies' + + assert_reflection MyApplication::Billing::Account, + :qualified_billing_firm, + :klass => MyApplication::Billing::Firm, + :class_name => 'MyApplication::Billing::Firm', + :table_name => 'companies' + + assert_reflection MyApplication::Billing::Account, + :unqualified_billing_firm, + :klass => MyApplication::Billing::Firm, + :class_name => 'Firm', + :table_name => 'companies' + + assert_reflection MyApplication::Billing::Account, + :nested_qualified_billing_firm, + :klass => MyApplication::Billing::Nested::Firm, + :class_name => 'MyApplication::Billing::Nested::Firm', + :table_name => 'companies' + + assert_reflection MyApplication::Billing::Account, + :nested_unqualified_billing_firm, + :klass => MyApplication::Billing::Nested::Firm, + :class_name => 'Nested::Firm', + :table_name => 'companies' + end + + def test_reflection_of_all_associations + assert_equal 13, Firm.reflect_on_all_associations.size + assert_equal 11, Firm.reflect_on_all_associations(:has_many).size + assert_equal 2, Firm.reflect_on_all_associations(:has_one).size + assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size + end + + private + def assert_reflection(klass, association, options) + assert reflection = klass.reflect_on_association(association) + options.each do |method, value| + assert_equal(value, reflection.send(method)) + end + end +end +require 'abstract_unit' +require "#{File.dirname(__FILE__)}/../lib/active_record/schema_dumper" +require 'stringio' + +if ActiveRecord::Base.connection.respond_to?(:tables) + + class SchemaDumperTest < Test::Unit::TestCase + def test_schema_dump + stream = StringIO.new + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) + output = stream.string + + assert_match %r{create_table "accounts"}, output + assert_match %r{create_table "authors"}, output + assert_no_match %r{create_table "schema_info"}, output + end + + def test_schema_dump_includes_not_null_columns + stream = StringIO.new + + ActiveRecord::SchemaDumper.ignore_tables = [/^[^s]/] + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) + output = stream.string + assert_match %r{:null => false}, output + end + + def test_schema_dump_with_string_ignored_table + stream = StringIO.new + + ActiveRecord::SchemaDumper.ignore_tables = ['accounts'] + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) + output = stream.string + assert_no_match %r{create_table "accounts"}, output + assert_match %r{create_table "authors"}, output + assert_no_match %r{create_table "schema_info"}, output + end + + + def test_schema_dump_with_regexp_ignored_table + stream = StringIO.new + + ActiveRecord::SchemaDumper.ignore_tables = [/^account/] + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) + output = stream.string + assert_no_match %r{create_table "accounts"}, output + assert_match %r{create_table "authors"}, output + assert_no_match %r{create_table "schema_info"}, output + end + + + def test_schema_dump_illegal_ignored_table_value + stream = StringIO.new + ActiveRecord::SchemaDumper.ignore_tables = [5] + assert_raise(StandardError) do + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream) + end + end + end + +end +require 'abstract_unit' + +class SchemaTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + SCHEMA_NAME = 'test_schema' + TABLE_NAME = 'things' + COLUMNS = [ + 'id integer', + 'name character varying(50)', + 'moment timestamp without time zone default now()' + ] + + def setup + @connection = ActiveRecord::Base.connection + @connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})" + end + + def teardown + @connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE" + end + + def test_with_schema_prefixed_table_name + assert_nothing_raised do + assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}") + end + end + + def test_with_schema_search_path + assert_nothing_raised do + with_schema_search_path(SCHEMA_NAME) do + assert_equal COLUMNS, columns(TABLE_NAME) + end + end + end + + def test_raise_on_unquoted_schema_name + assert_raise(ActiveRecord::StatementInvalid) do + with_schema_search_path '$user,public' + end + end + + def test_without_schema_search_path + assert_raise(ActiveRecord::StatementInvalid) { columns(TABLE_NAME) } + end + + def test_ignore_nil_schema_search_path + assert_nothing_raised { with_schema_search_path nil } + end + + private + def columns(table_name) + @connection.send(:column_definitions, table_name).map do |name, type, default| + "#{name} #{type}" + (default ? " default #{default}" : '') + end + end + + def with_schema_search_path(schema_search_path) + @connection.schema_search_path = schema_search_path + yield if block_given? + ensure + @connection.schema_search_path = "'$user', public" + end +end +require 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/subject' + +# confirm that synonyms work just like tables; in this case +# the "subjects" table in Oracle (defined in oci.sql) is just +# a synonym to the "topics" table + +class TestOracleSynonym < Test::Unit::TestCase + + def test_oracle_synonym + topic = Topic.new + subject = Subject.new + assert_equal(topic.attributes, subject.attributes) + end + +end +require 'abstract_unit' +require 'fixtures/topic' + +class ThreadedConnectionsTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + fixtures :topics + + def setup + @connection = ActiveRecord::Base.remove_connection + @connections = [] + @allow_concurrency = ActiveRecord::Base.allow_concurrency + end + + def teardown + # clear the connection cache + ActiveRecord::Base.send(:clear_all_cached_connections!) + # set allow_concurrency to saved value + ActiveRecord::Base.allow_concurrency = @allow_concurrency + # reestablish old connection + ActiveRecord::Base.establish_connection(@connection) + end + + def gather_connections(use_threaded_connections) + ActiveRecord::Base.allow_concurrency = use_threaded_connections + ActiveRecord::Base.establish_connection(@connection) + + 5.times do + Thread.new do + Topic.find :first + @connections << ActiveRecord::Base.active_connections.values.first + end.join + end + end + + def test_threaded_connections + gather_connections(true) + assert_equal @connections.uniq.length, 5 + end + + def test_unthreaded_connections + gather_connections(false) + assert_equal @connections.uniq.length, 1 + end +end +require 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/developer' + +class TransactionTest < Test::Unit::TestCase + self.use_transactional_fixtures = false + + fixtures :topics, :developers + + def setup + # sqlite does not seem to return these in the right order, so we sort them + # explicitly for sqlite's sake. sqlite3 does fine. + @first, @second = Topic.find(1, 2).sort_by { |t| t.id } + end + + def test_successful + Topic.transaction do + @first.approved = true + @second.approved = false + @first.save + @second.save + end + + assert Topic.find(1).approved?, "First should have been approved" + assert !Topic.find(2).approved?, "Second should have been unapproved" + end + + def transaction_with_return + Topic.transaction do + @first.approved = true + @second.approved = false + @first.save + @second.save + return + end + end + + def test_successful_with_return + class << Topic.connection + alias :real_commit_db_transaction :commit_db_transaction + def commit_db_transaction + $committed = true + real_commit_db_transaction + end + end + + $committed = false + transaction_with_return + assert $committed + + assert Topic.find(1).approved?, "First should have been approved" + assert !Topic.find(2).approved?, "Second should have been unapproved" + ensure + class << Topic.connection + alias :commit_db_transaction :real_commit_db_transaction rescue nil + end + end + + def test_successful_with_instance_method + @first.transaction do + @first.approved = true + @second.approved = false + @first.save + @second.save + end + + assert Topic.find(1).approved?, "First should have been approved" + assert !Topic.find(2).approved?, "Second should have been unapproved" + end + + def test_failing_on_exception + begin + Topic.transaction do + @first.approved = true + @second.approved = false + @first.save + @second.save + raise "Bad things!" + end + rescue + # caught it + end + + assert @first.approved?, "First should still be changed in the objects" + assert !@second.approved?, "Second should still be changed in the objects" + + assert !Topic.find(1).approved?, "First shouldn't have been approved" + assert Topic.find(2).approved?, "Second should still be approved" + end + + def test_failing_with_object_rollback + assert !@first.approved?, "First should be unapproved initially" + + begin + Topic.transaction(@first, @second) do + @first.approved = true + @second.approved = false + @first.save + @second.save + raise "Bad things!" + end + rescue + # caught it + end + + assert !@first.approved?, "First shouldn't have been approved" + assert @second.approved?, "Second should still be approved" + end + + def test_callback_rollback_in_save + add_exception_raising_after_save_callback_to_topic + + begin + @first.approved = true + @first.save + flunk + rescue => e + assert_equal "Make the transaction rollback", e.message + assert !Topic.find(1).approved? + ensure + remove_exception_raising_after_save_callback_to_topic + end + end + + def test_nested_explicit_transactions + Topic.transaction do + Topic.transaction do + @first.approved = true + @second.approved = false + @first.save + @second.save + end + end + + assert Topic.find(1).approved?, "First should have been approved" + assert !Topic.find(2).approved?, "Second should have been unapproved" + end + + # This will cause transactions to overlap and fail unless they are + # performed on separate database connections. + def test_transaction_per_thread + assert_nothing_raised do + threads = (1..20).map do + Thread.new do + Topic.transaction do + topic = Topic.find(:first) + topic.approved = !topic.approved? + topic.save! + topic.approved = !topic.approved? + topic.save! + end + end + end + + threads.each { |t| t.join } + end + end + + # Test for dirty reads among simultaneous transactions. + def test_transaction_isolation__read_committed + # Should be invariant. + original_salary = Developer.find(1).salary + temporary_salary = 200000 + + assert_nothing_raised do + threads = (1..20).map do + Thread.new do + Developer.transaction do + # Expect original salary. + dev = Developer.find(1) + assert_equal original_salary, dev.salary + + dev.salary = temporary_salary + dev.save! + + # Expect temporary salary. + dev = Developer.find(1) + assert_equal temporary_salary, dev.salary + + dev.salary = original_salary + dev.save! + + # Expect original salary. + dev = Developer.find(1) + assert_equal original_salary, dev.salary + end + end + end + + # Keep our eyes peeled. + threads << Thread.new do + 10.times do + sleep 0.05 + Developer.transaction do + # Always expect original salary. + assert_equal original_salary, Developer.find(1).salary + end + end + end + + threads.each { |t| t.join } + end + + assert_equal original_salary, Developer.find(1).salary + end + + + private + def add_exception_raising_after_save_callback_to_topic + Topic.class_eval { def after_save() raise "Make the transaction rollback" end } + end + + def remove_exception_raising_after_save_callback_to_topic + Topic.class_eval { remove_method :after_save } + end +end +require 'abstract_unit' + +class TestRecord < ActiveRecord::Base +end + +class TestUnconnectedAdaptor < Test::Unit::TestCase + self.use_transactional_fixtures = false + + def setup + @underlying = ActiveRecord::Base.connection + @specification = ActiveRecord::Base.remove_connection + end + + def teardown + @underlying = nil + ActiveRecord::Base.establish_connection(@specification) + end + + def test_connection_no_longer_established + assert_raise(ActiveRecord::ConnectionNotEstablished) do + TestRecord.find(1) + end + + assert_raise(ActiveRecord::ConnectionNotEstablished) do + TestRecord.new.save + end + end + + def test_underlying_adapter_no_longer_active + assert !@underlying.active?, "Removed adapter should no longer be active" + end +end +require 'abstract_unit' +require 'fixtures/topic' +require 'fixtures/reply' +require 'fixtures/developer' + +# The following methods in Topic are used in test_conditional_validation_* +class Topic + def condition_is_true + return true + end + + def condition_is_true_but_its_not + return false + end +end + +class ValidationsTest < Test::Unit::TestCase + fixtures :topics, :developers + + def setup + Topic.write_inheritable_attribute(:validate, nil) + Topic.write_inheritable_attribute(:validate_on_create, nil) + Topic.write_inheritable_attribute(:validate_on_update, nil) + end + + def test_single_field_validation + r = Reply.new + r.title = "There's no content!" + assert !r.save, "A reply without content shouldn't be saveable" + + r.content = "Messa content!" + assert r.save, "A reply with content should be saveable" + end + + def test_single_attr_validation_and_error_msg + r = Reply.new + r.title = "There's no content!" + r.save + assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid" + assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error" + assert_equal 1, r.errors.count + end + + def test_double_attr_validation_and_error_msg + r = Reply.new + assert !r.save + + assert r.errors.invalid?("title"), "A reply without title should mark that attribute as invalid" + assert_equal "Empty", r.errors.on("title"), "A reply without title should contain an error" + + assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid" + assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error" + + assert_equal 2, r.errors.count + end + + def test_error_on_create + r = Reply.new + r.title = "Wrong Create" + assert !r.save + assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid" + assert_equal "is Wrong Create", r.errors.on("title"), "A reply with a bad content should contain an error" + end + + def test_error_on_update + r = Reply.new + r.title = "Bad" + r.content = "Good" + assert r.save, "First save should be successful" + + r.title = "Wrong Update" + assert !r.save, "Second save should fail" + + assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid" + assert_equal "is Wrong Update", r.errors.on("title"), "A reply with a bad content should contain an error" + end + + def test_invalid_record_exception + assert_raises(ActiveRecord::RecordInvalid) { Reply.create! } + assert_raises(ActiveRecord::RecordInvalid) { Reply.new.save! } + + begin + r = Reply.new + r.save! + flunk + rescue ActiveRecord::RecordInvalid => invalid + assert_equal r, invalid.record + end + end + + def test_single_error_per_attr_iteration + r = Reply.new + r.save + + errors = [] + r.errors.each { |attr, msg| errors << [attr, msg] } + + assert errors.include?(["title", "Empty"]) + assert errors.include?(["content", "Empty"]) + end + + def test_multiple_errors_per_attr_iteration_with_full_error_composition + r = Reply.new + r.title = "Wrong Create" + r.content = "Mismatch" + r.save + + errors = [] + r.errors.each_full { |error| errors << error } + + assert_equal "Title is Wrong Create", errors[0] + assert_equal "Title is Content Mismatch", errors[1] + assert_equal 2, r.errors.count + end + + def test_errors_on_base + r = Reply.new + r.content = "Mismatch" + r.save + r.errors.add_to_base "Reply is not dignifying" + + errors = [] + r.errors.each_full { |error| errors << error } + + assert_equal "Reply is not dignifying", r.errors.on_base + + assert errors.include?("Title Empty") + assert errors.include?("Reply is not dignifying") + assert_equal 2, r.errors.count + end + + def test_create_without_validation + reply = Reply.new + assert !reply.save + assert reply.save(false) + end + + def test_validates_each + perform = true + hits = 0 + Topic.validates_each(:title, :content, [:title, :content]) do |record, attr| + if perform + record.errors.add attr, 'gotcha' + hits += 1 + end + end + t = Topic.new("title" => "valid", "content" => "whatever") + assert !t.save + assert_equal 4, hits + assert_equal %w(gotcha gotcha), t.errors.on(:title) + assert_equal %w(gotcha gotcha), t.errors.on(:content) + ensure + perform = false + end + + def test_errors_on_boundary_breaking + developer = Developer.new("name" => "xs") + assert !developer.save + assert_equal "is too short (minimum is 3 characters)", developer.errors.on("name") + + developer.name = "All too very long for this boundary, it really is" + assert !developer.save + assert_equal "is too long (maximum is 20 characters)", developer.errors.on("name") + + developer.name = "Just right" + assert developer.save + end + + def test_title_confirmation_no_confirm + Topic.validates_confirmation_of(:title) + + t = Topic.create("title" => "We should not be confirmed") + assert t.save + end + + def test_title_confirmation + Topic.validates_confirmation_of(:title) + + t = Topic.create("title" => "We should be confirmed","title_confirmation" => "") + assert !t.save + + t.title_confirmation = "We should be confirmed" + assert t.save + end + + def test_terms_of_service_agreement_no_acceptance + Topic.validates_acceptance_of(:terms_of_service, :on => :create) + + t = Topic.create("title" => "We should not be confirmed") + assert t.save + end + + def test_terms_of_service_agreement + Topic.validates_acceptance_of(:terms_of_service, :on => :create) + + t = Topic.create("title" => "We should be confirmed","terms_of_service" => "") + assert !t.save + assert_equal "must be accepted", t.errors.on(:terms_of_service) + + t.terms_of_service = "1" + assert t.save + end + + + def test_eula + Topic.validates_acceptance_of(:eula, :message => "must be abided", :on => :create) + + t = Topic.create("title" => "We should be confirmed","eula" => "") + assert !t.save + assert_equal "must be abided", t.errors.on(:eula) + + t.eula = "1" + assert t.save + end + + def test_terms_of_service_agreement_with_accept_value + Topic.validates_acceptance_of(:terms_of_service, :on => :create, :accept => "I agree.") + + t = Topic.create("title" => "We should be confirmed", "terms_of_service" => "") + assert !t.save + assert_equal "must be accepted", t.errors.on(:terms_of_service) + + t.terms_of_service = "I agree." + assert t.save + end + + def test_validate_presences + Topic.validates_presence_of(:title, :content) + + t = Topic.create + assert !t.save + assert_equal "can't be blank", t.errors.on(:title) + assert_equal "can't be blank", t.errors.on(:content) + + t.title = "something" + t.content = " " + + assert !t.save + assert_equal "can't be blank", t.errors.on(:content) + + t.content = "like stuff" + + assert t.save + end + + def test_validate_uniqueness + Topic.validates_uniqueness_of(:title) + + t = Topic.new("title" => "I'm unique!") + assert t.save, "Should save t as unique" + + t.content = "Remaining unique" + assert t.save, "Should still save t as unique" + + t2 = Topic.new("title" => "I'm unique!") + assert !t2.valid?, "Shouldn't be valid" + assert !t2.save, "Shouldn't save t2 as unique" + assert_equal "has already been taken", t2.errors.on(:title) + + t2.title = "Now Im really also unique" + assert t2.save, "Should now save t2 as unique" + end + + def test_validate_uniqueness_with_scope + Reply.validates_uniqueness_of(:content, :scope => "parent_id") + + t = Topic.create("title" => "I'm unique!") + + r1 = t.replies.create "title" => "r1", "content" => "hello world" + assert r1.valid?, "Saving r1" + + r2 = t.replies.create "title" => "r2", "content" => "hello world" + assert !r2.valid?, "Saving r2 first time" + + r2.content = "something else" + assert r2.save, "Saving r2 second time" + + t2 = Topic.create("title" => "I'm unique too!") + r3 = t2.replies.create "title" => "r3", "content" => "hello world" + assert r3.valid?, "Saving r3" + end + + def test_validate_uniqueness_with_scope_array + Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id]) + + t = Topic.create("title" => "The earth is actually flat!") + + r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply" + assert r1.valid?, "Saving r1" + + r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..." + assert !r2.valid?, "Saving r2. Double reply by same author." + + r2.author_email_address = "jeremy_alt_email@rubyonrails.com" + assert r2.save, "Saving r2 the second time." + + r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic" + assert !r3.valid?, "Saving r3" + + r3.author_name = "jj" + assert r3.save, "Saving r3 the second time." + + r3.author_name = "jeremy" + assert !r3.save, "Saving r3 the third time." + end + + def test_validate_format + Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data") + + t = Topic.create("title" => "i'm incorrect", "content" => "Validation macros rule!") + assert !t.valid?, "Shouldn't be valid" + assert !t.save, "Shouldn't save because it's invalid" + assert_equal "is bad data", t.errors.on(:title) + assert_nil t.errors.on(:content) + + t.title = "Validation macros rule!" + + assert t.save + assert_nil t.errors.on(:title) + + assert_raise(ArgumentError) { Topic.validates_format_of(:title, :content) } + end + + # testing ticket #3142 + def test_validate_format_numeric + Topic.validates_format_of(:title, :content, :with => /^[1-9][0-9]*$/, :message => "is bad data") + + t = Topic.create("title" => "72x", "content" => "6789") + assert !t.valid?, "Shouldn't be valid" + assert !t.save, "Shouldn't save because it's invalid" + assert_equal "is bad data", t.errors.on(:title) + assert_nil t.errors.on(:content) + + t.title = "-11" + assert !t.valid?, "Shouldn't be valid" + + t.title = "03" + assert !t.valid?, "Shouldn't be valid" + + t.title = "z44" + assert !t.valid?, "Shouldn't be valid" + + t.title = "5v7" + assert !t.valid?, "Shouldn't be valid" + + t.title = "1" + + assert t.save + assert_nil t.errors.on(:title) + end + + def test_validates_inclusion_of + Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) ) + + assert !Topic.create("title" => "a!", "content" => "abc").valid? + assert !Topic.create("title" => "a b", "content" => "abc").valid? + assert !Topic.create("title" => nil, "content" => "def").valid? + + t = Topic.create("title" => "a", "content" => "I know you are but what am I?") + assert t.valid? + t.title = "uhoh" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is not included in the list", t.errors["title"] + + assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => nil ) } + assert_raise(ArgumentError) { Topic.validates_inclusion_of( :title, :in => 0) } + + assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => "hi!" ) } + assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => {} ) } + assert_nothing_raised(ArgumentError) { Topic.validates_inclusion_of( :title, :in => [] ) } + end + + def test_validates_inclusion_of_with_allow_nil + Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ), :allow_nil=>true ) + + assert !Topic.create("title" => "a!", "content" => "abc").valid? + assert !Topic.create("title" => "", "content" => "abc").valid? + assert Topic.create("title" => nil, "content" => "abc").valid? + end + + def test_numericality_with_allow_nil_and_getter_method + Developer.validates_numericality_of( :salary, :allow_nil => true) + developer = Developer.new("name" => "michael", "salary" => nil) + developer.instance_eval("def salary; read_attribute('salary') ? read_attribute('salary') : 100000; end") + assert developer.valid? + end + + def test_validates_exclusion_of + Topic.validates_exclusion_of( :title, :in => %w( abe monkey ) ) + + assert Topic.create("title" => "something", "content" => "abc").valid? + assert !Topic.create("title" => "monkey", "content" => "abc").valid? + end + + def test_validates_length_of_using_minimum + Topic.validates_length_of :title, :minimum => 5 + + t = Topic.create("title" => "valid", "content" => "whatever") + assert t.valid? + + t.title = "not" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is too short (minimum is 5 characters)", t.errors["title"] + + t.title = "" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is too short (minimum is 5 characters)", t.errors["title"] + + t.title = nil + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is too short (minimum is 5 characters)", t.errors["title"] + end + + def test_optionally_validates_length_of_using_minimum + Topic.validates_length_of :title, :minimum => 5, :allow_nil => true + + t = Topic.create("title" => "valid", "content" => "whatever") + assert t.valid? + + t.title = nil + assert t.valid? + end + + def test_validates_length_of_using_maximum + Topic.validates_length_of :title, :maximum => 5 + + t = Topic.create("title" => "valid", "content" => "whatever") + assert t.valid? + + t.title = "notvalid" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is too long (maximum is 5 characters)", t.errors["title"] + + t.title = "" + assert t.valid? + + t.title = nil + assert !t.valid? + end + + def test_optionally_validates_length_of_using_maximum + Topic.validates_length_of :title, :maximum => 5, :allow_nil => true + + t = Topic.create("title" => "valid", "content" => "whatever") + assert t.valid? + + t.title = nil + assert t.valid? + end + + def test_validates_length_of_using_within + Topic.validates_length_of(:title, :content, :within => 3..5) + + t = Topic.new("title" => "a!", "content" => "I'm ooooooooh so very long") + assert !t.valid? + assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title) + assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content) + + t.title = nil + t.content = nil + assert !t.valid? + assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title) + assert_equal "is too short (minimum is 3 characters)", t.errors.on(:content) + + t.title = "abe" + t.content = "mad" + assert t.valid? + end + + def test_optionally_validates_length_of_using_within + Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true + + t = Topic.create('title' => 'abc', 'content' => 'abcd') + assert t.valid? + + t.title = nil + assert t.valid? + end + + def test_optionally_validates_length_of_using_within_on_create + Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "my string is too long: %d" + + t = Topic.create("title" => "thisisnotvalid", "content" => "whatever") + assert !t.save + assert t.errors.on(:title) + assert_equal "my string is too long: 10", t.errors[:title] + + t.title = "butthisis" + assert t.save + + t.title = "few" + assert t.save + + t.content = "andthisislong" + assert t.save + + t.content = t.title = "iamfine" + assert t.save + end + + def test_optionally_validates_length_of_using_within_on_update + Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "my string is too short: %d" + + t = Topic.create("title" => "vali", "content" => "whatever") + assert !t.save + assert t.errors.on(:title) + + t.title = "not" + assert !t.save + assert t.errors.on(:title) + assert_equal "my string is too short: 5", t.errors[:title] + + t.title = "valid" + t.content = "andthisistoolong" + assert !t.save + assert t.errors.on(:content) + + t.content = "iamfine" + assert t.save + end + + def test_validates_length_of_using_is + Topic.validates_length_of :title, :is => 5 + + t = Topic.create("title" => "valid", "content" => "whatever") + assert t.valid? + + t.title = "notvalid" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is the wrong length (should be 5 characters)", t.errors["title"] + + t.title = "" + assert !t.valid? + + t.title = nil + assert !t.valid? + end + + def test_optionally_validates_length_of_using_is + Topic.validates_length_of :title, :is => 5, :allow_nil => true + + t = Topic.create("title" => "valid", "content" => "whatever") + assert t.valid? + + t.title = nil + assert t.valid? + end + + def test_validates_length_of_using_bignum + bigmin = 2 ** 30 + bigmax = 2 ** 32 + bigrange = bigmin...bigmax + assert_nothing_raised do + Topic.validates_length_of :title, :is => bigmin + 5 + Topic.validates_length_of :title, :within => bigrange + Topic.validates_length_of :title, :in => bigrange + Topic.validates_length_of :title, :minimum => bigmin + Topic.validates_length_of :title, :maximum => bigmax + end + end + + def test_validates_length_with_globaly_modified_error_message + ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre %d' + Topic.validates_length_of :title, :minimum => 10 + t = Topic.create(:title => 'too short') + assert !t.valid? + + assert_equal 'tu est trops petit hombre 10', t.errors['title'] + end + + def test_validates_size_of_association + assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 } + t = Topic.new('title' => 'noreplies', 'content' => 'whatever') + assert !t.save + assert t.errors.on(:replies) + t.replies.create('title' => 'areply', 'content' => 'whateveragain') + assert t.valid? + end + + def test_validates_length_of_nasty_params + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>6, :maximum=>9) } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :maximum=>9) } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :minimum=>9) } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>6, :is=>9) } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :minimum=>"a") } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :maximum=>"a") } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :within=>"a") } + assert_raise(ArgumentError) { Topic.validates_length_of(:title, :is=>"a") } + end + + def test_validates_length_of_custom_errors_for_minimum_with_message + Topic.validates_length_of( :title, :minimum=>5, :message=>"boo %d" ) + t = Topic.create("title" => "uhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "boo 5", t.errors["title"] + end + + def test_validates_length_of_custom_errors_for_minimum_with_too_short + Topic.validates_length_of( :title, :minimum=>5, :too_short=>"hoo %d" ) + t = Topic.create("title" => "uhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "hoo 5", t.errors["title"] + end + + def test_validates_length_of_custom_errors_for_maximum_with_message + Topic.validates_length_of( :title, :maximum=>5, :message=>"boo %d" ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "boo 5", t.errors["title"] + end + + def test_validates_length_of_custom_errors_for_maximum_with_too_long + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d" ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "hoo 5", t.errors["title"] + end + + def test_validates_length_of_custom_errors_for_is_with_message + Topic.validates_length_of( :title, :is=>5, :message=>"boo %d" ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "boo 5", t.errors["title"] + end + + def test_validates_length_of_custom_errors_for_is_with_wrong_length + Topic.validates_length_of( :title, :is=>5, :wrong_length=>"hoo %d" ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "hoo 5", t.errors["title"] + end + + def kcode_scope(kcode) + orig_kcode = $KCODE + $KCODE = kcode + begin + yield + ensure + $KCODE = orig_kcode + end + end + + def test_validates_length_of_using_minimum_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of :title, :minimum => 5 + + t = Topic.create("title" => "一二三四五", "content" => "whatever") + assert t.valid? + + t.title = "一二三四" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is too short (minimum is 5 characters)", t.errors["title"] + end + end + + def test_validates_length_of_using_maximum_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of :title, :maximum => 5 + + t = Topic.create("title" => "一二三四五", "content" => "whatever") + assert t.valid? + + t.title = "一二34五å…" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is too long (maximum is 5 characters)", t.errors["title"] + end + end + + def test_validates_length_of_using_within_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of(:title, :content, :within => 3..5) + + t = Topic.new("title" => "一二", "content" => "12三四五å…七") + assert !t.valid? + assert_equal "is too short (minimum is 3 characters)", t.errors.on(:title) + assert_equal "is too long (maximum is 5 characters)", t.errors.on(:content) + t.title = "一二三" + t.content = "12三" + assert t.valid? + end + end + + def test_optionally_validates_length_of_using_within_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of :title, :content, :within => 3..5, :allow_nil => true + + t = Topic.create('title' => '一二三', 'content' => '一二三四五') + assert t.valid? + + t.title = nil + assert t.valid? + end + end + + def test_optionally_validates_length_of_using_within_on_create_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of :title, :content, :within => 5..10, :on => :create, :too_long => "é•·ã™ãŽã¾ã™: %d" + + t = Topic.create("title" => "一二三四五å…七八ä¹åA", "content" => "whatever") + assert !t.save + assert t.errors.on(:title) + assert_equal "é•·ã™ãŽã¾ã™: 10", t.errors[:title] + + t.title = "一二三四五å…七八ä¹" + assert t.save + + t.title = "一二3" + assert t.save + + t.content = "一二三四五å…七八ä¹å" + assert t.save + + t.content = t.title = "一二三四五å…" + assert t.save + end + end + + def test_optionally_validates_length_of_using_within_on_update_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of :title, :content, :within => 5..10, :on => :update, :too_short => "çŸã™ãŽã¾ã™: %d" + + t = Topic.create("title" => "一二三4", "content" => "whatever") + assert !t.save + assert t.errors.on(:title) + + t.title = "1二三4" + assert !t.save + assert t.errors.on(:title) + assert_equal "çŸã™ãŽã¾ã™: 5", t.errors[:title] + + t.title = "valid" + t.content = "一二三四五å…七八ä¹åA" + assert !t.save + assert t.errors.on(:content) + + t.content = "一二345" + assert t.save + end + end + + def test_validates_length_of_using_is_utf8 + kcode_scope('UTF8') do + Topic.validates_length_of :title, :is => 5 + + t = Topic.create("title" => "一二345", "content" => "whatever") + assert t.valid? + + t.title = "一二345å…" + assert !t.valid? + assert t.errors.on(:title) + assert_equal "is the wrong length (should be 5 characters)", t.errors["title"] + end + end + + def test_validates_size_of_association_utf8 + kcode_scope('UTF8') do + assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 } + t = Topic.new('title' => 'ã‚ã„ã†ãˆãŠ', 'content' => 'ã‹ããã‘ã“') + assert !t.save + assert t.errors.on(:replies) + t.replies.create('title' => 'ã‚ã„ã†ãˆãŠ', 'content' => 'ã‹ããã‘ã“') + assert t.valid? + end + end + + def test_validates_associated_many + Topic.validates_associated( :replies ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + t.replies << [r = Reply.create("title" => "A reply"), r2 = Reply.create("title" => "Another reply")] + assert !t.valid? + assert t.errors.on(:replies) + assert_equal 1, r.errors.count # make sure all associated objects have been validated + assert_equal 1, r2.errors.count + r.content = r2.content = "non-empty" + assert t.valid? + end + + def test_validates_associated_one + Reply.validates_associated( :topic ) + Topic.validates_presence_of( :content ) + r = Reply.create("title" => "A reply", "content" => "with content!") + r.topic = Topic.create("title" => "uhohuhoh") + assert !r.valid? + assert r.errors.on(:topic) + r.topic.content = "non-empty" + assert r.valid? + end + + def test_validate_block + Topic.validate { |topic| topic.errors.add("title", "will never be valid") } + t = Topic.create("title" => "Title", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "will never be valid", t.errors["title"] + end + + def test_invalid_validator + Topic.validate 3 + assert_raise(ActiveRecord::ActiveRecordError) { t = Topic.create } + end + + def test_throw_away_typing + d = Developer.create "name" => "David", "salary" => "100,000" + assert !d.valid? + assert_equal 100, d.salary + assert_equal "100,000", d.salary_before_type_cast + end + + def test_validates_acceptance_of_with_custom_error_using_quotes + Developer.validates_acceptance_of :salary, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.salary = "0" + assert !d.valid? + assert_equal d.errors.on(:salary).first, "This string contains 'single' and \"double\" quotes" + end + + def test_validates_confirmation_of_with_custom_error_using_quotes + Developer.validates_confirmation_of :name, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "John" + d.name_confirmation = "Johnny" + assert !d.valid? + assert_equal d.errors.on(:name), "This string contains 'single' and \"double\" quotes" + end + + def test_validates_format_of_with_custom_error_using_quotes + Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "John 32" + assert !d.valid? + assert_equal d.errors.on(:name), "This string contains 'single' and \"double\" quotes" + end + + def test_validates_inclusion_of_with_custom_error_using_quotes + Developer.validates_inclusion_of :salary, :in => 1000..80000, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.salary = "90,000" + assert !d.valid? + assert_equal d.errors.on(:salary).first, "This string contains 'single' and \"double\" quotes" + end + + def test_validates_length_of_with_custom_too_long_using_quotes + Developer.validates_length_of :name, :maximum => 4, :too_long=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "Jeffrey" + assert !d.valid? + assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes" + end + + def test_validates_length_of_with_custom_too_short_using_quotes + Developer.validates_length_of :name, :minimum => 4, :too_short=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "Joe" + assert !d.valid? + assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes" + end + + def test_validates_length_of_with_custom_message_using_quotes + Developer.validates_length_of :name, :minimum => 4, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "Joe" + assert !d.valid? + assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes" + end + + def test_validates_presence_of_with_custom_message_using_quotes + Developer.validates_presence_of :non_existent, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "Joe" + assert !d.valid? + assert_equal d.errors.on(:non_existent), "This string contains 'single' and \"double\" quotes" + end + + def test_validates_uniqueness_of_with_custom_message_using_quotes + Developer.validates_uniqueness_of :name, :message=> "This string contains 'single' and \"double\" quotes" + d = Developer.new + d.name = "David" + assert !d.valid? + assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes" + end + + def test_validates_associated_with_custom_message_using_quotes + Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes" + Topic.validates_presence_of :content + r = Reply.create("title" => "A reply", "content" => "with content!") + r.topic = Topic.create("title" => "uhohuhoh") + assert !r.valid? + assert_equal r.errors.on(:topic).first, "This string contains 'single' and \"double\" quotes" + end + + def test_conditional_validation_using_method_true + # When the method returns true + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "hoo 5", t.errors["title"] + end + + def test_conditional_validation_using_method_false + # When the method returns false + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true_but_its_not ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert t.valid? + assert !t.errors.on(:title) + end + + def test_conditional_validation_using_string_true + # When the evaluated string returns true + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => "a = 1; a == 1" ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "hoo 5", t.errors["title"] + end + + def test_conditional_validation_using_string_false + # When the evaluated string returns false + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => "false") + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert t.valid? + assert !t.errors.on(:title) + end + + def test_conditional_validation_using_block_true + # When the block returns true + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", + :if => Proc.new { |r| r.content.size > 4 } ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert !t.valid? + assert t.errors.on(:title) + assert_equal "hoo 5", t.errors["title"] + end + + def test_conditional_validation_using_block_false + # When the block returns false + Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", + :if => Proc.new { |r| r.title != "uhohuhoh"} ) + t = Topic.create("title" => "uhohuhoh", "content" => "whatever") + assert t.valid? + assert !t.errors.on(:title) + end + + def test_validates_associated_missing + Reply.validates_presence_of(:topic) + r = Reply.create("title" => "A reply", "content" => "with content!") + assert !r.valid? + assert r.errors.on(:topic) + + r.topic = Topic.find :first + assert r.valid? + end +end + + +class ValidatesNumericalityTest + NIL = [nil, "", " ", " \t \r \n"] + FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1) + INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090) + FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS + INTEGERS = [0, 10, -10] + INTEGER_STRINGS + JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12"] + + def setup + Topic.write_inheritable_attribute(:validate, nil) + Topic.write_inheritable_attribute(:validate_on_create, nil) + Topic.write_inheritable_attribute(:validate_on_update, nil) + end + + def test_default_validates_numericality_of + Topic.validates_numericality_of :approved + + invalid!(NIL + JUNK) + valid!(FLOATS + INTEGERS) + end + + def test_validates_numericality_of_with_nil_allowed + Topic.validates_numericality_of :approved, :allow_nil => true + + invalid!(JUNK) + valid!(NIL + FLOATS + INTEGERS) + end + + def test_validates_numericality_of_with_integer_only + Topic.validates_numericality_of :approved, :only_integer => true + + invalid!(NIL + JUNK + FLOATS) + valid!(INTEGERS) + end + + def test_validates_numericality_of_with_integer_only_and_nil_allowed + Topic.validates_numericality_of :approved, :only_integer => true, :allow_nil => true + + invalid!(JUNK + FLOATS) + valid!(NIL + INTEGERS) + end + + private + def invalid!(values) + values.each do |value| + topic = Topic.create("title" => "numeric test", "content" => "whatever", "approved" => value) + assert !topic.valid?, "#{value} not rejected as a number" + assert topic.errors.on(:approved) + end + end + + def valid!(values) + values.each do |value| + topic = Topic.create("title" => "numeric test", "content" => "whatever", "approved" => value) + assert topic.valid?, "#{value} not accepted as a number" + end + end +end +begin + require 'simplecc' +rescue LoadError + class Continuation # :nodoc: # for RDoc + end + def Continuation.create(*args, &block) # :nodoc: + cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?} + result ||= args + return *[cc, *result] + end +end + +class Binding; end # for RDoc +# This method returns the binding of the method that called your +# method. It will raise an Exception when you're not inside a method. +# +# It's used like this: +# def inc_counter(amount = 1) +# Binding.of_caller do |binding| +# # Create a lambda that will increase the variable 'counter' +# # in the caller of this method when called. +# inc = eval("lambda { |arg| counter += arg }", binding) +# # We can refer to amount from inside this block safely. +# inc.call(amount) +# end +# # No other statements can go here. Put them inside the block. +# end +# counter = 0 +# 2.times { inc_counter } +# counter # => 2 +# +# Binding.of_caller must be the last statement in the method. +# This means that you will have to put everything you want to +# do after the call to Binding.of_caller into the block of it. +# This should be no problem however, because Ruby has closures. +# If you don't do this an Exception will be raised. Because of +# the way that Binding.of_caller is implemented it has to be +# done this way. +def Binding.of_caller(&block) + old_critical = Thread.critical + Thread.critical = true + count = 0 + cc, result, error, extra_data = Continuation.create(nil, nil) + error.call if error + + tracer = lambda do |*args| + type, context, extra_data = args[0], args[4], args + if type == "return" + count += 1 + # First this method and then calling one will return -- + # the trace event of the second event gets the context + # of the method which called the method that called this + # method. + if count == 2 + # It would be nice if we could restore the trace_func + # that was set before we swapped in our own one, but + # this is impossible without overloading set_trace_func + # in current Ruby. + set_trace_func(nil) + cc.call(eval("binding", context), nil, extra_data) + end + elsif type == "line" then + nil + elsif type == "c-return" and extra_data[3] == :set_trace_func then + nil + else + set_trace_func(nil) + error_msg = "Binding.of_caller used in non-method context or " + + "trailing statements of method using it aren't in the block." + cc.call(nil, lambda { raise(ArgumentError, error_msg) }, nil) + end + end + + unless result + set_trace_func(tracer) + return nil + else + Thread.critical = old_critical + case block.arity + when 1 then yield(result) + else yield(result, extra_data) + end + end +end +# The Breakpoint library provides the convenience of +# being able to inspect and modify state, diagnose +# bugs all via IRB by simply setting breakpoints in +# your applications by the call of a method. +# +# This library was written and is supported by me, +# Florian Gross. I can be reached at flgr@ccan.de +# and enjoy getting feedback about my libraries. +# +# The whole library (including breakpoint_client.rb +# and binding_of_caller.rb) is licensed under the +# same license that Ruby uses. (Which is currently +# either the GNU General Public License or a custom +# one that allows for commercial usage.) If you for +# some good reason need to use this under another +# license please contact me. + +require 'irb' +require File.dirname(__FILE__) + '/binding_of_caller' unless defined? Binding.of_caller +require 'drb' +require 'drb/acl' + +module Breakpoint + id = %q$Id: breakpoint.rb 92 2005-02-04 22:35:53Z flgr $ + Version = id.split(" ")[2].to_i + + extend self + + # This will pop up an interactive ruby session at a + # pre-defined break point in a Ruby application. In + # this session you can examine the environment of + # the break point. + # + # You can get a list of variables in the context using + # local_variables via +local_variables+. You can then + # examine their values by typing their names. + # + # You can have a look at the call stack via +caller+. + # + # The source code around the location where the breakpoint + # was executed can be examined via +source_lines+. Its + # argument specifies how much lines of context to display. + # The default amount of context is 5 lines. Note that + # the call to +source_lines+ can raise an exception when + # it isn't able to read in the source code. + # + # breakpoints can also return a value. They will execute + # a supplied block for getting a default return value. + # A custom value can be returned from the session by doing + # +throw(:debug_return, value)+. + # + # You can also give names to break points which will be + # used in the message that is displayed upon execution + # of them. + # + # Here's a sample of how breakpoints should be placed: + # + # class Person + # def initialize(name, age) + # @name, @age = name, age + # breakpoint("Person#initialize") + # end + # + # attr_reader :age + # def name + # breakpoint("Person#name") { @name } + # end + # end + # + # person = Person.new("Random Person", 23) + # puts "Name: #{person.name}" + # + # And here is a sample debug session: + # + # Executing break point "Person#initialize" at file.rb:4 in `initialize' + # irb(#<Person:0x292fbe8>):001:0> local_variables + # => ["name", "age", "_", "__"] + # irb(#<Person:0x292fbe8>):002:0> [name, age] + # => ["Random Person", 23] + # irb(#<Person:0x292fbe8>):003:0> [@name, @age] + # => ["Random Person", 23] + # irb(#<Person:0x292fbe8>):004:0> self + # => #<Person:0x292fbe8 @age=23, @name="Random Person"> + # irb(#<Person:0x292fbe8>):005:0> @age += 1; self + # => #<Person:0x292fbe8 @age=24, @name="Random Person"> + # irb(#<Person:0x292fbe8>):006:0> exit + # Executing break point "Person#name" at file.rb:9 in `name' + # irb(#<Person:0x292fbe8>):001:0> throw(:debug_return, "Overriden name") + # Name: Overriden name + # + # Breakpoint sessions will automatically have a few + # convenience methods available. See Breakpoint::CommandBundle + # for a list of them. + # + # Breakpoints can also be used remotely over sockets. + # This is implemented by running part of the IRB session + # in the application and part of it in a special client. + # You have to call Breakpoint.activate_drb to enable + # support for remote breakpoints and then run + # breakpoint_client.rb which is distributed with this + # library. See the documentation of Breakpoint.activate_drb + # for details. + def breakpoint(id = nil, context = nil, &block) + callstack = caller + callstack.slice!(0, 3) if callstack.first["breakpoint"] + file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures + + message = "Executing break point " + (id ? "#{id.inspect} " : "") + + "at #{file}:#{line}" + (method ? " in `#{method}'" : "") + + if context then + return handle_breakpoint(context, message, file, line, &block) + end + + Binding.of_caller do |binding_context| + handle_breakpoint(binding_context, message, file, line, &block) + end + end + + module CommandBundle #:nodoc: + # Proxy to a Breakpoint client. Lets you directly execute code + # in the context of the client. + class Client #:nodoc: + def initialize(eval_handler) # :nodoc: + eval_handler.untaint + @eval_handler = eval_handler + end + + instance_methods.each do |method| + next if method[/^__.+__$/] + undef_method method + end + + # Executes the specified code at the client. + def eval(code) + @eval_handler.call(code) + end + + # Will execute the specified statement at the client. + def method_missing(method, *args, &block) + if args.empty? and not block + result = eval "#{method}" + else + # This is a bit ugly. The alternative would be using an + # eval context instead of an eval handler for executing + # the code at the client. The problem with that approach + # is that we would have to handle special expressions + # like "self", "nil" or constants ourself which is hard. + remote = eval %{ + result = lambda { |block, *args| #{method}(*args, &block) } + def result.call_with_block(*args, &block) + call(block, *args) + end + result + } + remote.call_with_block(*args, &block) + end + + return result + end + end + + # Returns the source code surrounding the location where the + # breakpoint was issued. + def source_lines(context = 5, return_line_numbers = false) + lines = File.readlines(@__bp_file).map { |line| line.chomp } + + break_line = @__bp_line + start_line = [break_line - context, 1].max + end_line = break_line + context + + result = lines[(start_line - 1) .. (end_line - 1)] + + if return_line_numbers then + return [start_line, break_line, result] + else + return result + end + end + + # Lets an object that will forward method calls to the breakpoint + # client. This is useful for outputting longer things at the client + # and so on. You can for example do these things: + # + # client.puts "Hello" # outputs "Hello" at client console + # # outputs "Hello" into the file temp.txt at the client + # client.File.open("temp.txt", "w") { |f| f.puts "Hello" } + def client() + if Breakpoint.use_drb? then + sleep(0.5) until Breakpoint.drb_service.eval_handler + Client.new(Breakpoint.drb_service.eval_handler) + else + Client.new(lambda { |code| eval(code, TOPLEVEL_BINDING) }) + end + end + end + + def handle_breakpoint(context, message, file = "", line = "", &block) # :nodoc: + catch(:debug_return) do |value| + eval(%{ + @__bp_file = #{file.inspect} + @__bp_line = #{line} + extend Breakpoint::CommandBundle + extend DRbUndumped if self + }, context) rescue nil + + if not use_drb? then + puts message + IRB.start(nil, IRB::WorkSpace.new(context)) + else + @drb_service.add_breakpoint(context, message) + end + + block.call if block + end + end + + # These exceptions will be raised on failed asserts + # if Breakpoint.asserts_cause_exceptions is set to + # true. + class FailedAssertError < RuntimeError #:nodoc: + end + + # This asserts that the block evaluates to true. + # If it doesn't evaluate to true a breakpoint will + # automatically be created at that execution point. + # + # You can disable assert checking in production + # code by setting Breakpoint.optimize_asserts to + # true. (It will still be enabled when Ruby is run + # via the -d argument.) + # + # Example: + # person_name = "Foobar" + # assert { not person_name.nil? } + # + # Note: If you want to use this method from an + # unit test, you will have to call it by its full + # name, Breakpoint.assert. + def assert(context = nil, &condition) + return if Breakpoint.optimize_asserts and not $DEBUG + return if yield + + callstack = caller + callstack.slice!(0, 3) if callstack.first["assert"] + file, line, method = *callstack.first.match(/^(.+?):(\d+)(?::in `(.*?)')?/).captures + + message = "Assert failed at #{file}:#{line}#{" in `#{method}'" if method}." + + if Breakpoint.asserts_cause_exceptions and not $DEBUG then + raise(Breakpoint::FailedAssertError, message) + end + + message += " Executing implicit breakpoint." + + if context then + return handle_breakpoint(context, message, file, line) + end + + Binding.of_caller do |context| + handle_breakpoint(context, message, file, line) + end + end + + # Whether asserts should be ignored if not in debug mode. + # Debug mode can be enabled by running ruby with the -d + # switch or by setting $DEBUG to true. + attr_accessor :optimize_asserts + self.optimize_asserts = false + + # Whether an Exception should be raised on failed asserts + # in non-$DEBUG code or not. By default this is disabled. + attr_accessor :asserts_cause_exceptions + self.asserts_cause_exceptions = false + @use_drb = false + + attr_reader :drb_service # :nodoc: + + class DRbService # :nodoc: + include DRbUndumped + + def initialize + @handler = @eval_handler = @collision_handler = nil + + IRB.instance_eval { @CONF[:RC] = true } + IRB.run_config + end + + def collision + sleep(0.5) until @collision_handler + + @collision_handler.untaint + + @collision_handler.call + end + + def ping() end + + def add_breakpoint(context, message) + workspace = IRB::WorkSpace.new(context) + workspace.extend(DRbUndumped) + + sleep(0.5) until @handler + + @handler.untaint + @handler.call(workspace, message) + end + + attr_accessor :handler, :eval_handler, :collision_handler + end + + # Will run Breakpoint in DRb mode. This will spawn a server + # that can be attached to via the breakpoint-client command + # whenever a breakpoint is executed. This is useful when you + # are debugging CGI applications or other applications where + # you can't access debug sessions via the standard input and + # output of your application. + # + # You can specify an URI where the DRb server will run at. + # This way you can specify the port the server runs on. The + # default URI is druby://localhost:42531. + # + # Please note that breakpoints will be skipped silently in + # case the DRb server can not spawned. (This can happen if + # the port is already used by another instance of your + # application on CGI or another application.) + # + # Also note that by default this will only allow access + # from localhost. You can however specify a list of + # allowed hosts or nil (to allow access from everywhere). + # But that will still not protect you from somebody + # reading the data as it goes through the net. + # + # A good approach for getting security and remote access + # is setting up an SSH tunnel between the DRb service + # and the client. This is usually done like this: + # + # $ ssh -L20000:127.0.0.1:20000 -R10000:127.0.0.1:10000 example.com + # (This will connect port 20000 at the client side to port + # 20000 at the server side, and port 10000 at the server + # side to port 10000 at the client side.) + # + # After that do this on the server side: (the code being debugged) + # Breakpoint.activate_drb("druby://127.0.0.1:20000", "localhost") + # + # And at the client side: + # ruby breakpoint_client.rb -c druby://127.0.0.1:10000 -s druby://127.0.0.1:20000 + # + # Running through such a SSH proxy will also let you use + # breakpoint.rb in case you are behind a firewall. + # + # Detailed information about running DRb through firewalls is + # available at http://www.rubygarden.org/ruby?DrbTutorial + def activate_drb(uri = nil, allowed_hosts = ['localhost', '127.0.0.1', '::1'], + ignore_collisions = false) + + return false if @use_drb + + uri ||= 'druby://localhost:42531' + + if allowed_hosts then + acl = ["deny", "all"] + + Array(allowed_hosts).each do |host| + acl += ["allow", host] + end + + DRb.install_acl(ACL.new(acl)) + end + + @use_drb = true + @drb_service = DRbService.new + did_collision = false + begin + @service = DRb.start_service(uri, @drb_service) + rescue Errno::EADDRINUSE + if ignore_collisions then + nil + else + # The port is already occupied by another + # Breakpoint service. We will try to tell + # the old service that we want its port. + # It will then forward that request to the + # user and retry. + unless did_collision then + DRbObject.new(nil, uri).collision + did_collision = true + end + sleep(10) + retry + end + end + + return true + end + + # Deactivates a running Breakpoint service. + def deactivate_drb + @service.stop_service unless @service.nil? + @service = nil + @use_drb = false + @drb_service = nil + end + + # Returns true when Breakpoints are used over DRb. + # Breakpoint.activate_drb causes this to be true. + def use_drb? + @use_drb == true + end +end + +module IRB #:nodoc: + class << self; remove_method :start; end + def self.start(ap_path = nil, main_context = nil, workspace = nil) + $0 = File::basename(ap_path, ".rb") if ap_path + + # suppress some warnings about redefined constants + old_verbose, $VERBOSE = $VERBOSE, nil + IRB.setup(ap_path) + $VERBOSE = old_verbose + + if @CONF[:SCRIPT] then + irb = Irb.new(main_context, @CONF[:SCRIPT]) + else + irb = Irb.new(main_context) + end + + if workspace then + irb.context.workspace = workspace + end + + @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] + @CONF[:MAIN_CONTEXT] = irb.context + + old_sigint = trap("SIGINT") do + begin + irb.signal_handle + rescue RubyLex::TerminateLineInput + # ignored + end + end + + catch(:IRB_EXIT) do + irb.eval_input + end + ensure + trap("SIGINT", old_sigint) + end + + class << self + alias :old_CurrentContext :CurrentContext + remove_method :CurrentContext + end + def IRB.CurrentContext + if old_CurrentContext.nil? and Breakpoint.use_drb? then + result = Object.new + def result.last_value; end + return result + else + old_CurrentContext + end + end + def IRB.parse_opts() end + + class Context #:nodoc: + alias :old_evaluate :evaluate + def evaluate(line, line_no) + if line.chomp == "exit" then + exit + else + old_evaluate(line, line_no) + end + end + end + + class WorkSpace #:nodoc: + alias :old_evaluate :evaluate + + def evaluate(*args) + if Breakpoint.use_drb? then + result = old_evaluate(*args) + if args[0] != :no_proxy and + not [true, false, nil].include?(result) + then + result.extend(DRbUndumped) rescue nil + end + return result + else + old_evaluate(*args) + end + end + end + + module InputCompletor #:nodoc: + def self.eval(code, context, *more) + # Big hack, this assumes that InputCompletor + # will only call eval() when it wants code + # to be executed in the IRB context. + IRB.conf[:MAIN_CONTEXT].workspace.evaluate(:no_proxy, code, *more) + end + end +end + +module DRb # :nodoc: + class DRbObject #:nodoc: + undef :inspect if method_defined?(:inspect) + undef :clone if method_defined?(:clone) + end +end + +# See Breakpoint.breakpoint +def breakpoint(id = nil, &block) + Binding.of_caller do |context| + Breakpoint.breakpoint(id, context, &block) + end +end + +# See Breakpoint.assert +def assert(&block) + Binding.of_caller do |context| + Breakpoint.assert(context, &block) + end +end +module ActiveSupport + module CachingTools #:nodoc: + + # Provide shortcuts to simply the creation of nested default hashes. This + # pattern is useful, common practice, and unsightly when done manually. + module HashCaching + # Dynamically create a nested hash structure used to cache calls to +method_name+ + # The cache method is named +#{method_name}_cache+ unless :as => :alternate_name + # is given. + # + # The hash structure is created using nested Hash.new. For example: + # + # def slow_method(a, b) a ** b end + # + # can be cached using hash_cache :slow_method, which will define the method + # slow_method_cache. We can then find the result of a ** b using: + # + # slow_method_cache[a][b] + # + # The hash structure returned by slow_method_cache would look like this: + # + # Hash.new do |as, a| + # as[a] = Hash.new do |bs, b| + # bs[b] = slow_method(a, b) + # end + # end + # + # The generated code is actually compressed onto a single line to maintain + # sensible backtrace signatures. + # + def hash_cache(method_name, options = {}) + selector = options[:as] || "#{method_name}_cache" + method = self.instance_method(method_name) + + args = [] + code = "def #{selector}(); @#{selector} ||= " + + (1..method.arity).each do |n| + args << "v#{n}" + code << "Hash.new {|h#{n}, v#{n}| h#{n}[v#{n}] = " + end + + # Add the method call with arguments, followed by closing braces and end. + code << "#{method_name}(#{args * ', '}) #{'}' * method.arity} end" + + # Extract the line number information from the caller. Exceptions arising + # in the generated code should point to the +hash_cache :...+ line. + if caller[0] && /^(.*):(\d+)$/ =~ caller[0] + file, line_number = $1, $2.to_i + else # We can't give good trackback info; fallback to this line: + file, line_number = __FILE__, __LINE__ + end + + # We use eval rather than building proc's because it allows us to avoid + # linking the Hash's to this method's binding. Experience has shown that + # doing so can cause obtuse memory leaks. + class_eval code, file, line_number + end + end + + end +end +require 'logger' +require File.dirname(__FILE__) + '/core_ext/class/attribute_accessors' + +class Logger #:nodoc: + cattr_accessor :silencer + self.silencer = true + + # Silences the logger for the duration of the block. + def silence(temporary_level = Logger::ERROR) + if silencer + begin + old_logger_level, self.level = level, temporary_level + yield self + ensure + self.level = old_logger_level + end + else + yield self + end + end + + private + alias old_format_message format_message + + # Ruby 1.8.3 transposed the msg and progname arguments to format_message. + # We can't test RUBY_VERSION because some distributions don't keep Ruby + # and its standard library in sync, leading to installations of Ruby 1.8.2 + # with Logger from 1.8.3 and vice versa. + if method_defined?(:formatter=) + def format_message(severity, timestamp, progname, msg) + "#{msg}\n" + end + else + def format_message(severity, timestamp, msg, progname) + "#{msg}\n" + end + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Array #:nodoc: + module Conversions + # Converts the array to comma-seperated sentence where the last element is joined by the connector word. Options: + # * <tt>:connector</tt>: The word used to join the last element in arrays with more than two elements (default: "and") + # * <tt>:skip_last_comma</tt>: Set to true to return "a, b, and c" instead of "a, b and c". + def to_sentence(options = {}) + options.assert_valid_keys(:connector, :skip_last_comma) + options.reverse_merge! :connector => 'and', :skip_last_comma => false + + case length + when 0 + "" + when 1 + self[0] + when 2 + "#{self[0]} #{options[:connector]} #{self[1]}" + else + "#{self[0...-1].join(', ')}#{options[:skip_last_comma] ? '' : ','} #{options[:connector]} #{self[-1]}" + end + end + + # When an array is given to url_for, it is converted to a slash separated string. + def to_param + join '/' + end + + def to_xml(options = {}) + raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml } + + options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records" + options[:children] ||= options[:root].singularize + options[:indent] ||= 2 + options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) + + root = options.delete(:root) + children = options.delete(:children) + + options[:builder].instruct! unless options.delete(:skip_instruct) + options[:builder].tag!(root.to_s.dasherize) { each { |e| e.to_xml(options.merge({ :skip_instruct => true, :root => children })) } } + end + end + end + end +end +require File.dirname(__FILE__) + '/array/conversions' + +class Array #:nodoc: + include ActiveSupport::CoreExtensions::Array::Conversions + + # Iterate over an array in groups of a certain size, padding any remaining + # slots with specified value (<tt>nil</tt> by default). + # + # E.g. + # + # %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g} + # ["1", "2", "3"] + # ["4", "5", "6"] + # ["7", nil, nil] + def in_groups_of(number, fill_with = nil, &block) + require 'enumerator' + collection = dup + collection << fill_with until collection.size.modulo(number).zero? + collection.each_slice(number, &block) + end +end +class Object #:nodoc: + # "", " ", nil, [], and {} are blank + def blank? + if respond_to?(:empty?) && respond_to?(:strip) + empty? or strip.empty? + elsif respond_to?(:empty?) + empty? + else + !self + end + end +end + +class NilClass #:nodoc: + def blank? + true + end +end + +class FalseClass #:nodoc: + def blank? + true + end +end + +class TrueClass #:nodoc: + def blank? + false + end +end + +class Array #:nodoc: + alias_method :blank?, :empty? +end + +class Hash #:nodoc: + alias_method :blank?, :empty? +end + +class String #:nodoc: + def blank? + empty? || strip.empty? + end +end + +class Numeric #:nodoc: + def blank? + false + end +endmodule ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module CGI #:nodoc: + module EscapeSkippingSlashes #:nodoc: + def escape_skipping_slashes(str) + str = str.join('/') if str.respond_to? :join + str.gsub(/([^ \/a-zA-Z0-9_.-])/n) do + "%#{$1.unpack('H2').first.upcase}" + end.tr(' ', '+') + end + end + end + end +end +require File.dirname(__FILE__) + '/cgi/escape_skipping_slashes' + +class CGI #:nodoc: + extend(ActiveSupport::CoreExtensions::CGI::EscapeSkippingSlashes) +end +# Extends the class object with class and instance accessors for class attributes, +# just like the native attr* accessors for instance attributes. +class Class # :nodoc: + def cattr_reader(*syms) + syms.flatten.each do |sym| + class_eval(<<-EOS, __FILE__, __LINE__) + unless defined? @@#{sym} + @@#{sym} = nil + end + + def self.#{sym} + @@#{sym} + end + + def #{sym} + @@#{sym} + end + EOS + end + end + + def cattr_writer(*syms) + syms.flatten.each do |sym| + class_eval(<<-EOS, __FILE__, __LINE__) + unless defined? @@#{sym} + @@#{sym} = nil + end + + def self.#{sym}=(obj) + @@#{sym} = obj + end + + def #{sym}=(obj) + @@#{sym} = obj + end + EOS + end + end + + def cattr_accessor(*syms) + cattr_reader(*syms) + cattr_writer(*syms) + end +end +# Retain for backward compatibility. Methods are now included in Class. +module ClassInheritableAttributes # :nodoc: +end + +# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of +# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements +# to, for example, an array without those additions being shared with either their parent, siblings, or +# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy. +class Class # :nodoc: + def class_inheritable_reader(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym} + read_inheritable_attribute(:#{sym}) + end + + def #{sym} + self.class.#{sym} + end + EOS + end + end + + def class_inheritable_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym}=(obj) + write_inheritable_attribute(:#{sym}, obj) + end + + def #{sym}=(obj) + self.class.#{sym} = obj + end + EOS + end + end + + def class_inheritable_array_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym}=(obj) + write_inheritable_array(:#{sym}, obj) + end + + def #{sym}=(obj) + self.class.#{sym} = obj + end + EOS + end + end + + def class_inheritable_hash_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + def self.#{sym}=(obj) + write_inheritable_hash(:#{sym}, obj) + end + + def #{sym}=(obj) + self.class.#{sym} = obj + end + EOS + end + end + + def class_inheritable_accessor(*syms) + class_inheritable_reader(*syms) + class_inheritable_writer(*syms) + end + + def class_inheritable_array(*syms) + class_inheritable_reader(*syms) + class_inheritable_array_writer(*syms) + end + + def class_inheritable_hash(*syms) + class_inheritable_reader(*syms) + class_inheritable_hash_writer(*syms) + end + + def inheritable_attributes + @inheritable_attributes ||= {} + end + + def write_inheritable_attribute(key, value) + inheritable_attributes[key] = value + end + + def write_inheritable_array(key, elements) + write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil? + write_inheritable_attribute(key, read_inheritable_attribute(key) + elements) + end + + def write_inheritable_hash(key, hash) + write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil? + write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash)) + end + + def read_inheritable_attribute(key) + inheritable_attributes[key] + end + + def reset_inheritable_attributes + inheritable_attributes.clear + end + + private + def inherited_with_inheritable_attributes(child) + inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes) + child.instance_variable_set('@inheritable_attributes', inheritable_attributes.dup) + end + + alias inherited_without_inheritable_attributes inherited + alias inherited inherited_with_inheritable_attributes +end +class Class #:nodoc: + def remove_subclasses + Object.remove_subclasses_of(self) + end + + def subclasses + Object.subclasses_of(self).map { |o| o.to_s } + end + + def remove_class(*klasses) + klasses.flatten.each do |klass| + # Skip this class if there is nothing bound to this name + next unless defined?(klass.name) + + basename = klass.to_s.split("::").last + parent = klass.parent + + # Skip this class if it does not match the current one bound to this name + next unless parent.const_defined?(basename) && klass = parent.const_get(basename) + + parent.send :remove_const, basename unless parent == klass + end + end +end +require File.dirname(__FILE__) + '/class/attribute_accessors' +require File.dirname(__FILE__) + '/class/inheritable_attributes' +require File.dirname(__FILE__) + '/class/removal'module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Date #:nodoc: + # Getting dates in different convenient string representations and other objects + module Conversions + DATE_FORMATS = { + :short => "%e %b", + :long => "%B %e, %Y" + } + + def self.included(klass) #:nodoc: + klass.send(:alias_method, :to_default_s, :to_s) + klass.send(:alias_method, :to_s, :to_formatted_s) + end + + def to_formatted_s(format = :default) + DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s + end + + # To be able to keep Dates and Times interchangeable on conversions + def to_date + self + end + + def to_time(form = :local) + ::Time.send(form, year, month, day) + end + + alias :xmlschema :to_s + end + end + end +endrequire 'date' +require File.dirname(__FILE__) + '/date/conversions' + +class Date#:nodoc: + include ActiveSupport::CoreExtensions::Date::Conversions +end +module Enumerable #:nodoc: + def first_match + match = nil + each do |items| + break if match = yield(items) + end + match + end + + # Collect an enumerable into sets, grouped by the result of a block. Useful, + # for example, for grouping records by date. + # + # e.g. + # + # latest_transcripts.group_by(&:day).each do |day, transcripts| + # p "#{day} -> #{transcripts.map(&:class) * ', '}" + # end + # "2006-03-01 -> Transcript" + # "2006-02-28 -> Transcript" + # "2006-02-27 -> Transcript, Transcript" + # "2006-02-26 -> Transcript, Transcript" + # "2006-02-25 -> Transcript" + # "2006-02-24 -> Transcript, Transcript" + # "2006-02-23 -> Transcript" + def group_by + inject({}) do |groups, element| + (groups[yield(element)] ||= []) << element + groups + end + end +end +class Exception # :nodoc: + def clean_message + Pathname.clean_within message + end + + TraceSubstitutions = [] + FrameworkRegexp = /generated|vendor|dispatch|ruby|script\/\w+/ + + def clean_backtrace + backtrace.collect do |line| + Pathname.clean_within(TraceSubstitutions.inject(line) do |line, (regexp, sub)| + line.gsub regexp, sub + end) + end + end + + def application_backtrace + before_application_frame = true + + trace = clean_backtrace.reject do |line| + non_app_frame = (line =~ FrameworkRegexp) + before_application_frame = false unless non_app_frame + non_app_frame && ! before_application_frame + end + + # If we didn't find any application frames, return an empty app trace. + before_application_frame ? [] : trace + end + + def framework_backtrace + clean_backtrace.select {|line| line =~ FrameworkRegexp} + end +endmodule ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + module Conversions + XML_TYPE_NAMES = { + "Fixnum" => "integer", + "Date" => "date", + "Time" => "datetime", + "TrueClass" => "boolean", + "FalseClass" => "boolean" + } + + XML_FORMATTING = { + "date" => Proc.new { |date| date.to_s(:db) }, + "datetime" => Proc.new { |time| time.xmlschema } + } + + def to_xml(options = {}) + options[:indent] ||= 2 + options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]), :root => "hash" }) + options[:builder].instruct! unless options.delete(:skip_instruct) + + options[:builder].__send__(options[:root].to_s.dasherize) do + each do |key, value| + case value + when ::Hash + value.to_xml(options.merge({ :root => key, :skip_instruct => true })) + when ::Array + value.to_xml(options.merge({ :root => key, :children => key.to_s.singularize, :skip_instruct => true})) + else + type_name = XML_TYPE_NAMES[value.class.to_s] + + options[:builder].tag!(key.to_s.dasherize, + XML_FORMATTING[type_name] ? XML_FORMATTING[type_name].call(value) : value, + options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name } + ) + end + end + end + end + end + end + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + module Diff + def diff(h2) + self.dup.delete_if { |k, v| h2[k] == v }.merge(h2.dup.delete_if { |k, v| self.has_key?(k) }) + end + end + end + end +end +# this class has dubious semantics and we only have it so that +# people can write params[:key] instead of params['key'] + +class HashWithIndifferentAccess < Hash + def initialize(constructor = {}) + if constructor.is_a?(Hash) + super() + update(constructor) + else + super(constructor) + end + end + + def default(key) + self[key.to_s] if key.is_a?(Symbol) + end + + alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) + alias_method :regular_update, :update unless method_defined?(:regular_update) + + def []=(key, value) + regular_writer(convert_key(key), convert_value(value)) + end + + def update(other_hash) + other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } + self + end + + alias_method :merge!, :update + + def key?(key) + super(convert_key(key)) + end + + alias_method :include?, :key? + alias_method :has_key?, :key? + alias_method :member?, :key? + + def fetch(key, *extras) + super(convert_key(key), *extras) + end + + def values_at(*indices) + indices.collect {|key| self[convert_key(key)]} + end + + def dup + HashWithIndifferentAccess.new(self) + end + + def merge(hash) + self.dup.update(hash) + end + + def delete(key) + super(convert_key(key)) + end + + protected + def convert_key(key) + key.kind_of?(Symbol) ? key.to_s : key + end + def convert_value(value) + value.is_a?(Hash) ? value.with_indifferent_access : value + end +end + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + module IndifferentAccess #:nodoc: + def with_indifferent_access + HashWithIndifferentAccess.new(self) + end + end + end + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + module Keys + # Return a new hash with all keys converted to strings. + def stringify_keys + inject({}) do |options, (key, value)| + options[key.to_s] = value + options + end + end + + # Destructively convert all keys to strings. + def stringify_keys! + keys.each do |key| + unless key.class.to_s == "String" # weird hack to make the tests run when string_ext_test.rb is also running + self[key.to_s] = self[key] + delete(key) + end + end + self + end + + # Return a new hash with all keys converted to symbols. + def symbolize_keys + inject({}) do |options, (key, value)| + options[key.to_sym] = value + options + end + end + + # Destructively convert all keys to symbols. + def symbolize_keys! + keys.each do |key| + unless key.is_a?(Symbol) + self[key.to_sym] = self[key] + delete(key) + end + end + self + end + + alias_method :to_options, :symbolize_keys + alias_method :to_options!, :symbolize_keys! + + def assert_valid_keys(*valid_keys) + unknown_keys = keys - [valid_keys].flatten + raise(ArgumentError, "Unknown key(s): #{unknown_keys.join(", ")}") unless unknown_keys.empty? + end + end + end + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Hash #:nodoc: + # Allows for reverse merging where its the keys in the calling hash that wins over those in the <tt>other_hash</tt>. + # This is particularly useful for initializing an incoming option hash with default values: + # + # def setup(options = {}) + # options.reverse_merge! :size => 25, :velocity => 10 + # end + # + # The default :size and :velocity is only set if the +options+ passed in doesn't already have those keys set. + module ReverseMerge + def reverse_merge(other_hash) + other_hash.merge(self) + end + + def reverse_merge!(other_hash) + replace(reverse_merge(other_hash)) + end + + alias_method :reverse_update, :reverse_merge + end + end + end +endrequire File.dirname(__FILE__) + '/hash/keys' +require File.dirname(__FILE__) + '/hash/indifferent_access' +require File.dirname(__FILE__) + '/hash/reverse_merge' +require File.dirname(__FILE__) + '/hash/conversions' +require File.dirname(__FILE__) + '/hash/diff' + +class Hash #:nodoc: + include ActiveSupport::CoreExtensions::Hash::Keys + include ActiveSupport::CoreExtensions::Hash::IndifferentAccess + include ActiveSupport::CoreExtensions::Hash::ReverseMerge + include ActiveSupport::CoreExtensions::Hash::Conversions + include ActiveSupport::CoreExtensions::Hash::Diff +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Integer #:nodoc: + # For checking if a fixnum is even or odd. + # * 1.even? # => false + # * 1.odd? # => true + # * 2.even? # => true + # * 2.odd? # => false + module EvenOdd + def multiple_of?(number) + self % number == 0 + end + + def even? + multiple_of? 2 + end + + def odd? + !even? + end + end + end + end +end +require File.dirname(__FILE__) + '/../../inflector' unless defined? Inflector +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Integer #:nodoc: + module Inflections + # 1.ordinalize # => "1st" + # 3.ordinalize # => "3rd" + # 10.ordinalize # => "10th" + def ordinalize + Inflector.ordinalize(self) + end + end + end + end +end +require File.dirname(__FILE__) + '/integer/even_odd' +require File.dirname(__FILE__) + '/integer/inflections' + +class Integer #:nodoc: + include ActiveSupport::CoreExtensions::Integer::EvenOdd + include ActiveSupport::CoreExtensions::Integer::Inflections +end +class Object + # Makes backticks behave (somewhat more) similarly on all platforms. + # On win32 `nonexistent_command` raises Errno::ENOENT; on Unix, the + # spawned shell prints a message to stderr and sets $?. We emulate + # Unix on the former but not the latter. + def `(command) #:nodoc: + super + rescue Errno::ENOENT => e + STDERR.puts "#$0: #{e}" + end +endmodule Kernel + # Turns the current script into a daemon process that detaches from the console. + # It can be shut down with a TERM signal. + def daemonize + exit if fork # Parent exits, child continues. + Process.setsid # Become session leader. + exit if fork # Zap session leader. See [1]. + Dir.chdir "/" # Release old working directory. + File.umask 0000 # Ensure sensible umask. Adjust as needed. + STDIN.reopen "/dev/null" # Free file descriptors and + STDOUT.reopen "/dev/null", "a" # point them somewhere sensible. + STDERR.reopen STDOUT # STDOUT/ERR should better go to a logfile. + trap("TERM") { exit } + end +endmodule Kernel + # Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards. + # + # silence_warnings do + # value = noisy_call # no warning voiced + # end + # + # noisy_call # warning voiced + def silence_warnings + old_verbose, $VERBOSE = $VERBOSE, nil + yield + ensure + $VERBOSE = old_verbose + end + + # Sets $VERBOSE to true for the duration of the block and back to its original value afterwards. + def enable_warnings + old_verbose, $VERBOSE = $VERBOSE, true + yield + ensure + $VERBOSE = old_verbose + end + + # For compatibility + def silence_stderr #:nodoc: + silence_stream(STDERR) { yield } + end + + # Silences any stream for the duration of the block. + # + # silence_stream(STDOUT) do + # puts 'This will never be seen' + # end + # + # puts 'But this will' + def silence_stream(stream) + old_stream = stream.dup + stream.reopen(RUBY_PLATFORM =~ /mswin/ ? 'NUL:' : '/dev/null') + stream.sync = true + yield + ensure + stream.reopen(old_stream) + end + + def suppress(*exception_classes) + begin yield + rescue Exception => e + raise unless exception_classes.any? { |cls| e.kind_of?(cls) } + end + end +endmodule Kernel + # Require a library with fallback to RubyGems. Warnings during library + # loading are silenced to increase signal/noise for application warnings. + def require_library_or_gem(library_name) + silence_warnings do + begin + require library_name + rescue LoadError => cannot_require + # 1. Requiring the module is unsuccessful, maybe it's a gem and nobody required rubygems yet. Try. + begin + require 'rubygems' + rescue LoadError => rubygems_not_installed + raise cannot_require + end + # 2. Rubygems is installed and loaded. Try to load the library again + begin + require library_name + rescue LoadError => gem_not_installed + raise cannot_require + end + end + end + end +endrequire File.dirname(__FILE__) + '/kernel/daemonizing' +require File.dirname(__FILE__) + '/kernel/reporting' +require File.dirname(__FILE__) + '/kernel/agnostics' +require File.dirname(__FILE__) + '/kernel/requires' +class MissingSourceFile < LoadError #:nodoc: + attr_reader :path + def initialize(message, path) + super(message) + @path = path + end + + def is_missing?(path) + path.gsub(/\.rb$/, '') == self.path.gsub(/\.rb$/, '') + end + + def self.from_message(message) + REGEXPS.each do |regexp, capture| + match = regexp.match(message) + return MissingSourceFile.new(message, match[capture]) unless match.nil? + end + nil + end + + REGEXPS = [ + [/^no such file to load -- (.+)$/i, 1], + [/^Missing \w+ (file\s*)?([^\s]+.rb)$/i, 2], + [/^Missing API definition file in (.+)$/i, 1] + ] +end + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module LoadErrorExtensions #:nodoc: + module LoadErrorClassMethods #:nodoc: + def new(*args) + (self == LoadError && MissingSourceFile.from_message(args.first)) || super + end + end + ::LoadError.extend(LoadErrorClassMethods) + end + end +end +# Adds the 'around_level' method to Logger. + +class Logger + def self.define_around_helper(level) + module_eval <<-end_eval + def around_#{level}(before_message, after_message, &block) + self.#{level}(before_message) + return_value = block.call(self) + self.#{level}(after_message) + return return_value + end + end_eval + end + [:debug, :info, :error, :fatal].each {|level| define_around_helper(level) } + +end# Extends the module object with module and instance accessors for class attributes, +# just like the native attr* accessors for instance attributes. +class Module # :nodoc: + def mattr_reader(*syms) + syms.each do |sym| + class_eval(<<-EOS, __FILE__, __LINE__) + unless defined? @@#{sym} + @@#{sym} = nil + end + + def self.#{sym} + @@#{sym} + end + + def #{sym} + @@#{sym} + end + EOS + end + end + + def mattr_writer(*syms) + syms.each do |sym| + class_eval(<<-EOS, __FILE__, __LINE__) + unless defined? @@#{sym} + @@#{sym} = nil + end + + def self.#{sym}=(obj) + @@#{sym} = obj + end + + def #{sym}=(obj) + @@#{sym} = obj + end + EOS + end + end + + def mattr_accessor(*syms) + mattr_reader(*syms) + mattr_writer(*syms) + end +end +class Module + def delegate(*methods) + options = methods.pop + unless options.is_a?(Hash) && to = options[:to] + raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key" + end + + methods.each do |method| + module_eval(<<-EOS, "(__DELEGATION__)", 1) + def #{method}(*args, &block) + #{to}.__send__(#{method.inspect}, *args, &block) + end + EOS + end + end +endclass Module + def included_in_classes + classes = [] + ObjectSpace.each_object(Class) { |k| classes << k if k.included_modules.include?(self) } + + classes.reverse.inject([]) do |unique_classes, klass| + unique_classes << klass unless unique_classes.collect { |k| k.to_s }.include?(klass.to_s) + unique_classes + end + end +endclass Module + # Return the module which contains this one; if this is a root module, such as + # +::MyModule+, then Object is returned. + def parent + parent_name = name.split('::')[0..-2] * '::' + parent_name.empty? ? Object : parent_name.constantize + end + + # Return all the parents of this module, ordered from nested outwards. The + # receiver is not contained within the result. + def parents + parents = [] + parts = name.split('::')[0..-2] + until parts.empty? + parents << (parts * '::').constantize + parts.pop + end + parents << Object unless parents.include? Object + parents + end +end +class Module + def as_load_path + if self == Object || self == Kernel + '' + elsif is_a? Class + parent == self ? '' : parent.as_load_path + else + name.split('::').collect do |word| + word.underscore + end * '/' + end + end +endrequire File.dirname(__FILE__) + '/module/inclusion' +require File.dirname(__FILE__) + '/module/attribute_accessors' +require File.dirname(__FILE__) + '/module/delegation' +require File.dirname(__FILE__) + '/module/introspection' +require File.dirname(__FILE__) + '/module/loading' +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Numeric #:nodoc: + # Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes + module Bytes + def bytes + self + end + alias :byte :bytes + + def kilobytes + self * 1024 + end + alias :kilobyte :kilobytes + + def megabytes + self * 1024.kilobytes + end + alias :megabyte :megabytes + + def gigabytes + self * 1024.megabytes + end + alias :gigabyte :gigabytes + + def terabytes + self * 1024.gigabytes + end + alias :terabyte :terabytes + + def petabytes + self * 1024.terabytes + end + alias :petabyte :petabytes + + def exabytes + self * 1024.petabytes + end + alias :exabyte :exabytes + + end + end + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Numeric #:nodoc: + # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years. + # + # If you need precise date calculations that doesn't just treat months as 30 days, then have + # a look at Time#advance. + # + # Some of these methods are approximations, Ruby's core + # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and + # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision + # date and time arithmetic + module Time + def seconds + self + end + alias :second :seconds + + def minutes + self * 60 + end + alias :minute :minutes + + def hours + self * 60.minutes + end + alias :hour :hours + + def days + self * 24.hours + end + alias :day :days + + def weeks + self * 7.days + end + alias :week :weeks + + def fortnights + self * 2.weeks + end + alias :fortnight :fortnights + + def months + self * 30.days + end + alias :month :months + + def years + (self * 365.25.days).to_i + end + alias :year :years + + # Reads best without arguments: 10.minutes.ago + def ago(time = ::Time.now) + time - self + end + + # Reads best with argument: 10.minutes.until(time) + alias :until :ago + + # Reads best with argument: 10.minutes.since(time) + def since(time = ::Time.now) + time + self + end + + # Reads best without arguments: 10.minutes.from_now + alias :from_now :since + end + end + end +end +require File.dirname(__FILE__) + '/numeric/time' +require File.dirname(__FILE__) + '/numeric/bytes' + +class Numeric #:nodoc: + include ActiveSupport::CoreExtensions::Numeric::Time + include ActiveSupport::CoreExtensions::Numeric::Bytes +end +class Object #:nodoc: + def remove_subclasses_of(*superclasses) + Class.remove_class(*subclasses_of(*superclasses)) + end + + def subclasses_of(*superclasses) + subclasses = [] + ObjectSpace.each_object(Class) do |k| + next if # Exclude this class if + (k.ancestors & superclasses).empty? || # It's not a subclass of our supers + superclasses.include?(k) || # It *is* one of the supers + eval("! defined?(::#{k})") || # It's not defined. + eval("::#{k}").object_id != k.object_id + subclasses << k + end + subclasses + end + + def extended_by + ancestors = class << self; ancestors end + ancestors.select { |mod| mod.class == Module } - [ Object, Kernel ] + end + + def copy_instance_variables_from(object, exclude = []) + exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables + + instance_variables = object.instance_variables - exclude.map { |name| name.to_s } + instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) } + end + + def extend_with_included_modules_from(object) + object.extended_by.each { |mod| extend mod } + end + + def instance_values + instance_variables.inject({}) do |values, name| + values[name[1..-1]] = instance_variable_get(name) + values + end + end + + unless defined? instance_exec # 1.9 + def instance_exec(*arguments, &block) + block.bind(self)[*arguments] + end + end +end +class Object #:nodoc: + # A Ruby-ized realization of the K combinator, courtesy of Mikael Brockman. + # + # def foo + # returning values = [] do + # values << 'bar' + # values << 'baz' + # end + # end + # + # foo # => ['bar', 'baz'] + # + # def foo + # returning [] do |values| + # values << 'bar' + # values << 'baz' + # end + # end + # + # foo # => ['bar', 'baz'] + # + def returning(value) + yield(value) + value + end + + def with_options(options) + yield ActiveSupport::OptionMerger.new(self, options) + end + + def to_json + ActiveSupport::JSON.encode(self) + end +endrequire File.dirname(__FILE__) + '/object/extending' +require File.dirname(__FILE__) + '/object/misc'module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Pathname #:nodoc: + module CleanWithin + # Clean the paths contained in the provided string. + def clean_within(string) + string.gsub(%r{[\w. ]+(/[\w. ]+)+(\.rb)?(\b|$)}) do |path| + new(path).cleanpath + end + end + end + end + end +end +require 'pathname' +require File.dirname(__FILE__) + '/pathname/clean_within' + +class Pathname#:nodoc: + extend ActiveSupport::CoreExtensions::Pathname::CleanWithin +end + +class Proc #:nodoc: + def bind(object) + block, time = self, Time.now + (class << object; self end).class_eval do + method_name = "__bind_#{time.to_i}_#{time.usec}" + define_method(method_name, &block) + method = instance_method(method_name) + remove_method(method_name) + method + end.bind(object) + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Range #:nodoc: + # Getting dates in different convenient string representations and other objects + module Conversions + DATE_FORMATS = { + :db => Proc.new { |start, stop| "BETWEEN '#{start.to_s(:db)}' AND '#{stop.to_s(:db)}'" } + } + + def self.included(klass) #:nodoc: + klass.send(:alias_method, :to_default_s, :to_s) + klass.send(:alias_method, :to_s, :to_formatted_s) + end + + def to_formatted_s(format = :default) + DATE_FORMATS[format] ? DATE_FORMATS[format].call(first, last) : to_default_s + end + end + end + end +endrequire File.dirname(__FILE__) + '/range/conversions' + +class Range #:nodoc: + include ActiveSupport::CoreExtensions::Range::Conversions +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module String #:nodoc: + # Makes it easier to access parts of a string, such as specific characters and substrings. + module Access + # Returns the character at the +position+ treating the string as an array (where 0 is the first character). + # + # Examples: + # "hello".at(0) # => "h" + # "hello".at(4) # => "o" + # "hello".at(10) # => nil + def at(position) + self[position, 1] + end + + # Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character). + # + # Examples: + # "hello".from(0) # => "hello" + # "hello".from(2) # => "llo" + # "hello".from(10) # => nil + def from(position) + self[position..-1] + end + + # Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character). + # + # Examples: + # "hello".to(0) # => "h" + # "hello".to(2) # => "hel" + # "hello".to(10) # => "hello" + def to(position) + self[0..position] + end + + # Returns the first character of the string or the first +limit+ characters. + # + # Examples: + # "hello".first # => "h" + # "hello".first(2) # => "he" + # "hello".first(10) # => "hello" + def first(limit = 1) + self[0..(limit - 1)] + end + + # Returns the last character of the string or the last +limit+ characters. + # + # Examples: + # "hello".last # => "o" + # "hello".last(2) # => "lo" + # "hello".last(10) # => "hello" + def last(limit = 1) + self[(-limit)..-1] || self + end + end + end + end +end +require 'parsedate' + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module String #:nodoc: + # Converting strings to other objects + module Conversions + # Form can be either :utc (default) or :local. + def to_time(form = :utc) + ::Time.send(form, *ParseDate.parsedate(self)) + end + + def to_date + ::Date.new(*ParseDate.parsedate(self)[0..2]) + end + end + end + end +endrequire File.dirname(__FILE__) + '/../../inflector' unless defined? Inflector +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module String #:nodoc: + # Makes it possible to do "posts".singularize that returns "post" and "MegaCoolClass".underscore that returns "mega_cool_class". + module Inflections + def pluralize + Inflector.pluralize(self) + end + + def singularize + Inflector.singularize(self) + end + + def camelize(first_letter = :upper) + case first_letter + when :upper then Inflector.camelize(self, true) + when :lower then Inflector.camelize(self, false) + end + end + alias_method :camelcase, :camelize + + def titleize + Inflector.titleize(self) + end + alias_method :titlecase, :titleize + + def underscore + Inflector.underscore(self) + end + + def dasherize + Inflector.dasherize(self) + end + + def demodulize + Inflector.demodulize(self) + end + + def tableize + Inflector.tableize(self) + end + + def classify + Inflector.classify(self) + end + + # Capitalizes the first word and turns underscores into spaces and strips _id, so "employee_salary" becomes "Employee salary" + # and "author_id" becomes "Author". + def humanize + Inflector.humanize(self) + end + + def foreign_key(separate_class_name_and_id_with_underscore = true) + Inflector.foreign_key(self, separate_class_name_and_id_with_underscore) + end + + def constantize + Inflector.constantize(self) + end + end + end + end +end +require 'strscan' + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module String #:nodoc: + # Custom string iterators + module Iterators + # Yields a single-character string for each character in the string. + # When $KCODE = 'UTF8', multi-byte characters are yielded appropriately. + def each_char + scanner, char = StringScanner.new(self), /./mu + loop { yield(scanner.scan(char) || break) } + end + end + end + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module String #:nodoc: + # Additional string tests. + module StartsEndsWith + # Does the string start with the specified +prefix+? + def starts_with?(prefix) + prefix = prefix.to_s + self[0, prefix.length] == prefix + end + + # Does the string end with the specified +suffix+? + def ends_with?(suffix) + suffix = suffix.to_s + self[-suffix.length, suffix.length] == suffix + end + end + end + end +end +require File.dirname(__FILE__) + '/string/inflections' +require File.dirname(__FILE__) + '/string/conversions' +require File.dirname(__FILE__) + '/string/access' +require File.dirname(__FILE__) + '/string/starts_ends_with' +require File.dirname(__FILE__) + '/string/iterators' + +class String #:nodoc: + include ActiveSupport::CoreExtensions::String::Access + include ActiveSupport::CoreExtensions::String::Conversions + include ActiveSupport::CoreExtensions::String::Inflections + include ActiveSupport::CoreExtensions::String::StartsEndsWith + include ActiveSupport::CoreExtensions::String::Iterators +end +class Symbol + # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples: + # + # # The same as people.collect { |p| p.name } + # people.collect(&:name) + # + # # The same as people.select { |p| p.manager? }.collect { |p| p.salary } + # people.select(&:manager?).collect(&:salary) + def to_proc + Proc.new { |obj, *args| obj.send(self, *args) } + end +end +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Time #:nodoc: + # Enables the use of time calculations within Time itself + module Calculations + def self.append_features(base) #:nodoc: + super + base.extend(ClassMethods) + end + + module ClassMethods + # Return the number of days in the given month. If a year is given, + # February will return the correct number of days for leap years. + # Otherwise, this method will always report February as having 28 + # days. + def days_in_month(month, year=nil) + if month == 2 + !year.nil? && (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)) ? 29 : 28 + elsif month <= 7 + month % 2 == 0 ? 30 : 31 + else + month % 2 == 0 ? 31 : 30 + end + end + end + + # Seconds since midnight: Time.now.seconds_since_midnight + def seconds_since_midnight + self.hour.hours + self.min.minutes + self.sec + (self.usec/1.0e+6) + end + + # Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options + # (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and + # minute is passed, then sec and usec is set to 0. + def change(options) + ::Time.send( + self.utc? ? :utc : :local, + options[:year] || self.year, + options[:month] || self.month, + options[:mday] || self.mday, + options[:hour] || self.hour, + options[:min] || (options[:hour] ? 0 : self.min), + options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec), + options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec) + ) + end + + # Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with + # any of these keys: :months, :days, :years. + def advance(options) + d = ::Date.new(year + (options.delete(:years) || 0), month, day) + d = d >> options.delete(:months) if options[:months] + d = d + options.delete(:days) if options[:days] + change(options.merge(:year => d.year, :month => d.month, :mday => d.day)) + end + + # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension + # Do not use this method in combination with x.months, use months_ago instead! + def ago(seconds) + seconds.until(self) + end + + # Returns a new Time representing the time a number of seconds since the instance time, this is basically a wrapper around + #the Numeric extension. Do not use this method in combination with x.months, use months_since instead! + def since(seconds) + seconds.since(self) + end + alias :in :since + + # Returns a new Time representing the time a number of specified months ago + def months_ago(months) + months_since(-months) + end + + def months_since(months) + year, month, mday = self.year, self.month, self.mday + + month += months + + # in case months is negative + while month < 1 + month += 12 + year -= 1 + end + + # in case months is positive + while month > 12 + month -= 12 + year += 1 + end + + max = ::Time.days_in_month(month, year) + mday = max if mday > max + + change(:year => year, :month => month, :mday => mday) + end + + # Returns a new Time representing the time a number of specified years ago + def years_ago(years) + change(:year => self.year - years) + end + + def years_since(years) + change(:year => self.year + years) + end + + # Short-hand for years_ago(1) + def last_year + years_ago(1) + end + + # Short-hand for years_since(1) + def next_year + years_since(1) + end + + + # Short-hand for months_ago(1) + def last_month + months_ago(1) + end + + # Short-hand for months_since(1) + def next_month + months_since(1) + end + + # Returns a new Time representing the "start" of this week (Monday, 0:00) + def beginning_of_week + days_to_monday = self.wday!=0 ? self.wday-1 : 6 + (self - days_to_monday.days).midnight + end + alias :monday :beginning_of_week + alias :at_beginning_of_week :beginning_of_week + + # Returns a new Time representing the start of the given day in next week (default is Monday). + def next_week(day = :monday) + days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6} + since(1.week).beginning_of_week.since(days_into_week[day].day).change(:hour => 0) + end + + # Returns a new Time representing the start of the day (0:00) + def beginning_of_day + (self - self.seconds_since_midnight).change(:usec => 0) + end + alias :midnight :beginning_of_day + alias :at_midnight :beginning_of_day + alias :at_beginning_of_day :beginning_of_day + + # Returns a new Time representing the start of the month (1st of the month, 0:00) + def beginning_of_month + #self - ((self.mday-1).days + self.seconds_since_midnight) + change(:mday => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0) + end + alias :at_beginning_of_month :beginning_of_month + + # Returns a new Time representing the end of the month (last day of the month, 0:00) + def end_of_month + #self - ((self.mday-1).days + self.seconds_since_midnight) + last_day = ::Time.days_in_month( self.month, self.year ) + change(:mday => last_day,:hour => 0, :min => 0, :sec => 0, :usec => 0) + end + alias :at_end_of_month :end_of_month + + # Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00) + def beginning_of_quarter + beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month }) + end + alias :at_beginning_of_quarter :beginning_of_quarter + + # Returns a new Time representing the start of the year (1st of january, 0:00) + def beginning_of_year + change(:month => 1,:mday => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0) + end + alias :at_beginning_of_year :beginning_of_year + + # Convenience method which returns a new Time representing the time 1 day ago + def yesterday + self.ago(1.day) + end + + # Convenience method which returns a new Time representing the time 1 day since the instance time + def tomorrow + self.since(1.day) + end + end + end + end +end +require 'date' +require 'time' + +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Time #:nodoc: + # Getting times in different convenient string representations and other objects + module Conversions + DATE_FORMATS = { + :db => "%Y-%m-%d %H:%M:%S", + :short => "%d %b %H:%M", + :long => "%B %d, %Y %H:%M", + :rfc822 => "%a, %d %b %Y %H:%M:%S %z" + } + + def self.append_features(klass) + super + klass.send(:alias_method, :to_default_s, :to_s) + klass.send(:alias_method, :to_s, :to_formatted_s) + end + + def to_formatted_s(format = :default) + DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s + end + + def to_date + ::Date.new(year, month, day) + end + + # To be able to keep Dates and Times interchangeable on conversions + def to_time + self + end + end + end + end +end +require File.dirname(__FILE__) + '/time/calculations' +require File.dirname(__FILE__) + '/time/conversions' + +class Time#:nodoc: + include ActiveSupport::CoreExtensions::Time::Calculations + include ActiveSupport::CoreExtensions::Time::Conversions +end +Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) } +require 'set' +require File.dirname(__FILE__) + '/core_ext/module/attribute_accessors' +require File.dirname(__FILE__) + '/core_ext/load_error' +require File.dirname(__FILE__) + '/core_ext/kernel' + +module Dependencies #:nodoc: + extend self + + # Should we turn on Ruby warnings on the first load of dependent files? + mattr_accessor :warnings_on_first_load + self.warnings_on_first_load = false + + # All files ever loaded. + mattr_accessor :history + self.history = Set.new + + # All files currently loaded. + mattr_accessor :loaded + self.loaded = Set.new + + # Should we load files or require them? + mattr_accessor :mechanism + self.mechanism = :load + + def load? + mechanism == :load + end + + def depend_on(file_name, swallow_load_errors = false) + require_or_load(file_name) + rescue LoadError + raise unless swallow_load_errors + end + + def associate_with(file_name) + depend_on(file_name, true) + end + + def clear + loaded.clear + end + + def require_or_load(file_name) + file_name = $1 if file_name =~ /^(.*)\.rb$/ + return if loaded.include?(file_name) + + # Record that we've seen this file *before* loading it to avoid an + # infinite loop with mutual dependencies. + loaded << file_name + + if load? + begin + # Enable warnings iff this file has not been loaded before and + # warnings_on_first_load is set. + if !warnings_on_first_load or history.include?(file_name) + load "#{file_name}.rb" + else + enable_warnings { load "#{file_name}.rb" } + end + rescue + loaded.delete file_name + raise + end + else + require file_name + end + + # Record history *after* loading so first load gets warnings. + history << file_name + end + + class LoadingModule + # Old style environment.rb referenced this method directly. Please note, it doesn't + # actualy *do* anything any more. + def self.root(*args) + if defined?(RAILS_DEFAULT_LOGGER) + RAILS_DEFAULT_LOGGER.warn "Your environment.rb uses the old syntax, it may not continue to work in future releases." + RAILS_DEFAULT_LOGGER.warn "For upgrade instructions please see: http://manuals.rubyonrails.com/read/book/19" + end + end + end +end + +Object.send(:define_method, :require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load) +Object.send(:define_method, :require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency) +Object.send(:define_method, :require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association) + +class Module #:nodoc: + # Rename the original handler so we can chain it to the new one + alias :rails_original_const_missing :const_missing + + # Use const_missing to autoload associations so we don't have to + # require_association when using single-table inheritance. + def const_missing(class_id) + file_name = class_id.to_s.demodulize.underscore + file_path = as_load_path.empty? ? file_name : "#{as_load_path}/#{file_name}" + begin + require_dependency(file_path) + brief_name = self == Object ? '' : "#{name}::" + raise NameError.new("uninitialized constant #{brief_name}#{class_id}") unless const_defined?(class_id) + return const_get(class_id) + rescue MissingSourceFile => e + # Re-raise the error if it does not concern the file we were trying to load. + raise unless e.is_missing? file_path + + # Look for a directory in the load path that we ought to load. + if $LOAD_PATH.any? { |base| File.directory? "#{base}/#{file_path}" } + mod = Module.new + const_set class_id, mod # Create the new module + return mod + end + + # Attempt to access the name from the parent, unless we don't have a valid + # parent, or the constant is already defined in the parent. If the latter + # is the case, then we are being queried via self::class_id, and we should + # avoid returning the constant from the parent if possible. + if parent && parent != self && ! parents.any? { |p| p.const_defined?(class_id) } + suppress(NameError) do + return parent.send(:const_missing, class_id) + end + end + + raise NameError.new("uninitialized constant #{class_id}").copy_blame!(e) + end + end +end + +class Class + def const_missing(class_id) + if [Object, Kernel].include?(self) || parent == self + super + else + parent.send :const_missing, class_id + end + end +end + +class Object #:nodoc: + def load(file, *extras) + super(file, *extras) + rescue Object => exception + exception.blame_file! file + raise + end + + def require(file, *extras) + super(file, *extras) + rescue Object => exception + exception.blame_file! file + raise + end +end + +# Add file-blaming to exceptions +class Exception #:nodoc: + def blame_file!(file) + (@blamed_files ||= []).unshift file + end + + def blamed_files + @blamed_files ||= [] + end + + def describe_blame + return nil if blamed_files.empty? + "This error occured while loading the following files:\n #{blamed_files.join "\n "}" + end + + def copy_blame!(exc) + @blamed_files = exc.blamed_files.clone + self + end +endInflector.inflections do |inflect| + inflect.plural(/$/, 's') + inflect.plural(/s$/i, 's') + inflect.plural(/(ax|test)is$/i, '\1es') + inflect.plural(/(octop|vir)us$/i, '\1i') + inflect.plural(/(alias|status)$/i, '\1es') + inflect.plural(/(bu)s$/i, '\1ses') + inflect.plural(/(buffal|tomat)o$/i, '\1oes') + inflect.plural(/([ti])um$/i, '\1a') + inflect.plural(/sis$/i, 'ses') + inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves') + inflect.plural(/(hive)$/i, '\1s') + inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies') + inflect.plural(/([^aeiouy]|qu)ies$/i, '\1y') + inflect.plural(/(x|ch|ss|sh)$/i, '\1es') + inflect.plural(/(matr|vert|ind)ix|ex$/i, '\1ices') + inflect.plural(/([m|l])ouse$/i, '\1ice') + inflect.plural(/^(ox)$/i, '\1en') + inflect.plural(/(quiz)$/i, '\1zes') + + inflect.singular(/s$/i, '') + inflect.singular(/(n)ews$/i, '\1ews') + inflect.singular(/([ti])a$/i, '\1um') + inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis') + inflect.singular(/(^analy)ses$/i, '\1sis') + inflect.singular(/([^f])ves$/i, '\1fe') + inflect.singular(/(hive)s$/i, '\1') + inflect.singular(/(tive)s$/i, '\1') + inflect.singular(/([lr])ves$/i, '\1f') + inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y') + inflect.singular(/(s)eries$/i, '\1eries') + inflect.singular(/(m)ovies$/i, '\1ovie') + inflect.singular(/(x|ch|ss|sh)es$/i, '\1') + inflect.singular(/([m|l])ice$/i, '\1ouse') + inflect.singular(/(bus)es$/i, '\1') + inflect.singular(/(o)es$/i, '\1') + inflect.singular(/(shoe)s$/i, '\1') + inflect.singular(/(cris|ax|test)es$/i, '\1is') + inflect.singular(/([octop|vir])i$/i, '\1us') + inflect.singular(/(alias|status)es$/i, '\1') + inflect.singular(/^(ox)en/i, '\1') + inflect.singular(/(vert|ind)ices$/i, '\1ex') + inflect.singular(/(matr)ices$/i, '\1ix') + inflect.singular(/(quiz)zes$/i, '\1') + + inflect.irregular('person', 'people') + inflect.irregular('man', 'men') + inflect.irregular('child', 'children') + inflect.irregular('sex', 'sexes') + inflect.irregular('move', 'moves') + + inflect.uncountable(%w(equipment information rice money species series fish sheep)) +end +require 'singleton' + +# The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without, +# and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept +# in inflections.rb. +module Inflector + # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional + # inflection rules. Examples: + # + # Inflector.inflections do |inflect| + # inflect.plural /^(ox)$/i, '\1\2en' + # inflect.singular /^(ox)en/i, '\1' + # + # inflect.irregular 'octopus', 'octopi' + # + # inflect.uncountable "equipment" + # end + # + # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the + # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may + # already have been loaded. + class Inflections + include Singleton + + attr_reader :plurals, :singulars, :uncountables + + def initialize + @plurals, @singulars, @uncountables = [], [], [] + end + + # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. + # The replacement should always be a string that may include references to the matched data from the rule. + def plural(rule, replacement) + @plurals.insert(0, [rule, replacement]) + end + + # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. + # The replacement should always be a string that may include references to the matched data from the rule. + def singular(rule, replacement) + @singulars.insert(0, [rule, replacement]) + end + + # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used + # for strings, not regular expressions. You simply pass the irregular in singular and plural form. + # + # Examples: + # irregular 'octopus', 'octopi' + # irregular 'person', 'people' + def irregular(singular, plural) + plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1]) + singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1]) + end + + # Add uncountable words that shouldn't be attempted inflected. + # + # Examples: + # uncountable "money" + # uncountable "money", "information" + # uncountable %w( money information rice ) + def uncountable(*words) + (@uncountables << words).flatten! + end + + # Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type, + # the options are: :plurals, :singulars, :uncountables + # + # Examples: + # clear :all + # clear :plurals + def clear(scope = :all) + case scope + when :all + @plurals, @singulars, @uncountables = [], [], [] + else + instance_variable_set "@#{scope}", [] + end + end + end + + extend self + + def inflections + if block_given? + yield Inflections.instance + else + Inflections.instance + end + end + + def pluralize(word) + result = word.to_s.dup + + if inflections.uncountables.include?(result.downcase) + result + else + inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } + result + end + end + + def singularize(word) + result = word.to_s.dup + + if inflections.uncountables.include?(result.downcase) + result + else + inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) } + result + end + end + + def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) + if first_letter_in_uppercase + lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase } + else + lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1] + end + end + + def titleize(word) + humanize(underscore(word)).gsub(/\b([a-z])/) { $1.capitalize } + end + + def underscore(camel_cased_word) + camel_cased_word.to_s.gsub(/::/, '/'). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + downcase + end + + def dasherize(underscored_word) + underscored_word.gsub(/_/, '-') + end + + def humanize(lower_case_and_underscored_word) + lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize + end + + def demodulize(class_name_in_module) + class_name_in_module.to_s.gsub(/^.*::/, '') + end + + def tableize(class_name) + pluralize(underscore(class_name)) + end + + def classify(table_name) + camelize(singularize(table_name)) + end + + def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) + underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") + end + + def constantize(camel_cased_word) + raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!" unless + /^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ camel_cased_word + + camel_cased_word = "::#{camel_cased_word}" unless $1 + Object.module_eval(camel_cased_word, __FILE__, __LINE__) + end + + def ordinalize(number) + if (11..13).include?(number.to_i % 100) + "#{number}th" + else + case number.to_i % 10 + when 1: "#{number}st" + when 2: "#{number}nd" + when 3: "#{number}rd" + else "#{number}th" + end + end + end +end + +require File.dirname(__FILE__) + '/inflections' +module ActiveSupport + module JSON #:nodoc: + module Encoders #:nodoc: + define_encoder Object do |object| + object.instance_values.to_json + end + + define_encoder TrueClass do + 'true' + end + + define_encoder FalseClass do + 'false' + end + + define_encoder NilClass do + 'null' + end + + define_encoder String do |string| + returning value = '"' do + string.each_char do |char| + value << case + when char == "\010": '\b' + when char == "\f": '\f' + when char == "\n": '\n' + when char == "\r": '\r' + when char == "\t": '\t' + when char == '"': '\"' + when char == '\\': '\\\\' + when char.length > 1: "\\u#{'%04x' % char.unpack('U').first}" + else; char + end + end + value << '"' + end + end + + define_encoder Numeric do |numeric| + numeric.to_s + end + + define_encoder Symbol do |symbol| + symbol.to_s.to_json + end + + define_encoder Enumerable do |enumerable| + "[#{enumerable.map { |value| value.to_json } * ', '}]" + end + + define_encoder Hash do |hash| + returning result = '{' do + result << hash.map do |pair| + pair.map { |value| value.to_json } * ': ' + end * ', ' + result << '}' + end + end + + define_encoder Regexp do |regexp| + regexp.inspect + end + end + end +end +module ActiveSupport + module JSON #:nodoc: + module Encoders + mattr_accessor :encoders + @@encoders = {} + + class << self + def define_encoder(klass, &block) + encoders[klass] = block + end + + def [](klass) + klass.ancestors.each do |k| + encoder = encoders[k] + return encoder if encoder + end + end + end + end + end +end + +Dir[File.dirname(__FILE__) + '/encoders/*.rb'].each do |file| + require file[0..-4] +end +require 'active_support/json/encoders' + +module ActiveSupport + module JSON #:nodoc: + class CircularReferenceError < StandardError #:nodoc: + end + # returns the literal string as its JSON encoded form. Useful for passing javascript variables into functions. + # + # page.call 'Element.show', ActiveSupport::JSON::Variable.new("$$(#items li)") + class Variable < String #:nodoc: + def to_json + self + end + end + + class << self + REFERENCE_STACK_VARIABLE = :json_reference_stack + + def encode(value) + raise_on_circular_reference(value) do + Encoders[value.class].call(value) + end + end + + protected + def raise_on_circular_reference(value) + stack = Thread.current[REFERENCE_STACK_VARIABLE] ||= [] + raise CircularReferenceError, 'object references itself' if + stack.include? value + stack << value + yield + ensure + stack.pop + end + end + end +end +module ActiveSupport + class OptionMerger #:nodoc: + instance_methods.each do |method| + undef_method(method) if method !~ /^(__|instance_eval)/ + end + + def initialize(context, options) + @context, @options = context, options + end + + private + def method_missing(method, *arguments, &block) + merge_argument_options! arguments + @context.send(method, *arguments, &block) + end + + def merge_argument_options!(arguments) + arguments << if arguments.last.respond_to? :merge! + arguments.pop.dup.merge!(@options) + else + @options.dup + end + end + end +end +class OrderedHash < Array #:nodoc: + def []=(key, value) + if pair = find_pair(key) + pair.pop + pair << value + else + self << [key, value] + end + end + + def [](key) + pair = find_pair(key) + pair ? pair.last : nil + end + + def keys + self.collect { |i| i.first } + end + + private + def find_pair(key) + self.each { |i| return i if i.first == key } + return false + end +end + +class OrderedOptions < OrderedHash #:nodoc: + def []=(key, value) + super(key.to_sym, value) + end + + def [](key) + super(key.to_sym) + end + + def method_missing(name, *args) + if name.to_s =~ /(.*)=$/ + self[$1.to_sym] = args.first + else + self[name] + end + end +end# Classes that include this module will automatically be reloaded +# by the Rails dispatcher when Dependencies.mechanism = :load. +module Reloadable + class << self + def included(base) #nodoc: + raise TypeError, "Only Classes can be Reloadable!" unless base.is_a? Class + + unless base.respond_to?(:reloadable?) + class << base + define_method(:reloadable?) { true } + end + end + end + + def reloadable_classes + included_in_classes.select { |klass| klass.reloadable? } + end + end + + # Captures the common pattern where a base class should not be reloaded, + # but its subclasses should be. + module Subclasses + def self.included(base) #nodoc: + base.send :include, Reloadable + (class << base; self; end).send(:define_method, :reloadable?) do + base != self + end + end + end +end# A value object representing a time zone. A time zone is simply a named +# offset (in seconds) from GMT. Note that two time zone objects are only +# equivalent if they have both the same offset, and the same name. +# +# A TimeZone instance may be used to convert a Time value to the corresponding +# time zone. +# +# The class also includes #all, which returns a list of all TimeZone objects. +class TimeZone + include Comparable + + attr_reader :name, :utc_offset + + # Create a new TimeZone object with the given name and offset. The offset is + # the number of seconds that this time zone is offset from UTC (GMT). Seconds + # were chosen as the offset unit because that is the unit that Ruby uses + # to represent time zone offsets (see Time#utc_offset). + def initialize(name, utc_offset) + @name = name + @utc_offset = utc_offset + end + + # Returns the offset of this time zone as a formatted string, of the + # format "+HH:MM". If the offset is zero, this returns the empty + # string. If +colon+ is false, a colon will not be inserted into the + # result. + def formatted_offset( colon=true ) + return "" if utc_offset == 0 + sign = (utc_offset < 0 ? -1 : 1) + hours = utc_offset.abs / 3600 + minutes = (utc_offset.abs % 3600) / 60 + "%+03d%s%02d" % [ hours * sign, colon ? ":" : "", minutes ] + end + + # Compute and return the current time, in the time zone represented by + # +self+. + def now + adjust(Time.now) + end + + # Return the current date in this time zone. + def today + now.to_date + end + + # Adjust the given time to the time zone represented by +self+. + def adjust(time) + time = time.to_time + time + utc_offset - time.utc_offset + end + + # Reinterprets the given time value as a time in the current time + # zone, and then adjusts it to return the corresponding time in the + # local time zone. + def unadjust(time) + time = Time.local(*time.to_time.to_a) + time - utc_offset + time.utc_offset + end + + # Compare this time zone to the parameter. The two are comapred first on + # their offsets, and then by name. + def <=>(zone) + result = (utc_offset <=> zone.utc_offset) + result = (name <=> zone.name) if result == 0 + result + end + + # Returns a textual representation of this time zone. + def to_s + "(GMT#{formatted_offset}) #{name}" + end + + @@zones = nil + + class << self + # Create a new TimeZone instance with the given name and offset. + def create(name, offset) + zone = allocate + zone.send :initialize, name, offset + zone + end + + # Return a TimeZone instance with the given name, or +nil+ if no + # such TimeZone instance exists. (This exists to support the use of + # this class with the #composed_of macro.) + def new(name) + self[name] + end + + # Return an array of all TimeZone objects. There are multiple TimeZone + # objects per time zone, in many cases, to make it easier for users to + # find their own time zone. + def all + unless @@zones + @@zones = [] + [[-43_200, "International Date Line West" ], + [-39_600, "Midway Island", "Samoa" ], + [-36_000, "Hawaii" ], + [-32_400, "Alaska" ], + [-28_800, "Pacific Time (US & Canada)", "Tijuana" ], + [-25_200, "Mountain Time (US & Canada)", "Chihuahua", "La Paz", + "Mazatlan", "Arizona" ], + [-21_600, "Central Time (US & Canada)", "Saskatchewan", "Guadalajara", + "Mexico City", "Monterrey", "Central America" ], + [-18_000, "Eastern Time (US & Canada)", "Indiana (East)", "Bogota", + "Lima", "Quito" ], + [-14_400, "Atlantic Time (Canada)", "Caracas", "La Paz", "Santiago" ], + [-12_600, "Newfoundland" ], + [-10_800, "Brasilia", "Buenos Aires", "Georgetown", "Greenland" ], + [ -7_200, "Mid-Atlantic" ], + [ -3_600, "Azores", "Cape Verde Is." ], + [ 0, "Dublin", "Edinburgh", "Lisbon", "London", "Casablanca", + "Monrovia" ], + [ 3_600, "Belgrade", "Bratislava", "Budapest", "Ljubljana", "Prague", + "Sarajevo", "Skopje", "Warsaw", "Zagreb", "Brussels", + "Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin", + "Bern", "Rome", "Stockholm", "Vienna", + "West Central Africa" ], + [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyev", "Riga", "Sofia", + "Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk", + "Jerusalem", "Harare", "Pretoria" ], + [ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh", + "Nairobi", "Baghdad" ], + [ 12_600, "Tehran" ], + [ 14_400, "Abu Dhabi", "Muscat", "Baku", "Tbilisi", "Yerevan" ], + [ 16_200, "Kabul" ], + [ 18_000, "Ekaterinburg", "Islamabad", "Karachi", "Tashkent" ], + [ 19_800, "Chennai", "Kolkata", "Mumbai", "New Delhi" ], + [ 20_700, "Kathmandu" ], + [ 21_600, "Astana", "Dhaka", "Sri Jayawardenepura", "Almaty", + "Novosibirsk" ], + [ 23_400, "Rangoon" ], + [ 25_200, "Bangkok", "Hanoi", "Jakarta", "Krasnoyarsk" ], + [ 28_800, "Beijing", "Chongqing", "Hong Kong", "Urumqi", + "Kuala Lumpur", "Singapore", "Taipei", "Perth", "Irkutsk", + "Ulaan Bataar" ], + [ 32_400, "Seoul", "Osaka", "Sapporo", "Tokyo", "Yakutsk" ], + [ 34_200, "Darwin", "Adelaide" ], + [ 36_000, "Canberra", "Melbourne", "Sydney", "Brisbane", "Hobart", + "Vladivostok", "Guam", "Port Moresby" ], + [ 39_600, "Magadan", "Solomon Is.", "New Caledonia" ], + [ 43_200, "Fiji", "Kamchatka", "Marshall Is.", "Auckland", + "Wellington" ], + [ 46_800, "Nuku'alofa" ]]. + each do |offset, *places| + places.each { |place| @@zones << create(place, offset).freeze } + end + @@zones.sort! + end + @@zones + end + + # Locate a specific time zone object. If the argument is a string, it + # is interpreted to mean the name of the timezone to locate. If it is a + # numeric value it is either the hour offset, or the second offset, of the + # timezone to find. (The first one with that offset will be returned.) + # Returns +nil+ if no such time zone is known to the system. + def [](arg) + case arg + when String + all.find { |z| z.name == arg } + when Numeric + arg *= 3600 if arg.abs <= 13 + all.find { |z| z.utc_offset == arg.to_i } + else + raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}" + end + end + + # A regular expression that matches the names of all time zones in + # the USA. + US_ZONES = /US|Arizona|Indiana|Hawaii|Alaska/ + + # A convenience method for returning a collection of TimeZone objects + # for time zones in the USA. + def us_zones + all.find_all { |z| z.name =~ US_ZONES } + end + end +end +#!/usr/bin/env ruby +#-- +# Copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +module Builder #:nodoc: + + # BlankSlate provides an abstract base class with no predefined + # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>). + # BlankSlate is useful as a base class when writing classes that + # depend upon <tt>method_missing</tt> (e.g. dynamic proxies). + class BlankSlate #:nodoc: + class << self + def hide(name) + undef_method name if + instance_methods.include?(name.to_s) and + name !~ /^(__|instance_eval)/ + end + end + + instance_methods.each { |m| hide(m) } + end +end + +# Since Ruby is very dynamic, methods added to the ancestors of +# BlankSlate <em>after BlankSlate is defined</em> will show up in the +# list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined +module Kernel #:nodoc: + class << self + alias_method :blank_slate_method_added, :method_added + def method_added(name) + blank_slate_method_added(name) + return if self != Kernel + Builder::BlankSlate.hide(name) + end + end +end + +class Object #:nodoc: + class << self + alias_method :blank_slate_method_added, :method_added + def method_added(name) + blank_slate_method_added(name) + return if self != Object + Builder::BlankSlate.hide(name) + end + end +end +#!/usr/bin/env ruby + +require 'builder/blankslate' + +module Builder #:nodoc: + + # Generic error for builder + class IllegalBlockError < RuntimeError #:nodoc: + end + + # XmlBase is a base class for building XML builders. See + # Builder::XmlMarkup and Builder::XmlEvents for examples. + class XmlBase < BlankSlate #:nodoc: + + # Create an XML markup builder. + # + # out:: Object receiving the markup.1 +out+ must respond to + # <tt><<</tt>. + # indent:: Number of spaces used for indentation (0 implies no + # indentation and no line breaks). + # initial:: Level of initial indentation. + # + def initialize(indent=0, initial=0) + @indent = indent + @level = initial + end + + # Create a tag named +sym+. Other than the first argument which + # is the tag name, the arguements are the same as the tags + # implemented via <tt>method_missing</tt>. + def tag!(sym, *args, &block) + self.__send__(sym, *args, &block) + end + + # Create XML markup based on the name of the method. This method + # is never invoked directly, but is called for each markup method + # in the markup block. + def method_missing(sym, *args, &block) + text = nil + attrs = nil + sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol) + args.each do |arg| + case arg + when Hash + attrs ||= {} + attrs.merge!(arg) + else + text ||= '' + text << arg.to_s + end + end + if block + unless text.nil? + raise ArgumentError, "XmlMarkup cannot mix a text argument with a block" + end + _capture_outer_self(block) if @self.nil? + _indent + _start_tag(sym, attrs) + _newline + _nested_structures(block) + _indent + _end_tag(sym) + _newline + elsif text.nil? + _indent + _start_tag(sym, attrs, true) + _newline + else + _indent + _start_tag(sym, attrs) + text! text + _end_tag(sym) + _newline + end + @target + end + + # Append text to the output target. Escape any markup. May be + # used within the markup brackets as: + # + # builder.p { br; text! "HI" } #=> <p><br/>HI</p> + def text!(text) + _text(_escape(text)) + end + + # Append text to the output target without escaping any markup. + # May be used within the markup brackets as: + # + # builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p> + # + # This is useful when using non-builder enabled software that + # generates strings. Just insert the string directly into the + # builder without changing the inserted markup. + # + # It is also useful for stacking builder objects. Builders only + # use <tt><<</tt> to append to the target, so by supporting this + # method/operation builders can use other builders as their + # targets. + def <<(text) + _text(text) + end + + # For some reason, nil? is sent to the XmlMarkup object. If nil? + # is not defined and method_missing is invoked, some strange kind + # of recursion happens. Since nil? won't ever be an XML tag, it + # is pretty safe to define it here. (Note: this is an example of + # cargo cult programming, + # cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming). + def nil? + false + end + + private + + def _escape(text) + text. + gsub(%r{&}, '&'). + gsub(%r{<}, '<'). + gsub(%r{>}, '>') + end + + def _capture_outer_self(block) + @self = eval("self", block) + end + + def _newline + return if @indent == 0 + text! "\n" + end + + def _indent + return if @indent == 0 || @level == 0 + text!(" " * (@level * @indent)) + end + + def _nested_structures(block) + @level += 1 + block.call(self) + ensure + @level -= 1 + end + end +end +#!/usr/bin/env ruby + +#-- +# Copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'builder/xmlmarkup' + +module Builder + + # Create a series of SAX-like XML events (e.g. start_tag, end_tag) + # from the markup code. XmlEvent objects are used in a way similar + # to XmlMarkup objects, except that a series of events are generated + # and passed to a handler rather than generating character-based + # markup. + # + # Usage: + # xe = Builder::XmlEvents.new(hander) + # xe.title("HI") # Sends start_tag/end_tag/text messages to the handler. + # + # Indentation may also be selected by providing value for the + # indentation size and initial indentation level. + # + # xe = Builder::XmlEvents.new(handler, indent_size, initial_indent_level) + # + # == XML Event Handler + # + # The handler object must expect the following events. + # + # [<tt>start_tag(tag, attrs)</tt>] + # Announces that a new tag has been found. +tag+ is the name of + # the tag and +attrs+ is a hash of attributes for the tag. + # + # [<tt>end_tag(tag)</tt>] + # Announces that an end tag for +tag+ has been found. + # + # [<tt>text(text)</tt>] + # Announces that a string of characters (+text+) has been found. + # A series of characters may be broken up into more than one + # +text+ call, so the client cannot assume that a single + # callback contains all the text data. + # + class XmlEvents < XmlMarkup #:nodoc: + def text!(text) + @target.text(text) + end + + def _start_tag(sym, attrs, end_too=false) + @target.start_tag(sym, attrs) + _end_tag(sym) if end_too + end + + def _end_tag(sym) + @target.end_tag(sym) + end + end + +end +#!/usr/bin/env ruby +#-- +# Copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +# Provide a flexible and easy to use Builder for creating XML markup. +# See XmlBuilder for usage details. + +require 'builder/xmlbase' + +module Builder + + # Create XML markup easily. All (well, almost all) methods sent to + # an XmlMarkup object will be translated to the equivalent XML + # markup. Any method with a block will be treated as an XML markup + # tag with nested markup in the block. + # + # Examples will demonstrate this easier than words. In the + # following, +xm+ is an +XmlMarkup+ object. + # + # xm.em("emphasized") # => <em>emphasized</em> + # xm.em { xmm.b("emp & bold") } # => <em><b>emph & bold</b></em> + # xm.a("A Link", "href"=>"http://onestepback.org") + # # => <a href="http://onestepback.org">A Link</a> + # xm.div { br } # => <div><br/></div> + # xm.target("name"=>"compile", "option"=>"fast") + # # => <target option="fast" name="compile"\> + # # NOTE: order of attributes is not specified. + # + # xm.instruct! # <?xml version="1.0" encoding="UTF-8"?> + # xm.html { # <html> + # xm.head { # <head> + # xm.title("History") # <title>History</title> + # } # </head> + # xm.body { # <body> + # xm.comment! "HI" # <!-- HI --> + # xm.h1("Header") # <h1>Header</h1> + # xm.p("paragraph") # <p>paragraph</p> + # } # </body> + # } # </html> + # + # == Notes: + # + # * The order that attributes are inserted in markup tags is + # undefined. + # + # * Sometimes you wish to insert text without enclosing tags. Use + # the <tt>text!</tt> method to accomplish this. + # + # Example: + # + # xm.div { # <div> + # xm.text! "line"; xm.br # line<br/> + # xm.text! "another line"; xmbr # another line<br/> + # } # </div> + # + # * The special XML characters <, >, and & are converted to <, + # > and & automatically. Use the <tt><<</tt> operation to + # insert text without modification. + # + # * Sometimes tags use special characters not allowed in ruby + # identifiers. Use the <tt>tag!</tt> method to handle these + # cases. + # + # Example: + # + # xml.tag!("SOAP:Envelope") { ... } + # + # will produce ... + # + # <SOAP:Envelope> ... </SOAP:Envelope>" + # + # <tt>tag!</tt> will also take text and attribute arguments (after + # the tag name) like normal markup methods. (But see the next + # bullet item for a better way to handle XML namespaces). + # + # * Direct support for XML namespaces is now available. If the + # first argument to a tag call is a symbol, it will be joined to + # the tag to produce a namespace:tag combination. It is easier to + # show this than describe it. + # + # xml.SOAP :Envelope do ... end + # + # Just put a space before the colon in a namespace to produce the + # right form for builder (e.g. "<tt>SOAP:Envelope</tt>" => + # "<tt>xml.SOAP :Envelope</tt>") + # + # * XmlMarkup builds the markup in any object (called a _target_) + # that accepts the <tt><<</tt> method. If no target is given, + # then XmlMarkup defaults to a string target. + # + # Examples: + # + # xm = Builder::XmlMarkup.new + # result = xm.title("yada") + # # result is a string containing the markup. + # + # buffer = "" + # xm = Builder::XmlMarkup.new(buffer) + # # The markup is appended to buffer (using <<) + # + # xm = Builder::XmlMarkup.new(STDOUT) + # # The markup is written to STDOUT (using <<) + # + # xm = Builder::XmlMarkup.new + # x2 = Builder::XmlMarkup.new(:target=>xm) + # # Markup written to +x2+ will be send to +xm+. + # + # * Indentation is enabled by providing the number of spaces to + # indent for each level as a second argument to XmlBuilder.new. + # Initial indentation may be specified using a third parameter. + # + # Example: + # + # xm = Builder.new(:ident=>2) + # # xm will produce nicely formatted and indented XML. + # + # xm = Builder.new(:indent=>2, :margin=>4) + # # xm will produce nicely formatted and indented XML with 2 + # # spaces per indent and an over all indentation level of 4. + # + # builder = Builder::XmlMarkup.new(:target=>$stdout, :indent=>2) + # builder.name { |b| b.first("Jim"); b.last("Weirich) } + # # prints: + # # <name> + # # <first>Jim</first> + # # <last>Weirich</last> + # # </name> + # + # * The instance_eval implementation which forces self to refer to + # the message receiver as self is now obsolete. We now use normal + # block calls to execute the markup block. This means that all + # markup methods must now be explicitly send to the xml builder. + # For instance, instead of + # + # xml.div { strong("text") } + # + # you need to write: + # + # xml.div { xml.strong("text") } + # + # Although more verbose, the subtle change in semantics within the + # block was found to be prone to error. To make this change a + # little less cumbersome, the markup block now gets the markup + # object sent as an argument, allowing you to use a shorter alias + # within the block. + # + # For example: + # + # xml_builder = Builder::XmlMarkup.new + # xml_builder.div { |xml| + # xml.stong("text") + # } + # + class XmlMarkup < XmlBase + + # Create an XML markup builder. Parameters are specified by an + # option hash. + # + # :target=><em>target_object</em>:: + # Object receiving the markup. +out+ must respond to the + # <tt><<</tt> operator. The default is a plain string target. + # :indent=><em>indentation</em>:: + # Number of spaces used for indentation. The default is no + # indentation and no line breaks. + # :margin=><em>initial_indentation_level</em>:: + # Amount of initial indentation (specified in levels, not + # spaces). + # + def initialize(options={}) + indent = options[:indent] || 0 + margin = options[:margin] || 0 + super(indent, margin) + @target = options[:target] || "" + end + + # Return the target of the builder. + def target! + @target + end + + def comment!(comment_text) + _ensure_no_block block_given? + _special("<!-- ", " -->", comment_text, nil) + end + + # Insert an XML declaration into the XML markup. + # + # For example: + # + # xml.declare! :ELEMENT, :blah, "yada" + # # => <!ELEMENT blah "yada"> + def declare!(inst, *args, &block) + _indent + @target << "<!#{inst}" + args.each do |arg| + case arg + when String + @target << %{ "#{arg}"} + when Symbol + @target << " #{arg}" + end + end + if block_given? + @target << " [" + _newline + _nested_structures(block) + @target << "]" + end + @target << ">" + _newline + end + + # Insert a processing instruction into the XML markup. E.g. + # + # For example: + # + # xml.instruct! + # #=> <?xml version="1.0" encoding="UTF-8"?> + # xml.instruct! :aaa, :bbb=>"ccc" + # #=> <?aaa bbb="ccc"?> + # + def instruct!(directive_tag=:xml, attrs={}) + _ensure_no_block block_given? + if directive_tag == :xml + a = { :version=>"1.0", :encoding=>"UTF-8" } + attrs = a.merge attrs + end + _special( + "<?#{directive_tag}", + "?>", + nil, + attrs, + [:version, :encoding, :standalone]) + end + + # Surrounds the given text with a CDATA tag + # + # For example: + # + # xml.cdata! "blah blah blah" + # # => <![CDATA[blah blah blah]]> + def cdata!(text) + _ensure_no_block block_given? + _special("<![CDATA[", "]]>", text, nil) + end + + private + + # NOTE: All private methods of a builder object are prefixed when + # a "_" character to avoid possible conflict with XML tag names. + + # Insert text directly in to the builder's target. + def _text(text) + @target << text + end + + # Insert special instruction. + def _special(open, close, data=nil, attrs=nil, order=[]) + _indent + @target << open + @target << data if data + _insert_attributes(attrs, order) if attrs + @target << close + _newline + end + + # Start an XML tag. If <tt>end_too</tt> is true, then the start + # tag is also the end tag (e.g. <br/> + def _start_tag(sym, attrs, end_too=false) + @target << "<#{sym}" + _insert_attributes(attrs) + @target << "/" if end_too + @target << ">" + end + + # Insert an ending tag. + def _end_tag(sym) + @target << "</#{sym}>" + end + + # Insert the attributes (given in the hash). + def _insert_attributes(attrs, order=[]) + return if attrs.nil? + order.each do |k| + v = attrs[k] + @target << %{ #{k}="#{v}"} if v + end + attrs.each do |k, v| + @target << %{ #{k}="#{v}"} unless order.member?(k) + end + end + + def _ensure_no_block(got_block) + if got_block + fail IllegalBlockError, + "Blocks are not allowed on XML instructions" + end + end + + end + +end +#!/usr/bin/env ruby + +#-- +# Copyright 2004 by Jim Weirich (jim@weirichhouse.org). +# All rights reserved. + +# Permission is granted for use, copying, modification, distribution, +# and distribution of modified versions of this work as long as the +# above copyright notice is included. +#++ + +require 'builder/xmlmarkup' +require 'builder/xmlevents' +module ActiveSupport + module VERSION #:nodoc: + MAJOR = 1 + MINOR = 3 + TINY = 1 + + STRING = [MAJOR, MINOR, TINY].join('.') + end +end +# Extensions to nil which allow for more helpful error messages for +# people who are new to rails. +# +# The aim is to ensure that when users pass nil to methods where that isn't +# appropriate, instead of NoMethodError and the name of some method used +# by the framework users will see a message explaining what type of object +# was expected. + +class NilClass + WHINERS = [ ::ActiveRecord::Base, ::Array ] + + @@method_class_map = Hash.new + + WHINERS.each do |klass| + methods = klass.public_instance_methods - public_instance_methods + methods.each do |method| + @@method_class_map[method.to_sym] = klass + end + end + + def id + raise RuntimeError, "Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id", caller + end + + private + def method_missing(method, *args, &block) + raise_nil_warning_for @@method_class_map[method], method, caller + end + + def raise_nil_warning_for(klass = nil, selector = nil, with_caller = nil) + message = "You have a nil object when you didn't expect it!" + message << "\nYou might have expected an instance of #{klass}." if klass + message << "\nThe error occured while evaluating nil.#{selector}" if selector + + raise NoMethodError, message, with_caller || caller + end +end + +#-- +# Copyright (c) 2005 David Heinemeier Hansson +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +$:.unshift(File.dirname(__FILE__)) +$:.unshift(File.dirname(__FILE__) + "/active_support/vendor") + +require 'builder' + +require 'active_support/inflector' + +require 'active_support/core_ext' +require 'active_support/clean_logger' +require 'active_support/dependencies' +require 'active_support/reloadable' + +require 'active_support/ordered_options' +require 'active_support/option_merger' + +require 'active_support/values/time_zone' + +require 'active_support/json'
\ No newline at end of file |